トップ 一覧 検索 ヘルプ RSS ログイン

PRG-stm32-forthの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!! CFOTH
https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads

https://github.com/MitchBradley/cforth/tree/master

! with WROOM32/ESP32
 make port=/dev/ttyUSB0 flash 


!! Arduino IDE CORE
 /* Forth サンプル */
 /* オリジナルは以下のところ 
 * http://phaendal.hatenablog.com/entry/2015/07/29/091821
 * https://github.com/phaendal/documentation- forth/tree/master/006.interactive_rstack_recur/c-sample 
 */
 /* 変更内容
  * STM32duino 用に書き換え
  /*
 // #define DICT_MAX 65535
 // #define DICT_MAX 2048  # STM32F103C6 MAX 
 #define DICT_MAX 1024
 // #define DICT_MAX 192
 // #define DICT_MAX 180
 
 //******************************************************
 //#include <avr/pgmspace.h>
 //******************************************************
 // typedef long int Number;
 // typedef int Number;
 typedef long Number;
 typedef char* FString;
 
 // Core
 typedef void (*Core)(void);
 
 // ワードのフラグ
 typedef struct  {
  unsigned int immediate:1;
  unsigned int hidden:1;
 } wflag;
 
 // Header
 typedef struct {
  int    next;
  char  *hname;
  wflag *flag;
 } Header ;
 
 typedef union {
  Number number;
  FString str;
  Core   core;
  Header *header;
 } DictValue;
 
 // スタック
 //=================================================================================================
 DictValue dstack[128] ;
 // DictValue dstack[64] ;
 // DictValue dstack[32] ;
 //****************************************************************************************************
 long int doToken (char);
 void procValue (DictValue);
 
 
 //=================================================================================================
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
 #include <stdarg.h>
 // =================================================================================================
 
 
 static int dsp = 0;
 
 // int rstack[128];
 // static int rstack[64];
 // static int rstack[32];
 static int rstack[128];
 static int rsp = 0;
 
 void rpush (int x) {
  rstack[rsp] = x;
  rsp++;
 }
 
 int rpop () {
  rsp--;
  return rstack[rsp];
 }
 
 void dpush (DictValue x) {
  dstack[dsp] = x;
  dsp++;
 }
 
 DictValue dpop () {
  if ( dsp <= 0 ) {
    Serial.print("Stuck underflow");
     return dstack[dsp];
  }
  dsp--;
  return dstack[dsp];
 }
 
 
 // 辞書とVM
 // =================================================================================================
 DictValue ip;
 int np;
 
 // #define DICT_MAX 65536
 // 終了用の番兵
 static DictValue dict[DICT_MAX] = { 0 } ; 
 // 終了用の番兵
 
 int latest = 0;
 int dict_here = 1;
 
 void pushDict(DictValue v) {
  dict[dict_here] = v;
  dict_here++;
 }
 
 // to Core Field Address
 int toCFA (int addr) {
  return addr + 1;
 }
 
 // フラグのチェックと操作
 int isHidden (wflag *flag) {
  // hiddenなら0を返す
  return flag->hidden;
 }
 
 int isImmediate (wflag *flag) {
  return flag->immediate;
 }
 
 void toggleHidden (wflag *flag) {
  flag->hidden = !flag->hidden;
 }
 
 void setImmediate (int addr, int flag) {
  Header *word = dict[addr].header;
  word->flag->immediate = flag;
 }
 
 
 // NEXTルーチン
 // =================================================================================================
 void next () {
  ip = dict[np];
  np++;
 }
 
 void docolon () {
  rpush(np);
  np = ip.number + 1;
  next();
 }
 
 void execute () {
  while (ip.number != 0) {
    dict[ip.number].core();
  }
 }
 
 
 // ワード定義関数
 // ==================================================================================== =============
 int createHeader (char *hname) {
  // ヘッダを作り、そのヘッダのアドレスを返す
  // Header *h = malloc(sizeof(Header));
  Header *h = new(Header);
  // wflag *flag = malloc(sizeof(wflag));
  wflag *flag = new(wflag);
  flag->immediate = 0;
  flag->hidden    = 0;
 
  DictValue d;
  h->next = latest;
  h->hname = strdup(hname);
  h->flag = flag;
 
  latest = dict_here;
  d.header = h;
  pushDict(d);
 
  return latest;
 }
 
 void freeHeader (Header *h) {
  free(h->hname);
  free(h->flag);
  free(h);
 }
 
 int defnative (char *cname, Core core) {
  // Coreのみのネイティブワードを作り、そのアドレスを返す
  int addr = createHeader(cname);
 
  DictValue d = {.core = core};
  pushDict(d);
  return addr;
 }
 
 int defword (char *name, ...) {
  // 可変長引数の準備
  va_list ap;
  va_start(ap, name);
 
  // コロンワードを作り、そのアドレスを返す
  // dfは0で終わっている必要がある
  int addr = createHeader(name);
 
  DictValue d = {.core = docolon};
  pushDict(d);
 
  int word = va_arg(ap, int);
  for (; word != 0; word = va_arg(ap, int)) {
    int cfa = toCFA(word);
    DictValue n = {.number = cfa};
    pushDict(n);
  }
 
  va_end(ap);
 
  return addr;
 } 
 
 
 // 組み込みワード用Core
 // 
 ==================================================================================== =============
 void pushTwo () {
  DictValue two = {.number = 2};
  dpush(two);
  next();
 }
 
 void mul () {
  Number a = dpop().number;
  Number b = dpop().number;
  DictValue x = {.number = a * b};
  dpush(x);
  next();
 }
 
 void add () {
  Number a = dpop().number;
  Number b = dpop().number;
  DictValue x = {.number = a + b};
  dpush(x);
  next();
 }
 
 void sub () {
  Number b = dpop().number;
  Number a = dpop().number;
  DictValue x = {.number = a - b};
  dpush(x);
  next();
 }
 
 
 // Stack Operation
 
 void w_swap () {
  DictValue a = dpop();
  DictValue b = dpop();
  dpush(a);
  dpush(b);
  next();
 }
 
 void w_dup () {
  DictValue x = dpop();
  dpush(x);
  dpush(x);
  next();
 }
 
 void w_drop () {
  dpop();
  next();
 }
 
 
 // リターンスタック
 
 void w_rpush () {
  rpush(dpop().number);
  next();
 }
 
 void w_rpop () {
  DictValue x;
  x.number = rpop();
  dpush(x);
  next();
 }
 
 
 void printStackItem () {
  // printf("%d ", dpop().number);
  // Serial.print("TTTTTTT");
  Serial.print(dpop().number);
  next();
 }
 
 void printStack () {
  Serial.print(dsp);
  int i;
  for (i = 0; i < dsp; i++) {
    Serial.print(dstack[i].number);
  }
  next();
 }
 
 void ret () {
  np = rpop();
  next();
 }
 
 
 // vm-mode
 // -------------------------------------------------------------------------------------------------
 // int vm_mode = 0; // 0: execute, 1: compile
 byte vm_mode = 0; // 0: execute, 1: compile
 
 void executeMode () {
  vm_mode = 0;
 } 
 
 void w_execute_mode () {
  executeMode();
  next();
 }
 
 void compileMode () {
  vm_mode = 1;
 }
 
 void w_compile_mode () {
  compileMode();
  next();
 }
 
 
 // read-token>
 // -------------------------------------------------------------------------------------------------
 // 前方宣言
 char* readToken ();
 
 // #define TOKEN_BUFFER_SIZE 16
 // #define MAX_TOKEN_LEN 128
 #define TOKEN_BUFFER_SIZE 16
 #define MAX_TOKEN_LEN 32
 
 char token_buffer[TOKEN_BUFFER_SIZE][MAX_TOKEN_LEN];
 
 int tokenBufPos () {
  // Returns token buffer position(r) and increment cycle counter(i)
  // static i = 0;
  static int i = 0;
  int r = i;
 
  i = (i + 1) % TOKEN_BUFFER_SIZE;
  return r;
 }
 
 char* bufferToken (char* token) {
  int pos = tokenBufPos();
  strcpy(token_buffer[pos], token);
  return token_buffer[pos];
 }
 
 void w_read_token () {
  char *token = bufferToken(readToken());
  DictValue s = {.str = token};
  dpush(s);
  next();
 }
 
 void printStr () {
  Serial.print(dpop().str);   // printf("str\n")
  Serial.print(F("\n"));
  next();
 }
 
 // 辞書操作
 
 void w_create_header () {
  DictValue d = dpop();
  createHeader(d.str);
 
  // コロンワード用にdocolを置く
  DictValue docol = {.core = docolon};
  pushDict(docol);
 
  next();
 }
 
 void w_toggle_hidden () {
  // latestワードのhiddenフラグを切り替える
  Header *h = dict[latest].header;
  wflag *flag = h->flag;
  toggleHidden(flag);
  next();
 }
 
 void w_fetch_dict_here () {
  DictValue x = {.number = dict_here};
  dpush(x);
  next();
 }
 
 void w_set_dict_here () {
  dict_here = dpop().number;
  next();
 }
 
 void w_latest () {
  DictValue x = {.number = latest};
  dpush(x);
  next();
 }
 
 void w_store_latest () {
  latest = dpop().number;
  next();
 }
 
 void lit () {
  // lit x という順番で辞書に追加されているxを、データスタックに置く。
  // 今、npがxが入ってるアドレスを指しているので、取り出してスタックに置き、
  // その分npを進める。
  dpush(dict[np]);
  np++;
  next();
 }
 
 void w_push_dict () {
  DictValue d = dpop();
  pushDict(d);
  next();
 }
 
 void w_immediate () {
  setImmediate(latest, 1);
  next();
 }
 
 // メモリ操作
 
 void w_mem_fetch () {
  DictValue d = dpop();
  dpush(dict[d.number]);
  next();
 }
 
 void w_mem_set () {
  DictValue a = dpop();
  DictValue v = dpop();
  dict[a.number] = v;
  next();
 }
 
 // branch
 
 void w_branch () {
  DictValue offset = dict[np];
  np += offset.number;
  next();
 }
 
 void w_0branch () {
  Number x = dpop().number;
 
  if (x != 0) {
    np++;
    next();
    return;
  }
 
  w_branch();
 }
 
 // find, >cfa
 
 int findWord (char *token, int addr) {
  Header *word;
 
  while (addr != 0) {
    word = dict[addr].header;
 
    if (!isHidden(word->flag) != 0 && strcmp(token, word->hname) == 0) {
      return addr;
    }
 
    addr = word->next;
  }
 
  return 0;
 }
 
 void w_find () {
  DictValue x = dpop();
  int addr = findWord(x.str, latest);
  DictValue a = {.number = addr};
  dpush(a);
  next();
 }
 
 void w_tcfa () {
  DictValue x = dpop();
  DictValue a = {.number = toCFA(x.number)};
  dpush(a);
  next();
 }
 
 // 比較
 #define BINCOMP(NAME,OP)       \
 void NAME () {                 \
  DictValue b = dpop();        \
  DictValue a = dpop();        \
  DictValue r = {.number = 0}; \
  if (a.number OP b.number) {  \
    r.number = 1;              \
  }                            \
  dpush(r);                    \
  next();                      \
 }
 
 BINCOMP(w_lt,  <);
 BINCOMP(w_gt,  >);
 BINCOMP(w_le,  <=);
 BINCOMP(w_ge,  >=);
 BINCOMP(w_eq,  ==);
 BINCOMP(w_neq, !=);
 
 void w_bye () {
  exit(0);
 }
 
 // コンパイル時などに使用するワード
 int word_lit;
 
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++
 void prepareBuiltins () {
  
  int word_2   = defnative((char *)F("2"), pushTwo);
  int word_mul = defnative((char *)F("*"), mul);
  int word_add = defnative((char *)F("+"), add);
    
  int word_sub = defnative((char *)F("-"), sub);
  
  int word_swap = defnative((char *)F("swap"), w_swap);
  int word_dup  = defnative((char *)F("dup"),  w_dup);
  int word_drop = defnative((char *)F("drop"), w_drop);
    
  int word_rpush = defnative((char *)F(">r"), w_rpush);
  int word_rpop  = defnative((char *)F("r>"), w_rpop);
  
  int word_find = defnative((char *)F("find"), w_find);
  int word_tcfa = defnative((char *)F(">cfa"), w_tcfa);
   
  int word_dot  = defnative((char *)F("."),  printStackItem);
  int word_print_str  = defnative((char *)F("print"), printStr);
  int word_dots = defnative((char *)F(".s"), printStack);
  
  int word_ret = defnative((char *)F("ret"), ret);
 
  int word_read_token = defnative((char *)F("read-token>"), w_read_token);
 
  int word_execute_mode = defnative((char *)F("execute-mode>>"), w_execute_mode);
      setImmediate(word_execute_mode, 1);
 
  int word_compile_mode = defnative((char *)F("compile-mode>>"), w_compile_mode);
 
  int word_create_header = defnative((char *)F("create-header"), w_create_header);
  int word_toggle_hidden = defnative((char *)F("toggle-hidden"), w_toggle_hidden);
 
  int word_fetch_dict_here = defnative((char *)F("dict-here"), w_fetch_dict_here);
  int word_set_dict_here   = defnative((char *)F("dict-here!"), w_set_dict_here);
  
  int word_latest = defnative((char *)F("latest"), w_latest);
  int word_store_latest = defnative((char *)F("latest!"), w_store_latest);
  
  word_lit = defnative((char *)F("lit"), lit);
  int word_push_dict = defnative((char *)F("push-dict"), w_push_dict);
 
  int word_mem_fetch = defnative((char *)F("@"), w_mem_fetch);
  int word_mem_set   = defnative((char *)F("!"), w_mem_set);
 
  int word_branch  = defnative((char *)F("branch"), w_branch);
  int word_0branch = defnative((char *)F("0branch"), w_0branch);
   
  int word_immediate = defnative((char *)F("immediate!"), w_immediate);
   
  // 比較
  int word_gt  = defnative((char *)F(">"),  w_gt);
  int word_lt  = defnative((char *)F("<"),  w_lt);
  int word_ge  = defnative((char *)F(">="), w_ge);
  int word_le  = defnative((char *)F("<="), w_le);
  int word_equ = defnative((char *)F("="),  w_eq);
  int word_neq = defnative((char *)F("<>"), w_neq);
  
  // defwordの引数は0で終わること
  int word_2x   = defword((char *)F("2*"), word_2, word_mul, word_ret, 0);
  int word_4x   = defword((char *)F("4*"), word_2x, word_2x, word_ret, 0);
  int word_16x  = defword((char *)F("16*"), word_4x, word_4x, word_ret, 0);
  int word_main = defword((char *)F("main"), word_2, word_16x, word_dot, word_ret, 0);
 
  int word_colon = defword((char *)F(":"),
            word_read_token, word_create_header,
            word_toggle_hidden, word_compile_mode, word_ret, 0);
 
  int word_semicolon =
    defword((char *)F(";"),
            word_lit, word_ret, word_push_dict,
            word_toggle_hidden, word_execute_mode, word_ret, 0);
    setImmediate(word_semicolon, 1);
 
  int word_bye = defnative((char *)F("bye"), w_bye);
  // defnative((char *)F("bye"), w_bye);
 }
 
 // interpret
 //=================================================================================================
 // Reader
 // -------------------------------------------------------------------------------------------------
 #define READER_BUFFER_SIZE 256
 // #define READER_BUFFER_SIZE 128
 
 char rbuffer[READER_BUFFER_SIZE];
 char token[READER_BUFFER_SIZE];
 int  rpos = 0;
 //byte  rpos = 0;
 
 void setupReader (char *cstr) {
  memset(rbuffer, 0, READER_BUFFER_SIZE);
  strcpy(rbuffer, cstr);
  rpos = 0;
 }
 
 char reader () {
  // 呼ばれる度に入力を1文字消費して返す
  rpos++;
  return rbuffer[rpos - 1];
 }
 
 int isDelimiter (char c) {
  return (c == ' '  ||
          c == '\n' ||
          c == '\0');
 }
 
 char skipSpace () {
  // 空白と改行を読み飛ばし続け、空白以外の文字が来たらそれを返す。
  // 入力が尽きたら0を返す(NULL文字)
  char c = reader();
  // Serial.print(c); // GREEN TEST
  // Serial.print(isDelimiter(c));
  while (c != 0 && isDelimiter(c)) {
    c = reader();
  }
  // Serial.print(c); // GREEN TEST
  return c;
 }
 
 char* readToken () {
  // トークンをバッファから切り出して、グローバル変数tokenに入れてそのアドレスを返す
  // 入力が尽きていた場合はNULLを返す
  int  pos = 0;
  char c = skipSpace();
  // Serial.print(c); // GREEN TEST
   
  // 入力が尽きていた
  if (c == '\0') { return NULL; }
 
  // Serial.print(pos);  // GREEN TEST
  token[pos] = c;
 
  while (!isDelimiter(c)) {
    pos++;
    c = reader();
    token[pos] = c;
  }
 
  // NULL終端
  token[pos] = 0;
 
  Serial.print(token); // GREEN TEST
  return token;
 }
 
 // ワードの実行、又はリテラルとして解釈
 // --------------------------------------------------------------------------------- ----------------
 void executeCFA (int cfa) {
  ip.number = cfa;
  np = 0;
  execute();
 }
 
 void procWord (int addr) {
  int cfa = toCFA(addr);
    
 Header *word = dict[addr].header;
  
  if (vm_mode == 0 || isImmediate(word->flag)) {
    executeCFA(cfa);
    return;
  }
 
  // コンパイル
  DictValue d = {.number = cfa};
  pushDict(d);
 }
 
 DictValue asValue (char *token, char **check) {
  // トークンを値(リテラル)として解釈し、その値を返す
  // 解釈に成功したら、checkにNULLをセットする。
  Number x = strtol(token, check, 10);
  DictValue d = {.number = x};
  return d;
 }
 
 void procValue (DictValue value) {
  if (vm_mode == 0) {
    dpush(value);
    return;
  }
 
  // コンパイル
  DictValue wlit = {.number = toCFA(word_lit)};
  pushDict(wlit);
  pushDict(value);
 }
 
 long int doToken (char *token) {
  // トークンを解釈し実行する。
  // 解釈できれば0、できなければ-1を返す。
  
  // DictValue dvalue ;
  int addr  = findWord(token, latest) ;
  char  *check = NULL ;
     
  // ワードが見つかった場合
  if (addr != 0) {
    procWord(addr);
    return 0;
  }
 
  // 数字として解釈出来た場合
   DictValue dvalue = asValue(token, &check);
  if (*check == '\0') {
    procValue(dvalue);
    return 0;
  }
 
  // エラー
  Serial.print(F("Word not found::"));
  Serial.print(token);
  Serial.print("::\n");
  // printf("Word not found: %s\n", token);
  return -1;
 }
 
 // コード実行
 // -------------------------------------------------------------------------------------------------
 void interpret (char *code) {
  // Serial.print("GREEN_TEST::");
  // Serial.print(code);  // GREEN.TEST
  // Serial.print("::GREEN_TEST\n");
  setupReader(code);
  // Serial.print(code);   // GreenTEST
  char *token = readToken();
  int succeeded = 0;
 
  while (token != NULL && succeeded == 0) {
    succeeded = doToken(token);
    token = readToken();
  }
 }
 
 // コマンドライン
 // -------------------------------------------------------------------------------------------------
 void repl () {
  // char buff[64]; //READER_BUFFER_SIZE
  char buff[READER_BUFFER_SIZE];
  // char buff[255];
  int cnt = 0;
  boolean ready = false;
  // ORIGN linux program
  // while (fgets(buff, 255, stdin)) {
  //   interpret(buff);
  // }
  while( true ) {
    if (ready)
     {
        // Serial.print("GREEN_TEST::");
        // Serial.print(buff);  // GREEN.TEST
        // Serial.print("::GREEN_TEST\n");
        interpret(buff);
        ready = false;
     } else while (Serial.available()) {
       char c = Serial.read();
        buff[cnt++] = c;
        if ((c == '\n') || (cnt == sizeof(buff)-1))
        {
            buff[cnt] = '\0';
            cnt = 0;
            ready = true;
        }
   }  }
 }
 
 /***********************************************/
 
 void loop() {
  // put your main code here, to run repeatedly:
 
  //  int main (int argc, char* argv[]) {
  prepareBuiltins();
 
  // // if
  interpret((char *)F(": 'lit lit lit push-dict ;"));
  interpret((char *)F(": 'push-dict lit push-dict push-dict ;"));
  interpret((char *)F(": compile> 'lit read-token> find >cfa push-dict 'push-dict ; immediate!"));
  // 
  interpret((char *)F(": if compile> 0branch dict-here 0 push-dict ; immediate!"));
  interpret((char *)F(": save-offset dup dict-here swap - swap ! ;"));
  interpret((char *)F(": then save-offset ; immediate!"));
  interpret((char *)F(": save-else-offset swap save-offset ;"));
  interpret((char *)F(": else compile> branch dict-here 0 push-dict save-else-offset ; immediate!"));
  //
  // // ループ
  // // begin ... until
  interpret((char *)F(": begin dict-here ; immediate!"));
  interpret((char *)F(": until compile> 0branch dict-here - push-dict ; immediate!"));
  //
  // // begin .. again
  interpret((char *)F(": 'back-branch compile> branch dict-here - push-dict ;"));
  interpret((char *)F(": again 'back-branch ; immediate!"));
  // 
  // // begin ... while ... repeat
  interpret((char *)F(": while compile> 0branch dict-here 0 push-dict ; immediate!"));
  interpret((char *)F(": repeat  swap 'back-branch  save-offset ; immediate!"));
  // 
  interpret((char *)F(": recur latest >cfa push-dict ; immediate!"));
  // 
  //
  Serial.print("TEST command ");
  interpret((char *)F(": testcmd 1 2 + . ; immediate!"));
  interpret((char *)F(" testcmd "));
  //
  repl();
  //
  Serial.println("EXIT");
  return ;
 }
  
 //***************************
 //***************************
 void setup() {
  // put your setup code here, to run once:
  // Serial.begin(9600); 
  //******************************
  pinMode(33, OUTPUT);
  Serial.begin();  // USB does not require BAUD
  // wait for serial monitor to be connected.
  while (!Serial)
  {
    digitalWrite(33,!digitalRead(33));// Turn the LED from off to on, or on to off
    delay(100);         // fast blink
  }
  //******************************
  Serial.println("YunoyamaFORTH");
  Serial.println("0.00");
 }
 //***************************