소스 검색

Add `@(require_results)` to `package reflect`

gingerBill 2 년 전
부모
커밋
8d43cc840a
3개의 변경된 파일86개의 추가작업 그리고 3개의 파일을 삭제
  1. 2 0
      core/reflect/iterator.odin
  2. 51 0
      core/reflect/reflect.odin
  3. 33 3
      core/reflect/types.odin

+ 2 - 0
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

+ 51 - 0
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

+ 33 - 3
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)