AstBlock *true_stmt;
AstBlock *false_stmt;
};
-struct AstSwitchCase { AstTyped *value; AstBlock *block; };
+struct AstSwitchCase {
+ // NOTE: All expressions that end up in this block
+ bh_arr(AstTyped *) values;
+
+ AstBlock *block;
+};
struct AstSwitch {
AstNode_base;
- // NOTE: These are not currently used;
Scope *scope;
AstLocal *local;
AstBinaryOp *assignment;
return 0;
}
+static b32 add_case_to_switch_statement(AstSwitch* switchnode, i64 case_value, AstBlock* block, OnyxFilePos pos) {
+ switchnode->min_case = bh_min(switchnode->min_case, case_value);
+ switchnode->max_case = bh_max(switchnode->max_case, case_value);
+
+ if (bh_imap_has(&switchnode->case_map, case_value)) {
+ onyx_report_error(pos, "Multiple cases for values '%d'.", case_value);
+ return 1;
+ }
+
+ bh_imap_put(&switchnode->case_map, case_value, (u64) block);
+ return 0;
+}
+
b32 check_switch(AstSwitch* switchnode) {
if (switchnode->assignment != NULL) check_statement((AstNode *) switchnode->assignment);
bh_arr_each(AstSwitchCase, sc, switchnode->cases) {
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;
- }
+ bh_arr_each(AstTyped *, value, sc->values) {
+ if (check_expression(value)) return 1;
- if (sc->value->kind != Ast_Kind_NumLit) {
- onyx_report_error(sc->value->token->pos, "case statement expected compile time known integer");
- return 1;
- }
+ if ((*value)->kind == Ast_Kind_Range_Literal) {
+ AstRangeLiteral* rl = (AstRangeLiteral *) (*value);
+ resolve_expression_type(rl->low);
+ resolve_expression_type(rl->high);
+ assert(rl->low->kind == Ast_Kind_NumLit && rl->high->kind == Ast_Kind_NumLit);
- resolve_expression_type(sc->value);
- promote_numlit_to_larger((AstNumLit *) sc->value);
+ promote_numlit_to_larger((AstNumLit *) rl->low);
+ promote_numlit_to_larger((AstNumLit *) rl->high);
- u64 value = ((AstNumLit *) sc->value)->value.l;
- switchnode->min_case = bh_min(switchnode->min_case, value);
- switchnode->max_case = bh_max(switchnode->max_case, value);
+ i64 lower = ((AstNumLit *) rl->low)->value.l;
+ i64 upper = ((AstNumLit *) rl->high)->value.l;
- if (bh_imap_has(&switchnode->case_map, value)) {
- onyx_report_error(sc->value->token->pos, "Multiple cases for values '%d'.", value);
- return 1;
- }
+ // NOTE: This is inclusive!!!!
+ fori (case_value, lower, upper + 1)
+ add_case_to_switch_statement(switchnode, case_value, sc->block, rl->token->pos);
+
+ continue;
+ }
+
+ if ((*value)->kind == Ast_Kind_Enum_Value) {
+ (*value) = (AstTyped *) ((AstEnumValue *) (*value))->value;
+ }
- bh_imap_put(&switchnode->case_map, value, (u64) sc->block);
+ if ((*value)->kind != Ast_Kind_NumLit) {
+ onyx_report_error((*value)->token->pos, "case statement expected compile time known integer");
+ return 1;
+ }
+
+ resolve_expression_type((*value));
+ promote_numlit_to_larger((AstNumLit *) (*value));
+
+ add_case_to_switch_statement(switchnode, ((AstNumLit *) (*value))->value.l, sc->block, sc->block->token->pos);
+ }
}
if (switchnode->default_case)
bh_arr_new(global_heap_allocator, dw->cases, bh_arr_length(sw->cases));
bh_arr_each(AstSwitchCase, c, sw->cases) {
+ bh_arr(AstTyped *) new_values = NULL;
+ bh_arr_new(global_heap_allocator, new_values, bh_arr_length(c->values));
+ bh_arr_each(AstTyped *, value, c->values)
+ bh_arr_push(new_values, (AstTyped *) ast_clone(a, *value));
+
AstSwitchCase sc;
- sc.value = (AstTyped *) ast_clone(a, c->value);
+ sc.values = new_values;
sc.block = (AstBlock *) ast_clone(a, c->block);
bh_arr_push(dw->cases, sc);
}
else if (parse_possible_directive(parser, "char")) {
AstNumLit* char_lit = make_node(AstNumLit, Ast_Kind_NumLit);
char_lit->flags |= Ast_Flag_Comptime;
- char_lit->type_node = (AstType *) &basic_type_u8;
+ char_lit->type_node = (AstType *) &basic_type_int_unsized;
char_lit->token = expect_token(parser, Token_Type_Literal_String);
switch_node->expr = parse_expression(parser);
expect_token(parser, '{');
- AstTyped** batch_cases = NULL;
- // NOTE: Look into bugs relating to switching this to the scratch allocator
- bh_arr_new(global_heap_allocator, batch_cases, 16);
-
while (parser->curr->type == Token_Type_Keyword_Case) {
+ bh_arr(AstTyped *) case_values = NULL;
+ bh_arr_new(global_heap_allocator, case_values, 1);
+
expect_token(parser, Token_Type_Keyword_Case);
if (parser->hit_unexpected_token) return switch_node;
}
AstTyped* value = parse_expression(parser);
- bh_arr_push(batch_cases, value);
+ bh_arr_push(case_values, value);
while (parser->curr->type == ',') {
if (parser->hit_unexpected_token) return switch_node;
consume_token(parser);
value = parse_expression(parser);
- bh_arr_push(batch_cases, value);
+ bh_arr_push(case_values, value);
}
AstBlock* block = parse_block(parser);
AstSwitchCase sc_node;
- sc_node.block = block;
+ sc_node.block = block;
+ sc_node.values = case_values;
- bh_arr_each(AstTyped *, value, batch_cases) {
- sc_node.value = *value;
- bh_arr_push(switch_node->cases, sc_node);
- }
-
- bh_arr_clear(batch_cases);
+ bh_arr_push(switch_node->cases, sc_node);
}
- bh_arr_free(batch_cases);
-
expect_token(parser, '}');
return switch_node;
}
symres_expression(&switchnode->expr);
bh_arr_each(AstSwitchCase, sc, switchnode->cases) {
- symres_expression(&sc->value);
+ bh_arr_each(AstTyped *, value, sc->values)
+ symres_expression(value);
+
symres_block(sc->block);
}