diff options
author | dan <[email protected]> | 2023-05-26 14:59:16 -0400 |
---|---|---|
committer | dan <[email protected]> | 2023-05-26 14:59:16 -0400 |
commit | 2b7ea0857da80e1353ce0a72239093f108fdc1e9 (patch) | |
tree | bdcfe9a653c94d0385cea58156225149f92dc3ad | |
parent | 4e26b8c0a1b7fc843741105d57da863997e7284b (diff) | |
download | forth-2b7ea0857da80e1353ce0a72239093f108fdc1e9.tar.gz forth-2b7ea0857da80e1353ce0a72239093f108fdc1e9.tar.bz2 forth-2b7ea0857da80e1353ce0a72239093f108fdc1e9.zip |
refactor: if and : moved to optable too
-rw-r--r-- | forth.c | 53 | ||||
-rw-r--r-- | makefile | 2 | ||||
-rw-r--r-- | optable.c | 61 | ||||
-rw-r--r-- | optable.h | 10 |
4 files changed, 74 insertions, 52 deletions
@@ -26,60 +26,43 @@ char isnumber(char *text) { void eval(stack* s, int len, char* line); -void exec(stack *s, char *word) { +void exec(stack *s, char *word, int len, char* line, int* i) { wordop* op = getop(word); if (op) { - if (op->isscript) { + if (op->optype == script) { eval(s, op->scriptlen, op->script); - } else { + } else if (op->optype == builtin) { op->op(s); + } else if (op->optype == directive) { + op->directive(s, len, line, i); } - return; - } - if (isnumber(word)) { + } else if (isnumber(word)) { push(s, atoi(word)); - return; } } +bool notdelim(char c) { + return c != ' ' && c != '\n' && c != '\t' && c != '\0'; +} + void eval(stack* s, int len, char* line) { - char word[WORD_LEN_LIMIT]; + char word[WORD_LEN_LIMIT]; int wordi = 0; for (int i = 0; i < len; i++) { - // end of input is \n, char after end of input is \0 - if (line[i] == '\0') { - return; - } - if (line[i] != ' ' && - line[i] != '\n' && wordi < WORD_LEN_LIMIT - 1) { - if (line[i] == ':') { - i = defineop(i, line); - wordi = 0; - } else { - word[wordi++] = line[i]; - } + if (notdelim(line[i]) && wordi < WORD_LEN_LIMIT - 1) { + word[wordi++] = line[i]; } else { // end of word if (wordi > 0) { // don't exec an empty string word[wordi] = '\0'; - if (!strcmp(word, "if")) { - stackitem predicate = pop(s); - if (!predicate) { - while (len > i && !( - line[i-3] == 't' && - line[i-2] == 'h' && - line[i-1] == 'e' && - line[i] == 'n' - )) { - i++; - } - } - } else { - exec(s, word); - } + exec(s, word, len, line, &i); } // start new word wordi = 0; } + // end of input string + if (line[i] == '\0') { + return; + } } } @@ -1,5 +1,5 @@ build: - gcc forth.c optable.c stack.c -o forth + clang forth.c optable.c stack.c -o ./forth -Wall run: ./forth run-rlwrap: @@ -1,4 +1,5 @@ #include "optable.h" +#include <stdio.h> #include <string.h> static void not(stack *s); @@ -15,22 +16,31 @@ static void dup(stack *s); static void popout(stack *s); static void peekout(stack *s); +static void ifdirective(stack *s, int len, char* line, int* i); +static void defineopdirective(stack *s, int len, char* line, int* i); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types" +// clang seems to not realise that the union can contain fp types beyond the first static wordop optable[OPTABLE_MAX_SIZE] = { - {".", false, popout}, - {"peek", false, peekout}, - {"+", false, add}, - {"-", false, sub}, - {"*", false, mult}, - {"/", false, s_div}, - {"dup", false, dup}, - {"not", false, not}, - {"=", false, eq}, - {"swap", false, swap}, - {"drop", false, drop}, - {"over", false, over}, - {"rot", false, rot}, + {".", builtin, {popout}}, + {"peek", builtin, {peekout}}, + {"+", builtin, {add}}, + {"-", builtin, {sub}}, + {"*", builtin, {mult}}, + {"/", builtin, {s_div}}, + {"dup", builtin, {dup}}, + {"not", builtin, {not}}, + {"=", builtin, {eq}}, + {"swap", builtin, {swap}}, + {"drop", builtin, {drop}}, + {"over", builtin, {over}}, + {"rot", builtin, {rot}}, + {"if", directive, {ifdirective}}, + {":", directive, {defineopdirective}}, }; -static int optablelen = 13; +static int optablelen = 15; +#pragma clang diagnostic pop int defineop(int starti, char *input) { // name by which the function will be called @@ -66,7 +76,7 @@ int defineop(int starti, char *input) { } // add op to end of table, and increment size optable[optablelen].word = opcode; - optable[optablelen].isscript = true; + optable[optablelen].optype = script; optable[optablelen].script = funcscript; optable[optablelen].scriptlen = funcscripti; optablelen++; @@ -162,3 +172,24 @@ static void peekout(stack *s) { push(s, x); printf("%d\n", x); } + + +/* Directives */ + +static void ifdirective(stack *s, int len, char* line, int* i) { + stackitem predicate = pop(s); + if (!predicate) { + while (len > *i && !( + line[*i-3] == 't' && + line[*i-2] == 'h' && + line[*i-1] == 'e' && + line[*i] == 'n' + )) { + (*i)++; + } + } +} + +static void defineopdirective(stack *s, int len, char* line, int* i) { + *i = defineop(*i, line); +} @@ -10,11 +10,19 @@ #define WORD_LEN_LIMIT 255 typedef void (*stackop)(stack *); +typedef void (*directiveop)(stack *, int len, char* line, int* i); + +typedef enum { + directive = 0, + builtin = 1, + script = 2, +} optype; typedef struct { char* word; - bool isscript; + optype optype; union { + directiveop directive; stackop op; struct { char* script; |