|
|
|
@ -136,6 +136,12 @@ struct fh_instruction_s { |
|
|
|
|
uint32_t data; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static inline void instr_init(struct fh_instruction_s *instr, enum fb_instruction_kind kind, uint32_t data) |
|
|
|
|
{ |
|
|
|
|
instr->kind = kind; |
|
|
|
|
instr->data = data; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define INSTR_SIZE (sizeof(struct fh_instruction_s)) |
|
|
|
|
|
|
|
|
|
/** Bytecode word indices that are not in the dict, have special effect */ |
|
|
|
@ -492,6 +498,7 @@ enum fh_error w_user_word(struct fh_thread_s *fh) |
|
|
|
|
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]); |
|
|
|
@ -555,7 +562,6 @@ enum fh_error w_colon(struct fh_thread_s *fh) |
|
|
|
|
enum fh_error w_semicolon(struct fh_thread_s *fh) |
|
|
|
|
{ |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t addr = 0; |
|
|
|
|
struct fh_instruction_s instr; |
|
|
|
|
|
|
|
|
|
if (fh->state != FH_STATE_COMPILE) { |
|
|
|
@ -651,20 +657,20 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh) |
|
|
|
|
{"s\"", w_s_quote, 1}, |
|
|
|
|
{".\"", w_dot_quote, 1}, |
|
|
|
|
/* Compiler control words */ |
|
|
|
|
{"bye", w_bye}, |
|
|
|
|
{"bye", w_bye, 0}, |
|
|
|
|
/* Basic arithmetics */ |
|
|
|
|
{"+", w_add}, |
|
|
|
|
{"-", w_sub}, |
|
|
|
|
{"*", w_mul}, |
|
|
|
|
{"+", w_add, 0}, |
|
|
|
|
{"-", w_sub, 0}, |
|
|
|
|
{"*", w_mul, 0}, |
|
|
|
|
/* Control words */ |
|
|
|
|
{":", w_colon}, |
|
|
|
|
{":", w_colon, 0}, |
|
|
|
|
{";", w_semicolon, 1}, |
|
|
|
|
{".", w_dot}, |
|
|
|
|
{"type", w_type}, |
|
|
|
|
{"cr", w_cr}, |
|
|
|
|
{"space", w_space}, |
|
|
|
|
{"\\", w_backslash}, // line comment
|
|
|
|
|
{"(", w_paren}, // enclosed comment
|
|
|
|
|
{".", w_dot, 0}, |
|
|
|
|
{"type", w_type, 0}, |
|
|
|
|
{"cr", w_cr, 0}, |
|
|
|
|
{"space", w_space, 0}, |
|
|
|
|
{"\\", w_backslash, 0}, // line comment
|
|
|
|
|
{"(", w_paren, 0}, // enclosed comment
|
|
|
|
|
{ /* end marker */ } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -730,10 +736,11 @@ static enum fh_error fh_handle_quoted_string( |
|
|
|
|
} else { |
|
|
|
|
LOG("Compile a string"); |
|
|
|
|
/* compile */ |
|
|
|
|
instr.kind = FH_INSTR_WORD; |
|
|
|
|
instr.data = fh->substate == FH_SUBSTATE_SQUOTE ? |
|
|
|
|
CPLWORD_ALLOCSTR : |
|
|
|
|
CPLWORD_TYPESTR; |
|
|
|
|
if (fh->substate == FH_SUBSTATE_SQUOTE) { |
|
|
|
|
instr_init(&instr, FH_INSTR_WORD, CPLWORD_ALLOCSTR); |
|
|
|
|
} else { |
|
|
|
|
instr_init(&instr, FH_INSTR_WORD, CPLWORD_TYPESTR); |
|
|
|
|
} |
|
|
|
|
uint32_t len32 = len; |
|
|
|
|
/* string is encoded as a special compiler command, the size,
|
|
|
|
|
* and then the string, all 4-byte aligned. */ |
|
|
|
@ -758,18 +765,17 @@ static enum fh_error fh_handle_word( |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* First, try if it's a known word */ |
|
|
|
|
// TODO we could use binary search if the dict was ordered
|
|
|
|
|
struct fh_word_s *w = &fh->dict[0]; |
|
|
|
|
struct fh_instruction_s instr; |
|
|
|
|
uint32_t cnt = 0; |
|
|
|
|
uint32_t addr = 0; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
while (w->handler) { |
|
|
|
|
if (0 == strncasecmp(start, w->name, len) && w->name[len] == 0) { |
|
|
|
|
// word found!
|
|
|
|
|
if (fh->state == FH_STATE_COMPILE && !w->immediate) { |
|
|
|
|
LOG("Compile word call: %s", w->name); |
|
|
|
|
instr.kind = FH_INSTR_WORD; |
|
|
|
|
instr.data = cnt; |
|
|
|
|
instr_init(&instr, FH_INSTR_WORD, cnt); |
|
|
|
|
TRY(fh_compile_put(fh, &instr, INSTR_SIZE)); |
|
|
|
|
} else { |
|
|
|
|
/* interpret */ |
|
|
|
@ -794,8 +800,7 @@ static enum fh_error fh_handle_word( |
|
|
|
|
|
|
|
|
|
if (fh->state == FH_STATE_COMPILE) { |
|
|
|
|
LOG("Compile number: %ld", v); |
|
|
|
|
instr.kind = FH_INSTR_NUMBER; |
|
|
|
|
instr.data = (uint32_t) v; |
|
|
|
|
instr_init(&instr, FH_INSTR_NUMBER, (uint32_t) v); |
|
|
|
|
TRY(fh_compile_put(fh, &instr, INSTR_SIZE)); |
|
|
|
|
} else { |
|
|
|
|
/* interpret */ |
|
|
|
@ -986,12 +991,8 @@ int main(int argc, char *argv[]) |
|
|
|
|
|
|
|
|
|
// Show resource usage
|
|
|
|
|
LOG("\nResources used: DS %dW, RS %dW, CS %dW, heap %dB, program %dB, dict %dx\n", |
|
|
|
|
(int) fh.data_stack_hwm, |
|
|
|
|
(int) fh.return_stack_hwm, |
|
|
|
|
(int) fh.control_stack_hwm, |
|
|
|
|
(int) fh.heap_top, |
|
|
|
|
(int) fh.compile_top, |
|
|
|
|
(int) fh.dict_top); |
|
|
|
|
(int) fh.data_stack_hwm, (int) fh.return_stack_hwm, (int) fh.control_stack_hwm, |
|
|
|
|
(int) fh.heap_top, (int) fh.compile_top, (int) fh.dict_top); |
|
|
|
|
|
|
|
|
|
FHPRINT_SVC("Bye.\n"); |
|
|
|
|
return 0; |
|
|
|
|