mirror of
https://github.com/odin-lang/Odin.git
synced 2026-03-02 22:58:20 +00:00
Add intrinsics.type_merge
This commit is contained in:
@@ -192,6 +192,7 @@ type_map_info :: proc($T: typeid/map[$K]$V) -> ^runtime.Map_Info ---
|
||||
type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
|
||||
|
||||
type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
|
||||
type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
|
||||
|
||||
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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 \
|
||||
|
||||
Reference in New Issue
Block a user