Forráskód Böngészése

Rename type_union_tag to type_union_tag_type

jakubtomsu 1 éve
szülő
commit
625cb03284
4 módosított fájl, 277 hozzáadás és 5 törlés
  1. 2 2
      core/intrinsics/intrinsics.odin
  2. 1 1
      src/check_builtin.cpp
  3. 2 2
      src/checker_builtin_procs.hpp
  4. 272 0
      test.odin

+ 2 - 2
core/intrinsics/intrinsics.odin

@@ -164,9 +164,9 @@ type_has_nil :: proc($T: typeid) -> bool ---
 type_is_specialization_of :: proc($T, $S: typeid) -> bool ---
 
 type_is_variant_of :: proc($U, $V: typeid) -> bool where type_is_union(U) ---
-type_union_tag :: proc($U: typeid) -> typeid where type_is_union(U) ---
+type_union_tag_type :: proc($U: typeid) -> typeid where type_is_union(U) ---
 type_union_tag_offset :: proc($U: typeid) -> int where type_is_union(U) ---
-type_variant_type_of_of :: proc($U: typeid, $index: int) -> typeid where type_is_union(U) ---
+type_variant_type_of :: proc($U: typeid, $index: int) -> typeid where type_is_union(U) ---
 type_variant_index_of :: proc($U, $V: typeid) -> int where type_is_union(U) ---
 
 type_has_field :: proc($T: typeid, $name: string) -> bool ---

+ 1 - 1
src/check_builtin.cpp

@@ -5138,7 +5138,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
 		}
 		break;
 
-	case BuiltinProc_type_union_tag:
+	case BuiltinProc_type_union_tag_type:
 		{
 			if (operand->mode != Addressing_Type) {
 				error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));

+ 2 - 2
src/checker_builtin_procs.hpp

@@ -260,7 +260,7 @@ BuiltinProc__type_simple_boolean_end,
 	BuiltinProc_type_is_specialization_of,
 
 	BuiltinProc_type_is_variant_of,
-	BuiltinProc_type_union_tag,
+	BuiltinProc_type_union_tag_type,
 	BuiltinProc_type_union_tag_offset,
 	BuiltinProc_type_variant_type_of,
 	BuiltinProc_type_variant_index_of,
