aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordan <[email protected]>2023-06-03 18:25:58 -0400
committerdan <[email protected]>2023-06-03 18:25:58 -0400
commitf59e909a1adaf545dba4c77d83523eeb5063fbcb (patch)
tree0c3b1a133d9023c2e988afd79233e363f348859d
parentb528f7d498b301bcfbd42ea011ed31569f36b378 (diff)
downloadforth-f59e909a1adaf545dba4c77d83523eeb5063fbcb.tar.gz
forth-f59e909a1adaf545dba4c77d83523eeb5063fbcb.tar.bz2
forth-f59e909a1adaf545dba4c77d83523eeb5063fbcb.zip
feat: add do ... loop;
-rw-r--r--forthmachine.c15
-rw-r--r--forthmachine.h3
-rw-r--r--forthmachine_optable.c26
3 files changed, 42 insertions, 2 deletions
diff --git a/forthmachine.c b/forthmachine.c
index 6cdefb5..d831106 100644
--- a/forthmachine.c
+++ b/forthmachine.c
@@ -11,8 +11,9 @@ forthmachine* forthmachine_new(errorhandler errorhandler) {
fm->ot = optable_new(errorhandler);
fm->s = stack_new(errorhandler);
fm->outputbuffer = (char*)malloc(sizeof(char) * MAX_OUTPUT_BUFFER_SIZE);
- fm->errorhandler = errorhandler;
strcpy(fm->outputbuffer, "");
+ fm->errorhandler = errorhandler;
+ fm->lcs = stack_new(errorhandler);
return fm;
}
@@ -39,6 +40,18 @@ static void op_exec(wordop* op, forthmachine* fm) {
}
break;
}
+ case compileditem_doloopcontrol:
+ {
+ int index = stack_pop(fm->lcs);
+ int limit = stack_pop(fm->lcs);
+ index++;
+ if (index < limit) {
+ j = op->oplist[j].loopbackto - 1;
+ stack_push(fm->lcs, limit);
+ stack_push(fm->lcs, index);
+ }
+ break;
+ }
}
}
break;
diff --git a/forthmachine.h b/forthmachine.h
index 4a55952..814e957 100644
--- a/forthmachine.h
+++ b/forthmachine.h
@@ -21,6 +21,7 @@ typedef enum {
compileditem_stackop = 0,
compileditem_literal = 1,
compileditem_ifcontrol = 2,
+ compileditem_doloopcontrol = 3,
} compileditem_type;
typedef struct {
@@ -31,6 +32,7 @@ typedef struct {
struct {
int jumpto;
};
+ int loopbackto;
};
} compileditem;
@@ -72,6 +74,7 @@ struct forthmachine {
stack* s;
char* outputbuffer;
errorhandler errorhandler;
+ stack* lcs;
};
#define MAX_OUTPUT_BUFFER_SIZE 1024
diff --git a/forthmachine_optable.c b/forthmachine_optable.c
index cd4b46b..2a51610 100644
--- a/forthmachine_optable.c
+++ b/forthmachine_optable.c
@@ -30,6 +30,8 @@ static void printall(forthmachine* fm);
static void pick(forthmachine* fm);
static void roll(forthmachine* fm);
static void clearstack(forthmachine* fm);
+static void doloopstart(forthmachine* fm);
+static void lcsindex(forthmachine* fm);
const static wordop inittable[] = {
{".", optype_builtin, {popout}},
@@ -56,6 +58,8 @@ const static wordop inittable[] = {
{"depth", optype_builtin, {depth}},
{".s", optype_builtin, {printall}},
{"clearstack", optype_builtin, {clearstack}},
+ {"do", optype_builtin, {doloopstart}},
+ {"i", optype_builtin, {lcsindex}},
};
@@ -280,6 +284,17 @@ static void clearstack(forthmachine* fm) {
stack_clear(fm->s);
}
+static void doloopstart(forthmachine* fm) {
+ int index = stack_pop(fm->s);
+ int limit = stack_pop(fm->s);
+ stack_push(fm->lcs, limit);
+ stack_push(fm->lcs, index);
+}
+
+static void lcsindex(forthmachine* fm) {
+ stack_push(fm->s, stack_peek(fm->lcs));
+}
+
/* Directives */
/**
@@ -318,7 +333,8 @@ void optable_defineop(optable* optable, char *input, int* starti) {
// get code
int wordi = 0;
char wordbuf[WORD_LEN_LIMIT];
- stack* ifcounter = stack_new(NULL);
+ stack* ifcounter = stack_new(optable->errorhandler);
+ stack* doloopcounter = stack_new(optable->errorhandler);
while (input[i] != ';' && opsi < DEFINED_FUNC_MAX_LENGTH) {
char c = input[i++];
if (notdelim(c) && wordi < WORD_LEN_LIMIT) {
@@ -333,6 +349,10 @@ void optable_defineop(optable* optable, char *input, int* starti) {
} else if (0 == strcmp(wordbuf, "then")) {
int ifopi = stack_pop(ifcounter);
oplist[ifopi].jumpto = opsi;
+ } else if (0 == strcmp(wordbuf, "loop")) {
+ oplist[opsi].type = compileditem_doloopcontrol;
+ oplist[opsi].loopbackto = stack_pop(doloopcounter);
+ opsi++;
} else if (0 == strcmp(wordbuf, opcode)) {
oplist[opsi].type = compileditem_stackop;
oplist[opsi].wordop = &optable->optable[optable->len];
@@ -343,6 +363,9 @@ void optable_defineop(optable* optable, char *input, int* starti) {
if (wordop) {
oplist[opsi].type = compileditem_stackop;
oplist[opsi].wordop = wordop;
+ if (0 == strcmp(wordbuf, "do")) {
+ stack_push(doloopcounter, opsi+1);
+ }
} else {
oplist[opsi].type = compileditem_literal;
oplist[opsi].literal = atoi(wordbuf);
@@ -353,6 +376,7 @@ void optable_defineop(optable* optable, char *input, int* starti) {
}
}
stack_free(ifcounter);
+ stack_free(doloopcounter);
wordop* existingop = optable_getop(optable, opcode);
if (existingop) {