#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_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_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) { LOG("state=SHUTDOWN"); 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}, /* Basic arithmetics */ {"+", w_add, 0}, {"-", w_sub, 0}, {"*", w_mul, 0}, /* Control words */ {":", w_colon, 0}, {";", w_semicolon, 1}, {".", 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 */ } }; // 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; }