@@ -562,7 +562,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 	{STR_LIT("type_is_specialization_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 
 	{STR_LIT("type_is_variant_of"),    2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("type_union_tag"),        1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_union_tag_type"),        1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 	{STR_LIT("type_union_tag_offset"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 	{STR_LIT("type_variant_type_of"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 	{STR_LIT("type_variant_index_of"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},

+ 272 - 0
test.odin

@@ -0,0 +1,272 @@
+package test
+
+import "core:fmt"
+import "core:intrinsics"
+import "core:mem"
+import "core:reflect"
+import "core:runtime"
+import "core:slice"
+
+// TODO: extend for loops?
+
+get_tag :: proc(u: $T) -> int where intrinsics.type_is_union(T) {
+	u := u
+	return int(
+		(cast(^intrinsics.type_union_tag_type(T))(uintptr(&u) +
+				intrinsics.type_union_tag_offset(T)))^,
+	)
+}
+
+set_tag :: proc(u: ^$T, tag: int) where intrinsics.type_is_union(T) {
+	TAG :: intrinsics.type_union_tag_type(T)
+	(cast(^TAG)(uintptr(u) + intrinsics.type_union_tag_offset(T)))^ = TAG(tag)
+}
+
+get_variant_index :: proc(u: $T) -> int where intrinsics.type_is_union(T) {
+	return min(T) + get_tag(u)
+}
+
+main :: proc() {
+	Foo :: union {
+		f32, // 1
+		u16, // 2
+		u8, // 3
+	}
+
+	fmt.println(typeid_of(Foo))
+	fmt.println("size_of:", size_of(Foo))
+	fmt.println("len:", len(Foo))
+	fmt.println("cap:", cap(Foo))
+	fmt.println("min:", min(Foo))
+	fmt.println("max:", max(Foo))
+	fmt.println("tag:", typeid_of(intrinsics.type_union_tag_type(Foo)))
+	fmt.println("tag offset:", intrinsics.type_union_tag_offset(Foo))
+	fmt.println("type of 0:", typeid_of(intrinsics.type_variant_type_of(Foo, 0)))
+	fmt.println("type of 1:", typeid_of(intrinsics.type_variant_type_of(Foo, 1)))
+	fmt.println("type of 2:", typeid_of(intrinsics.type_variant_type_of(Foo, 2)))
+	fmt.println("index of f32:", intrinsics.type_variant_index_of(Foo, f32))
+	fmt.println("index of u16:", intrinsics.type_variant_index_of(Foo, u16))
+	fmt.println("index of u8 :", intrinsics.type_variant_index_of(Foo, u8))
+	// Goofy test of unsafe tag manipulation
+	foo: Foo = u16(255 + 255 << 8)
+	assert(get_tag(foo) == 2)
+	fmt.println(foo)
+	set_tag(&foo, 3)
+	assert(get_tag(foo) == 3)
+	fmt.println(foo)
+	fmt.println()
+
+	Bar :: union #no_nil {
+		i8, // 0
+		u8, // 1
+		b8, // 2
+	}
+
+	fmt.println(typeid_of(Bar))
+	fmt.println("size_of:", size_of(Bar))
+	fmt.println("len:", len(Bar))
+	fmt.println("cap:", cap(Bar))
+	fmt.println("min:", min(Bar))
+	fmt.println("max:", max(Bar))
+	fmt.println("tag:", typeid_of(intrinsics.type_union_tag_type(Bar)))
+	fmt.println("tag offset:", intrinsics.type_union_tag_offset(Bar))
+	fmt.println("type of 0:", typeid_of(intrinsics.type_variant_type_of(Bar, 0)))
+	fmt.println("type of 1:", typeid_of(intrinsics.type_variant_type_of(Bar, 1)))
+	fmt.println("type of 2:", typeid_of(intrinsics.type_variant_type_of(Bar, 2)))
+	fmt.println("index of f32:", intrinsics.type_variant_index_of(Bar, i8))
+	fmt.println("index of u16:", intrinsics.type_variant_index_of(Bar, u8))
+	fmt.println("index of u8: ", intrinsics.type_variant_index_of(Bar, b8))
+	fmt.println()
+
+	Baz :: union #shared_nil {
+		[]u8, // 1
+		rawptr, // 2
+		^u8, // 3
+	}
+
+	fmt.println(typeid_of(Baz))
+	fmt.println("size_of:", size_of(Baz))
+	fmt.println("len:", len(Baz))
+	fmt.println("cap:", cap(Baz))
+	fmt.println("min:", min(Baz))
+	fmt.println("max:", max(Baz))
+	fmt.println("tag:", typeid_of(intrinsics.type_union_tag_type(Baz)))
+	fmt.println("tag offset:", intrinsics.type_union_tag_offset(Baz))
+	fmt.println("type of 0:", typeid_of(intrinsics.type_variant_type_of(Baz, 0)))
+	fmt.println("type of 1:", typeid_of(intrinsics.type_variant_type_of(Baz, 1)))
+	fmt.println("type of 2:", typeid_of(intrinsics.type_variant_type_of(Baz, 2)))
+	fmt.println("index of []u8:  ", intrinsics.type_variant_index_of(Baz, []u8))
+	fmt.println("index of rawptr:", intrinsics.type_variant_index_of(Baz, rawptr))
+	fmt.println("index of ^u8:   ", intrinsics.type_variant_index_of(Baz, ^u8))
+	fmt.println()
+
+	Mby :: Maybe(f32)
+
+	fmt.println(typeid_of(Mby))
+	fmt.println("size_of:", size_of(Mby))
+	fmt.println("len:", len(Mby))
+	fmt.println("cap:", cap(Mby))
+	fmt.println("min:", min(Mby))
+	fmt.println("max:", max(Mby))
+	fmt.println("tag:", typeid_of(intrinsics.type_union_tag_type(Mby)))
+	fmt.println("tag offset:", intrinsics.type_union_tag_offset(Mby))
+	fmt.println("type of 1:", typeid_of(intrinsics.type_variant_type_of(Mby, 0)))
+	fmt.println("index of f32:", intrinsics.type_variant_index_of(Mby, f32))
+	fmt.println()
+
+	// #unroll for i in 0 ..< intrinsics.type_proc_parameter_count(Proc) {
+	// 	fmt.println(intrinsics.type_proc_parameter_type(Proc, i))
+	// }
+
+	// arr: Packed_Union_Array(Foo)
+	// init(&arr)
+
+	// append(&arr, f32(1.23))
+	// append(&arr, f32(-1))
+	// append(&arr, f32(-2))
+	// append(&arr, f32(-3))
+	// append(&arr, u8(0))
+	// append(&arr, u8(255))
+	// append(&arr, u8(255))
+
+	// fmt.println(get_data(arr, f32))
+	// fmt.println(get_data(arr, u16))
+	// fmt.println(get_data(arr, u8))
+
+	// pool: Packed_Union_Pool(Foo)
+	// packed_union_pool_init(&pool)
+
+	// a := packed_union_pool_insert(&pool, f32(1.0))
+	// packed_union_pool_insert(&pool, f32(3.0))
+	// packed_union_pool_insert(&pool, u8(0))
+	// packed_union_pool_remove(&pool, a)
+	// packed_union_pool_insert(&pool, f32(1.234))
+
+	// // prints 1.234 since it was overwritten
+	// fmt.println(a^)
+}
+
+
+// Packed_Union_Array_Variant :: struct {
+// 	data: []u8,
+// 	len:  int,
+// }
+
+// Packed_Union_Array :: struct($T: typeid) where intrinsics.type_is_union(T) {
+// 	variants:  [len(T)]Packed_Union_Array_Variant,
+// 	allocator: runtime.Allocator,
+// }
+
+// packed_union_array_init :: proc(
+// 	a: ^$T/Packed_Union_Array($U),
+// 	cap: int = 32,
+// 	allocator := context.allocator,
+// ) {
+// 	a^ = {
+// 		allocator = allocator,
+// 	}
+
+// 	// RTTI hack since a loop cannot produce compile-time constant
+// 	ti := reflect.type_info_base(type_info_of(U)).variant.(reflect.Type_Info_Union)
+// 	for &v, i in a.variants {
+// 		data, _ := mem.alloc_bytes_non_zeroed(cap * ti.variants[i].size)
+// 		v = {
+// 			data = data,
+// 			len  = 0,
+// 		}
+// 	}
+// }
+
+// packed_union_array_append :: proc(
+// 	a: ^$T/Packed_Union_Array($U),
+// 	value: $V,
+// ) where intrinsics.type_is_variant_of(U, V) {
+// 	variants := &a.variants[intrinsics.type_variant_index_of(U, V)]
+
+// 	if variants.len >= len(variants.data) {
+// 		// alloc more
+// 	}
+
+// 	data := packed_union_array_get_data_buf(a^, V)
+// 	data[variants.len / size_of(V)] = value
+// 	variants.len += size_of(V)
+// }
+
+// packed_union_array_set :: proc(
+// 	a: $T/Packed_Union_Array($U),
+// 	index: int,
+// 	value: $V,
+// ) where intrinsics.type_is_variant_of(U, V) {
+// 	packed_union_array_get_data(a, V)[index] = value
+// }
+
+// packed_union_array_get :: proc(
+// 	a: $T/Packed_Union_Array($U),
+// 	$V: typeid,
+// 	index: int,
+// ) -> V where intrinsics.type_is_variant_of(U, V) {
+// 	return packed_union_array_get_data(a, V)[index]
+// }
+
+// packed_union_array_get_data :: proc(
+// 	a: $T/Packed_Union_Array($U),
+// 	$V: typeid,
+// ) -> []V where intrinsics.type_is_variant_of(U, V) {
+// 	vars := a.variants[intrinsics.type_variant_index_of(U, V)]
+// 	return slice.reinterpret([]V, vars.data)[:vars.len / size_of(V)]
+// }
+
+// packed_union_array_get_data_buf :: proc(
+// 	a: $T/Packed_Union_Array($U),
+// 	$V: typeid,
+// ) -> []V where intrinsics.type_is_variant_of(U, V) {
+// 	return slice.reinterpret([]V, a.variants[intrinsics.type_variant_index_of(U, V)].data)
+// }
+
+// // Basically like a pool with free list size buckets, but optimized for the specific union type.
+// Packed_Union_Pool :: struct($T: typeid) where intrinsics.type_is_union(T) {
+// 	// Should be a fast allocator like an arena.
+// 	allocator:  runtime.Allocator,
+// 	free_lists: [len(T)]rawptr,
+// }
+
+// Packed_Union_Pool_Item :: struct($T: typeid) {
+// 	data:      T,
+// 	next_free: rawptr,
+// }
+
+// packed_union_pool_init :: proc(p: ^$T/Packed_Union_Pool($U), allocator := context.allocator) {
+// 	p^ = {
+// 		allocator = allocator,
+// 	}
+// }
+
+// packed_union_pool_insert :: proc(
+// 	p: ^$T/Packed_Union_Pool($U),
+// 	val: $V,
+// ) -> (
+// 	result: ^V,
+// 	err: mem.Allocator_Error,
+// ) #optional_allocator_error {
+// 	ptr := cast(^Packed_Union_Pool_Item(V))p.free_lists[intrinsics.type_variant_index_of(U, V)]
+// 	if ptr == nil {
+// 		ptr = new(Packed_Union_Pool_Item(V), p.allocator) or_return
+// 	} else {
+// 		p.free_lists[intrinsics.type_variant_index_of(U, V)] = ptr.next_free
+// 	}
+
+// 	ptr^ = {
+// 		data      = val,
+// 		next_free = nil,
+// 	}
+
+// 	return &ptr.data, nil
+// }
+
+// packed_union_pool_remove :: proc(p: ^$T/Packed_Union_Pool($U), ptr: ^$V) {
+// 	assert(ptr != nil)
+
+// 	item := cast(^Packed_Union_Pool_Item(V))ptr
+// 	item.next_free = p.free_lists[intrinsics.type_variant_index_of(U, V)]
+// 	p.free_lists[intrinsics.type_variant_index_of(U, V)] = item
+// }