diff options
author | dan <[email protected]> | 2023-05-29 15:26:26 -0400 |
---|---|---|
committer | dan <[email protected]> | 2023-05-29 15:26:26 -0400 |
commit | c2138b3ba1d49ff93bdebe9b76aca7c356b46689 (patch) | |
tree | 4c53e16cca23852d8eef427edbffb1c0a43f70d2 | |
parent | b72c271d8731e1f67fdef29cd64726dfce893fe7 (diff) | |
download | forth-c2138b3ba1d49ff93bdebe9b76aca7c356b46689.tar.gz forth-c2138b3ba1d49ff93bdebe9b76aca7c356b46689.tar.bz2 forth-c2138b3ba1d49ff93bdebe9b76aca7c356b46689.zip |
feat: add jit-compiled optype ; add more new commands
-rw-r--r-- | forth.c | 12 | ||||
-rw-r--r-- | optable.c | 87 | ||||
-rw-r--r-- | optable.h | 15 | ||||
-rwxr-xr-x | runtests.sh | 7 | ||||
-rw-r--r-- | stack.c | 3 |
5 files changed, 122 insertions, 2 deletions
@@ -40,6 +40,14 @@ void exec(stack *s, char *word, int len, char* line, int* i) { case directive: op->directive(s, len, line, i); 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); + } + } } } else if (isnumber(word)) { stack_push(s, atoi(word)); @@ -67,8 +75,12 @@ void eval(stack* s, int len, char* line) { } } + int main(int argc, char** argv) { + optable_init(); + stack* s = stack_new(); + char *line = NULL; size_t len = 0; ssize_t read; @@ -1,5 +1,7 @@ #include "optable.h" +#include <stdbool.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> static void not(stack *s); @@ -11,6 +13,11 @@ static void eq(stack *s); static void add(stack *s); static void mult(stack *s); static void s_div(stack *s); +static void mod(stack *s); +static void negate(stack *s); +static void s_abs(stack *s); +static void max(stack *s); +static void min(stack *s); static void sub(stack *s); static void dup(stack *s); static void popout(stack *s); @@ -31,6 +38,11 @@ static wordop optable[OPTABLE_MAX_SIZE] = { {"-", builtin, {sub}}, {"*", builtin, {mult}}, {"/", builtin, {s_div}}, + {"negate", builtin, {negate}}, + {"abs", builtin, {s_abs}}, + {"mod", builtin, {mod}}, + {"max", builtin, {max}}, + {"min", builtin, {min}}, {"dup", builtin, {dup}}, {"not", builtin, {not}}, {"=", builtin, {eq}}, @@ -46,9 +58,47 @@ static wordop optable[OPTABLE_MAX_SIZE] = { {"if", directive, {ifdirective}}, {":", directive, {defineop}}, }; -static int optablelen = 20; +static int optablelen = 25; #pragma clang diagnostic pop +compileditem* compilewords(int len, char** script) { + compileditem* oplist = malloc(sizeof(compileditem) * len); + for (int i = 0; i < len; i++) { + wordop* wordop = getop(script[i]); + if (wordop) { + oplist[i].isliteral = false; + oplist[i].stackop = wordop->op; + } else { + oplist[i].isliteral = true; + oplist[i].literal = atoi(script[i]); + } + } + return oplist; +} + +void optable_init() { + + optable[optablelen].word = "nip"; + optable[optablelen].optype = compiled; + int oplistlen = 2; + optable[optablelen].oplistlen = oplistlen; + char* ws[] = {"swap", "drop"}; + compileditem* oplist = compilewords(2, ws); + optable[optablelen].oplist = oplist; + optablelen++; + + + optable[optablelen].word = "incr"; + optable[optablelen].optype = compiled; + oplistlen = 2; + optable[optablelen].oplistlen = oplistlen; + char* ws2[] = {"1", "+"}; + oplist = compilewords(2, ws2); + optable[optablelen].oplist = oplist; + optablelen++; + +} + wordop* getop(char *word) { for (int i = 0; i < optablelen; i++) { if (!strcmp(optable[i].word, word)) { @@ -117,6 +167,12 @@ static void s_div(stack *s) { stack_push(s, y / x); } +static void mod(stack *s) { + int x = stack_pop(s); + int y = stack_pop(s); + stack_push(s, y % x); +} + static void sub(stack *s) { int x = stack_pop(s); int y = stack_pop(s); @@ -147,6 +203,35 @@ static void depth(stack *s) { stack_push(s, stack_depth(s)); } +static void max(stack *s) { + int x = stack_pop(s); + int y = stack_pop(s); + if (x > y) { + stack_push(s, x); + } else { + stack_push(s, y); + } +} + +static void min(stack *s) { + int x = stack_pop(s); + int y = stack_pop(s); + if (x < y) { + stack_push(s, x); + } else { + stack_push(s, y); + } +} + +static void negate(stack *s) { + stack_push(s, 0 - stack_pop(s)); +} + +static void s_abs(stack *s) { + int x = stack_pop(s); + stack_push(s, x < 0 ? 0 - x : x); +} + /* Directives */ static void ifdirective(stack *s, int len, char* line, int* starti) { @@ -12,10 +12,19 @@ typedef void (*stackop)(stack *); typedef void (*directiveop)(stack *, int len, char* line, int* i); +typedef struct { + bool isliteral; + union { + stackop stackop; + stackitem literal; + }; +} compileditem; + typedef enum { directive = 0, builtin = 1, script = 2, + compiled = 3, } optype; typedef struct { @@ -28,6 +37,10 @@ typedef struct { char* script; int scriptlen; }; + struct { + compileditem* oplist; + int oplistlen; + }; }; } wordop; @@ -37,4 +50,6 @@ typedef struct { */ wordop* getop(char *word); +void optable_init(); + #endif //OPTABLE_H diff --git a/runtests.sh b/runtests.sh index ae77797..b93a45a 100755 --- a/runtests.sh +++ b/runtests.sh @@ -4,6 +4,11 @@ if [ -z "$FORTH_CMD" ] ; then FORTH_CMD="./forth" fi +dir='./tests' +if [ "$#" -gt 0 ] ; then + dir="$1" +fi + n=0 failed=0 @@ -27,7 +32,7 @@ runtest () { fi } -for f in ./tests/*; do +for f in $dir/*.forth; do n="$(expr "$n" + 1)" runtest "$f" done @@ -61,6 +61,9 @@ void stack_roll(stack *s) { s->start[i] = s->start[i+1]; } s->start[i] = newtop; + } else { + // no item found + stack_push(s, 0); } } |