|
|
|
@ -71,6 +71,98 @@ static enum fh_error w_postpone(struct fh_thread_s *fh, const struct fh_word_s * |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_read_value(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
enum fh_error rv; |
|
|
|
|
ENSURE_STATE(FH_STATE_INTERPRET); |
|
|
|
|
TRY(ds_push(fh, w->param)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_read_varaddr(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
enum fh_error rv; |
|
|
|
|
ENSURE_STATE(FH_STATE_INTERPRET); |
|
|
|
|
|
|
|
|
|
uint32_t addr = (void *) &w->param - (void *) &fh->heap[0]; // this is ugly
|
|
|
|
|
TRY(ds_push(fh, addr)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error wp_variable(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
ENSURE_STATE(FH_STATE_INTERPRET); |
|
|
|
|
|
|
|
|
|
char *wordname; |
|
|
|
|
size_t namelen = 0; |
|
|
|
|
fh_input_consume_spaces(fh); |
|
|
|
|
TRY(fh_input_read_word(fh, &wordname, &namelen)); |
|
|
|
|
|
|
|
|
|
uint32_t ptr; |
|
|
|
|
uint32_t value = 0; |
|
|
|
|
|
|
|
|
|
bool is_value = w->param == 1; |
|
|
|
|
bool is_const = w->param == 2; |
|
|
|
|
|
|
|
|
|
if (is_value || is_const) { |
|
|
|
|
TRY(ds_pop(fh, &value)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr)); |
|
|
|
|
|
|
|
|
|
struct fh_word_s *new_word = fh_word_at(fh, ptr); |
|
|
|
|
new_word->previous = fh->dict_last; |
|
|
|
|
new_word->param = value; |
|
|
|
|
new_word->handler = (is_value || is_const) ? w_read_value : w_read_varaddr; |
|
|
|
|
strncpy(new_word->name, wordname, namelen); |
|
|
|
|
new_word->name[namelen] = 0; |
|
|
|
|
new_word->flags = (is_const ? WORDFLAG_CONSTANT : WORDFLAG_VARIABLE) | WORDFLAG_BUILTIN; |
|
|
|
|
|
|
|
|
|
fh->dict_last = ptr; |
|
|
|
|
|
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_to(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
if (fh->state == FH_STATE_INTERPRET) { |
|
|
|
|
uint32_t value; |
|
|
|
|
TRY(ds_pop(fh, &value)); |
|
|
|
|
|
|
|
|
|
char *wordname; |
|
|
|
|
size_t namelen = 0; |
|
|
|
|
uint32_t waddr; |
|
|
|
|
fh_input_consume_spaces(fh); |
|
|
|
|
TRY(fh_input_read_word(fh, &wordname, &namelen)); |
|
|
|
|
TRY(fh_find_word(fh, wordname, namelen, &waddr)); |
|
|
|
|
|
|
|
|
|
struct fh_word_s *ww = fh_word_at(fh, waddr); |
|
|
|
|
|
|
|
|
|
if (ww->flags & WORDFLAG_CONSTANT) { |
|
|
|
|
LOGE("Cannot assign to constant!"); |
|
|
|
|
return FH_ERR_ILLEGAL_STORE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ww->param = value; |
|
|
|
|
} else if (fh->state == FH_STATE_COMPILE) { |
|
|
|
|
// immediate
|
|
|
|
|
char *wordname; |
|
|
|
|
size_t namelen = 0; |
|
|
|
|
uint32_t waddr; |
|
|
|
|
fh_input_consume_spaces(fh); |
|
|
|
|
TRY(fh_input_read_word(fh, &wordname, &namelen)); |
|
|
|
|
TRY(fh_find_word(fh, wordname, namelen, &waddr)); |
|
|
|
|
|
|
|
|
|
TRY(fh_put_instr(fh, FH_INSTR_TO, waddr)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_leftbracket(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
@ -172,6 +264,10 @@ const struct name_and_handler fh_builtins_meta[] = { |
|
|
|
|
{"literal", w_literal, 1, 0}, |
|
|
|
|
{"char", w_char, 0, 0}, |
|
|
|
|
{"[char]", w_char, 1, 0}, |
|
|
|
|
{"to", w_to, 1, 0}, |
|
|
|
|
{"variable", wp_variable, 1, 0}, |
|
|
|
|
{"value", wp_variable, 1, 1}, |
|
|
|
|
{"constant", wp_variable, 1, 2}, |
|
|
|
|
|
|
|
|
|
{ /* end marker */ } |
|
|
|
|
}; |
|
|
|
|