From 84e531b9abb5f7624f2890cbf11cf2ce4b5d29a2 Mon Sep 17 00:00:00 2001 From: Nunuhara Cabbage Date: Thu, 31 Oct 2019 17:27:03 -0700 Subject: [PATCH] Implement SWITCH, STRSWITCH --- instructions.c | 8 ++++---- test/Source/lang.jaf | 48 ++++++++++++++++++++++++++++++++++++++++++++ test/Source/main.jaf | 2 +- vm.c | 38 +++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 5 deletions(-) diff --git a/instructions.c b/instructions.c index 60e0529..20b6d55 100644 --- a/instructions.c +++ b/instructions.c @@ -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), diff --git a/test/Source/lang.jaf b/test/Source/lang.jaf index 492cad3..115f9be 100755 --- a/test/Source/lang.jaf +++ b/test/Source/lang.jaf @@ -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); } diff --git a/test/Source/main.jaf b/test/Source/main.jaf index f29f132..baf9ee4 100755 --- a/test/Source/main.jaf +++ b/test/Source/main.jaf @@ -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; diff --git a/vm.c b/vm.c index 915a643..5484fd0 100644 --- a/vm.c +++ b/vm.c @@ -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 --- //