From: Brendan Hansen Date: Tue, 25 Aug 2020 14:32:24 +0000 (-0500) Subject: Added initializer to switch statement; slight output improvements X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=aee0753bf6a50f95bfeb936fdbe918ede1e994f1;p=onyx.git Added initializer to switch statement; slight output improvements --- diff --git a/onyx b/onyx index 869201d2..df64f5ca 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/wasi_test.onyx b/progs/wasi_test.onyx index 7ac5eb5a..55af2806 100644 --- a/progs/wasi_test.onyx +++ b/progs/wasi_test.onyx @@ -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"); - } - } } + diff --git a/src/onyxchecker.c b/src/onyxchecker.c index cbd8710f..d8f95052 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -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, diff --git a/src/onyxparser.c b/src/onyxparser.c index e56d3483..e798391c 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -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, '{'); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 69813369..ba6776fe 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -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 diff --git a/src/onyxwasm.c b/src/onyxwasm.c index e370fa07..2da94b78 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -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; }