From a58c29582ed355a38f0029b3000aa725c85abb3f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 13 Aug 2019 23:21:33 +0100 Subject: [PATCH] Add new stuff to package reflect; fix -vet for odin_parser --- core/odin/parser/parser.odin | 2 +- core/reflect/reflect.odin | 309 ++++++++++++----------------------- 2 files changed, 104 insertions(+), 207 deletions(-) diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 2d8e42720..a9961fafd 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -1741,7 +1741,7 @@ string_to_calling_convention :: proc(s: string) -> ast.Proc_Calling_Convention { parse_proc_tags :: proc(p: ^Parser) -> (tags: ast.Proc_Tags) { for p.curr_tok.kind == token.Hash { - tok := expect_token(p, token.Hash); + _ = expect_token(p, token.Hash); ident := expect_token(p, token.Ident); switch ident.text { diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index 2e917710b..a4450490f 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -2,7 +2,6 @@ package reflect import "core:runtime" import "core:mem" -import "core:strings" Type_Kind :: enum { @@ -116,6 +115,31 @@ is_nil :: proc(v: any) -> bool { return true; } +length :: proc(val: any) -> int { + if val == nil do return 0; + + v := val; + v.id = runtime.typeid_base(v.id); + switch a in v { + case runtime.Type_Info_Array: + return a.count; + + case runtime.Type_Info_Slice: + return (^mem.Raw_Slice)(v.data).len; + + case runtime.Type_Info_Dynamic_Array: + return (^mem.Raw_Dynamic_Array)(v.data).len; + + case runtime.Type_Info_String: + if a.is_cstring { + return len((^cstring)(v.data)^); + } else { + return (^mem.Raw_String)(v.data).len; + } + } + return 0; +} + index :: proc(val: any, i: int, loc := #caller_location) -> any { if val == nil do return nil; @@ -196,6 +220,35 @@ 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 { + if a == nil do return nil; + + ti := runtime.type_info_base(type_info_of(a.id)); + + if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + for name, i in s.names { + if name == field { + return any{ + rawptr(uintptr(a.data) + s.offsets[i]), + s.types[i].id, + }; + } + + if recurse && 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 { + return res; + } + } + } + } + return nil; +} + struct_field_names :: proc(T: typeid) -> []string { @@ -286,212 +339,56 @@ struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: string, ok: b } -write_typeid :: proc(buf: ^strings.Builder, id: typeid) { - write_type(buf, type_info_of(id)); -} - -write_type :: proc(buf: ^strings.Builder, ti: ^runtime.Type_Info) { - using strings; - if ti == nil { - write_string(buf, "nil"); - return; +enum_string :: proc(a: any) -> string { + if a == nil do return ""; + ti := runtime.type_info_base(type_info_of(a.id)); + if e, ok := ti.variant.(runtime.Type_Info_Enum); ok { + for _, i in e.values { + value := &e.values[i]; + n := mem.compare_byte_ptrs((^byte)(a.data), (^byte)(value), ti.size); + if n == 0 { + return e.names[i]; + } + } + } else { + panic("expected an enum to reflect.enum_string"); } - switch info in ti.variant { - case runtime.Type_Info_Named: - write_string(buf, info.name); - case runtime.Type_Info_Integer: - switch ti.id { - case int: write_string(buf, "int"); - case uint: write_string(buf, "uint"); - case uintptr: write_string(buf, "uintptr"); - case: - write_byte(buf, info.signed ? 'i' : 'u'); - write_i64(buf, i64(8*ti.size), 10); - switch info.endianness { - case runtime.Type_Info_Endianness.Little: - write_string(buf, "le"); - case runtime.Type_Info_Endianness.Big: - write_string(buf, "be"); - } - } - case runtime.Type_Info_Rune: - write_string(buf, "rune"); - case runtime.Type_Info_Float: - write_byte(buf, 'f'); - write_i64(buf, i64(8*ti.size), 10); - case runtime.Type_Info_Complex: - write_string(buf, "complex"); - write_i64(buf, i64(8*ti.size), 10); - case runtime.Type_Info_String: - if info.is_cstring { - write_string(buf, "cstring"); - } else { - write_string(buf, "string"); - } - case runtime.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 runtime.Type_Info_Any: - write_string(buf, "any"); - - case runtime.Type_Info_Type_Id: - write_string(buf, "typeid"); - - case runtime.Type_Info_Pointer: - if info.elem == nil { - write_string(buf, "rawptr"); - } else { - write_string(buf, "^"); - write_type(buf, info.elem); - } - case runtime.Type_Info_Procedure: - write_string(buf, "proc"); - if info.params == nil { - write_string(buf, "()"); - } else { - t := info.params.variant.(runtime.Type_Info_Tuple); - write_string(buf, "("); - for t, i in t.types { - if i > 0 do write_string(buf, ", "); - write_type(buf, t); - } - write_string(buf, ")"); - } - if info.results != nil { - write_string(buf, " -> "); - write_type(buf, info.results); - } - case runtime.Type_Info_Tuple: - count := len(info.names); - if count != 1 do write_string(buf, "("); - for name, i in info.names { - if i > 0 do write_string(buf, ", "); - - t := info.types[i]; - - if len(name) > 0 { - write_string(buf, name); - write_string(buf, ": "); - } - write_type(buf, t); - } - if count != 1 do write_string(buf, ")"); - - case runtime.Type_Info_Array: - write_string(buf, "["); - write_i64(buf, i64(info.count), 10); - write_string(buf, "]"); - write_type(buf, info.elem); - case runtime.Type_Info_Dynamic_Array: - write_string(buf, "[dynamic]"); - write_type(buf, info.elem); - case runtime.Type_Info_Slice: - write_string(buf, "[]"); - write_type(buf, info.elem); - - case runtime.Type_Info_Map: - write_string(buf, "map["); - write_type(buf, info.key); - write_byte(buf, ']'); - write_type(buf, info.value); - - case runtime.Type_Info_Struct: - write_string(buf, "struct "); - if info.is_packed do write_string(buf, "#packed "); - if info.is_raw_union do write_string(buf, "#raw_union "); - if info.custom_align { - write_string(buf, "#align "); - write_i64(buf, i64(ti.align), 10); - write_byte(buf, ' '); - } - write_byte(buf, '{'); - for name, i in info.names { - if i > 0 do write_string(buf, ", "); - write_string(buf, name); - write_string(buf, ": "); - write_type(buf, info.types[i]); - } - write_byte(buf, '}'); - - case runtime.Type_Info_Union: - write_string(buf, "union "); - if info.custom_align { - write_string(buf, "#align "); - write_i64(buf, i64(ti.align), 10); - write_byte(buf, ' '); - } - write_byte(buf, '{'); - for variant, i in info.variants { - if i > 0 do write_string(buf, ", "); - write_type(buf, variant); - } - write_byte(buf, '}'); - - case runtime.Type_Info_Enum: - write_string(buf, "enum "); - write_type(buf, info.base); - write_string(buf, " {"); - for name, i in info.names { - if i > 0 do write_string(buf, ", "); - write_string(buf, name); - } - write_byte(buf, '}'); - - case runtime.Type_Info_Bit_Field: - write_string(buf, "bit_field "); - if ti.align != 1 { - write_string(buf, "#align "); - write_i64(buf, i64(ti.align), 10); - write_byte(buf, ' '); - } - write_string(buf, " {"); - for name, i in info.names { - if i > 0 do write_string(buf, ", "); - write_string(buf, name); - write_string(buf, ": "); - write_i64(buf, i64(info.bits[i]), 10); - } - write_byte(buf, '}'); - - case runtime.Type_Info_Bit_Set: - write_string(buf, "bit_set["); - switch { - case is_enum(info.elem): - write_type(buf, info.elem); - case is_rune(info.elem): - write_encoded_rune(buf, rune(info.lower)); - write_string(buf, ".."); - write_encoded_rune(buf, rune(info.upper)); - case: - write_i64(buf, info.lower, 10); - write_string(buf, ".."); - write_i64(buf, info.upper, 10); - } - if info.underlying != nil { - write_string(buf, "; "); - write_type(buf, info.underlying); - } - write_byte(buf, ']'); - - case runtime.Type_Info_Opaque: - write_string(buf, "opaque "); - write_type(buf, info.elem); - - case runtime.Type_Info_Simd_Vector: - if info.is_x86_mmx { - write_string(buf, "intrinsics.x86_mmx"); - } else { - write_string(buf, "intrinsics.vector("); - write_i64(buf, i64(info.count)); - write_string(buf, ", "); - write_type(buf, info.elem); - write_byte(buf, ')'); - } - } + return ""; } +union_variant_type_info :: proc(a: any) -> ^runtime.Type_Info { + id := union_variant_typeid(a); + return type_info_of(id); +} + +union_variant_typeid :: proc(a: any) -> typeid { + if a == nil do return nil; + + ti := runtime.type_info_base(type_info_of(a.id)); + if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + tag_ptr := uintptr(a.data) + info.tag_offset; + tag_any := any{rawptr(tag_ptr), info.tag_type.id}; + + tag: i64 = ---; + switch i in tag_any { + case u8: tag = i64(i); + case i8: tag = i64(i); + case u16: tag = i64(i); + case i16: tag = i64(i); + case u32: tag = i64(i); + case i32: tag = i64(i); + case u64: tag = i64(i); + case i64: tag = i64(i); + case: unimplemented(); + } + + if a.data != nil && tag != 0 { + return info.variants[tag-1].id; + } + } else { + panic("expected a union to reflect.union_variant_typeid"); + } + + return nil; +}