From f77709e67e405419b5e60c6645e2483484aeb010 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 8 Sep 2022 16:52:51 +0100 Subject: [PATCH] Add `intrinsics.type_convert_variants_to_pointers` and `reflect.get_union_as_ptr_variants` --- core/intrinsics/intrinsics.odin | 2 ++ core/reflect/reflect.odin | 10 +++++++++ src/check_builtin.cpp | 40 +++++++++++++++++++++++++++++++++ src/checker_builtin_procs.hpp | 3 +++ 4 files changed, 55 insertions(+) diff --git a/core/intrinsics/intrinsics.odin b/core/intrinsics/intrinsics.odin index 0b682fbc3..0146746e7 100644 --- a/core/intrinsics/intrinsics.odin +++ b/core/intrinsics/intrinsics.odin @@ -188,6 +188,8 @@ type_field_index_of :: proc($T: typeid, $name: string) -> uintptr --- type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) --- type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) --- +type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) --- + constant_utf16_cstring :: proc($literal: string) -> [^]u16 --- // SIMD related diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index 07ab94183..b65776397 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -2,6 +2,7 @@ package reflect import "core:runtime" import "core:intrinsics" +import "core:mem" _ :: intrinsics Type_Info :: runtime.Type_Info @@ -739,6 +740,15 @@ get_union_variant :: proc(a: any) -> any { return any{a.data, id} } +get_union_as_ptr_variants :: proc(val: ^$T) -> (res: intrinsics.type_convert_variants_to_pointers(T)) where intrinsics.type_is_union(T) { + ptr := rawptr(val) + tag := get_union_variant_raw_tag(val^) + mem.copy(&res, &ptr, size_of(ptr)) + set_union_variant_raw_tag(res, tag) + return +} + + set_union_variant_raw_tag :: proc(a: any, tag: i64) { if a == nil { return } diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 07eeeacca..f0db6afc4 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -4613,6 +4613,46 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->mode = Addressing_Type; break; + case BuiltinProc_type_convert_variants_to_pointers: + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + } else { + Type *bt = base_type(operand->type); + if (is_type_polymorphic(bt)) { + // IGNORE polymorphic types + return true; + } else if (bt->kind != Type_Union) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Expected a union type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } else if (bt->Union.is_polymorphic) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Expected a non-polymorphic union type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *new_type = alloc_type_union(); + auto variants = slice_make(permanent_allocator(), bt->Union.variants.count); + for_array(i, bt->Union.variants) { + variants[i] = alloc_type_pointer(bt->Union.variants[i]); + } + new_type->Union.variants = variants; + + // NOTE(bill): Is this even correct? + new_type->Union.scope = bt->Union.scope; + + operand->type = new_type; + } + operand->mode = Addressing_Type; + break; case BuiltinProc_type_is_boolean: case BuiltinProc_type_is_integer: diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 717422df1..b8cd84cc6 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -200,6 +200,8 @@ BuiltinProc__type_begin, BuiltinProc_type_core_type, BuiltinProc_type_elem_type, + BuiltinProc_type_convert_variants_to_pointers, + BuiltinProc__type_simple_boolean_begin, BuiltinProc_type_is_boolean, BuiltinProc_type_is_integer, @@ -492,6 +494,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_base_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {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(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_boolean"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},