diff options
| author | gingerBill <bill@gingerbill.org> | 2021-06-14 11:04:51 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-06-14 11:04:51 +0100 |
| commit | 3ca887a60ae1e681fd441edfe17805df97b6d6a3 (patch) | |
| tree | a28948ebf1122a814ec8a23a26eeacd4f5ca07e3 | |
| parent | 312a1e8a9402420947a4c8175e7a0a4142845d94 (diff) | |
Add `struct_fields_zipped` and `enum_fields_zipped` (allowing for iteration through an #soa slice)
| -rw-r--r-- | core/reflect/reflect.odin | 84 |
1 files changed, 63 insertions, 21 deletions
diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index 3a63d88a3..7226117c3 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -33,6 +33,8 @@ Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector; Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer; Type_Info_Relative_Slice :: runtime.Type_Info_Relative_Slice; +Type_Info_Enum_Value :: runtime.Type_Info_Enum_Value; + Type_Kind :: enum { Invalid, @@ -111,7 +113,7 @@ backing_type_kind :: proc(T: typeid) -> Type_Kind { } -type_info_base :: proc(info: ^runtime.Type_Info) -> ^runtime.Type_Info { +type_info_base :: proc(info: ^Type_Info) -> ^Type_Info { if info == nil { return nil; } base := info; @@ -125,7 +127,7 @@ type_info_base :: proc(info: ^runtime.Type_Info) -> ^runtime.Type_Info { } -type_info_core :: proc(info: ^runtime.Type_Info) -> ^runtime.Type_Info { +type_info_core :: proc(info: ^Type_Info) -> ^Type_Info { if info == nil { return nil; } base := info; @@ -344,7 +346,7 @@ Struct_Tag :: distinct string; Struct_Field :: struct { name: string, - type: typeid, + type: ^Type_Info, tag: Struct_Tag, offset: uintptr, is_using: bool, @@ -355,7 +357,7 @@ struct_field_at :: proc(T: typeid, i: int) -> (field: Struct_Field) { if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { if 0 <= i && i < len(s.names) { field.name = s.names[i]; - field.type = s.types[i].id; + field.type = s.types[i]; field.tag = Struct_Tag(s.tags[i]); field.offset = s.offsets[i]; field.is_using = s.usings[i]; @@ -370,7 +372,7 @@ struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) { for fname, i in s.names { if fname == name { field.name = s.names[i]; - field.type = s.types[i].id; + field.type = s.types[i]; field.tag = Struct_Tag(s.tags[i]); field.offset = s.offsets[i]; field.is_using = s.usings[i]; @@ -381,7 +383,7 @@ struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) { return; } -struct_field_value_by_name :: proc(a: any, field: string, recurse := false) -> any { +struct_field_value_by_name :: proc(a: any, field: string, allow_using := false) -> any { if a == nil { return nil; } ti := runtime.type_info_base(type_info_of(a.id)); @@ -395,13 +397,13 @@ struct_field_value_by_name :: proc(a: any, field: string, recurse := false) -> a }; } - if recurse && s.usings[i] { + if allow_using && s.usings[i] { f := any{ rawptr(uintptr(a.data) + s.offsets[i]), s.types[i].id, }; - if res := struct_field_value_by_name(f, field, recurse); res != nil { + if res := struct_field_value_by_name(f, field, allow_using); res != nil { return res; } } @@ -420,7 +422,7 @@ struct_field_names :: proc(T: typeid) -> []string { return nil; } -struct_field_types :: proc(T: typeid) -> []^runtime.Type_Info { +struct_field_types :: proc(T: typeid) -> []^Type_Info { ti := runtime.type_info_base(type_info_of(T)); if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { return s.types; @@ -445,6 +447,20 @@ struct_field_offsets :: proc(T: typeid) -> []uintptr { return nil; } +struct_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Struct_Field) { + ti := runtime.type_info_base(type_info_of(T)); + if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + return soa_zip( + name = s.names, + type = s.types, + tag = transmute([]Struct_Tag)s.tags, + offset = s.offsets, + is_using = s.usings, + ); + } + return nil; +} + struct_tag_get :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag) { @@ -468,7 +484,7 @@ struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag, o switch t[i] { case ':', '"': break loop; - case 0x00 ..< ' ', 0x7f .. 0x9f: // break if control character is found + case 0x00 ..< ' ', 0x7f ..= 0x9f: // break if control character is found break loop; } i += 1; @@ -516,7 +532,7 @@ enum_string :: proc(a: any) -> string { if e, ok := ti.variant.(runtime.Type_Info_Enum); ok { v, _ := as_i64(a); for value, i in e.values { - if value == runtime.Type_Info_Enum_Value(v) { + if value == Type_Info_Enum_Value(v) { return e.names[i]; } } @@ -528,26 +544,24 @@ enum_string :: proc(a: any) -> string { } // Given a enum type and a value name, get the enum value. -enum_from_name :: proc($EnumType: typeid, name: string) -> (value: EnumType, ok: bool) { - ti := type_info_base(type_info_of(EnumType)); +enum_from_name :: proc($Enum_Type: typeid, name: string) -> (value: Enum_Type, ok: bool) { + ti := type_info_base(type_info_of(Enum_Type)); if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { for value_name, i in eti.names { if value_name != name { continue; } v := eti.values[i]; - value = EnumType(v); + value = Enum_Type(v); ok = true; return; } - } else { - panic("expected enum type to reflect.enum_from_name"); } return; } -enum_from_name_any :: proc(EnumType: typeid, name: string) -> (value: runtime.Type_Info_Enum_Value, ok: bool) { - ti := runtime.type_info_base(type_info_of(EnumType)); +enum_from_name_any :: proc(Enum_Type: typeid, name: string) -> (value: Type_Info_Enum_Value, ok: bool) { + ti := runtime.type_info_base(type_info_of(Enum_Type)); if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { for value_name, i in eti.names { if value_name != name { @@ -557,14 +571,42 @@ enum_from_name_any :: proc(EnumType: typeid, name: string) -> (value: runtime.Ty ok = true; return; } - } else { - panic("expected enum type to reflect.enum_from_name_any"); } return; } -union_variant_type_info :: proc(a: any) -> ^runtime.Type_Info { +enum_field_names :: proc(Enum_Type: typeid) -> []string { + ti := runtime.type_info_base(type_info_of(Enum_Type)); + if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { + return eti.names; + } + return nil; +} +enum_field_values :: proc(Enum_Type: typeid) -> []Type_Info_Enum_Value { + ti := runtime.type_info_base(type_info_of(Enum_Type)); + if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { + return eti.values; + } + return nil; +} + +Enum_Field :: struct { + name: string, + value: Type_Info_Enum_Value, +} + +enum_fields_zipped :: proc(Enum_Type: typeid) -> (fields: #soa[]Enum_Field) { + ti := runtime.type_info_base(type_info_of(Enum_Type)); + if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { + return soa_zip(name=eti.names, value=eti.values); + } + return nil; +} + + + +union_variant_type_info :: proc(a: any) -> ^Type_Info { id := union_variant_typeid(a); return type_info_of(id); } |