|
|
|
@ -8,8 +8,11 @@ |
|
|
|
|
#include "fh_stack.h" |
|
|
|
|
#include "fh_mem.h" |
|
|
|
|
|
|
|
|
|
static enum fh_error w_add(struct fh_thread_s *fh) |
|
|
|
|
#define TOBOOL(a) (a == 0 ? 0 : 0xFFFFFFFF) |
|
|
|
|
|
|
|
|
|
static enum fh_error w_plus(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)); |
|
|
|
@ -18,8 +21,9 @@ static enum fh_error w_add(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_sub(struct fh_thread_s *fh) |
|
|
|
|
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)); |
|
|
|
@ -28,8 +32,9 @@ static enum fh_error w_sub(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_mul(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_star(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)); |
|
|
|
@ -38,8 +43,176 @@ static enum fh_error w_mul(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_colon(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_zero_less(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, TOBOOL(a < 0))); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_zero_greater(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, TOBOOL(a > 0))); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_zero_equals(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, TOBOOL(a == 0))); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_zero_not_equals(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, TOBOOL(a != 0))); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static enum fh_error w_less(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, &b)); |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, TOBOOL(a < b))); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_greater(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, &b)); |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, TOBOOL(a > b))); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_equals(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, &b)); |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, TOBOOL(a == b))); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_not_equals(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, &b)); |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, TOBOOL(a != b))); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error wp_add(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, a + w->param)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error wp_mul(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, a * w->param)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error wp_div(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, a * w->param)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_star_slash(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0, b = 0, c = 0; |
|
|
|
|
TRY(ds_pop(fh, &c)); |
|
|
|
|
TRY(ds_pop(fh, &b)); |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
|
|
|
|
|
if (c == 0) { |
|
|
|
|
return FH_ERR_DIV_BY_ZERO; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint64_t v = ((uint64_t) a * (uint64_t) b) / (uint64_t) c; |
|
|
|
|
|
|
|
|
|
TRY(ds_push(fh, (uint32_t) v)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_slash(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, &b)); |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
|
|
|
|
|
if (b == 0) { |
|
|
|
|
return FH_ERR_DIV_BY_ZERO; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TRY(ds_push(fh, a / b)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_slash_mod(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, &b)); |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
|
|
|
|
|
if (b == 0) { |
|
|
|
|
return FH_ERR_DIV_BY_ZERO; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t rem = a % b; |
|
|
|
|
uint32_t div = a / b; |
|
|
|
|
|
|
|
|
|
TRY(ds_push(fh, rem)); |
|
|
|
|
TRY(ds_push(fh, div)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_colon(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
if (fh->state != FH_STATE_INTERPRET) { |
|
|
|
|
return FH_ERR_INVALID_STATE; |
|
|
|
|
} |
|
|
|
@ -54,8 +227,9 @@ static enum fh_error w_colon(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_semicolon(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_semicolon(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
struct fh_instruction_s instr; |
|
|
|
|
|
|
|
|
@ -73,8 +247,9 @@ static enum fh_error w_semicolon(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_dup(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_dup(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_peek(fh, &a)); |
|
|
|
@ -82,30 +257,76 @@ static enum fh_error w_dup(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_drop(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_two_dup(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
uint32_t b = 0; |
|
|
|
|
TRY(ds_peek_n(fh, &a, 0)); |
|
|
|
|
TRY(ds_peek_n(fh, &b, 1)); |
|
|
|
|
TRY(ds_push(fh, b)); |
|
|
|
|
TRY(ds_push(fh, a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_drop(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_two_drop(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_swap(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_swap(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
TRY(ds_roll(fh, 1)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_rot(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_two_swap(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
if (fh->data_stack_top < 4) { |
|
|
|
|
LOG("DS two-swap UNDERFLOW"); |
|
|
|
|
return FH_ERR_DS_UNDERFLOW; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t n = fh->data_stack_top - 4; |
|
|
|
|
uint32_t a = fh->data_stack[n]; |
|
|
|
|
uint32_t b = fh->data_stack[n + 1]; |
|
|
|
|
fh->data_stack[n] = fh->data_stack[n + 2]; |
|
|
|
|
fh->data_stack[n + 1] = fh->data_stack[n + 3]; |
|
|
|
|
fh->data_stack[n + 2] = a; |
|
|
|
|
fh->data_stack[n + 3] = b; |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_rot(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
TRY(ds_roll(fh, 2)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_over(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_over(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_peek_n(fh, &a, 1)); |
|
|
|
@ -113,8 +334,22 @@ static enum fh_error w_over(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_tuck(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_two_over(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
uint32_t b = 0; |
|
|
|
|
TRY(ds_peek_n(fh, &a, 2)); |
|
|
|
|
TRY(ds_peek_n(fh, &b, 3)); |
|
|
|
|
TRY(ds_push(fh, b)); |
|
|
|
|
TRY(ds_push(fh, a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_tuck(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
uint32_t b = 0; |
|
|
|
@ -126,8 +361,9 @@ static enum fh_error w_tuck(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_pick(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_pick(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t nth = 0; |
|
|
|
|
uint32_t a = 0; |
|
|
|
@ -137,8 +373,9 @@ static enum fh_error w_pick(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_roll(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_roll(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t n = 0; |
|
|
|
|
TRY(ds_pop(fh, &n)); |
|
|
|
@ -146,8 +383,78 @@ static enum fh_error w_roll(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_dot(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_to_r(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(rs_push(fh, a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_two_to_r(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a; |
|
|
|
|
uint32_t b; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_pop(fh, &b)); |
|
|
|
|
TRY(rs_push(fh, b)); |
|
|
|
|
TRY(rs_push(fh, a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_two_r_from(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a; |
|
|
|
|
uint32_t b; |
|
|
|
|
TRY(rs_pop(fh, &a)); |
|
|
|
|
TRY(rs_pop(fh, &b)); |
|
|
|
|
TRY(ds_push(fh, b)); |
|
|
|
|
TRY(ds_push(fh, a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_two_r_fetch(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a; |
|
|
|
|
uint32_t b; |
|
|
|
|
TRY(rs_peek_n(fh, &a, 0)); |
|
|
|
|
TRY(rs_peek_n(fh, &b, 1)); |
|
|
|
|
TRY(ds_push(fh, b)); |
|
|
|
|
TRY(ds_push(fh, a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_r_from(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a; |
|
|
|
|
TRY(rs_pop(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_r_fetch(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a; |
|
|
|
|
TRY(rs_peek(fh, &a)); |
|
|
|
|
TRY(ds_push(fh, a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_dot(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t a = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
@ -156,8 +463,9 @@ static enum fh_error w_dot(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_type(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_type(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t count = 0, addr = 0; |
|
|
|
|
TRY(ds_pop(fh, &count)); |
|
|
|
@ -167,59 +475,167 @@ static enum fh_error w_type(struct fh_thread_s *fh) |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_cr(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_cr(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
(void) fh; |
|
|
|
|
FHPRINT("\n"); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_space(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_space(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
(void) fh; |
|
|
|
|
FHPRINT(" "); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_dump(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_dump(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
(void) fh; |
|
|
|
|
|
|
|
|
|
FHPRINT("DS "); |
|
|
|
|
for (int i = 0; i < fh->data_stack_top; i++) { |
|
|
|
|
FHPRINT("%d ", fh->data_stack[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FHPRINT("\nRS "); |
|
|
|
|
for (int i = 0; i < fh->return_stack_top; i++) { |
|
|
|
|
FHPRINT("%d ", fh->return_stack[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FHPRINT("\n"); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_s_quote(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_abort(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
|
|
|
|
|
fh->data_stack_top = 0; |
|
|
|
|
fh->return_stack_top = 0; |
|
|
|
|
fh->state = FH_STATE_QUIT; |
|
|
|
|
|
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_quit(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
|
|
|
|
|
fh->return_stack_top = 0; |
|
|
|
|
fh->state = FH_STATE_QUIT; |
|
|
|
|
|
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_s_quote(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_SQUOTE); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_dot_quote(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_dot_quote(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_DOTQUOTE); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_backslash(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_backslash(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_LINECOMMENT); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_paren(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_paren(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_PARENCOMMENT); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_bye(struct fh_thread_s *fh) |
|
|
|
|
static enum fh_error w_bye(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
fh_setstate(fh, FH_STATE_SHUTDOWN, 0); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error wp_setbase(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
fh->base = w->param; |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_base(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
TRY(ds_push(fh, MAGICADDR_BASE)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_fetch(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t addr = 0; |
|
|
|
|
TRY(ds_pop(fh, &addr)); |
|
|
|
|
uint32_t val = 0; |
|
|
|
|
TRY(fh_fetch(fh, addr, &val)); |
|
|
|
|
TRY(ds_push(fh, val)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_store(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t addr = 0; |
|
|
|
|
TRY(ds_pop(fh, &addr)); |
|
|
|
|
uint32_t val = 0; |
|
|
|
|
TRY(ds_pop(fh, &val)); |
|
|
|
|
|
|
|
|
|
TRY(fh_store(fh, addr, val)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_two_store(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t addr = 0; |
|
|
|
|
TRY(ds_pop(fh, &addr)); |
|
|
|
|
uint32_t a = 0, b = 0; |
|
|
|
|
TRY(ds_pop(fh, &a)); |
|
|
|
|
TRY(ds_pop(fh, &b)); |
|
|
|
|
|
|
|
|
|
TRY(fh_store(fh, addr, a)); |
|
|
|
|
TRY(fh_store(fh, addr + CELL, b)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static enum fh_error w_two_fetch(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
{ |
|
|
|
|
(void) w; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
uint32_t addr = 0; |
|
|
|
|
TRY(ds_pop(fh, &addr)); |
|
|
|
|
uint32_t a = 0, b = 0; |
|
|
|
|
TRY(fh_fetch(fh, addr, &a)); |
|
|
|
|
TRY(fh_fetch(fh, addr + CELL, &b)); |
|
|
|
|
TRY(ds_push(fh, b)); |
|
|
|
|
TRY(ds_push(fh, a)); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Add pointers to built-in word handlers to a runtime struct */ |
|
|
|
|
enum fh_error register_builtin_words(struct fh_thread_s *fh) |
|
|
|
|
{ |
|
|
|
@ -227,37 +643,79 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh) |
|
|
|
|
const char *name; |
|
|
|
|
word_exec_t handler; |
|
|
|
|
bool immediate; |
|
|
|
|
uint32_t param; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const struct name_and_handler builtins[] = { |
|
|
|
|
{"s\"", w_s_quote, 1}, |
|
|
|
|
{".\"", w_dot_quote, 1}, |
|
|
|
|
{"s\"", w_s_quote, 1, 0}, |
|
|
|
|
{".\"", w_dot_quote, 1, 0}, |
|
|
|
|
/* Compiler control words */ |
|
|
|
|
{"bye", w_bye, 0}, |
|
|
|
|
{"bye", w_bye, 0, 0}, |
|
|
|
|
/* Pointers */ |
|
|
|
|
{"@", w_fetch, 0, 0}, |
|
|
|
|
{"!", w_store, 0, 0}, |
|
|
|
|
{"2!", w_two_store, 0, 0}, |
|
|
|
|
{"2@", w_two_fetch, 0, 0}, |
|
|
|
|
/* Arithmetics */ |
|
|
|
|
{"+", w_add, 0}, |
|
|
|
|
{"-", w_sub, 0}, |
|
|
|
|
{"*", w_mul, 0}, |
|
|
|
|
{"dec", wp_setbase, 0, 10}, |
|
|
|
|
{"hex", wp_setbase, 0, 16}, |
|
|
|
|
{"base", w_base, 0, 0}, |
|
|
|
|
{"+", w_plus, 0, 0}, |
|
|
|
|
{"-", w_minus, 0, 0}, |
|
|
|
|
{"*", w_star, 0, 0}, |
|
|
|
|
{"*/", w_star_slash, 0, 0}, |
|
|
|
|
{"/", w_slash, 0, 0}, |
|
|
|
|
{"/mod", w_slash_mod, 0, 0}, |
|
|
|
|
{"0<", w_zero_less, 0, 0}, |
|
|
|
|
{"0=", w_zero_equals, 0, 0}, |
|
|
|
|
{"0<>", w_zero_not_equals, 0, 0}, |
|
|
|
|
{"0>", w_zero_greater, 0, 0}, |
|
|
|
|
{"<", w_less, 0, 0}, |
|
|
|
|
{"=", w_equals, 0, 0}, |
|
|
|
|
{"<>", w_not_equals, 0, 0}, |
|
|
|
|
{">", w_greater, 0, 0}, |
|
|
|
|
{"1+", wp_add, 0, 1}, |
|
|
|
|
{"1-", wp_add, 0, -1}, |
|
|
|
|
{"2+", wp_add, 0, 2}, |
|
|
|
|
{"2-", wp_add, 0, -2}, |
|
|
|
|
{"2*", wp_mul, 0, 2}, |
|
|
|
|
{"2/", wp_div, 0, 2}, |
|
|
|
|
/* Stack manip */ |
|
|
|
|
{"dup", w_dup, 0}, |
|
|
|
|
{"drop", w_drop, 0}, |
|
|
|
|
{"swap", w_swap, 0}, |
|
|
|
|
{"rot", w_rot, 0}, |
|
|
|
|
{"over", w_over, 0}, |
|
|
|
|
{"tuck", w_tuck, 0}, |
|
|
|
|
{"pick", w_pick, 0}, |
|
|
|
|
{"roll", w_roll, 0}, |
|
|
|
|
{"drop", w_drop, 0, 0}, |
|
|
|
|
{"dup", w_dup, 0, 0}, |
|
|
|
|
{"over", w_over, 0, 0}, |
|
|
|
|
{"swap", w_swap, 0, 0}, |
|
|
|
|
{"rot", w_rot, 0, 0}, |
|
|
|
|
{"tuck", w_tuck, 0, 0}, |
|
|
|
|
{"pick", w_pick, 0, 0}, |
|
|
|
|
{"roll", w_roll, 0, 0}, |
|
|
|
|
/* Double wide stack manip */ |
|
|
|
|
{"2drop", w_two_drop, 0, 0}, |
|
|
|
|
{"2dup", w_two_dup, 0, 0}, |
|
|
|
|
{"2over", w_two_over, 0, 0}, |
|
|
|
|
{"2swap", w_two_swap, 0, 0}, |
|
|
|
|
// /* Return stack manip */
|
|
|
|
|
{">r", w_to_r, 0, 0}, |
|
|
|
|
{"r>", w_r_from, 0, 0}, |
|
|
|
|
{"r@", w_r_fetch, 0, 0}, |
|
|
|
|
// /* Double wide return stack manip */
|
|
|
|
|
{"2>r", w_two_to_r, 0, 0}, |
|
|
|
|
{"2r>", w_two_r_from, 0, 0}, |
|
|
|
|
{"2r@", w_two_r_fetch, 0, 0}, |
|
|
|
|
/* Printing */ |
|
|
|
|
{".", w_dot, 0}, |
|
|
|
|
{"type", w_type, 0}, |
|
|
|
|
{"cr", w_cr, 0}, |
|
|
|
|
{"space", w_space, 0}, |
|
|
|
|
{"dump", w_dump, 0}, |
|
|
|
|
/* Control words */ |
|
|
|
|
{":", w_colon, 0}, |
|
|
|
|
{";", w_semicolon, 1}, |
|
|
|
|
{"\\", w_backslash, 1}, // line comment
|
|
|
|
|
{"(", w_paren, 1}, // enclosed comment
|
|
|
|
|
{".", w_dot, 0, 0}, |
|
|
|
|
{"type", w_type, 0, 0}, |
|
|
|
|
{"cr", w_cr, 0, 0}, |
|
|
|
|
{"space", w_space, 0, 0}, |
|
|
|
|
{"dump", w_dump, 0, 0}, |
|
|
|
|
/* Control flow */ |
|
|
|
|
{"abort", w_abort, 0, 0}, |
|
|
|
|
{"quit", w_quit, 0, 0}, |
|
|
|
|
/* Syntax */ |
|
|
|
|
{":", w_colon, 0, 0}, |
|
|
|
|
{";", w_semicolon, 1, 0}, |
|
|
|
|
{"\\", w_backslash, 1, 0}, // line comment
|
|
|
|
|
{"(", w_paren, 1, 0}, // enclosed comment
|
|
|
|
|
{ /* end marker */ } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -270,6 +728,7 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh) |
|
|
|
|
w.handler = p->handler; |
|
|
|
|
w.builtin = 1; |
|
|
|
|
w.immediate = p->immediate; |
|
|
|
|
w.param = p->param; |
|
|
|
|
rv = fh_add_word(&w, fh); |
|
|
|
|
if (rv != FH_OK) { |
|
|
|
|
return rv; |
|
|
|
|