fix DOES>
This commit is contained in:
@@ -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
|
||||
|
||||
+9
-29
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user