|
|
|
@ -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}, |
|
|
|
|