implemented CASE-OF
This commit is contained in:
@@ -118,6 +118,7 @@ static enum fh_error wp_loop(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
ii->data = endaddr;
|
||||
}
|
||||
|
||||
// Resolve LEAVEs
|
||||
while (startaddr < loopendaddr) {
|
||||
ii = fh_instr_at(fh, startaddr);
|
||||
if (!ii) {
|
||||
@@ -223,6 +224,86 @@ static enum fh_error wp_ij(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static enum fh_error w_case(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
TRY(cs_push(fh, fh->here)); // save marker for ENDCASE to resolve all the ENDOF's within
|
||||
ENSURE_STATE(FH_STATE_COMPILE);
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_of(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
ENSURE_STATE(FH_STATE_COMPILE);
|
||||
TRY(cs_push(fh, fh->here)); // save the marker for ENDOF
|
||||
TRY(fh_put_instr(fh, FH_INSTR_OF, MAGICADDR_UNRESOLVED));
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_endof(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
ENSURE_STATE(FH_STATE_COMPILE);
|
||||
uint32_t ofaddr;
|
||||
TRY(cs_pop(fh, &ofaddr));
|
||||
|
||||
struct fh_instruction_s *of_instr = fh_instr_at(fh, ofaddr);
|
||||
if (!of_instr || of_instr->data != MAGICADDR_UNRESOLVED) {
|
||||
LOGE("CASE-OF control stack corruption");
|
||||
return FH_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
of_instr->data = fh->here + INSTR_SIZE; // next
|
||||
|
||||
TRY(fh_put_instr(fh, FH_INSTR_JUMP, MAGICADDR_ENDCASE_UNRESOLVED)); // go to end of CASEs
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_endcase(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
ENSURE_STATE(FH_STATE_COMPILE);
|
||||
uint32_t caseaddr;
|
||||
TRY(cs_pop(fh, &caseaddr));
|
||||
|
||||
// Now walk the instructions and resolve every MAGICADDR_ENDCASE_UNRESOLVED
|
||||
|
||||
uint32_t caseendaddr = fh->here;
|
||||
struct fh_instruction_s *ii;
|
||||
|
||||
// Resolve ENDOF. TODO copied from LOOP impl, unify?
|
||||
while (caseaddr < caseendaddr) {
|
||||
ii = fh_instr_at(fh, caseaddr);
|
||||
if (!ii) {
|
||||
LOGE("WHAT?");
|
||||
return FH_ERR_INTERNAL;
|
||||
}
|
||||
if (ii->kind == FH_INSTR_JUMP && ii->data == MAGICADDR_ENDCASE_UNRESOLVED) {
|
||||
LOG("Resolve endof jump");
|
||||
ii->data = caseendaddr + INSTR_SIZE;
|
||||
}
|
||||
|
||||
// forward, skipping strings safely
|
||||
if (ii->kind == FH_INSTR_TYPESTR || ii->kind == FH_INSTR_ALLOCSTR) {
|
||||
caseaddr += INSTR_SIZE + ii->data;
|
||||
caseaddr = WORDALIGNED(caseaddr);
|
||||
} else {
|
||||
caseaddr += INSTR_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
TRY(fh_put_instr(fh, FH_INSTR_ENDCASE, 0));
|
||||
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
const struct name_and_handler fh_builtins_control[] = {
|
||||
{"i", wp_ij, 0, 0},
|
||||
{"j", wp_ij, 0, 1},
|
||||
@@ -241,6 +322,10 @@ const struct name_and_handler fh_builtins_control[] = {
|
||||
{"again", w_again, 1, 0},
|
||||
{"until", w_until, 1, 0},
|
||||
{"unloop", w_unloop, 0, 0},
|
||||
{"case", w_case, 1, 0},
|
||||
{"of", w_of, 1, 0},
|
||||
{"endof", w_endof, 1, 0},
|
||||
{"endcase", w_endcase, 1, 0},
|
||||
|
||||
{ /* end marker */ }
|
||||
};
|
||||
|
||||
+24
-1
@@ -139,7 +139,7 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
|
||||
fh->execptr += INSTR_SIZE;
|
||||
|
||||
uint32_t strl;
|
||||
uint32_t val;
|
||||
uint32_t val, testval;
|
||||
uint32_t limit, index;
|
||||
|
||||
LOG("0x%08x: Instr %s, 0x%08x", fh->execptr, instr_name(instr->kind), instr->data);
|
||||
@@ -321,6 +321,29 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
|
||||
fh->execptr = instr->data;
|
||||
goto instr;
|
||||
|
||||
case FH_INSTR_OF:
|
||||
LOG("\x1b[35mExec: OF\x1b[m");
|
||||
if (instr->data == MAGICADDR_UNRESOLVED) {
|
||||
LOGE("Encountered unresolved OF!");
|
||||
goto end;
|
||||
}
|
||||
TRY(ds_pop(fh, &testval));
|
||||
TRY(ds_pop(fh, &val));
|
||||
|
||||
LOG("Val %d, testval %d", val, testval);
|
||||
|
||||
if (testval != val) {
|
||||
LOG("No match, go to ENDOF");
|
||||
TRY(ds_push(fh, val));
|
||||
fh->execptr = instr->data;
|
||||
}
|
||||
goto instr;
|
||||
|
||||
case FH_INSTR_ENDCASE:
|
||||
LOG("\x1b[35mExec: ENDCASE\x1b[m");
|
||||
TRY(ds_pop(fh, &val)); // discard the tested value
|
||||
goto instr;
|
||||
|
||||
/* special case for strings stored in compile memory */
|
||||
case FH_INSTR_ALLOCSTR:
|
||||
case FH_INSTR_TYPESTR:
|
||||
|
||||
@@ -53,6 +53,14 @@ static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
}
|
||||
break;
|
||||
|
||||
case FH_INSTR_OF:
|
||||
FHPRINT("OF(value %d / 0x%08x)\n", instr->data, instr->data);
|
||||
break;
|
||||
|
||||
case FH_INSTR_ENDCASE:
|
||||
FHPRINT("ENDCASE\n");
|
||||
break;
|
||||
|
||||
case FH_INSTR_TO:
|
||||
w2 = fh_word_at(fh, instr->data);
|
||||
if (w2) {
|
||||
|
||||
Reference in New Issue
Block a user