From 9b7f780d91da41bd8f83dc97b8c03ddf45e84eea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 21 Nov 2021 09:32:15 +0100 Subject: [PATCH] fix DOES> --- include/fh_runtime.h | 6 +++++- src/fh_builtins_meta.c | 38 +++++++++----------------------------- src/fh_runtime.c | 5 +++++ src/fh_see.c | 1 + 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/include/fh_runtime.h b/include/fh_runtime.h index cb9d219..de5810d 100644 --- a/include/fh_runtime.h +++ b/include/fh_runtime.h @@ -117,7 +117,7 @@ extern const char *substatenames[FH_SUBSTATE_MAX]; #define WORDFLAG_VARIABLE 0x08 /** Constant with a value assigned */ #define WORDFLAG_CONSTANT 0x10 -/** Something CREATEd */ +/** Something CREATEd. When executed, put the data field address on stack */ #define WORDFLAG_CREATED 0x20 /** Word struct as they are stored in the dictionary */ @@ -250,4 +250,8 @@ enum fh_error fh_init(struct fh_thread_s *fh); enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf, size_t len); +static inline uint32_t word_addr(struct fh_thread_s *fh, const struct fh_word_s *w) { + return (uint32_t) ((void*)w - (void*)&fh->heap[0]); +} + #endif //FORTH_FH_RUNTIME_H diff --git a/src/fh_builtins_meta.c b/src/fh_builtins_meta.c index 45ac6b7..50ba874 100644 --- a/src/fh_builtins_meta.c +++ b/src/fh_builtins_meta.c @@ -61,50 +61,30 @@ static enum fh_error w_does(struct fh_thread_s *fh, const struct fh_word_s *w) { (void) w; enum fh_error rv; - bool crazy = 0; - if (fh->executing_compiled) { - LOG("DOES> in compiled code. OK but weird"); - //FIXME make this less shitty - - // FIXME this works correctly, but the test fails, because it assumes - // that compiled DOES> just changes some pointer in the dict entry, - // whereas we do it by generating helper instructions. - - crazy = 1; - goto banana; - banana2: - - // We are in :NONAME or : NAME. - // This word should be compiled. - TRY(fh_put_instr(fh, FH_INSTR_JUMP, fh->execptr + INSTR_SIZE)); // skip two forward - // next instr run is the ENDWORD emitted at compile time - + if (fh->executing_compiled) { + struct fh_word_s *last_word = fh_word_at(fh, fh->dict_last); + if (!last_word) return FH_ERR_INTERNAL; + last_word->param = fh->execptr + INSTR_SIZE; + last_word->handler = w_user_word; + last_word->flags = WORDFLAG_WORD | WORDFLAG_CREATED; return FH_OK; } if (fh->state == FH_STATE_COMPILE) { TRY(fh_put_instr(fh, FH_INSTR_WORD, (void*)w - (void*)&fh->heap[0])); // call the DOES word - TRY(fh_put_instr(fh, FH_INSTR_ENDWORD, 1)); + TRY(fh_put_instr(fh, FH_INSTR_ENDWORD, 1)); // synthetic exit so we dont also run the "postponed" DOES> content return FH_OK; } fh_setstate(fh, FH_STATE_COMPILE, 0); - banana: struct fh_word_s *last_word = fh_word_at(fh, fh->dict_last); if (!last_word) return FH_ERR_INTERNAL; last_word->handler = w_user_word; - last_word->param = fh->here; // + CELL; // skip the one cell used to hold data. this is a shitty hack - last_word->flags = WORDFLAG_WORD; - - uint32_t dptr = fh->here; - //TRY(fh_heap_reserve(fh, CELL, NULL)); - - TRY(fh_put_instr(fh, FH_INSTR_NUMBER, dptr)); // put pointer to the reserved cell - - if (crazy) goto banana2; + last_word->param = fh->here; + last_word->flags = WORDFLAG_WORD | WORDFLAG_CREATED; return FH_OK; } diff --git a/src/fh_runtime.c b/src/fh_runtime.c index adfe246..2cc70c2 100644 --- a/src/fh_runtime.c +++ b/src/fh_runtime.c @@ -117,6 +117,11 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0) TRY(rs_push(fh, fh->execptr)); fh->execptr = w->param; + + if ((WORDFLAG_WORD | WORDFLAG_CREATED) == (w->flags & (WORDFLAG_WORD | WORDFLAG_CREATED))) { + // push the >BODY addr if this is a CREATE'd word + TRY(ds_push(fh, word_addr(fh, w) + DICTWORD_SIZE)); + } instr:; if (fh->state == FH_STATE_QUIT) { diff --git a/src/fh_see.c b/src/fh_see.c index 17e3113..2280255 100644 --- a/src/fh_see.c +++ b/src/fh_see.c @@ -6,6 +6,7 @@ static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w) LOGE("NULL!"); return; } + FHPRINT("Dict entry at 0x%08x\n", word_addr(fh, w)); if (w->flags & WORDFLAG_WORD) { if (w->handler == w_user_word) { uint32_t execptr = w->param;