aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordan <[email protected]>2023-05-29 15:26:26 -0400
committerdan <[email protected]>2023-05-29 15:26:26 -0400
commitc2138b3ba1d49ff93bdebe9b76aca7c356b46689 (patch)
tree4c53e16cca23852d8eef427edbffb1c0a43f70d2
parentb72c271d8731e1f67fdef29cd64726dfce893fe7 (diff)
downloadforth-c2138b3ba1d49ff93bdebe9b76aca7c356b46689.tar.gz
forth-c2138b3ba1d49ff93bdebe9b76aca7c356b46689.tar.bz2
forth-c2138b3ba1d49ff93bdebe9b76aca7c356b46689.zip
feat: add jit-compiled optype ; add more new commands
-rw-r--r--forth.c12
-rw-r--r--optable.c87
-rw-r--r--optable.h15
-rwxr-xr-xruntests.sh7
-rw-r--r--stack.c3
5 files changed, 122 insertions, 2 deletions
diff --git a/forth.c b/forth.c
index 0ebb7d5..cc437a2 100644
--- a/forth.c
+++ b/forth.c
@@ -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;
diff --git a/optable.c b/optable.c
index 5751e31..8bbca07 100644
--- a/optable.c
+++ b/optable.c
@@ -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) {
diff --git a/optable.h b/optable.h
index b55b38e..e84ad31 100644
--- a/optable.h
+++ b/optable.h
@@ -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
diff --git a/stack.c b/stack.c
index 617e621..e1f0281 100644
--- a/stack.c
+++ b/stack.c
@@ -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);
}
}