diff --git a/loops.forth b/loops.forth new file mode 100644 index 0000000..449deac --- /dev/null +++ b/loops.forth @@ -0,0 +1,5 @@ +: test1 begin dup while 1 - dup . repeat ; +10 test1 + +: test2 begin 1 - dup . dup 0= until ; +10 test2 diff --git a/src/fh_builtins.c b/src/fh_builtins.c index fb76605..1fe3e03 100644 --- a/src/fh_builtins.c +++ b/src/fh_builtins.c @@ -82,8 +82,8 @@ static enum fh_error w_minus(struct fh_thread_s *fh, const struct fh_word_s *w) (void) w; enum fh_error rv; uint32_t a = 0, b = 0; - TRY(ds_pop(fh, &a)); TRY(ds_pop(fh, &b)); + TRY(ds_pop(fh, &a)); TRY(ds_push(fh, a - b)); return FH_OK; } @@ -778,7 +778,6 @@ static enum fh_error w_then(struct fh_thread_s *fh, const struct fh_word_s *w) { (void) w; enum fh_error rv; - struct fh_instruction_s instr; ENSURE_STATE(FH_STATE_COMPILE); @@ -794,6 +793,76 @@ static enum fh_error w_then(struct fh_thread_s *fh, const struct fh_word_s *w) return FH_OK; } +static enum fh_error w_until(struct fh_thread_s *fh, const struct fh_word_s *w) +{ + (void) w; + enum fh_error rv; + struct fh_instruction_s instr; + + ENSURE_STATE(FH_STATE_COMPILE); + + uint32_t destaddr = 0; + TRY(cs_pop(fh, &destaddr)); + + instr_init(&instr, FH_INSTR_JUMPZERO, destaddr); + TRY(fh_compile_put(fh, &instr, INSTR_SIZE)); + return FH_OK; +} + +static enum fh_error w_begin(struct fh_thread_s *fh, const struct fh_word_s *w) +{ + (void) w; + enum fh_error rv; + ENSURE_STATE(FH_STATE_COMPILE); + TRY(cs_push(fh, fh->compile_top)); /* dest */ + return FH_OK; +} + +static enum fh_error w_while(struct fh_thread_s *fh, const struct fh_word_s *w) +{ + (void) w; + enum fh_error rv; + struct fh_instruction_s instr; + + ENSURE_STATE(FH_STATE_COMPILE); + + uint32_t destaddr = 0; + TRY(cs_pop(fh, &destaddr)); + + TRY(cs_push(fh, fh->compile_top)); // orig + TRY(cs_push(fh, destaddr)); // dest + + instr_init(&instr, FH_INSTR_JUMPZERO, MAGICADDR_UNRESOLVED); + TRY(fh_compile_put(fh, &instr, INSTR_SIZE)); + return FH_OK; +} + +static enum fh_error w_repeat(struct fh_thread_s *fh, const struct fh_word_s *w) +{ + (void) w; + enum fh_error rv; + struct fh_instruction_s instr; + + ENSURE_STATE(FH_STATE_COMPILE); + + uint32_t origaddr = 0; + uint32_t destaddr = 0; + TRY(cs_pop(fh, &destaddr)); + TRY(cs_pop(fh, &origaddr)); + + struct fh_instruction_s *branch_instr = (void *) &fh->compile[origaddr]; + if (branch_instr->data != MAGICADDR_UNRESOLVED) { + LOGE("REPEAT control stack corruption"); + return FH_ERR_INTERNAL; + } + branch_instr->data = fh->compile_top + INSTR_SIZE; + + instr_init(&instr, FH_INSTR_JUMP, destaddr); + TRY(fh_compile_put(fh, &instr, INSTR_SIZE)); + + return FH_OK; +} + static enum fh_error wp_setbase(struct fh_thread_s *fh, const struct fh_word_s *w) { fh_setbase(fh, w->param); @@ -998,12 +1067,16 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh) {"if", w_if, 1, 0}, {"else", w_else, 1, 0}, {"then", w_then, 1, 0}, + {"recurse", w_recurse, 1, 0}, + {"begin", w_begin, 1, 0}, + {"while", w_while, 1, 0}, + {"repeat", w_repeat, 1, 0}, + {"until", w_until, 1, 0}, /* Syntax */ {":", w_colon, 0, 0}, {";", w_semicolon, 1, 0}, {"\\", w_backslash, 1, 0}, // line comment {"(", w_paren, 1, 0}, // enclosed comment - {"recurse", w_recurse, 1, 0}, {"reset", w_reset, 1, 0}, {"immediate", w_immediate, 1, 0}, {"postpone", w_postpone, 1, 0},