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

PRG-arduino-tforthの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
! Tiny-FORTH by Arduino 

もとプログラム

http://middleriver.chagasi.com/electronics/tforth.html

https://gist.github.com/monsonite/087218561b11557dd2f8

これ

https://gist.github.com/anonymous/e4f9bad7eefd8b74cceb


そのまま、ではチョット使いずらいので Serial.print / Serial.read で置き換え

ただメモリが足りなくなった(涙)



 //  Tiny FORTH by  T. NAKAGAWA   2004/07/04-10,7/29,8/5-6
 //   Def :: 2016-12-29 :: IDE setup / loop  用に書き換え 
 /*
  Tiny FORTH
  Experimental Forth for Arduino
  T. Nakagawa
  2004/07/10
  ==
  Export
    IDE 1.6.x で書き換え
    main の部分を setup / loop で 書き換え
    getch の部分が不安
    メモリの使用量が問題か?
 */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <avr/io.h>
 
 void initl(void);
 unsigned char getchr(void);
 void putchr(unsigned char c);
 
 /****************************************************************/ 
 
 #ifndef _SYSTEM_H_
 #define _SYSTEM_H_
 #define BUF_SIZE 128  /* 8 - 255 */
 // #define STACK_SIZE (256) /* 8 - 65536 */
 // #define DIC_SIZE (1024) /* 8 - 8*1024 */
 #define STACK_SIZE (128) /* 8 - 65536 */
 #define DIC_SIZE (512) /* 8 - 8*1024 */
 #define R2V(base, ptr) ((unsigned short)((ptr) - (base)))
 #define V2R(base, ptr) ((unsigned char *)((base) + (ptr)))
 
 #endif
 
 void initl(void) {
  return;
 }
  
 
 unsigned char getchr(void) {
  int c;
  c = u_getchar();
  if (c == '\x03') exit(0); /* CTRL+C */
  if (c < 0) c = 0;
  u_putchar(c);
  return (unsigned char)c;
 }
 
 
 void putchr(unsigned char c) {
  u_putchar(c);
  return;
 }
 
 
 #include <stdio.h>
 #include <stdlib.h>
 
 
 #define KEY_RUNMODE "\x03" ":  " "VAR" "FGT"
 #define KEY_COMPILEMODE "\x0b" ";  " "IF " "ELS" "THN" "BGN" "END" "WHL" "RPT" "DO " "LOP" "I  "
 #define KEY_PRIMITIVE "\x19" "DRP" "DUP" "SWP" ">R " "R> " "+  " "-  " "*  " "/  " "MOD" "AND" "OR " "XOR" "=  " "<  " ">  " "<= " ">= " "<> " "NOT" "@  " "@@ " "!  " "!! " ".  "
 #define PFX_UDJ 0x80U
 #define PFX_CDJ 0xa0U
 #define PFX_CALL 0xc0U
 #define PFX_PRIMITIVE 0xe0U
 #define I_LIT 0xffU
 #define I_RET 0xfeU
 #define I_LOOP (PFX_PRIMITIVE | 25U)
 #define I_RDROP2 (PFX_PRIMITIVE | 26U)
 #define I_I (PFX_PRIMITIVE | 27U)
 #define I_P2R2 (PFX_PRIMITIVE | 28U)
 
 static unsigned short stack[STACK_SIZE];
 static unsigned short *retstk;
 static unsigned short *parstk;
 static unsigned char dic[DIC_SIZE];
 static unsigned char *dicptr;
 static unsigned char *dicent;
 
 static void putmsg(char *msg);
 static unsigned char *gettkn(void);
 static char literal(unsigned char *str, unsigned short *num);
 static char lookup(unsigned char *key, unsigned short *adrs);
 static char find(unsigned char *key, char *list, unsigned char *id);
 static void compile(void);
 static void variable(void);
 static void forget(void);
 static void execute(unsigned short adrs);
 static void primitive(unsigned char ic);
 static void putnum(unsigned short num);
 
 //  Put a message
 static void putmsg(char *msg) {
  while (*msg != '\0') putchr(*(msg++));
  putchr('\r');
  putchr('\n');
  return;
 }
 
 //  Get a Token
 static unsigned char *gettkn(void) {
  static unsigned char buf[BUF_SIZE] = " ";           // == " \0\0\0..." 
  unsigned char ptr;
 
  // remove leading non-delimiters
  while (*buf != ' ') {
    for (ptr = 0; ptr < BUF_SIZE - 1; ptr++) buf[ptr] = buf[ptr + 1];
    buf[ptr] = '\0';
  }
 
  for (; ; ) {
    // remove leading delimiters 
    while (*buf == ' ') {
      for (ptr = 0; ptr < BUF_SIZE - 1; ptr++) buf[ptr] = buf[ptr + 1];
      buf[ptr] = '\0';
    }
 
    if (*buf == '\0') {
      for (ptr = 0; ; ) {
        unsigned char c;
        c = getchr();
        if (c == '\r') {
          putchr('\n');
          buf[ptr] = ' ';
          break;
        } else if (c == '\b') {
          if (ptr == 0) continue;
              buf[--ptr] = '\0';
              putchr(' ');
              putchr('\b');
        } else if (c <= 0x1fU) {
        } else if (ptr < BUF_SIZE - 1) {
          buf[ptr++] = c;
        } else {
          putchr('\b');
          putchr(' ');
          putchr('\b');
        }
      }
    } else {
      return buf;
    }
  }
 }
 
 // Process a Literal 
 static char literal(unsigned char *str, unsigned short *num) {
  if (*str == '$') {
    unsigned short n = 0;
    for (str++; *str != ' '; str++) {
      n *= 16;
      if (*str <= '9') n += *str - '0'; else n += *str - 'A' + 10;
    }
    *num = n;
    return 1;
  } else if ('0' <= *str && *str <= '9') {
    unsigned short n = 0;
    for (; *str != ' '; str++) {
      n *= 10;
      n += *str - '0';
    }
    *num = n;
    return 1;
  } else {
    return 0;
  }
 }
 
 //  Lookup the Keyword from the Dictionary
 static char lookup(unsigned char *key, unsigned short *adrs) {
  unsigned char *ptr;
 
  for (ptr = dicent; ptr != V2R(dic, 0xffffU); ptr = V2R(dic, *ptr + *(ptr + 1) * 256U)) {
    if (ptr[2] == key[0] && ptr[3] == key[1] && (ptr[3] == ' ' || ptr[4] == key[2])) {
      *adrs = R2V(dic, ptr);
      return 1;
    }
  }
  return 0;
 }
 
 //  Find the Keyword in a List
 static char find(unsigned char *key, char *list, unsigned char *id) {
  unsigned char n, m;
 
  for (n = 0, m = *(list++); n < m; n++, list += 3) {
    if (list[0] == key[0] && list[1] == key[1] && (key[1] == ' ' || list[2] == key[2])) {
      *id = n;
      return 1;
    }
  }
  return 0;
 }
 
 // Compile Mode
  static void compile(void) {
  unsigned char *tkn;
  unsigned char tmp8;
  unsigned short tmp16;
 
  // get the identifier 
  tkn = gettkn();
 
  // Write the header
  tmp16 = R2V(dic, dicent);
  dicent = dicptr;
  *(dicptr++) = tmp16 % 256U;
  *(dicptr++) = tmp16 / 256U;
  *(dicptr++) = tkn[0];
  *(dicptr++) = tkn[1];
  *(dicptr++) = (tkn[1] != ' ') ? tkn[2] : ' ';
 
  for (; ; ) {
    putmsg((char *)">");
    tkn = gettkn();
 
    if (find(tkn, KEY_COMPILEMODE, &tmp8)) {
      if (tmp8 == 0) {  /* ; */
  *(dicptr++) = I_RET;
        break;
      }
      switch (tmp8) {
        unsigned char *ptr;
 
      case 1: /* IF */
        *(retstk++) = R2V(dic, dicptr);
        *(dicptr++) = PFX_CDJ;
        dicptr++;
        break;
      case 2: /* ELS */
        tmp16 = *(--retstk);
        ptr = V2R(dic, tmp16);
  tmp8 = *(ptr);
  tmp16 = R2V(dic, dicptr + 2) - tmp16 + 4096U;
        *(ptr++) = tmp8 | (tmp16 / 256U);
        *(ptr++) = tmp16 % 256U;
        *(retstk++) = R2V(dic, dicptr);
        *(dicptr++) = PFX_UDJ;
        dicptr++;
        break;
      case 3: /* THN */
        tmp16 = *(--retstk);
        ptr = V2R(dic, tmp16);
  tmp8 = *(ptr);
  tmp16 = R2V(dic, dicptr) - tmp16 + 4096U;
        *(ptr++) = tmp8 | (tmp16 / 256U);
        *(ptr++) = tmp16 % 256U;
        break;
      case 4: /* BGN */
        *(retstk++) = R2V(dic, dicptr);
        break;
      case 5: /* END */
  tmp16 = *(--retstk) - R2V(dic, dicptr) + 4096U;
        *(dicptr++) = PFX_CDJ | (tmp16 / 256U);
        *(dicptr++) = tmp16 % 256U;
        break;
      case 6: /* WHL */
        *(retstk++) = R2V(dic, dicptr);
        dicptr += 2;
        break;
      case 7: /* RPT */
        tmp16 = *(--retstk);
        ptr = V2R(dic, tmp16);
  tmp16 = R2V(dic, dicptr + 2) - tmp16 + 4096U;
        *(ptr++) = PFX_CDJ | (tmp16 / 256U);
        *(ptr++) = tmp16 % 256U;
  tmp16 = *(--retstk) - R2V(dic, dicptr) + 4096U;
        *(dicptr++) = PFX_UDJ | (tmp16 / 256U);
        *(dicptr++) = tmp16 % 256U;
        break;
      case 8: /* DO */
        *(retstk++) = R2V(dic, dicptr + 1);
        *(dicptr++) = I_P2R2;
        break;
      case 9: /* LOP */
        *(dicptr++) = I_LOOP;
  tmp16 = *(--retstk) - R2V(dic, dicptr) + 4096U;
        *(dicptr++) = PFX_CDJ | (tmp16 / 256U);
        *(dicptr++) = tmp16 % 256U;
        *(dicptr++) = I_RDROP2;
        break;
      case 10:  /* I */
        *(dicptr++) = I_I;
        break;
      }
    } else if (lookup(tkn, &tmp16)) {
      tmp16 += 2 + 3 - R2V(dic, dicptr) + 4096U;
      *(dicptr++) = PFX_CALL | (tmp16 / 256U);
      *(dicptr++) = tmp16 % 256U;
    } else if (find(tkn, KEY_PRIMITIVE, &tmp8)) {
      *(dicptr++) = PFX_PRIMITIVE | tmp8;
    } else if (literal(tkn, &tmp16)) {
      if (tmp16 < 128U) {
        *(dicptr++) = (unsigned char)tmp16;
      } else {
        *(dicptr++) = I_LIT;
        *(dicptr++) = tmp16 % 256U;
        *(dicptr++) = tmp16 / 256U;
      }
    } else {
      /* error */
      putmsg((char *)"!");
      continue;
    }
  }
  return;
 }
 
 // VARIABLE instruction
 static void variable(void) {
  unsigned char *tkn;
  unsigned short tmp16;
 
  // get an identifier 
  tkn = gettkn();
 
  // Write the header 
  tmp16 = R2V(dic, dicent);
  dicent = dicptr;
  *(dicptr++) = tmp16 % 256U;
  *(dicptr++) = tmp16 / 256U;
  *(dicptr++) = tkn[0];
  *(dicptr++) = tkn[1];
  *(dicptr++) = (tkn[1] != ' ') ? tkn[2] : ' ';
 
  tmp16 = R2V(dic, dicptr + 2);
  if (tmp16 < 128U) {
    *(dicptr++) = (unsigned char)tmp16;
  } else {
    tmp16 = R2V(dic, dicptr + 4);
    *(dicptr++) = I_LIT;
    *(dicptr++) = tmp16 % 256U;
    *(dicptr++) = tmp16 / 256U;
  }
  *(dicptr++) = I_RET;
  *(dicptr++) = 0;  /* data area */
  *(dicptr++) = 0;  /* data area */
 
  return;
 }
 
 //  Forget Words in the Dictionary
  static void forget(void) {
  unsigned short tmp16;
  unsigned char *ptr;
 
  // get a word 
  if (!lookup(gettkn(), &tmp16)) {
    putmsg((char *)"??");
    return;
  }
 
  ptr = V2R(dic, tmp16);
  dicent = V2R(dic, *ptr + *(ptr + 1) * 256U);
  dicptr = ptr;
  return;
 }
 
 //  Virtual Code Execution
 static void execute(unsigned short adrs) {
  unsigned char *pc;
 
  *(retstk++) = 0xffffU;
 
  for (pc = V2R(dic, adrs); pc != V2R(dic, 0xffffU); ) {
    unsigned char ir; /* instruction register */
 
    ir = *(pc++);
 
    if ((ir & 0x80U) == 0) {
      /* literal(0-127) */
      *(--parstk) = ir;
    } else if (ir == I_LIT) {
      /* literal(128-65535) */
      unsigned short tmp16;
      tmp16 = *(pc++);
      tmp16 += *(pc++) * 256U;
      *(--parstk) = tmp16;
    } else if (ir == I_RET) {
      /* RET: return */
      pc = V2R(dic, *(--retstk));
    } else if ((ir & 0xe0U) == PFX_UDJ) {
      /* UDJ: unconditional direct jump */
      pc = V2R(dic, R2V(dic, pc - 1) + (ir & 0x1fU) * 256U + *pc - 4096U);
    } else if ((ir & 0xe0U) == PFX_CDJ) {
      /* CDJ: conditional direct jump */
      if (*(parstk++) == 0) pc = V2R(dic, R2V(dic, pc - 1) + (ir & 0x1fU) * 256U + *pc - 4096U); else pc++;
    } else if ((ir & 0xe0U) == PFX_CALL) {
      /* CALL: subroutine call */
      *(retstk++) = R2V(dic, pc + 1);
      pc = V2R(dic, R2V(dic, pc - 1) + (ir & 0x1fU) * 256U + *pc - 4096U);
    } else {
      /* primitive functions */
      primitive(ir & 0x1fU);
    }
  }
  return;
 }
 
 //  Execute a Primitive Instruction
 static void primitive(unsigned char ic) {
  unsigned short x0, x1;
 
  switch (ic) {
  case 0: /* DRP */
    parstk++;
    break;
  case 1: /* DUP */
    x0 = *parstk;
    *(--parstk) = x0;
    break;
  case 2: /* SWP */
    x1 = *(parstk++);
    x0 = *(parstk++);
    *(--parstk) = x1;
    *(--parstk) = x0;
    break;
  case 3: /* >R */
    *(retstk++) = *(parstk++);
    break;
  case 4: /* R> */
    *(--parstk) = *(--retstk);
    break;
  case 5: /* + */
    x0 = *(parstk++);
    *parstk += x0;
    break;
  case 6: /* - */
    x0 = *(parstk++);
    *parstk -= x0;
    break;
  case 7: /* * */
    x0 = *(parstk++);
    *parstk *= x0;
    break;
  case 8: /* / */
    x0 = *(parstk++);
    *parstk /= x0;
    break;
  case 9: /* MOD */
    x0 = *(parstk++);
    *parstk %= x0;
    break;
  case 10:  /* AND */
    x0 = *(parstk++);
    *parstk &= x0;
    break;
  case 11:  /* OR */
    x0 = *(parstk++);
    *parstk |= x0;
    break;
  case 12:  /* XOR */
    x0 = *(parstk++);
    *parstk ^= x0;
    break;
  case 13:  /* = */
    x1 = *(parstk++);
    x0 = *(parstk++);
    *(--parstk) = (x0 == x1);
    break;
  case 14:  /* < */
    x1 = *(parstk++);
    x0 = *(parstk++);
    *(--parstk) = (x0 < x1);
    break;
  case 15:  /* > */
    x1 = *(parstk++);
    x0 = *(parstk++);
    *(--parstk) = (x0 > x1);
    break;
  case 16:  /* <= */
    x1 = *(parstk++);
    x0 = *(parstk++);
    *(--parstk) = (x0 <= x1);
    break;
  case 17:  /* >= */
    x1 = *(parstk++);
    x0 = *(parstk++);
    *(--parstk) = (x0 >= x1);
    break;
  case 18:  /* <> */
    x1 = *(parstk++);
    x0 = *(parstk++);
    *(--parstk) = (x0 != x1);
    break;
  case 19:  /* NOT */
    *parstk = (*parstk == 0);
    break;
  case 20:  /* @ */
    x0 = *(parstk++);
    x1 = *(V2R(dic, x0));
    x1 += *(V2R(dic, x0 + 1)) * 256U;
    *(--parstk) = x1;
    break;
  case 21:  /* @@ */
    x0 = *(parstk++);
    x1 = *(V2R(dic, x0));
    *(--parstk) = x1;
    break;
  case 22:  /* ! */
    x1 = *(parstk++);
    x0 = *(parstk++);
    *(V2R(dic, x1)) = x0 % 256U;
    *(V2R(dic, x1 + 1)) = x0 / 256U;
    break;
  case 23:  /* !! */
    x1 = *(parstk++);
    x0 = *(parstk++);
    *(V2R(dic, x1)) = (unsigned char)x0;
    break;
  case 24:  /* . */
    putnum(*(parstk++));
    putchr(' ');
    break;
  case 25:  /* LOOP */
    (*(retstk - 2))++;
    x1 = *(retstk - 2);
    x0 = *(retstk - 1);
    *(--parstk) = (x0 <= x1);
    break;
  case 26:  /* RDROP2 */
    retstk -= 2;
    break;
  case 27:  /* I */
    *(--parstk) = *(retstk - 2);
    break;
  case 28:  /* P2R2 */
    *(retstk++) = *(parstk++);
    *(retstk++) = *(parstk++);
    break;
  }
  return;
 }
 
 // Put a Number
 static void putnum(unsigned short num) {
  if (num / (unsigned short)10 != 0) putnum(num / (unsigned short)10);
  putchr((char)(num % (unsigned short)10) + '0');
  return;
 }
 
 //--------------------------------------------------------------------------------------
 // UART Routines
 //--------------------------------------------------------------------------------------
 
 void u_putchar(char c) {
    Serial.write(c);
 }
 
 char rx_byte = 0;
 char u_getchar(void) {
    // loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
    // return UDR0;
    if (Serial.available() > 0) {    // is a character available?
        rx_byte = Serial.read();       // get the character
    } else {
      rx_byte = '\0';
    }
    return rx_byte;
 }
 
 //-----------------------------------------------------------------------------------------
 
 void loop () {
    
    unsigned char tmp8;
    unsigned short tmp16;
    unsigned char *tkn;
 
    for ( ;; ) {
    tkn = gettkn();
 
    // keyword
    if (find(tkn, KEY_RUNMODE, &tmp8)) {
      switch (tmp8) {
      case 0:  /* : */
        compile();
        break;
      case 1: /* VAR */
        variable();
        break;
      case 2: /* FORGET */
        forget();
        break;
      }
    } else if (lookup(tkn, &tmp16)) {
      execute(tmp16 + 2 + 3);
    } else if (find(tkn, KEY_PRIMITIVE, &tmp8)) {
      primitive(tmp8);
    } else if (literal(tkn, &tmp16)) {
      *(--parstk) = tmp16;
    } else {
      // error 
      putmsg((char *)"?");
      continue;
      // return ;    // GreenTST
    }
 
    if (parstk > &(stack[STACK_SIZE])) {
      putmsg((char *)"OVF");
      parstk = &(stack[STACK_SIZE]);
    } else {
      putmsg((char *)"OK");
    }
  }
 }
 
 // Setup the various arrary and initialisation routines
 void setup() 
 { 
    // Enable UART
    Serial.begin(9600);
 
    initl();
 
    // Initialize the stack and dictionary 
    retstk = &(stack[0]);
    parstk = &(stack[STACK_SIZE]);
    dicptr = dic;
    dicent = V2R(dic, 0xffffU);
    
    putmsg((char *)"Tiny-FORTH");
 
 }