aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-05-19 11:18:20 +0100
committergingerBill <bill@gingerbill.org>2023-05-19 11:18:20 +0100
commit2631e07beab29558249341c329c69bb604dd61fb (patch)
tree8bd29f9d3e88f38609899833e62dffc8acdc9299 /src
parent76a1851cb80a181a24140efedf8914d3cedc8051 (diff)
Add `intrinsics.type_merge`
Diffstat (limited to 'src')
-rw-r--r--src/check_builtin.cpp69
-rw-r--r--src/check_expr.cpp2
-rw-r--r--src/checker_builtin_procs.hpp2
-rw-r--r--src/parser.hpp9
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 \