master
Ondřej Hruška 3 years ago
parent a096f55a67
commit 9b7f780d91
  1. 6
      include/fh_runtime.h
  2. 38
      src/fh_builtins_meta.c
  3. 5
      src/fh_runtime.c
  4. 1
      src/fh_see.c

@ -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

@ -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;
}

@ -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) {

@ -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;

Loading…
Cancel
Save