diff options
author | dan <[email protected]> | 2023-06-03 18:25:58 -0400 |
---|---|---|
committer | dan <[email protected]> | 2023-06-03 18:25:58 -0400 |
commit | f59e909a1adaf545dba4c77d83523eeb5063fbcb (patch) | |
tree | 0c3b1a133d9023c2e988afd79233e363f348859d | |
parent | b528f7d498b301bcfbd42ea011ed31569f36b378 (diff) | |
download | forth-f59e909a1adaf545dba4c77d83523eeb5063fbcb.tar.gz forth-f59e909a1adaf545dba4c77d83523eeb5063fbcb.tar.bz2 forth-f59e909a1adaf545dba4c77d83523eeb5063fbcb.zip |
feat: add do ... loop;
-rw-r--r-- | forthmachine.c | 15 | ||||
-rw-r--r-- | forthmachine.h | 3 | ||||
-rw-r--r-- | forthmachine_optable.c | 26 |
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) { |