mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Add intrinsics.type_convert_variants_to_pointers and reflect.get_union_as_ptr_variants
This commit is contained in:
@@ -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_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_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 ---
|
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
|
||||||
|
|
||||||
// SIMD related
|
// SIMD related
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package reflect
|
|||||||
|
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
import "core:mem"
|
||||||
_ :: intrinsics
|
_ :: intrinsics
|
||||||
|
|
||||||
Type_Info :: runtime.Type_Info
|
Type_Info :: runtime.Type_Info
|
||||||
@@ -739,6 +740,15 @@ get_union_variant :: proc(a: any) -> any {
|
|||||||
return any{a.data, id}
|
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) {
|
set_union_variant_raw_tag :: proc(a: any, tag: i64) {
|
||||||
if a == nil { return }
|
if a == nil { return }
|
||||||
|
|||||||
@@ -4613,6 +4613,46 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|||||||
operand->mode = Addressing_Type;
|
operand->mode = Addressing_Type;
|
||||||
break;
|
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<Type *>(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_boolean:
|
||||||
case BuiltinProc_type_is_integer:
|
case BuiltinProc_type_is_integer:
|
||||||
|
|||||||
@@ -200,6 +200,8 @@ BuiltinProc__type_begin,
|
|||||||
BuiltinProc_type_core_type,
|
BuiltinProc_type_core_type,
|
||||||
BuiltinProc_type_elem_type,
|
BuiltinProc_type_elem_type,
|
||||||
|
|
||||||
|
BuiltinProc_type_convert_variants_to_pointers,
|
||||||
|
|
||||||
BuiltinProc__type_simple_boolean_begin,
|
BuiltinProc__type_simple_boolean_begin,
|
||||||
BuiltinProc_type_is_boolean,
|
BuiltinProc_type_is_boolean,
|
||||||
BuiltinProc_type_is_integer,
|
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_base_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
{STR_LIT("type_core_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_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(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||||
{STR_LIT("type_is_boolean"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
{STR_LIT("type_is_boolean"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
|
|||||||
Reference in New Issue
Block a user