mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-06 18:54:12 +00:00
Add more helpers to package reflect
This commit is contained in:
@@ -3,6 +3,34 @@ package reflect
|
||||
import "core:runtime"
|
||||
import "core:mem"
|
||||
|
||||
Type_Info :: runtime.Type_Info;
|
||||
|
||||
Type_Info_Named :: runtime.Type_Info_Named;
|
||||
Type_Info_Integer :: runtime.Type_Info_Integer;
|
||||
Type_Info_Rune :: runtime.Type_Info_Rune;
|
||||
Type_Info_Float :: runtime.Type_Info_Float;
|
||||
Type_Info_Complex :: runtime.Type_Info_Complex;
|
||||
Type_Info_Quaternion :: runtime.Type_Info_Quaternion;
|
||||
Type_Info_String :: runtime.Type_Info_String;
|
||||
Type_Info_Boolean :: runtime.Type_Info_Boolean;
|
||||
Type_Info_Any :: runtime.Type_Info_Any;
|
||||
Type_Info_Type_Id :: runtime.Type_Info_Type_Id;
|
||||
Type_Info_Pointer :: runtime.Type_Info_Pointer;
|
||||
Type_Info_Procedure :: runtime.Type_Info_Procedure;
|
||||
Type_Info_Array :: runtime.Type_Info_Array;
|
||||
Type_Info_Enumerated_Array :: runtime.Type_Info_Enumerated_Array;
|
||||
Type_Info_Dynamic_Array :: runtime.Type_Info_Dynamic_Array;
|
||||
Type_Info_Slice :: runtime.Type_Info_Slice;
|
||||
Type_Info_Tuple :: runtime.Type_Info_Tuple;
|
||||
Type_Info_Struct :: runtime.Type_Info_Struct;
|
||||
Type_Info_Union :: runtime.Type_Info_Union;
|
||||
Type_Info_Enum :: runtime.Type_Info_Enum;
|
||||
Type_Info_Map :: runtime.Type_Info_Map;
|
||||
Type_Info_Bit_Field :: runtime.Type_Info_Bit_Field;
|
||||
Type_Info_Bit_Set :: runtime.Type_Info_Bit_Set;
|
||||
Type_Info_Opaque :: runtime.Type_Info_Opaque;
|
||||
Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector;
|
||||
|
||||
|
||||
Type_Kind :: enum {
|
||||
Invalid,
|
||||
@@ -39,31 +67,31 @@ type_kind :: proc(T: typeid) -> Type_Kind {
|
||||
ti := type_info_of(T);
|
||||
if ti != nil {
|
||||
switch _ in ti.variant {
|
||||
case runtime.Type_Info_Named: return .Named;
|
||||
case runtime.Type_Info_Integer: return .Integer;
|
||||
case runtime.Type_Info_Rune: return .Rune;
|
||||
case runtime.Type_Info_Float: return .Float;
|
||||
case runtime.Type_Info_Complex: return .Complex;
|
||||
case runtime.Type_Info_Quaternion: return .Quaternion;
|
||||
case runtime.Type_Info_String: return .String;
|
||||
case runtime.Type_Info_Boolean: return .Boolean;
|
||||
case runtime.Type_Info_Any: return .Any;
|
||||
case runtime.Type_Info_Type_Id: return .Type_Id;
|
||||
case runtime.Type_Info_Pointer: return .Pointer;
|
||||
case runtime.Type_Info_Procedure: return .Procedure;
|
||||
case runtime.Type_Info_Array: return .Array;
|
||||
case runtime.Type_Info_Enumerated_Array: return .Enumerated_Array;
|
||||
case runtime.Type_Info_Dynamic_Array: return .Dynamic_Array;
|
||||
case runtime.Type_Info_Slice: return .Slice;
|
||||
case runtime.Type_Info_Tuple: return .Tuple;
|
||||
case runtime.Type_Info_Struct: return .Struct;
|
||||
case runtime.Type_Info_Union: return .Union;
|
||||
case runtime.Type_Info_Enum: return .Enum;
|
||||
case runtime.Type_Info_Map: return .Map;
|
||||
case runtime.Type_Info_Bit_Field: return .Bit_Field;
|
||||
case runtime.Type_Info_Bit_Set: return .Bit_Set;
|
||||
case runtime.Type_Info_Opaque: return .Opaque;
|
||||
case runtime.Type_Info_Simd_Vector: return .Simd_Vector;
|
||||
case Type_Info_Named: return .Named;
|
||||
case Type_Info_Integer: return .Integer;
|
||||
case Type_Info_Rune: return .Rune;
|
||||
case Type_Info_Float: return .Float;
|
||||
case Type_Info_Complex: return .Complex;
|
||||
case Type_Info_Quaternion: return .Quaternion;
|
||||
case Type_Info_String: return .String;
|
||||
case Type_Info_Boolean: return .Boolean;
|
||||
case Type_Info_Any: return .Any;
|
||||
case Type_Info_Type_Id: return .Type_Id;
|
||||
case Type_Info_Pointer: return .Pointer;
|
||||
case Type_Info_Procedure: return .Procedure;
|
||||
case Type_Info_Array: return .Array;
|
||||
case Type_Info_Enumerated_Array: return .Enumerated_Array;
|
||||
case Type_Info_Dynamic_Array: return .Dynamic_Array;
|
||||
case Type_Info_Slice: return .Slice;
|
||||
case Type_Info_Tuple: return .Tuple;
|
||||
case Type_Info_Struct: return .Struct;
|
||||
case Type_Info_Union: return .Union;
|
||||
case Type_Info_Enum: return .Enum;
|
||||
case Type_Info_Map: return .Map;
|
||||
case Type_Info_Bit_Field: return .Bit_Field;
|
||||
case Type_Info_Bit_Set: return .Bit_Set;
|
||||
case Type_Info_Opaque: return .Opaque;
|
||||
case Type_Info_Simd_Vector: return .Simd_Vector;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -81,6 +109,75 @@ backing_type_kind :: proc(T: typeid) -> Type_Kind {
|
||||
}
|
||||
|
||||
|
||||
type_info_base :: proc(info: ^runtime.Type_Info) -> ^runtime.Type_Info {
|
||||
if info == nil do return nil;
|
||||
|
||||
base := info;
|
||||
loop: for {
|
||||
#partial switch i in base.variant {
|
||||
case Type_Info_Named: base = i.base;
|
||||
case: break loop;
|
||||
}
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
type_info_core :: proc(info: ^runtime.Type_Info) -> ^runtime.Type_Info {
|
||||
if info == nil do return nil;
|
||||
|
||||
base := info;
|
||||
loop: for {
|
||||
#partial switch i in base.variant {
|
||||
case Type_Info_Named: base = i.base;
|
||||
case Type_Info_Enum: base = i.base;
|
||||
case Type_Info_Opaque: base = i.elem;
|
||||
case: break loop;
|
||||
}
|
||||
}
|
||||
return base;
|
||||
}
|
||||
type_info_base_without_enum :: type_info_core;
|
||||
|
||||
|
||||
typeid_base :: proc(id: typeid) -> typeid {
|
||||
ti := type_info_of(id);
|
||||
ti = type_info_base(ti);
|
||||
return ti.id;
|
||||
}
|
||||
typeid_core :: proc(id: typeid) -> typeid {
|
||||
ti := type_info_base_without_enum(type_info_of(id));
|
||||
return ti.id;
|
||||
}
|
||||
typeid_base_without_enum :: typeid_core;
|
||||
|
||||
typeid_elem :: proc(id: typeid) -> typeid {
|
||||
ti := type_info_of(id);
|
||||
if ti == nil do return nil;
|
||||
|
||||
bits := 8*ti.size;
|
||||
|
||||
#partial switch v in ti.variant {
|
||||
case Type_Info_Complex:
|
||||
switch bits {
|
||||
case 64: return f32;
|
||||
case 128: return f64;
|
||||
}
|
||||
case Type_Info_Quaternion:
|
||||
switch bits {
|
||||
case 128: return f32;
|
||||
case 256: return f64;
|
||||
}
|
||||
case Type_Info_Pointer: return v.elem.id;
|
||||
case Type_Info_Opaque: return v.elem.id;
|
||||
case Type_Info_Array: return v.elem.id;
|
||||
case Type_Info_Enumerated_Array: return v.elem.id;
|
||||
case Type_Info_Slice: return v.elem.id;
|
||||
case Type_Info_Dynamic_Array: return v.elem.id;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
size_of_typeid :: proc(T: typeid) -> int {
|
||||
if ti := type_info_of(T); ti != nil {
|
||||
@@ -109,6 +206,9 @@ any_data :: inline proc(v: any) -> (data: rawptr, id: typeid) {
|
||||
}
|
||||
|
||||
is_nil :: proc(v: any) -> bool {
|
||||
if v == nil {
|
||||
return true;
|
||||
}
|
||||
data := to_bytes(v);
|
||||
if data != nil {
|
||||
return true;
|
||||
@@ -125,16 +225,22 @@ length :: proc(val: any) -> int {
|
||||
v := val;
|
||||
v.id = runtime.typeid_base(v.id);
|
||||
switch a in v {
|
||||
case runtime.Type_Info_Array:
|
||||
case Type_Info_Array:
|
||||
return a.count;
|
||||
|
||||
case runtime.Type_Info_Slice:
|
||||
case Type_Info_Enumerated_Array:
|
||||
return a.count;
|
||||
|
||||
case Type_Info_Slice:
|
||||
return (^mem.Raw_Slice)(v.data).len;
|
||||
|
||||
case runtime.Type_Info_Dynamic_Array:
|
||||
case Type_Info_Dynamic_Array:
|
||||
return (^mem.Raw_Dynamic_Array)(v.data).len;
|
||||
|
||||
case runtime.Type_Info_String:
|
||||
case Type_Info_Map:
|
||||
return (^mem.Raw_Map)(v.data).entries.len;
|
||||
|
||||
case Type_Info_String:
|
||||
if a.is_cstring {
|
||||
return len((^cstring)(v.data)^);
|
||||
} else {
|
||||
@@ -144,6 +250,27 @@ length :: proc(val: any) -> int {
|
||||
return 0;
|
||||
}
|
||||
|
||||
capacity :: proc(val: any) -> int {
|
||||
if val == nil do return 0;
|
||||
|
||||
v := val;
|
||||
v.id = runtime.typeid_base(v.id);
|
||||
switch a in v {
|
||||
case Type_Info_Array:
|
||||
return a.count;
|
||||
|
||||
case Type_Info_Enumerated_Array:
|
||||
return a.count;
|
||||
|
||||
case Type_Info_Dynamic_Array:
|
||||
return (^mem.Raw_Dynamic_Array)(v.data).cap;
|
||||
|
||||
case Type_Info_Map:
|
||||
return (^mem.Raw_Map)(v.data).entries.cap;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
index :: proc(val: any, i: int, loc := #caller_location) -> any {
|
||||
if val == nil do return nil;
|
||||
@@ -151,27 +278,33 @@ index :: proc(val: any, i: int, loc := #caller_location) -> any {
|
||||
v := val;
|
||||
v.id = runtime.typeid_base(v.id);
|
||||
switch a in v {
|
||||
case runtime.Type_Info_Array:
|
||||
case Type_Info_Array:
|
||||
runtime.bounds_check_error_loc(loc, i, a.count);
|
||||
offset := uintptr(a.elem.size * i);
|
||||
data := rawptr(uintptr(v.data) + offset);
|
||||
return any{data, a.elem.id};
|
||||
|
||||
case runtime.Type_Info_Slice:
|
||||
case Type_Info_Enumerated_Array:
|
||||
runtime.bounds_check_error_loc(loc, i, a.count);
|
||||
offset := uintptr(a.elem.size * i);
|
||||
data := rawptr(uintptr(v.data) + offset);
|
||||
return any{data, a.elem.id};
|
||||
|
||||
case Type_Info_Slice:
|
||||
raw := (^mem.Raw_Slice)(v.data);
|
||||
runtime.bounds_check_error_loc(loc, i, raw.len);
|
||||
offset := uintptr(a.elem.size * i);
|
||||
data := rawptr(uintptr(raw.data) + offset);
|
||||
return any{data, a.elem.id};
|
||||
|
||||
case runtime.Type_Info_Dynamic_Array:
|
||||
case Type_Info_Dynamic_Array:
|
||||
raw := (^mem.Raw_Dynamic_Array)(v.data);
|
||||
runtime.bounds_check_error_loc(loc, i, raw.len);
|
||||
offset := uintptr(a.elem.size * i);
|
||||
data := rawptr(uintptr(raw.data) + offset);
|
||||
return any{data, a.elem.id};
|
||||
|
||||
case runtime.Type_Info_String:
|
||||
case Type_Info_String:
|
||||
if a.is_cstring do return nil;
|
||||
|
||||
raw := (^mem.Raw_String)(v.data);
|
||||
@@ -290,12 +423,12 @@ struct_field_offsets :: proc(T: typeid) -> []uintptr {
|
||||
|
||||
|
||||
|
||||
struct_tag_get :: proc(tag: Struct_Tag, key: string) -> (value: string) {
|
||||
struct_tag_get :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag) {
|
||||
value, _ = struct_tag_lookup(tag, key);
|
||||
return;
|
||||
}
|
||||
|
||||
struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: string, ok: bool) {
|
||||
struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag, ok: bool) {
|
||||
for t := tag; t != ""; /**/ {
|
||||
i := 0;
|
||||
for i < len(t) && t[i] == ' ' { // Skip whitespace
|
||||
@@ -336,7 +469,7 @@ struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: string, ok: b
|
||||
t = t[i+1:];
|
||||
|
||||
if key == name {
|
||||
return val[1:i], true;
|
||||
return Struct_Tag(val[1:i]), true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package reflect
|
||||
|
||||
import rt "core:runtime"
|
||||
import "core:strings"
|
||||
|
||||
are_types_identical :: proc(a, b: ^rt.Type_Info) -> bool {
|
||||
are_types_identical :: proc(a, b: ^Type_Info) -> bool {
|
||||
if a == b do return true;
|
||||
|
||||
if (a == nil && b != nil) ||
|
||||
@@ -18,55 +17,55 @@ are_types_identical :: proc(a, b: ^rt.Type_Info) -> bool {
|
||||
}
|
||||
|
||||
switch x in a.variant {
|
||||
case rt.Type_Info_Named:
|
||||
y, ok := b.variant.(rt.Type_Info_Named);
|
||||
case Type_Info_Named:
|
||||
y, ok := b.variant.(Type_Info_Named);
|
||||
if !ok do return false;
|
||||
return x.base == y.base;
|
||||
|
||||
case rt.Type_Info_Integer:
|
||||
y, ok := b.variant.(rt.Type_Info_Integer);
|
||||
case Type_Info_Integer:
|
||||
y, ok := b.variant.(Type_Info_Integer);
|
||||
if !ok do return false;
|
||||
return x.signed == y.signed;
|
||||
return x.signed == y.signed && x.endianness == y.endianness;
|
||||
|
||||
case rt.Type_Info_Rune:
|
||||
_, ok := b.variant.(rt.Type_Info_Rune);
|
||||
case Type_Info_Rune:
|
||||
_, ok := b.variant.(Type_Info_Rune);
|
||||
return ok;
|
||||
|
||||
case rt.Type_Info_Float:
|
||||
_, ok := b.variant.(rt.Type_Info_Float);
|
||||
case Type_Info_Float:
|
||||
_, ok := b.variant.(Type_Info_Float);
|
||||
return ok;
|
||||
|
||||
case rt.Type_Info_Complex:
|
||||
_, ok := b.variant.(rt.Type_Info_Complex);
|
||||
case Type_Info_Complex:
|
||||
_, ok := b.variant.(Type_Info_Complex);
|
||||
return ok;
|
||||
|
||||
case rt.Type_Info_Quaternion:
|
||||
_, ok := b.variant.(rt.Type_Info_Quaternion);
|
||||
case Type_Info_Quaternion:
|
||||
_, ok := b.variant.(Type_Info_Quaternion);
|
||||
return ok;
|
||||
|
||||
case rt.Type_Info_Type_Id:
|
||||
_, ok := b.variant.(rt.Type_Info_Type_Id);
|
||||
case Type_Info_Type_Id:
|
||||
_, ok := b.variant.(Type_Info_Type_Id);
|
||||
return ok;
|
||||
|
||||
case rt.Type_Info_String:
|
||||
_, ok := b.variant.(rt.Type_Info_String);
|
||||
case Type_Info_String:
|
||||
_, ok := b.variant.(Type_Info_String);
|
||||
return ok;
|
||||
|
||||
case rt.Type_Info_Boolean:
|
||||
_, ok := b.variant.(rt.Type_Info_Boolean);
|
||||
case Type_Info_Boolean:
|
||||
_, ok := b.variant.(Type_Info_Boolean);
|
||||
return ok;
|
||||
|
||||
case rt.Type_Info_Any:
|
||||
_, ok := b.variant.(rt.Type_Info_Any);
|
||||
case Type_Info_Any:
|
||||
_, ok := b.variant.(Type_Info_Any);
|
||||
return ok;
|
||||
|
||||
case rt.Type_Info_Pointer:
|
||||
y, ok := b.variant.(rt.Type_Info_Pointer);
|
||||
case Type_Info_Pointer:
|
||||
y, ok := b.variant.(Type_Info_Pointer);
|
||||
if !ok do return false;
|
||||
return are_types_identical(x.elem, y.elem);
|
||||
|
||||
case rt.Type_Info_Procedure:
|
||||
y, ok := b.variant.(rt.Type_Info_Procedure);
|
||||
case Type_Info_Procedure:
|
||||
y, ok := b.variant.(Type_Info_Procedure);
|
||||
if !ok do return false;
|
||||
switch {
|
||||
case x.variadic != y.variadic,
|
||||
@@ -76,31 +75,31 @@ are_types_identical :: proc(a, b: ^rt.Type_Info) -> bool {
|
||||
|
||||
return are_types_identical(x.params, y.params) && are_types_identical(x.results, y.results);
|
||||
|
||||
case rt.Type_Info_Array:
|
||||
y, ok := b.variant.(rt.Type_Info_Array);
|
||||
case Type_Info_Array:
|
||||
y, ok := b.variant.(Type_Info_Array);
|
||||
if !ok do return false;
|
||||
if x.count != y.count do return false;
|
||||
return are_types_identical(x.elem, y.elem);
|
||||
|
||||
case rt.Type_Info_Enumerated_Array:
|
||||
y, ok := b.variant.(rt.Type_Info_Enumerated_Array);
|
||||
case Type_Info_Enumerated_Array:
|
||||
y, ok := b.variant.(Type_Info_Enumerated_Array);
|
||||
if !ok do return false;
|
||||
if x.count != y.count do return false;
|
||||
return are_types_identical(x.index, y.index) &&
|
||||
are_types_identical(x.elem, y.elem);
|
||||
|
||||
case rt.Type_Info_Dynamic_Array:
|
||||
y, ok := b.variant.(rt.Type_Info_Dynamic_Array);
|
||||
case Type_Info_Dynamic_Array:
|
||||
y, ok := b.variant.(Type_Info_Dynamic_Array);
|
||||
if !ok do return false;
|
||||
return are_types_identical(x.elem, y.elem);
|
||||
|
||||
case rt.Type_Info_Slice:
|
||||
y, ok := b.variant.(rt.Type_Info_Slice);
|
||||
case Type_Info_Slice:
|
||||
y, ok := b.variant.(Type_Info_Slice);
|
||||
if !ok do return false;
|
||||
return are_types_identical(x.elem, y.elem);
|
||||
|
||||
case rt.Type_Info_Tuple:
|
||||
y, ok := b.variant.(rt.Type_Info_Tuple);
|
||||
case Type_Info_Tuple:
|
||||
y, ok := b.variant.(Type_Info_Tuple);
|
||||
if !ok do return false;
|
||||
if len(x.types) != len(y.types) do return false;
|
||||
for _, i in x.types {
|
||||
@@ -111,14 +110,17 @@ are_types_identical :: proc(a, b: ^rt.Type_Info) -> bool {
|
||||
}
|
||||
return true;
|
||||
|
||||
case rt.Type_Info_Struct:
|
||||
y, ok := b.variant.(rt.Type_Info_Struct);
|
||||
case Type_Info_Struct:
|
||||
y, ok := b.variant.(Type_Info_Struct);
|
||||
if !ok do return false;
|
||||
switch {
|
||||
case len(x.types) != len(y.types),
|
||||
x.is_packed != y.is_packed,
|
||||
x.is_raw_union != y.is_raw_union,
|
||||
x.custom_align != y.custom_align:
|
||||
case len(x.types) != len(y.types),
|
||||
x.is_packed != y.is_packed,
|
||||
x.is_raw_union != y.is_raw_union,
|
||||
x.custom_align != y.custom_align,
|
||||
x.soa_kind != y.soa_kind,
|
||||
x.soa_base_type != y.soa_base_type,
|
||||
x.soa_len != y.soa_len:
|
||||
return false;
|
||||
}
|
||||
for _, i in x.types {
|
||||
@@ -132,8 +134,8 @@ are_types_identical :: proc(a, b: ^rt.Type_Info) -> bool {
|
||||
}
|
||||
return true;
|
||||
|
||||
case rt.Type_Info_Union:
|
||||
y, ok := b.variant.(rt.Type_Info_Union);
|
||||
case Type_Info_Union:
|
||||
y, ok := b.variant.(Type_Info_Union);
|
||||
if !ok do return false;
|
||||
if len(x.variants) != len(y.variants) do return false;
|
||||
|
||||
@@ -143,17 +145,17 @@ are_types_identical :: proc(a, b: ^rt.Type_Info) -> bool {
|
||||
}
|
||||
return true;
|
||||
|
||||
case rt.Type_Info_Enum:
|
||||
case Type_Info_Enum:
|
||||
// NOTE(bill): Should be handled above
|
||||
return false;
|
||||
|
||||
case rt.Type_Info_Map:
|
||||
y, ok := b.variant.(rt.Type_Info_Map);
|
||||
case Type_Info_Map:
|
||||
y, ok := b.variant.(Type_Info_Map);
|
||||
if !ok do return false;
|
||||
return are_types_identical(x.key, y.key) && are_types_identical(x.value, y.value);
|
||||
|
||||
case rt.Type_Info_Bit_Field:
|
||||
y, ok := b.variant.(rt.Type_Info_Bit_Field);
|
||||
case Type_Info_Bit_Field:
|
||||
y, ok := b.variant.(Type_Info_Bit_Field);
|
||||
if !ok do return false;
|
||||
if len(x.names) != len(y.names) do return false;
|
||||
|
||||
@@ -168,18 +170,18 @@ are_types_identical :: proc(a, b: ^rt.Type_Info) -> bool {
|
||||
}
|
||||
return true;
|
||||
|
||||
case rt.Type_Info_Bit_Set:
|
||||
y, ok := b.variant.(rt.Type_Info_Bit_Set);
|
||||
case Type_Info_Bit_Set:
|
||||
y, ok := b.variant.(Type_Info_Bit_Set);
|
||||
if !ok do return false;
|
||||
return x.elem == y.elem && x.lower == y.lower && x.upper == y.upper;
|
||||
|
||||
case rt.Type_Info_Opaque:
|
||||
y, ok := b.variant.(rt.Type_Info_Opaque);
|
||||
case Type_Info_Opaque:
|
||||
y, ok := b.variant.(Type_Info_Opaque);
|
||||
if !ok do return false;
|
||||
return x.elem == y.elem;
|
||||
|
||||
case rt.Type_Info_Simd_Vector:
|
||||
y, ok := b.variant.(rt.Type_Info_Simd_Vector);
|
||||
case Type_Info_Simd_Vector:
|
||||
y, ok := b.variant.(Type_Info_Simd_Vector);
|
||||
if !ok do return false;
|
||||
return x.count == y.count && x.elem == y.elem;
|
||||
}
|
||||
@@ -187,112 +189,137 @@ are_types_identical :: proc(a, b: ^rt.Type_Info) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
is_signed :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_signed :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
#partial switch i in rt.type_info_base(info).variant {
|
||||
case rt.Type_Info_Integer: return i.signed;
|
||||
case rt.Type_Info_Float: return true;
|
||||
#partial switch i in type_info_base(info).variant {
|
||||
case Type_Info_Integer: return i.signed;
|
||||
case Type_Info_Float: return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
is_integer :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_unsigned :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Integer);
|
||||
#partial switch i in type_info_base(info).variant {
|
||||
case Type_Info_Integer: return !i.signed;
|
||||
case Type_Info_Float: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
is_integer :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Integer);
|
||||
return ok;
|
||||
}
|
||||
is_rune :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_rune :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Rune);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Rune);
|
||||
return ok;
|
||||
}
|
||||
is_float :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_float :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Float);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Float);
|
||||
return ok;
|
||||
}
|
||||
is_complex :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_complex :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Complex);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Complex);
|
||||
return ok;
|
||||
}
|
||||
is_any :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_quaternion :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Any);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Quaternion);
|
||||
return ok;
|
||||
}
|
||||
is_string :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_any :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_String);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Any);
|
||||
return ok;
|
||||
}
|
||||
is_boolean :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_string :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Boolean);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_String);
|
||||
return ok;
|
||||
}
|
||||
is_pointer :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_cstring :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Pointer);
|
||||
v, ok := type_info_base(info).variant.(Type_Info_String);
|
||||
return ok && v.is_cstring;
|
||||
}
|
||||
is_boolean :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Boolean);
|
||||
return ok;
|
||||
}
|
||||
is_procedure :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_pointer :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Procedure);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Pointer);
|
||||
return ok;
|
||||
}
|
||||
is_array :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_procedure :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Array);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Procedure);
|
||||
return ok;
|
||||
}
|
||||
is_dynamic_array :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_array :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Dynamic_Array);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Array);
|
||||
return ok;
|
||||
}
|
||||
is_dynamic_map :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_enumerated_array :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Map);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Enumerated_Array);
|
||||
return ok;
|
||||
}
|
||||
is_slice :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_dynamic_array :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Slice);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Dynamic_Array);
|
||||
return ok;
|
||||
}
|
||||
is_tuple :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_dynamic_map :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Tuple);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Map);
|
||||
return ok;
|
||||
}
|
||||
is_struct :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_slice :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
s, ok := rt.type_info_base(info).variant.(rt.Type_Info_Struct);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Slice);
|
||||
return ok;
|
||||
}
|
||||
is_tuple :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Tuple);
|
||||
return ok;
|
||||
}
|
||||
is_struct :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
s, ok := type_info_base(info).variant.(Type_Info_Struct);
|
||||
return ok && !s.is_raw_union;
|
||||
}
|
||||
is_raw_union :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_raw_union :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
s, ok := rt.type_info_base(info).variant.(rt.Type_Info_Struct);
|
||||
s, ok := type_info_base(info).variant.(Type_Info_Struct);
|
||||
return ok && s.is_raw_union;
|
||||
}
|
||||
is_union :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_union :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Union);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Union);
|
||||
return ok;
|
||||
}
|
||||
is_enum :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_enum :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Enum);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Enum);
|
||||
return ok;
|
||||
}
|
||||
is_opaque :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_opaque :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Opaque);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Opaque);
|
||||
return ok;
|
||||
}
|
||||
is_simd_vector :: proc(info: ^rt.Type_Info) -> bool {
|
||||
is_simd_vector :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Simd_Vector);
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Simd_Vector);
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -301,11 +328,13 @@ is_simd_vector :: proc(info: ^rt.Type_Info) -> bool {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
write_typeid :: proc(buf: ^strings.Builder, id: typeid) {
|
||||
write_type(buf, type_info_of(id));
|
||||
}
|
||||
|
||||
write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
||||
write_type :: proc(buf: ^strings.Builder, ti: ^Type_Info) {
|
||||
using strings;
|
||||
if ti == nil {
|
||||
write_string(buf, "nil");
|
||||
@@ -313,9 +342,9 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
||||
}
|
||||
|
||||
switch info in ti.variant {
|
||||
case rt.Type_Info_Named:
|
||||
case Type_Info_Named:
|
||||
write_string(buf, info.name);
|
||||
case rt.Type_Info_Integer:
|
||||
case Type_Info_Integer:
|
||||
switch ti.id {
|
||||
case int: write_string(buf, "int");
|
||||
case uint: write_string(buf, "uint");
|
||||
@@ -329,49 +358,49 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
||||
case .Big: write_string(buf, "be");
|
||||
}
|
||||
}
|
||||
case rt.Type_Info_Rune:
|
||||
case Type_Info_Rune:
|
||||
write_string(buf, "rune");
|
||||
case rt.Type_Info_Float:
|
||||
case Type_Info_Float:
|
||||
write_byte(buf, 'f');
|
||||
write_i64(buf, i64(8*ti.size), 10);
|
||||
case rt.Type_Info_Complex:
|
||||
case Type_Info_Complex:
|
||||
write_string(buf, "complex");
|
||||
write_i64(buf, i64(8*ti.size), 10);
|
||||
case rt.Type_Info_Quaternion:
|
||||
case Type_Info_Quaternion:
|
||||
write_string(buf, "quaternion");
|
||||
write_i64(buf, i64(8*ti.size), 10);
|
||||
case rt.Type_Info_String:
|
||||
case Type_Info_String:
|
||||
if info.is_cstring {
|
||||
write_string(buf, "cstring");
|
||||
} else {
|
||||
write_string(buf, "string");
|
||||
}
|
||||
case rt.Type_Info_Boolean:
|
||||
case Type_Info_Boolean:
|
||||
switch ti.id {
|
||||
case bool: write_string(buf, "bool");
|
||||
case:
|
||||
write_byte(buf, 'b');
|
||||
write_i64(buf, i64(8*ti.size), 10);
|
||||
}
|
||||
case rt.Type_Info_Any:
|
||||
case Type_Info_Any:
|
||||
write_string(buf, "any");
|
||||
|
||||
case rt.Type_Info_Type_Id:
|
||||
case Type_Info_Type_Id:
|
||||
write_string(buf, "typeid");
|
||||
|
||||
case rt.Type_Info_Pointer:
|
||||
case Type_Info_Pointer:
|
||||
if info.elem == nil {
|
||||
write_string(buf, "rawptr");
|
||||
} else {
|
||||
write_string(buf, "^");
|
||||
write_type(buf, info.elem);
|
||||
}
|
||||
case rt.Type_Info_Procedure:
|
||||
case Type_Info_Procedure:
|
||||
write_string(buf, "proc");
|
||||
if info.params == nil {
|
||||
write_string(buf, "()");
|
||||
} else {
|
||||
t := info.params.variant.(rt.Type_Info_Tuple);
|
||||
t := info.params.variant.(Type_Info_Tuple);
|
||||
write_string(buf, "(");
|
||||
for t, i in t.types {
|
||||
if i > 0 do write_string(buf, ", ");
|
||||
@@ -383,7 +412,7 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
||||
write_string(buf, " -> ");
|
||||
write_type(buf, info.results);
|
||||
}
|
||||
case rt.Type_Info_Tuple:
|
||||
case Type_Info_Tuple:
|
||||
count := len(info.names);
|
||||
if count != 1 do write_string(buf, "(");
|
||||
for name, i in info.names {
|
||||
@@ -399,32 +428,32 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
||||
}
|
||||
if count != 1 do write_string(buf, ")");
|
||||
|
||||
case rt.Type_Info_Array:
|
||||
case Type_Info_Array:
|
||||
write_string(buf, "[");
|
||||
write_i64(buf, i64(info.count), 10);
|
||||
write_string(buf, "]");
|
||||
write_type(buf, info.elem);
|
||||
|
||||
case rt.Type_Info_Enumerated_Array:
|
||||
case Type_Info_Enumerated_Array:
|
||||
write_string(buf, "[");
|
||||
write_type(buf, info.index);
|
||||
write_string(buf, "]");
|
||||
write_type(buf, info.elem);
|
||||
|
||||
case rt.Type_Info_Dynamic_Array:
|
||||
case Type_Info_Dynamic_Array:
|
||||
write_string(buf, "[dynamic]");
|
||||
write_type(buf, info.elem);
|
||||
case rt.Type_Info_Slice:
|
||||
case Type_Info_Slice:
|
||||
write_string(buf, "[]");
|
||||
write_type(buf, info.elem);
|
||||
|
||||
case rt.Type_Info_Map:
|
||||
case Type_Info_Map:
|
||||
write_string(buf, "map[");
|
||||
write_type(buf, info.key);
|
||||
write_byte(buf, ']');
|
||||
write_type(buf, info.value);
|
||||
|
||||
case rt.Type_Info_Struct:
|
||||
case Type_Info_Struct:
|
||||
switch info.soa_kind {
|
||||
case .None: // Ignore
|
||||
case .Fixed:
|
||||
@@ -460,7 +489,7 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
||||
}
|
||||
write_byte(buf, '}');
|
||||
|
||||
case rt.Type_Info_Union:
|
||||
case Type_Info_Union:
|
||||
write_string(buf, "union ");
|
||||
if info.custom_align {
|
||||
write_string(buf, "#align ");
|
||||
@@ -474,7 +503,7 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
||||
}
|
||||
write_byte(buf, '}');
|
||||
|
||||
case rt.Type_Info_Enum:
|
||||
case Type_Info_Enum:
|
||||
write_string(buf, "enum ");
|
||||
write_type(buf, info.base);
|
||||
write_string(buf, " {");
|
||||
@@ -484,7 +513,7 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
||||
}
|
||||
write_byte(buf, '}');
|
||||
|
||||
case rt.Type_Info_Bit_Field:
|
||||
case Type_Info_Bit_Field:
|
||||
write_string(buf, "bit_field ");
|
||||
if ti.align != 1 {
|
||||
write_string(buf, "#align ");
|
||||
@@ -500,7 +529,7 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
||||
}
|
||||
write_byte(buf, '}');
|
||||
|
||||
case rt.Type_Info_Bit_Set:
|
||||
case Type_Info_Bit_Set:
|
||||
write_string(buf, "bit_set[");
|
||||
switch {
|
||||
case is_enum(info.elem):
|
||||
@@ -520,11 +549,11 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
||||
}
|
||||
write_byte(buf, ']');
|
||||
|
||||
case rt.Type_Info_Opaque:
|
||||
case Type_Info_Opaque:
|
||||
write_string(buf, "opaque ");
|
||||
write_type(buf, info.elem);
|
||||
|
||||
case rt.Type_Info_Simd_Vector:
|
||||
case Type_Info_Simd_Vector:
|
||||
if info.is_x86_mmx {
|
||||
write_string(buf, "intrinsics.x86_mmx");
|
||||
} else {
|
||||
|
||||
@@ -5446,13 +5446,16 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
switch (bt->Basic.kind) {
|
||||
case Basic_complex64: operand->type = t_f32; break;
|
||||
case Basic_complex128: operand->type = t_f64; break;
|
||||
case Basic_quaternion128: operand->type = t_f32; break;
|
||||
case Basic_quaternion256: operand->type = t_f64; break;
|
||||
}
|
||||
break;
|
||||
case Type_Pointer: operand->type = bt->Pointer.elem; break;
|
||||
case Type_Opaque: operand->type = bt->Opaque.elem; break;
|
||||
case Type_Array: operand->type = bt->Array.elem; break;
|
||||
case Type_Slice: operand->type = bt->Slice.elem; break;
|
||||
case Type_DynamicArray: operand->type = bt->DynamicArray.elem; break;
|
||||
case Type_Pointer: operand->type = bt->Pointer.elem; break;
|
||||
case Type_Opaque: operand->type = bt->Opaque.elem; break;
|
||||
case Type_Array: operand->type = bt->Array.elem; break;
|
||||
case Type_EnumeratedArray: operand->type = bt->EnumeratedArray.elem; break;
|
||||
case Type_Slice: operand->type = bt->Slice.elem; break;
|
||||
case Type_DynamicArray: operand->type = bt->DynamicArray.elem; break;
|
||||
}
|
||||
}
|
||||
operand->mode = Addressing_Type;
|
||||
|
||||
Reference in New Issue
Block a user