diff options
| author | gingerBill <bill@gingerbill.org> | 2023-05-19 11:18:20 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2023-05-19 11:18:20 +0100 |
| commit | 2631e07beab29558249341c329c69bb604dd61fb (patch) | |
| tree | 8bd29f9d3e88f38609899833e62dffc8acdc9299 /src | |
| parent | 76a1851cb80a181a24140efedf8914d3cedc8051 (diff) | |
Add `intrinsics.type_merge`
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_builtin.cpp | 69 | ||||
| -rw-r--r-- | src/check_expr.cpp | 2 | ||||
| -rw-r--r-- | src/checker_builtin_procs.hpp | 2 | ||||
| -rw-r--r-- | src/parser.hpp | 9 |
4 files changed, 81 insertions, 1 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 5f9715959..0f8cdfd69 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -4843,6 +4843,75 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } operand->mode = Addressing_Type; break; + case BuiltinProc_type_merge: + { + operand->mode = Addressing_Type; + operand->type = t_invalid; + + Operand x = {}; + Operand y = {}; + check_expr_or_type(c, &x, ce->args[0]); + check_expr_or_type(c, &y, ce->args[1]); + if (x.mode != Addressing_Type) { + error(x.expr, "Expected a type for '%.*s'", LIT(builtin_name)); + return false; + } + if (y.mode != Addressing_Type) { + error(y.expr, "Expected a type for '%.*s'", LIT(builtin_name)); + return false; + } + + if (is_type_polymorphic(x.type)) { + gbString t = type_to_string(x.type); + error(x.expr, "Expected a non-polymorphic type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + if (is_type_polymorphic(y.type)) { + gbString t = type_to_string(y.type); + error(y.expr, "Expected a non-polymorphic type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + if (!is_type_union(x.type)) { + gbString t = type_to_string(x.type); + error(x.expr, "Expected a union type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + if (!is_type_union(y.type)) { + gbString t = type_to_string(y.type); + error(x.expr, "Expected a union type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + Type *ux = base_type(x.type); + Type *uy = base_type(y.type); + GB_ASSERT(ux->kind == Type_Union); + GB_ASSERT(uy->kind == Type_Union); + + i64 custom_align = gb_max(ux->Union.custom_align, uy->Union.custom_align); + if (ux->Union.kind != uy->Union.kind) { + error(x.expr, "Union kinds must match, got %s vs %s", union_type_kind_strings[ux->Union.kind], union_type_kind_strings[uy->Union.kind]); + } + + Type *merged_union = alloc_type_union(); + + merged_union->Union.node = call; + merged_union->Union.scope = create_scope(c->info, c->scope); + merged_union->Union.kind = ux->Union.kind; + merged_union->Union.custom_align = custom_align; + + auto variants = slice_make<Type *>(permanent_allocator(), ux->Union.variants.count+uy->Union.variants.count); + slice_copy(&variants, ux->Union.variants, 0); + slice_copy(&variants, uy->Union.variants, ux->Union.variants.count); + merged_union->Union.variants = variants; + + operand->mode = Addressing_Type; + operand->type = merged_union; + } + break; + case BuiltinProc_type_is_boolean: case BuiltinProc_type_is_integer: diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 0db12aba0..1552b1ef5 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1067,7 +1067,7 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ if (check_is_assignable_to(c, operand, type)) { if (operand->mode == Addressing_Type && is_type_typeid(type)) { - add_type_info_type(c, operand->type); + add_type_info_type(c, operand->type); add_type_and_value(c, operand->expr, Addressing_Value, type, exact_value_typeid(operand->type)); } } else { diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 72f001c70..edd046087 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -203,6 +203,7 @@ BuiltinProc__type_begin, BuiltinProc_type_elem_type, BuiltinProc_type_convert_variants_to_pointers, + BuiltinProc_type_merge, BuiltinProc__type_simple_boolean_begin, BuiltinProc_type_is_boolean, @@ -501,6 +502,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_core_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_elem_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_convert_variants_to_pointers"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_merge"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_boolean"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/parser.hpp b/src/parser.hpp index 5302fd274..aea3bbf21 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -356,6 +356,15 @@ enum UnionTypeKind : u8 { UnionType_Normal = 0, UnionType_no_nil = 2, UnionType_shared_nil = 3, + + UnionType_COUNT +}; + +gb_global char const *union_type_kind_strings[UnionType_COUNT] = { + "(normal)", + "#maybe", + "#no_nil", + "#shared_nil", }; #define AST_KINDS \ |