Implement SWITCH, STRSWITCH

This commit is contained in:
Nunuhara Cabbage
2019-10-31 17:27:03 -07:00
parent 3ff406cb58
commit 84e531b9ab
4 changed files with 91 additions and 5 deletions
+4 -4
View File
@@ -141,8 +141,8 @@ const struct instruction instructions[NR_OPCODES] = {
JMP(CALLMETHOD, 1, INSTR_FUN),
OP(SH_GLOBALREF, 1, INSTR_INT),
OP(SH_LOCALREF, 1, INSTR_INT),
OP(SWITCH, 0), // TODO
OP(STRSWITCH, 0), // TODO
JMP(SWITCH, 1),
JMP(STRSWITCH, 1),
OP(FUNC, 1, INSTR_FUN),
OP(_EOF, 1, INSTR_FILE),
OP(CALLSYS, 1, INSTR_INT),
@@ -175,8 +175,8 @@ const struct instruction instructions[NR_OPCODES] = {
OP(ENDFUNC, 1, INSTR_FUN),
OP(R_EQUALE, 0), // TODO
OP(R_NOTE, 0), // TODO
OP(SH_LOCALCREATE, 2), // TODO
OP(SH_LOCALDELETE, 1), // TODO
OP(SH_LOCALCREATE, 2),
OP(SH_LOCALDELETE, 1),
OP(STOI, 0), // TODO
OP(A_PUSHBACK, 0),
OP(A_POPBACK, 0),
+48
View File
@@ -48,6 +48,48 @@ int arithmetic_sub(int a, int b)
return a - b;
}
int test_switch(int i)
{
switch (i) {
case 0: return 0;
case 1: return 1;
case 2: return 2;
}
return 100;
}
int test_switch_default(int i)
{
switch (i) {
case 0: return 0;
case 1: return 1;
case 2: return 2;
default: return 100;
}
return -1;
}
int test_string_switch(string s)
{
switch (s) {
case "a": return 0;
case "b": return 1;
case "c": return 2;
}
return 100;
}
int test_string_switch_default(string s)
{
switch (s) {
case "a": return 0;
case "b": return 1;
case "c": return 2;
default: return 100;
}
return -1;
}
void test_lang(void)
{
int i;
@@ -64,4 +106,10 @@ void test_lang(void)
test_equal("array pass-by-value", (ar[1][1] = 2, array_set_local(ar, 1, 1, 42), ar[1][1]), 2);
test_equal("conditional", (i = 1, i ? 42 : 0), 42);
test_equal("functype", (f = &arithmetic_sub, f(7, 2)), 5);
test_equal("switch", test_switch(2), 2);
test_equal("switch (no default)", test_switch(3), 100);
test_equal("switch (default)", test_switch_default(3), 100);
test_equal("string switch", test_string_switch("b"), 1);
test_equal("string switch (no default)", test_string_switch("d"), 100);
test_equal("string switch (default)", test_string_switch_default("d"), 100);
}
+1 -1
View File
@@ -76,7 +76,7 @@ int main(void)
if (total_failed > 0) {
system.Output(string(total_failed) + " tests failed.\n");
} else {
system.Output("All tests passed.\n");
system.Output("All tests passed „¤|�æ|„¢\n");
}
system.Exit(total_failed > 0);
return 0;
+38
View File
@@ -337,6 +337,36 @@ static void system_call(int32_t code)
}
}
void exec_switch(int no, int val)
{
struct ain_switch *s = &ain->switches[no];
for (int i = 0; i < s->nr_cases; i++) {
if (s->cases[i].value == val) {
instr_ptr = s->cases[i].address;
return;
}
}
if (s->default_address > 0)
instr_ptr = s->default_address;
else
instr_ptr += instruction_width(SWITCH);
}
void exec_strswitch(int no, struct string *str)
{
struct ain_switch *s = &ain->switches[no];
for (int i = 0; i < s->nr_cases; i++) {
if (!strcmp(str->text, ain->strings[s->cases[i].value]->text)) {
instr_ptr = s->cases[i].address;
return;
}
}
if (s->default_address > 0)
instr_ptr = s->default_address;
else
instr_ptr += instruction_width(STRSWITCH);
}
static void execute_instruction(int16_t opcode)
{
int32_t a, b, c, v, pageno, varno, slot;
@@ -485,6 +515,14 @@ static void execute_instruction(int16_t opcode)
else
instr_ptr += instruction_width(IFNZ);
break;
case SWITCH:
exec_switch(get_argument(0), stack_pop().i);
break;
case STRSWITCH:
slot = stack_pop().i;
exec_strswitch(get_argument(0), heap[slot].s);
heap_unref(slot);
break;
//
// --- Arithmetic ---
//