|
|
|
@ -72,7 +72,6 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0) |
|
|
|
|
enum fh_error rv; |
|
|
|
|
const struct fh_word_s *w; |
|
|
|
|
const struct fh_word_s *w2; |
|
|
|
|
uint32_t wn; |
|
|
|
|
|
|
|
|
|
w = w0; |
|
|
|
|
call: |
|
|
|
@ -95,6 +94,7 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0) |
|
|
|
|
fh->execptr += INSTR_SIZE; |
|
|
|
|
|
|
|
|
|
uint32_t strl; |
|
|
|
|
uint32_t val; |
|
|
|
|
uint32_t addr = 0; |
|
|
|
|
switch (instr->kind) { |
|
|
|
|
case FH_INSTR_NUMBER: |
|
|
|
@ -102,54 +102,60 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0) |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
case FH_INSTR_WORD: |
|
|
|
|
wn = instr->data; |
|
|
|
|
switch (wn) { |
|
|
|
|
/* special case for strings stored in compile memory */ |
|
|
|
|
case CPLWORD_ALLOCSTR: |
|
|
|
|
case CPLWORD_TYPESTR: |
|
|
|
|
strl = *((uint32_t *) &fh->compile[fh->execptr]); |
|
|
|
|
fh->execptr += 4; // advance past the length
|
|
|
|
|
if (wn == CPLWORD_ALLOCSTR) { |
|
|
|
|
TRY(fh_heap_reserve(fh, strl, &addr)); |
|
|
|
|
fh_heap_copy_from_compile(fh, addr, fh->execptr, strl); |
|
|
|
|
LOG("Exec: alloc-str \"%.*s\"", strl, &fh->heap[addr]); |
|
|
|
|
TRY(ds_push(fh, addr)); |
|
|
|
|
TRY(ds_push(fh, strl)); |
|
|
|
|
} else { |
|
|
|
|
LOG("Exec: type-str \"%.*s\"", strl, &fh->compile[fh->execptr]); |
|
|
|
|
FHPRINT("%.*s", (int) strl, &fh->compile[fh->execptr]); |
|
|
|
|
} |
|
|
|
|
fh->execptr += strl; |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
case CPLWORD_ENDWORD: |
|
|
|
|
LOG("Exec: word-end (RETURN)"); |
|
|
|
|
w2 = &fh->dict[instr->data]; |
|
|
|
|
if (w2->builtin) { |
|
|
|
|
LOG("Exec: builtin-word %s", w2->name); |
|
|
|
|
w2->handler(fh, w2); |
|
|
|
|
if (fh->substate == FH_SUBSTATE_EXIT) { |
|
|
|
|
fh_setsubstate(fh, 0); |
|
|
|
|
LOG("Exec: early return"); |
|
|
|
|
TRY(rs_pop(fh, &fh->execptr)); |
|
|
|
|
if (fh->execptr == MAGICADDR_INTERACTIVE) { |
|
|
|
|
goto end; |
|
|
|
|
} |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
w2 = &fh->dict[instr->data]; |
|
|
|
|
if (w2->builtin) { |
|
|
|
|
LOG("Exec: builtin-word %s", w2->name); |
|
|
|
|
w2->handler(fh, w2); |
|
|
|
|
if (fh->substate == FH_SUBSTATE_EXIT) { |
|
|
|
|
fh_setsubstate(fh, 0); |
|
|
|
|
LOG("Exec: early return"); |
|
|
|
|
TRY(rs_pop(fh, &fh->execptr)); |
|
|
|
|
if (fh->execptr == MAGICADDR_INTERACTIVE) { |
|
|
|
|
goto end; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
goto instr; |
|
|
|
|
} else { |
|
|
|
|
LOG("Exec: user-word %s (CALL)", w2->name); |
|
|
|
|
w = &fh->dict[instr->data]; |
|
|
|
|
goto call; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
goto instr; |
|
|
|
|
} else { |
|
|
|
|
LOG("Exec: user-word %s (CALL)", w2->name); |
|
|
|
|
w = &fh->dict[instr->data]; |
|
|
|
|
goto call; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case FH_INSTR_JUMPZERO: |
|
|
|
|
TRY(ds_pop(fh, &val)); |
|
|
|
|
if (0 == val) { |
|
|
|
|
fh->execptr = instr->data; |
|
|
|
|
} |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
case FH_INSTR_JUMP: |
|
|
|
|
fh->execptr = instr->data; |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
/* special case for strings stored in compile memory */ |
|
|
|
|
case FH_INSTR_ALLOCSTR: |
|
|
|
|
case FH_INSTR_TYPESTR: |
|
|
|
|
strl = instr->data; |
|
|
|
|
if (instr->kind == FH_INSTR_ALLOCSTR) { |
|
|
|
|
TRY(fh_heap_reserve(fh, strl, &addr)); |
|
|
|
|
fh_heap_copy_from_compile(fh, addr, fh->execptr, strl); |
|
|
|
|
LOG("Exec: alloc-str \"%.*s\"", strl, &fh->heap[addr]); |
|
|
|
|
TRY(ds_push(fh, addr)); |
|
|
|
|
TRY(ds_push(fh, strl)); |
|
|
|
|
} else { |
|
|
|
|
LOG("Exec: type-str \"%.*s\"", strl, &fh->compile[fh->execptr]); |
|
|
|
|
FHPRINT("%.*s", (int) strl, &fh->compile[fh->execptr]); |
|
|
|
|
} |
|
|
|
|
fh->execptr += strl; |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
case FH_INSTR_ENDWORD: |
|
|
|
|
LOG("Exec: word-end (RETURN)"); |
|
|
|
|
TRY(rs_pop(fh, &fh->execptr)); |
|
|
|
|
if (fh->execptr == MAGICADDR_INTERACTIVE) { |
|
|
|
|
goto end; |
|
|
|
|
} |
|
|
|
|
goto instr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
end: |
|
|
|
@ -201,18 +207,12 @@ static enum fh_error fh_handle_quoted_string( |
|
|
|
|
LOG("Compile a string"); |
|
|
|
|
/* compile */ |
|
|
|
|
if (fh->substate == FH_SUBSTATE_SQUOTE) { |
|
|
|
|
instr_init(&instr, FH_INSTR_WORD, CPLWORD_ALLOCSTR); |
|
|
|
|
instr_init(&instr, FH_INSTR_ALLOCSTR, len); |
|
|
|
|
} else { |
|
|
|
|
instr_init(&instr, FH_INSTR_WORD, CPLWORD_TYPESTR); |
|
|
|
|
instr_init(&instr, FH_INSTR_TYPESTR, len); |
|
|
|
|
} |
|
|
|
|
uint32_t len32 = len; |
|
|
|
|
/* string is encoded as a special compiler command, the size,
|
|
|
|
|
* and then the string, all 4-byte aligned. */ |
|
|
|
|
TRY(fh_compile_put(fh, &instr, INSTR_SIZE)); |
|
|
|
|
|
|
|
|
|
TRY(fh_compile_reserve(fh, len + 4, &addr)); |
|
|
|
|
fh_compile_write(fh, addr, &len32, 4); |
|
|
|
|
fh_compile_write(fh, addr + 4, start, len); |
|
|
|
|
TRY(fh_compile_put(fh, start, len)); |
|
|
|
|
} |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
@ -289,13 +289,12 @@ static enum fh_error fh_handle_word( |
|
|
|
|
|
|
|
|
|
static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w) { |
|
|
|
|
if (w->handler == w_user_word) { |
|
|
|
|
FHPRINT("addr 0x%08x ", w->start); |
|
|
|
|
|
|
|
|
|
uint32_t execptr = w->start; |
|
|
|
|
|
|
|
|
|
instr:; |
|
|
|
|
// make sure it's aligned
|
|
|
|
|
execptr = WORDALIGNED(execptr); |
|
|
|
|
FHPRINT("0x%08x: ", execptr); |
|
|
|
|
const struct fh_instruction_s *instr = (const struct fh_instruction_s *) &fh->compile[execptr]; |
|
|
|
|
execptr += INSTR_SIZE; |
|
|
|
|
|
|
|
|
@ -304,39 +303,39 @@ static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w) { |
|
|
|
|
const struct fh_word_s *w2; |
|
|
|
|
switch (instr->kind) { |
|
|
|
|
case FH_INSTR_NUMBER: |
|
|
|
|
FHPRINT("Value(%d) ", instr->data); |
|
|
|
|
FHPRINT("Number(%d)\n", instr->data); |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
case FH_INSTR_WORD: |
|
|
|
|
wn = instr->data; |
|
|
|
|
switch (wn) { |
|
|
|
|
/* special case for strings stored in compile memory */ |
|
|
|
|
case CPLWORD_ALLOCSTR: |
|
|
|
|
case CPLWORD_TYPESTR: |
|
|
|
|
strl = *((uint32_t *) &fh->compile[execptr]); |
|
|
|
|
execptr += 4; // advance past the length
|
|
|
|
|
if (wn == CPLWORD_ALLOCSTR) { |
|
|
|
|
FHPRINT("AllocStr(\"%.*s\") ", strl, &fh->compile[execptr]); |
|
|
|
|
execptr += strl; |
|
|
|
|
} else { |
|
|
|
|
FHPRINT("PrintStr(\"%.*s\") ", strl, &fh->compile[execptr]); |
|
|
|
|
execptr += strl; |
|
|
|
|
} |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
case CPLWORD_ENDWORD: |
|
|
|
|
FHPRINT("END"); |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
w2 = &fh->dict[instr->data]; |
|
|
|
|
if (w2->name[0]) { |
|
|
|
|
FHPRINT("Call(%s) ", w2->name); |
|
|
|
|
} else { |
|
|
|
|
FHPRINT("Call(0x%08x) ", instr->data); |
|
|
|
|
} |
|
|
|
|
goto instr; |
|
|
|
|
w2 = &fh->dict[instr->data]; |
|
|
|
|
FHPRINT("Call(%s, 0x%08x)\n", w2->name, instr->data); |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
case FH_INSTR_JUMPZERO: |
|
|
|
|
FHPRINT("JumpIfZero(0x%08x)\n", instr->data); |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
case FH_INSTR_JUMP: |
|
|
|
|
FHPRINT("Jump(0x%08x)\n", instr->data); |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
/* special case for strings stored in compile memory */ |
|
|
|
|
case FH_INSTR_ALLOCSTR: |
|
|
|
|
case FH_INSTR_TYPESTR: |
|
|
|
|
strl = instr->data; |
|
|
|
|
if (instr->kind == FH_INSTR_ALLOCSTR) { |
|
|
|
|
FHPRINT("AllocStr(\"%.*s\")\n", strl, &fh->compile[execptr]); |
|
|
|
|
execptr += strl; |
|
|
|
|
} else { |
|
|
|
|
FHPRINT("PrintStr(\"%.*s\")\n", strl, &fh->compile[execptr]); |
|
|
|
|
execptr += strl; |
|
|
|
|
} |
|
|
|
|
goto instr; |
|
|
|
|
|
|
|
|
|
case FH_INSTR_ENDWORD: |
|
|
|
|
FHPRINT("END\n"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|