#include #include #include "fh_runtime.h" #include "fh_config.h" #include "fh_error.h" #include "fh_print.h" #include "fh_builtins.h" #include "fh_stack.h" #include "fh_mem.h" static enum fh_error w_add(struct fh_thread_s *fh) { enum fh_error rv; uint32_t a = 0, b = 0; TRY(ds_pop(fh, &a)); TRY(ds_pop(fh, &b)); TRY(ds_push(fh, a + b)); return FH_OK; } static enum fh_error w_sub(struct fh_thread_s *fh) { enum fh_error rv; uint32_t a = 0, b = 0; TRY(ds_pop(fh, &a)); TRY(ds_pop(fh, &b)); TRY(ds_push(fh, a - b)); return FH_OK; } static enum fh_error w_mul(struct fh_thread_s *fh) { enum fh_error rv; uint32_t a = 0, b = 0; TRY(ds_pop(fh, &a)); TRY(ds_pop(fh, &b)); TRY(ds_push(fh, a * b)); return FH_OK; } static enum fh_error w_colon(struct fh_thread_s *fh) { if (fh->state != FH_STATE_INTERPRET) { return FH_ERR_INVALID_STATE; } fh_setstate(fh, FH_STATE_COMPILE, FH_SUBSTATE_COLONNAME); if (fh->dict_top >= DICT_SIZE) { return FH_ERR_DICT_FULL; } fh->dict[fh->dict_top].start = fh->compile_top; fh->dict[fh->dict_top].handler = w_user_word; return FH_OK; } static enum fh_error w_semicolon(struct fh_thread_s *fh) { enum fh_error rv; struct fh_instruction_s instr; if (fh->state != FH_STATE_COMPILE) { return FH_ERR_INVALID_STATE; } instr.kind = FH_INSTR_WORD; instr.data = CPLWORD_ENDWORD; TRY(fh_compile_put(fh, &instr, INSTR_SIZE)); /* Return to interpret state */ fh_setstate(fh, FH_STATE_INTERPRET, 0); fh->dict_top++; return FH_OK; } static enum fh_error w_dup(struct fh_thread_s *fh) { enum fh_error rv; uint32_t a = 0; TRY(ds_peek(fh, &a)); TRY(ds_push(fh, a)); return FH_OK; } static enum fh_error w_drop(struct fh_thread_s *fh) { enum fh_error rv; uint32_t a = 0; TRY(ds_pop(fh, &a)); return FH_OK; } static enum fh_error w_swap(struct fh_thread_s *fh) { enum fh_error rv; TRY(ds_roll(fh, 1)); return FH_OK; } static enum fh_error w_rot(struct fh_thread_s *fh) { enum fh_error rv; TRY(ds_roll(fh, 2)); return FH_OK; } static enum fh_error w_over(struct fh_thread_s *fh) { enum fh_error rv; uint32_t a = 0; TRY(ds_peek_n(fh, &a, 1)); TRY(ds_push(fh, a)); return FH_OK; } static enum fh_error w_tuck(struct fh_thread_s *fh) { enum fh_error rv; uint32_t a = 0; uint32_t b = 0; TRY(ds_pop(fh, &a)); TRY(ds_pop(fh, &b)); TRY(ds_push(fh, a)); TRY(ds_push(fh, b)); TRY(ds_push(fh, a)); return FH_OK; } static enum fh_error w_pick(struct fh_thread_s *fh) { enum fh_error rv; uint32_t nth = 0; uint32_t a = 0; TRY(ds_pop(fh, &nth)); TRY(ds_peek_n(fh, &a, nth)); TRY(ds_push(fh, a)); return FH_OK; } static enum fh_error w_roll(struct fh_thread_s *fh) { enum fh_error rv; uint32_t n = 0; TRY(ds_pop(fh, &n)); TRY(ds_roll(fh, n)); return FH_OK; } static enum fh_error w_dot(struct fh_thread_s *fh) { enum fh_error rv; uint32_t a = 0; TRY(ds_pop(fh, &a)); FHPRINT("%d ", (int32_t) a); return FH_OK; } static enum fh_error w_type(struct fh_thread_s *fh) { enum fh_error rv; uint32_t count = 0, addr = 0; TRY(ds_pop(fh, &count)); TRY(ds_pop(fh, &addr)); FHPRINT("%.*s", count, &fh->heap[addr]); return FH_OK; } static enum fh_error w_cr(struct fh_thread_s *fh) { (void) fh; FHPRINT("\n"); return FH_OK; } static enum fh_error w_space(struct fh_thread_s *fh) { (void) fh; FHPRINT(" "); return FH_OK; } static enum fh_error w_dump(struct fh_thread_s *fh) { (void) fh; for (int i = 0; i < fh->data_stack_top; i++) { FHPRINT("%d ", fh->data_stack[i]); } return FH_OK; } static enum fh_error w_s_quote(struct fh_thread_s *fh) { fh_setsubstate(fh, FH_SUBSTATE_SQUOTE); return FH_OK; } static enum fh_error w_dot_quote(struct fh_thread_s *fh) { fh_setsubstate(fh, FH_SUBSTATE_DOTQUOTE); return FH_OK; } static enum fh_error w_backslash(struct fh_thread_s *fh) { fh_setsubstate(fh, FH_SUBSTATE_LINECOMMENT); return FH_OK; } static enum fh_error w_paren(struct fh_thread_s *fh) { fh_setsubstate(fh, FH_SUBSTATE_PARENCOMMENT); return FH_OK; } static enum fh_error w_bye(struct fh_thread_s *fh) { fh_setstate(fh, FH_STATE_SHUTDOWN, 0); 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) { struct name_and_handler { const char *name; word_exec_t handler; bool immediate; }; const struct name_and_handler builtins[] = { {"s\"", w_s_quote, 1}, {".\"", w_dot_quote, 1}, /* Compiler control words */ {"bye", w_bye, 0}, /* Arithmetics */ {"+", w_add, 0}, {"-", w_sub, 0}, {"*", w_mul, 0}, /* 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}, /* 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 { /* end marker */ } }; // foreach struct fh_word_s w; const struct name_and_handler *p = builtins; enum fh_error rv; while (p->handler) { strcpy(w.name, p->name); w.handler = p->handler; w.builtin = 1; w.immediate = p->immediate; rv = fh_add_word(&w, fh); if (rv != FH_OK) { return rv; } p++; } return FH_OK; }