diff options
| -rw-r--r-- | forth.c | 78 | ||||
| -rw-r--r-- | optable.c | 80 | ||||
| -rw-r--r-- | optable.h | 14 | ||||
| -rwxr-xr-x | runtests.sh | 2 | 
4 files changed, 113 insertions, 61 deletions
| @@ -27,28 +27,32 @@ bool notdelim(char c) {  void eval(optable* ot, stack* s, int len, char* line); +void op_exec(wordop* op, optable* ot, stack *s, char *word, int len, char* line, int* i) { +    switch (op->optype) { +        case script: +            eval(ot, s, op->scriptlen, op->script); +            break; +        case builtin: +            op->op(s); +            break; +        case directive: +            op->directive(s, len, line, i, ot); +            break; +        case compiled: +            for (int j = 0; j < op->oplistlen; j++) { +                if (op->oplist[j].isliteral) { +                    stack_push(s, op->oplist[j].literal); +                } else { +                    op_exec(op->oplist[j].wordop, ot, s, word, len, line, i); +                } +            } +    } +} +  void exec(optable* ot, stack *s, char *word, int len, char* line, int* i) {      wordop* op = optable_getop(ot, word);      if (op) { -        switch (op->optype) { -            case script: -                eval(ot, s, op->scriptlen, op->script); -                break; -            case builtin: -                op->op(s); -                break; -            case directive: -                op->directive(s, len, line, i, ot); -                break; -            case compiled: -                for (int i = 0; i < op->oplistlen; i++) { -                    if (op->oplist[i].isliteral) { -                        stack_push(s, op->oplist[i].literal); -                    } else { -                        (op->oplist[i].stackop)(s); -                    } -                } -        } +        op_exec(op, ot, s, word, len, line, i);      } else if (isnumber(word)) {          stack_push(s, atoi(word));      } @@ -76,11 +80,11 @@ void eval(optable* ot, stack* s, int len, char* line) {  } -int main(int argc, char** argv) { -    optable* ot = optable_init(); +#ifndef __EMSCRIPTEN__ +int main(int argc, char** argv) { +    optable* ot = optable_new();      stack* s = stack_new(); -      char *line = NULL;      size_t len = 0;      ssize_t read; @@ -88,3 +92,33 @@ int main(int argc, char** argv) {          eval(ot, s, len, line);      }  } + +#else + +#include <emscripten/emscripten.h> +int initialised = false; +optable* ot; +stack* s; +int lastline = 0; + +#define EXTERN + +EXTERN EMSCRIPTEN_KEEPALIVE char* extern_eval(int len, char* line) { +    if (!initialised) { +        ot = optable_new(); +        s = stack_new(); +        initialised = true; +        outputline = malloc(sizeof(int)); +        *outputline = 0; +        // outputtobuffer = true; +    } +    eval(ot, s, len, line); +    if (*outputline != lastline) { +        lastline = *outputline; +        return outputbuffer; +    } else { +        return ""; +    } + +} +#endif @@ -63,13 +63,13 @@ const static wordop inittable[] = {  //static int optable->len = 26;  #pragma clang diagnostic pop -compileditem* compilewords(optable* ot, int len, char** script) { +compileditem* optable_compilewords(optable* ot, int len, char** script) {      compileditem* oplist = malloc(sizeof(compileditem) * len);      for (int i = 0; i < len; i++) {          wordop* wordop = optable_getop(ot, script[i]);          if (wordop) {              oplist[i].isliteral = false; -            oplist[i].stackop = wordop->op; +            oplist[i].wordop = wordop;          } else {              oplist[i].isliteral = true;              oplist[i].literal = atoi(script[i]); @@ -78,39 +78,40 @@ compileditem* compilewords(optable* ot, int len, char** script) {      return oplist;  } -optable* optable_init() { -    optable* ot = malloc(sizeof(optable)); -    ot->optable = malloc(sizeof(wordop) * OPTABLE_MAX_SIZE); -    int inittablesize =sizeof(inittable); -    ot->len = inittablesize / sizeof(*inittable); -    memcpy(ot->optable, inittable, inittablesize); - -    ot->optable[ot->len].word = "nip"; +void optable_addop(optable* ot, char* name, int len, char** words) { +    ot->optable[ot->len].word = malloc(sizeof(name)); +    strcpy(ot->optable[ot->len].word, name);      ot->optable[ot->len].optype = compiled; -    int oplistlen = 2; -    ot->optable[ot->len].oplistlen = oplistlen; -    char* ws[] = {"swap", "drop"}; -    compileditem* oplist = compilewords(ot, 2, ws); +    ot->optable[ot->len].oplistlen = len; +    compileditem* oplist = optable_compilewords(ot, len, words);      ot->optable[ot->len].oplist = oplist;      ot->len++; +} -    ot->optable[ot->len].word = "tuck"; -    ot->optable[ot->len].optype = compiled; -    oplistlen = 3; -    ot->optable[ot->len].oplistlen = oplistlen; -    char* ws2[] = {"dup", "rot", "rot"}; -    oplist = compilewords(ot, oplistlen, ws2); -    ot->optable[ot->len].oplist = oplist; -    ot->len++; +optable* optable_new() { +    optable* ot = malloc(sizeof(optable)); +    ot->optable = malloc(sizeof(wordop) * OPTABLE_MAX_SIZE); +    int inittablesize = sizeof(inittable); +    ot->len = inittablesize / sizeof(*inittable); +    memcpy(ot->optable, inittable, inittablesize); -    ot->optable[ot->len].word = "incr"; -    ot->optable[ot->len].optype = compiled; -    oplistlen = 2; -    ot->optable[ot->len].oplistlen = oplistlen; -    char* ws3[] = {"1", "+"}; -    oplist = compilewords(ot, 2, ws3); -    ot->optable[ot->len].oplist = oplist; -    ot->len++; +    typedef struct { +        char* name; +        int len; +        char** words; +    } tocompile; +    tocompile defs[] = { +        {"nip", 2, (char*[]){"swap","drop"}}, +        {"tuck", 3, (char*[]){"dup", "rot", "rot"}}, +        {"incr", 2, (char*[]){"1", "+"}}, +    }; +    int defslen = sizeof(defs) / sizeof(*defs); +    for (int i = 0; i < defslen; i++) { +        tocompile d = defs[i]; +        char* nm = defs[i].name; +        char** ws = d.words; +        optable_addop(ot,nm, d.len,ws); +    }      return ot;  } @@ -200,14 +201,25 @@ static void dup(stack *s) {      stack_push(s, x);  } +  static void popout(stack *s) { -    printf("%d\n", stack_pop(s)); +#ifdef __EMSCRIPTEN__ +        sprintf(outputbuffer, "%d\n", stack_pop(s)); +        (*outputline)++; +#else +        printf("%d\n", stack_pop(s)); +#endif  }  static void peekout(stack *s) {      int x = stack_pop(s);      stack_push(s, x); -    printf("%d\n", x); +#ifdef __EMSCRIPTEN__ +        sprintf(outputbuffer, "%d\n", x); +        (*outputline)++; +#else +        printf("%d\n", x); +#endif  }  static void donothing(stack *s) { @@ -278,11 +290,11 @@ static void defineop(stack* s_IGNORED, int len_IGNORED, char *input, int* starti      // value easier to deal with (than pointer)      int i = *starti;      // name by which the function will be called -    char *opcode = malloc(sizeof(char) * WORD_LEN_LIMIT); +    char* opcode = malloc(sizeof(char) * WORD_LEN_LIMIT);      int opcodei = 0;      // code to be evaluated when function is called -    char *funcscript = malloc(sizeof(char) * DEFINED_FUNC_MAX_LENGTH); +    char* funcscript = malloc(sizeof(char) * DEFINED_FUNC_MAX_LENGTH);      int funcscripti = 0;      // skip ' ' and ':' @@ -10,14 +10,20 @@  #define WORD_LEN_LIMIT 255  typedef struct optable optable; +typedef struct wordop wordop;  typedef void (*stackop)(stack *);  typedef void (*directiveop)(stack *, int len, char* line, int* i, optable* optable); +#ifdef __EMSCRIPTEN__ +extern char outputbuffer[1024]; +extern int* outputline; +#endif +  typedef struct {      bool isliteral;      union { -        stackop stackop; +        wordop* wordop;          stackitem literal;      };  } compileditem; @@ -29,7 +35,7 @@ typedef enum {      compiled = 3,  } optype; -typedef struct { +struct wordop {      char* word;      optype optype;      union { @@ -44,7 +50,7 @@ typedef struct {              int oplistlen;          };      }; -} wordop; +};  struct optable {      int len; @@ -57,6 +63,6 @@ struct optable {   */  wordop* optable_getop(optable* optable, char *word); -optable* optable_init(); +optable* optable_new();  #endif //OPTABLE_H diff --git a/runtests.sh b/runtests.sh index 766850d..3900871 100755 --- a/runtests.sh +++ b/runtests.sh @@ -24,7 +24,7 @@ runtest () {      if [ "1" -eq "$?" ] ; then          echo "Test $n failed: $file" >&2 -        echo "Diff: (expected vs actual)" >&2 +        echo "Diff: (actual vs expected)" >&2          echo "$diff"          exitcode=1          failed="$(expr "$failed" + 1)" | 
