diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index 0c1b13e8f..9d4d5a205 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -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; diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 3ea121bc3..d21d6eeb5 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -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 { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index cda9debfa..a9afbf8a4 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -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;