From 8d43cc840a530c33e2c35fece99b764c958fe06a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 29 Jan 2023 11:28:05 +0000 Subject: [PATCH] Add `@(require_results)` to `package reflect` --- core/reflect/iterator.odin | 2 ++ core/reflect/reflect.odin | 51 ++++++++++++++++++++++++++++++++++++++ core/reflect/types.odin | 36 ++++++++++++++++++++++++--- 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/core/reflect/iterator.odin b/core/reflect/iterator.odin index 9fb6489ca..2e143284a 100644 --- a/core/reflect/iterator.odin +++ b/core/reflect/iterator.odin @@ -2,6 +2,7 @@ package reflect import "core:runtime" +@(require_results) iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) { if val == nil || it == nil { return @@ -41,6 +42,7 @@ iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) { return } +@(require_results) iterate_map :: proc(val: any, it: ^int) -> (key, value: any, ok: bool) { if val == nil || it == nil { return diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index 668baa893..ae82e3f76 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -74,6 +74,7 @@ Type_Kind :: enum { } +@(require_results) type_kind :: proc(T: typeid) -> Type_Kind { ti := type_info_of(T) if ti != nil { @@ -113,11 +114,13 @@ type_kind :: proc(T: typeid) -> Type_Kind { } // TODO(bill): Better name +@(require_results) underlying_type_kind :: proc(T: typeid) -> Type_Kind { return type_kind(runtime.typeid_base(T)) } // TODO(bill): Better name +@(require_results) backing_type_kind :: proc(T: typeid) -> Type_Kind { return type_kind(runtime.typeid_core(T)) } @@ -135,6 +138,7 @@ when !ODIN_DISALLOW_RTTI { } +@(require_results) any_base :: proc(v: any) -> any { v := v if v != nil { @@ -142,6 +146,7 @@ any_base :: proc(v: any) -> any { } return v } +@(require_results) any_core :: proc(v: any) -> any { v := v if v != nil { @@ -150,6 +155,7 @@ any_core :: proc(v: any) -> any { return v } +@(require_results) typeid_elem :: proc(id: typeid) -> typeid { ti := type_info_of(id) if ti == nil { return nil } @@ -179,6 +185,7 @@ typeid_elem :: proc(id: typeid) -> typeid { } +@(require_results) size_of_typeid :: proc(T: typeid) -> int { if ti := type_info_of(T); ti != nil { return ti.size @@ -186,6 +193,7 @@ size_of_typeid :: proc(T: typeid) -> int { return 0 } +@(require_results) align_of_typeid :: proc(T: typeid) -> int { if ti := type_info_of(T); ti != nil { return ti.align @@ -193,6 +201,7 @@ align_of_typeid :: proc(T: typeid) -> int { return 1 } +@(require_results) as_bytes :: proc(v: any) -> []byte { if v != nil { sz := size_of_typeid(v.id) @@ -201,10 +210,12 @@ as_bytes :: proc(v: any) -> []byte { return nil } +@(require_results) any_data :: #force_inline proc(v: any) -> (data: rawptr, id: typeid) { return v.data, v.id } +@(require_results) is_nil :: proc(v: any) -> bool { if v == nil { return true @@ -221,6 +232,7 @@ is_nil :: proc(v: any) -> bool { return true } +@(require_results) length :: proc(val: any) -> int { if val == nil { return 0 } @@ -256,6 +268,7 @@ length :: proc(val: any) -> int { return 0 } +@(require_results) capacity :: proc(val: any) -> int { if val == nil { return 0 } @@ -282,6 +295,7 @@ capacity :: proc(val: any) -> int { } +@(require_results) index :: proc(val: any, i: int, loc := #caller_location) -> any { if val == nil { return nil } @@ -341,6 +355,7 @@ index :: proc(val: any, i: int, loc := #caller_location) -> any { return nil } +@(require_results) deref :: proc(val: any) -> any { if val != nil { ti := type_info_base(type_info_of(val.id)) @@ -370,6 +385,7 @@ Struct_Field :: struct { is_using: bool, } +@(require_results) struct_field_at :: proc(T: typeid, i: int) -> (field: Struct_Field) { ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { @@ -384,6 +400,7 @@ struct_field_at :: proc(T: typeid, i: int) -> (field: Struct_Field) { return } +@(require_results) struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) { ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { @@ -401,6 +418,7 @@ struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) { return } +@(require_results) struct_field_value_by_name :: proc(a: any, field: string, allow_using := false) -> any { if a == nil { return nil } @@ -432,6 +450,7 @@ struct_field_value_by_name :: proc(a: any, field: string, allow_using := false) +@(require_results) struct_field_names :: proc(T: typeid) -> []string { ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { @@ -440,6 +459,7 @@ struct_field_names :: proc(T: typeid) -> []string { return nil } +@(require_results) 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 { @@ -449,6 +469,7 @@ struct_field_types :: proc(T: typeid) -> []^Type_Info { } +@(require_results) struct_field_tags :: proc(T: typeid) -> []Struct_Tag { ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { @@ -457,6 +478,7 @@ struct_field_tags :: proc(T: typeid) -> []Struct_Tag { return nil } +@(require_results) struct_field_offsets :: proc(T: typeid) -> []uintptr { ti := runtime.type_info_base(type_info_of(T)) if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { @@ -465,6 +487,7 @@ struct_field_offsets :: proc(T: typeid) -> []uintptr { return nil } +@(require_results) 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 { @@ -481,11 +504,13 @@ struct_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Struct_Field) { +@(require_results) struct_tag_get :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag) { value, _ = struct_tag_lookup(tag, key) return } +@(require_results) struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag, ok: bool) { for t := tag; t != ""; /**/ { i := 0 @@ -544,6 +569,7 @@ struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: Struct_Tag, o } +@(require_results) enum_string :: proc(a: any) -> string { if a == nil { return "" } ti := runtime.type_info_base(type_info_of(a.id)) @@ -562,6 +588,7 @@ enum_string :: proc(a: any) -> string { } // Given a enum type and a value name, get the enum value. +@(require_results) 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 { @@ -578,6 +605,7 @@ enum_from_name :: proc($Enum_Type: typeid, name: string) -> (value: Enum_Type, o return } +@(require_results) 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 { @@ -594,6 +622,7 @@ enum_from_name_any :: proc(Enum_Type: typeid, name: string) -> (value: Type_Info } +@(require_results) 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 { @@ -601,6 +630,7 @@ enum_field_names :: proc(Enum_Type: typeid) -> []string { } return nil } +@(require_results) 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 { @@ -614,6 +644,7 @@ Enum_Field :: struct { value: Type_Info_Enum_Value, } +@(require_results) 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 { @@ -624,15 +655,18 @@ enum_fields_zipped :: proc(Enum_Type: typeid) -> (fields: #soa[]Enum_Field) { +@(require_results) union_variant_type_info :: proc(a: any) -> ^Type_Info { id := union_variant_typeid(a) return type_info_of(id) } +@(require_results) type_info_union_is_pure_maybe :: proc(info: runtime.Type_Info_Union) -> bool { return len(info.variants) == 1 && is_pointer(info.variants[0]) } +@(require_results) union_variant_typeid :: proc(a: any) -> typeid { if a == nil { return nil } @@ -672,6 +706,7 @@ union_variant_typeid :: proc(a: any) -> typeid { panic("expected a union to reflect.union_variant_typeid") } +@(require_results) get_union_variant_raw_tag :: proc(a: any) -> i64 { if a == nil { return -1 } @@ -702,6 +737,7 @@ get_union_variant_raw_tag :: proc(a: any) -> i64 { panic("expected a union to reflect.get_union_variant_raw_tag") } +@(require_results) get_union_variant :: proc(a: any) -> any { if a == nil { return nil @@ -713,6 +749,7 @@ get_union_variant :: proc(a: any) -> any { return any{a.data, id} } +@(require_results) 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^) @@ -813,6 +850,7 @@ set_union_variant_type_info :: proc(a: any, tag_ti: ^Type_Info) { panic("expected a union to reflect.set_union_variant_type_info") } +@(require_results) set_union_value :: proc(dst: any, value: any) -> bool { if dst == nil { return false } @@ -853,6 +891,7 @@ set_union_value :: proc(dst: any, value: any) -> bool { +@(require_results) as_bool :: proc(a: any) -> (value: bool, valid: bool) { if a == nil { return } a := a @@ -875,6 +914,7 @@ as_bool :: proc(a: any) -> (value: bool, valid: bool) { return } +@(require_results) as_int :: proc(a: any) -> (value: int, valid: bool) { v: i64 v, valid = as_i64(a) @@ -882,6 +922,7 @@ as_int :: proc(a: any) -> (value: int, valid: bool) { return } +@(require_results) as_uint :: proc(a: any) -> (value: uint, valid: bool) { v: u64 v, valid = as_u64(a) @@ -889,6 +930,7 @@ as_uint :: proc(a: any) -> (value: uint, valid: bool) { return } +@(require_results) as_i64 :: proc(a: any) -> (value: i64, valid: bool) { if a == nil { return } a := a @@ -996,6 +1038,7 @@ as_i64 :: proc(a: any) -> (value: i64, valid: bool) { return } +@(require_results) as_u64 :: proc(a: any) -> (value: u64, valid: bool) { if a == nil { return } a := a @@ -1105,6 +1148,7 @@ as_u64 :: proc(a: any) -> (value: u64, valid: bool) { } +@(require_results) as_f64 :: proc(a: any) -> (value: f64, valid: bool) { if a == nil { return } a := a @@ -1211,6 +1255,7 @@ as_f64 :: proc(a: any) -> (value: f64, valid: bool) { } +@(require_results) as_string :: proc(a: any) -> (value: string, valid: bool) { if a == nil { return } a := a @@ -1230,6 +1275,7 @@ as_string :: proc(a: any) -> (value: string, valid: bool) { return } +@(require_results) relative_pointer_to_absolute :: proc(a: any) -> rawptr { if a == nil { return nil } a := a @@ -1244,6 +1290,7 @@ relative_pointer_to_absolute :: proc(a: any) -> rawptr { } +@(require_results) relative_pointer_to_absolute_raw :: proc(data: rawptr, base_integer_id: typeid) -> rawptr { _handle :: proc(ptr: ^$T) -> rawptr where intrinsics.type_is_integer(T) { if ptr^ == 0 { @@ -1286,6 +1333,7 @@ relative_pointer_to_absolute_raw :: proc(data: rawptr, base_integer_id: typeid) +@(require_results) as_pointer :: proc(a: any) -> (value: rawptr, valid: bool) { if a == nil { return } a := a @@ -1313,6 +1361,7 @@ as_pointer :: proc(a: any) -> (value: rawptr, valid: bool) { } +@(require_results) as_raw_data :: proc(a: any) -> (value: rawptr, valid: bool) { if a == nil { return } a := a @@ -1349,9 +1398,11 @@ ne :: not_equal DEFAULT_EQUAL_MAX_RECURSION_LEVEL :: 32 +@(require_results) not_equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_level := 0) -> bool { return !equal(a, b, including_indirect_array_recursion, recursion_level) } +@(require_results) equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_level := 0) -> bool { if a == nil && b == nil { return true diff --git a/core/reflect/types.odin b/core/reflect/types.odin index f53b18e0d..1ee09af9d 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -3,17 +3,16 @@ package reflect import "core:io" import "core:strings" +@(require_results) are_types_identical :: proc(a, b: ^Type_Info) -> bool { if a == b { return true } - if (a == nil && b != nil) || - (a != nil && b == nil) { + if a == nil || b == nil { return false } - switch { case a.size != b.size, a.align != b.align: return false @@ -180,6 +179,7 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { return false } +@(require_results) is_signed :: proc(info: ^Type_Info) -> bool { if info == nil { return false } #partial switch i in type_info_base(info).variant { @@ -188,6 +188,7 @@ is_signed :: proc(info: ^Type_Info) -> bool { } return false } +@(require_results) is_unsigned :: proc(info: ^Type_Info) -> bool { if info == nil { return false } #partial switch i in type_info_base(info).variant { @@ -197,6 +198,7 @@ is_unsigned :: proc(info: ^Type_Info) -> bool { return false } +@(require_results) is_byte :: proc(info: ^Type_Info) -> bool { if info == nil { return false } #partial switch i in type_info_base(info).variant { @@ -206,66 +208,79 @@ is_byte :: proc(info: ^Type_Info) -> bool { } +@(require_results) is_integer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Integer) return ok } +@(require_results) is_rune :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Rune) return ok } +@(require_results) is_float :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Float) return ok } +@(require_results) is_complex :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Complex) return ok } +@(require_results) is_quaternion :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Quaternion) return ok } +@(require_results) is_any :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Any) return ok } +@(require_results) is_string :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_String) return ok } +@(require_results) is_cstring :: proc(info: ^Type_Info) -> bool { if info == nil { return false } v, ok := type_info_base(info).variant.(Type_Info_String) return ok && v.is_cstring } +@(require_results) is_boolean :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Boolean) return ok } +@(require_results) is_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Pointer) return ok } +@(require_results) is_multi_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Multi_Pointer) return ok } +@(require_results) is_soa_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Soa_Pointer) return ok } +@(require_results) is_pointer_internally :: proc(info: ^Type_Info) -> bool { if info == nil { return false } #partial switch v in info.variant { @@ -277,76 +292,91 @@ is_pointer_internally :: proc(info: ^Type_Info) -> bool { } return false } +@(require_results) is_procedure :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Procedure) return ok } +@(require_results) is_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Array) return ok } +@(require_results) is_enumerated_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Enumerated_Array) return ok } +@(require_results) is_dynamic_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Dynamic_Array) return ok } +@(require_results) is_dynamic_map :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Map) return ok } +@(require_results) is_bit_set :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Bit_Set) return ok } +@(require_results) is_slice :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Slice) return ok } +@(require_results) is_tuple :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Tuple) return ok } +@(require_results) is_struct :: proc(info: ^Type_Info) -> bool { if info == nil { return false } s, ok := type_info_base(info).variant.(Type_Info_Struct) return ok && !s.is_raw_union } +@(require_results) is_raw_union :: proc(info: ^Type_Info) -> bool { if info == nil { return false } s, ok := type_info_base(info).variant.(Type_Info_Struct) return ok && s.is_raw_union } +@(require_results) is_union :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Union) return ok } +@(require_results) is_enum :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Enum) return ok } +@(require_results) is_simd_vector :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Simd_Vector) return ok } +@(require_results) is_relative_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Relative_Pointer) return ok } +@(require_results) is_relative_slice :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Relative_Slice)