Added initializer to switch statement; slight output improvements
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 25 Aug 2020 14:32:24 +0000 (09:32 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 25 Aug 2020 14:32:24 +0000 (09:32 -0500)
onyx
progs/wasi_test.onyx
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c
src/onyxwasm.c

diff --git a/onyx b/onyx
index 869201d2b1f3675cb1aa7bf43b4951822296eac0..df64f5caae3d40145d9af5269a0f65a34a67f61b 100755 (executable)
Binary files a/onyx and b/onyx differ
index 7ac5eb5a00b5316466a6929bf14b4b3d6f0e55fe..55af2806fa18040d20ec5e3e63738637979538a2 100644 (file)
@@ -278,7 +278,6 @@ main :: proc (args: []cstring) {
             case #char "-" do acc -= 1;
             case #char "*" do acc *= 2;
             case #char "/" do acc /= 2;
-
             case #char "s" do acc *= acc;
 
             case #default {
@@ -334,22 +333,7 @@ main :: proc (args: []cstring) {
     print_arr(^sb, arr[5 : 10]);
 
     ss := string_substr("Hello, World!", "World");
-    if ss.count > 0 {
-        print(ss);
-    }
+    if ss.count > 0 do print(ss);
     print("\n");
-
-    num := 36;
-    switch num {
-        case 36 do print("6 squared\n");
-
-        case 42 {
-            print("The meaning of life\n");
-            fallthrough;
-        }
-
-        case #default {
-            print("Nothing was found");
-        }
-    }
 }
+
index cbd8710fa03538211c69da18124de66308f7703e..d8f950529a4643851a586651245115df73eb61d5 100644 (file)
@@ -158,11 +158,13 @@ CHECK(for, AstFor* fornode) {
 }
 
 CHECK(switch, AstSwitch* switchnode) {
+    if (switchnode->assignment != NULL) check_statement((AstNode *) switchnode->assignment);
+
     if (check_expression(&switchnode->expr)) return 1;
-    if (!type_is_integer(switchnode->expr->type)) {
+    if (!type_is_integer(switchnode->expr->type) && switchnode->expr->type->kind != Type_Kind_Enum) {
         onyx_message_add(Msg_Type_Literal,
                 switchnode->expr->token->pos,
-                "expected integer type for switch expression");
+                "expected integer or enum type for switch expression");
         return 1;
     }
 
@@ -174,6 +176,10 @@ CHECK(switch, AstSwitch* switchnode) {
         if (check_block(sc->block)) return 1;
         if (check_expression(&sc->value)) return 1;
 
+        if (sc->value->kind == Ast_Kind_Enum_Value) {
+            sc->value = (AstTyped *) ((AstEnumValue *) sc->value)->value;
+        }
+
         if (sc->value->kind != Ast_Kind_NumLit) {
             onyx_message_add(Msg_Type_Literal,
                     sc->value->token->pos,
index e56d34832771cb81f380469075b11c17f77987d6..e798391c1b8486a1abfb785d25144a7ccc294c2b 100644 (file)
@@ -849,6 +849,22 @@ static AstSwitch* parse_switch_stmt(OnyxParser* parser) {
 
     bh_arr_new(global_heap_allocator, switch_node->cases, 4);
 
+    if ((parser->curr + 1)->type == ':') {
+        switch_node->local = make_node(AstLocal, Ast_Kind_Local);
+        switch_node->local->token = expect_token(parser, Token_Type_Symbol);
+
+        expect_token(parser, ':');
+
+        AstBinaryOp* assignment = make_node(AstBinaryOp, Ast_Kind_Binary_Op);
+        assignment->operation = Binary_Op_Assign;
+        assignment->token = expect_token(parser, '=');
+        assignment->left = (AstTyped *) switch_node->local;
+        assignment->right = parse_expression(parser);
+
+        switch_node->assignment = assignment;
+        expect_token(parser, ';');
+    }
+
     switch_node->expr = parse_expression(parser);
     expect_token(parser, '{');
 
index 698133690357109ec058715348a06f0449366b16..ba6776fe4c7908461543ab5c681d4a6ffe5d2c5c 100644 (file)
@@ -391,6 +391,15 @@ static void symres_for(AstFor* fornode) {
 }
 
 static void symres_switch(AstSwitch* switchnode) {
+    if (switchnode->assignment != NULL) {
+        switchnode->scope = scope_create(semstate.node_allocator, semstate.curr_scope);
+        scope_enter(switchnode->scope);
+
+        symbol_introduce(semstate.curr_scope, switchnode->local->token, (AstNode *) switchnode->local);
+
+        symres_statement((AstNode **) &switchnode->assignment);
+    }
+
     symres_expression(&switchnode->expr);
 
     bh_arr_each(AstSwitchCase, sc, switchnode->cases) {
@@ -400,6 +409,8 @@ static void symres_switch(AstSwitch* switchnode) {
 
     if (switchnode->default_case)
         symres_block(switchnode->default_case);
+
+    if (switchnode->assignment != NULL) scope_leave();
 }
 
 // NOTE: Returns 1 if the statment should be removed
index e370fa0761b59a23f03291d87f8596e0a82af9e4..2da94b78b707c7038e0798b5266cf2e475807fd5 100644 (file)
@@ -437,7 +437,10 @@ COMPILE_FUNC(structured_jump, i32 jump_count, JumpType jump) {
     }
 
     if (success) {
-        WID(WI_JUMP, labelidx);
+        // NOTE: If the previous instruction was a non conditional jump,
+        // don't emit another jump since it will never be reached.
+        if (bh_arr_last(code).type != WI_JUMP)
+            WID(WI_JUMP, labelidx);
     } else {
         assert(("Invalid structured jump", 0));
     }
@@ -701,7 +704,8 @@ COMPILE_FUNC(while, AstIfWhile* while_node) {
         bh_arr_pop(mod->structured_jump_target);
         bh_arr_pop(mod->structured_jump_target);
 
-        WID(WI_JUMP, 0x00);
+        if (bh_arr_last(code).type != WI_JUMP)
+            WID(WI_JUMP, 0x00);
 
         WI(WI_LOOP_END);
         WI(WI_BLOCK_END);
@@ -795,7 +799,8 @@ COMPILE_FUNC(for, AstFor* for_node) {
     bh_arr_pop(mod->structured_jump_target);
     bh_arr_pop(mod->structured_jump_target);
 
-    WID(WI_JUMP, 0x00);
+    if (bh_arr_last(code).type != WI_JUMP)
+        WID(WI_JUMP, 0x00);
 
     WI(WI_LOOP_END);
     WI(WI_BLOCK_END);
@@ -811,21 +816,21 @@ COMPILE_FUNC(switch, AstSwitch* switch_node) {
     bh_imap block_map;
     bh_imap_init(&block_map, global_heap_allocator, bh_arr_length(switch_node->cases));
 
-    u32 jump_target = 1;
-
-    if (switch_node->default_case != NULL) {
-        WID(WI_BLOCK_START, 0x40);
+    if (switch_node->assignment != NULL) {
+        bh_imap_put(&mod->local_map, (u64) switch_node->local, local_allocate(mod->local_alloc, switch_node->local));
 
-        bh_arr_push(mod->structured_jump_target, jump_target);
-        jump_target = 3;
+        compile_assignment(mod, &code, switch_node->assignment);
     }
 
+    WID(WI_BLOCK_START, 0x40);
+    bh_arr_push(mod->structured_jump_target, 1);
+
     u64 block_num = 0;
     bh_arr_each(AstSwitchCase, sc, switch_node->cases) {
         if (bh_imap_has(&block_map, (u64) sc->block)) continue;
 
         WID(WI_BLOCK_START, 0x40);
-        bh_arr_push(mod->structured_jump_target, jump_target);
+        bh_arr_push(mod->structured_jump_target, 3);
 
         bh_imap_put(&block_map, (u64) sc->block, block_num);
         block_num++;
@@ -856,7 +861,10 @@ COMPILE_FUNC(switch, AstSwitch* switch_node) {
         u64 bn = bh_imap_get(&block_map, (u64) sc->block);
 
         compile_block(mod, &code, sc->block, 0);
-        WID(WI_JUMP, block_num - bn);
+
+        if (bh_arr_last(code).type != WI_JUMP)
+            WID(WI_JUMP, block_num - bn);
+
         WI(WI_BLOCK_END);
         bh_arr_pop(mod->structured_jump_target);
 
@@ -865,10 +873,14 @@ COMPILE_FUNC(switch, AstSwitch* switch_node) {
 
     if (switch_node->default_case != NULL) {
         compile_block(mod, &code, switch_node->default_case, 0);
-        WI(WI_BLOCK_END);
-        bh_arr_pop(mod->structured_jump_target);
     }
 
+    WI(WI_BLOCK_END);
+    bh_arr_pop(mod->structured_jump_target);
+
+    if (switch_node->assignment != NULL)
+        local_free(mod->local_alloc, switch_node->local);
+
     bh_imap_free(&block_map);
     *pcode = code;
 }