Add new stuff to package reflect; fix -vet for odin_parser

This commit is contained in:
gingerBill
2019-08-13 23:21:33 +01:00
parent 3ad20a2d2d
commit a58c29582e
2 changed files with 104 additions and 207 deletions

View File

@@ -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 {

View File

@@ -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;
}