From c21439dc5c093178f100e0925325c009ffebd47a Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 22 May 2023 14:45:28 -0500 Subject: [PATCH] bugfix: misc with unions --- compiler/include/parser.h | 1 + compiler/src/checker.c | 8 ++++++++ compiler/src/clone.c | 1 + compiler/src/parser.c | 6 ++++++ compiler/src/polymorph.h | 12 ++++++------ core/container/slice.onyx | 10 +++++----- tests/tagged_unions.onyx | 14 ++++++++++++++ 7 files changed, 41 insertions(+), 11 deletions(-) diff --git a/compiler/include/parser.h b/compiler/include/parser.h index a4c96588..237f5f8f 100644 --- a/compiler/include/parser.h +++ b/compiler/include/parser.h @@ -56,6 +56,7 @@ typedef struct OnyxParser { b32 hit_unexpected_token : 1; b32 parse_calls : 1; + b32 parse_quick_functions : 1; // Currently, package expressions are only allowed in certain places. b32 allow_package_expressions : 1; diff --git a/compiler/src/checker.c b/compiler/src/checker.c index e9140f79..568e315a 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -487,6 +487,10 @@ CheckStatus check_switch(AstSwitch* switchnode) { ERROR(sc->token->pos, "Expected exactly one value in switch-case when using a capture."); } + if (sc->capture && switchnode->switch_kind != Switch_Kind_Union) { + ERROR(sc->capture->token->pos, "Captures in switch cases are only allowed when switching over a union type."); + } + if (sc->flags & Ast_Flag_Has_Been_Checked) goto check_switch_case_block; bh_arr_each(AstTyped *, value, sc->values) { @@ -1483,6 +1487,8 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) { } if (sl->type->kind == Type_Kind_Union) { + if ((sl->flags & Ast_Flag_Has_Been_Checked) != 0) return Check_Success; + if (bh_arr_length(sl->args.values) != 0 || bh_arr_length(sl->args.named_values) != 1) { ERROR_(sl->token->pos, "Expected exactly one named member when constructing an instance of a union type, '%s'.", type_get_name(sl->type)); } @@ -1513,6 +1519,8 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) { bh_arr_push(sl->args.values, (AstTyped *) tag_value); bh_arr_push(sl->args.values, value->value); + + sl->flags |= Ast_Flag_Has_Been_Checked; return Check_Success; } diff --git a/compiler/src/clone.c b/compiler/src/clone.c index c44ec994..fdbe7a8c 100644 --- a/compiler/src/clone.c +++ b/compiler/src/clone.c @@ -304,6 +304,7 @@ AstNode* ast_clone(bh_allocator a, void* n) { break; case Ast_Kind_Switch_Case: { + C(AstSwitchCase, capture); C(AstSwitchCase, block); AstSwitchCase *dw = (AstSwitchCase *) nn; diff --git a/compiler/src/parser.c b/compiler/src/parser.c index e5564092..ad037020 100644 --- a/compiler/src/parser.c +++ b/compiler/src/parser.c @@ -1309,6 +1309,7 @@ static AstSwitchCase* parse_case_stmt(OnyxParser* parser) { } else { bh_arr_new(global_heap_allocator, sc_node->values, 1); + parser->parse_quick_functions = 0; AstTyped* value = parse_expression(parser, 1); bh_arr_push(sc_node->values, value); while (consume_token_if_next(parser, ',')) { @@ -1317,6 +1318,8 @@ static AstSwitchCase* parse_case_stmt(OnyxParser* parser) { value = parse_expression(parser, 1); bh_arr_push(sc_node->values, value); } + + parser->parse_quick_functions = 1; } if (consume_token_if_next(parser, Token_Type_Fat_Right_Arrow)) { @@ -2859,6 +2862,8 @@ typedef struct QuickParam { } QuickParam; static b32 parse_possible_quick_function_definition_no_consume(OnyxParser* parser) { + if (!parser->parse_quick_functions) return 0; + // // x => x + 1 case. if (next_tokens_are(parser, 2, Token_Type_Symbol, Token_Type_Fat_Right_Arrow)) { @@ -3933,6 +3938,7 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer) { parser.scope_flags = NULL; parser.stored_tags = NULL; parser.parse_calls = 1; + parser.parse_quick_functions = 1; parser.tag_depth = 0; parser.overload_count = 0; parser.injection_point = NULL; diff --git a/compiler/src/polymorph.h b/compiler/src/polymorph.h index de83db13..440688e9 100644 --- a/compiler/src/polymorph.h +++ b/compiler/src/polymorph.h @@ -648,11 +648,6 @@ static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstFunc } else { resolve_expression_type(value); - if ((value->flags & Ast_Flag_Comptime) == 0) { - if (err_msg) *err_msg = "Expected compile-time known argument here."; - return; - } - param_type = type_build_from_ast(context.ast_alloc, param_type_expr); if (param_type == NULL) { flag_to_yield = 1; @@ -679,7 +674,12 @@ static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstFunc if (tm == TYPE_MATCH_YIELD) flag_to_yield = 1; - *resolved = ((PolySolveResult) { PSK_Value, value }); + if ((value_to_use->flags & Ast_Flag_Comptime) == 0) { + if (err_msg) *err_msg = "Expected compile-time known argument here."; + return; + } + + *resolved = ((PolySolveResult) { PSK_Value, value_to_use }); } if (orig_value->kind == Ast_Kind_Argument) { diff --git a/core/container/slice.onyx b/core/container/slice.onyx index 2b37b24b..e5fed638 100644 --- a/core/container/slice.onyx +++ b/core/container/slice.onyx @@ -160,14 +160,14 @@ set :: (arr: [] $T, idx: i32, value: T) { } contains :: #match #locked { - macro (arr: [] $T, $cmp: Code) -> bool { - for it: arr do if #unquote cmp do return true; - return false; - }, - (arr: [] $T, x: T) -> bool { for it: arr do if it == x do return true; return false; + }, + + macro (arr: [] $T, $cmp: Code) -> bool { + for it: arr do if #unquote cmp do return true; + return false; } } diff --git a/tests/tagged_unions.onyx b/tests/tagged_unions.onyx index f616c301..71704020 100644 --- a/tests/tagged_unions.onyx +++ b/tests/tagged_unions.onyx @@ -1,6 +1,16 @@ use core {*} +extract_variant :: macro (u: $U, $variant: U.tag_enum) => { + switch u { + case variant => v { + return Optional.make(v); + } + } + + return .{}; +} + SimpleUnion :: union { a: i32; b: struct { @@ -40,6 +50,10 @@ simple_test :: () { println(cast(SimpleUnion.tag_enum) u); call_test(u); + + if cast(SimpleUnion.tag_enum, u) == .b { + println(extract_variant(u, .b)?); + } } main :: () {simple_test(); link_test();} -- 2.25.1