case #char "-" do acc -= 1;
case #char "*" do acc *= 2;
case #char "/" do acc /= 2;
-
case #char "s" do acc *= acc;
case #default {
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");
- }
- }
}
+
}
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;
}
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,
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, '{');
}
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) {
if (switchnode->default_case)
symres_block(switchnode->default_case);
+
+ if (switchnode->assignment != NULL) scope_leave();
}
// NOTE: Returns 1 if the statment should be removed
}
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));
}
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);
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);
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++;
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);
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;
}