mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-18 20:02:22 -07:00
type_info_of allows typeid; typeid_of allows ^Type_Info; Otherwise only allow type
This commit is contained in:
+18
-21
@@ -211,7 +211,7 @@ __Map_Header :: struct {
|
||||
|
||||
|
||||
|
||||
type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil do return nil;
|
||||
|
||||
base := info;
|
||||
@@ -225,7 +225,7 @@ type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
}
|
||||
|
||||
|
||||
type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
type_info_base_without_enum :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil do return nil;
|
||||
|
||||
base := info;
|
||||
@@ -239,27 +239,24 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
typeid_from_type_info :: proc(ti: ^Type_Info) -> typeid {
|
||||
id: uintptr = 0;
|
||||
if ti != nil {
|
||||
id = (uintptr(ti) - uintptr(&__type_table[0]))/size_of(Type_Info);
|
||||
}
|
||||
__typeid_of :: proc "contextless" (ti: ^Type_Info) -> typeid {
|
||||
if ti == nil do return nil;
|
||||
start := uintptr(&__type_table[0]);
|
||||
end := uintptr(ti);
|
||||
id := (end-start)/size_of(Type_Info);
|
||||
return transmute(typeid)id;
|
||||
}
|
||||
type_info_from_typeid :: proc(t: typeid) -> ^Type_Info {
|
||||
index := transmute(uintptr)t;
|
||||
return &__type_table[index];
|
||||
}
|
||||
typeid_base :: proc(id: typeid) -> typeid {
|
||||
ti := type_info_from_typeid(id);
|
||||
|
||||
|
||||
typeid_base :: proc "contextless" (id: typeid) -> typeid {
|
||||
ti := type_info_of(id);
|
||||
ti = type_info_base(ti);
|
||||
return typeid_from_type_info(ti);
|
||||
return typeid_of(ti);
|
||||
}
|
||||
typeid_base_without_enum :: proc(id: typeid) -> typeid {
|
||||
ti := type_info_from_typeid(id);
|
||||
typeid_base_without_enum :: proc "contextless" (id: typeid) -> typeid {
|
||||
ti := type_info_of(id);
|
||||
ti = type_info_base_without_enum(ti);
|
||||
return typeid_from_type_info(ti);
|
||||
return typeid_of(ti);
|
||||
}
|
||||
|
||||
|
||||
@@ -668,7 +665,7 @@ __print_caller_location :: proc(fd: os.Handle, using loc: Source_Code_Location)
|
||||
os.write_byte(fd, ')');
|
||||
}
|
||||
__print_typeid :: proc(fd: os.Handle, id: typeid) {
|
||||
ti := type_info_from_typeid(id);
|
||||
ti := type_info_of(id);
|
||||
__print_type(fd, ti);
|
||||
}
|
||||
__print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
|
||||
@@ -681,7 +678,7 @@ __print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
|
||||
case Type_Info_Named:
|
||||
os.write_string(fd, info.name);
|
||||
case Type_Info_Integer:
|
||||
a := any{typeid = typeid_from_type_info(ti)};
|
||||
a := any{typeid = typeid_of(ti)};
|
||||
switch _ in a {
|
||||
case int: os.write_string(fd, "int");
|
||||
case uint: os.write_string(fd, "uint");
|
||||
@@ -701,7 +698,7 @@ __print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
|
||||
case Type_Info_String:
|
||||
os.write_string(fd, "string");
|
||||
case Type_Info_Boolean:
|
||||
a := any{typeid = typeid_from_type_info(ti)};
|
||||
a := any{typeid = typeid_of(ti)};
|
||||
switch _ in a {
|
||||
case bool: os.write_string(fd, "bool");
|
||||
case:
|
||||
|
||||
+20
-20
@@ -151,7 +151,7 @@ fprint_type :: proc(fd: os.Handle, info: ^Type_Info) {
|
||||
}
|
||||
|
||||
write_typeid :: proc(buf: ^String_Buffer, id: typeid) {
|
||||
write_type(buf, type_info_from_typeid(id));
|
||||
write_type(buf, type_info_of(id));
|
||||
}
|
||||
|
||||
write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
||||
@@ -164,7 +164,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
||||
case Type_Info_Named:
|
||||
write_string(buf, info.name);
|
||||
case Type_Info_Integer:
|
||||
a := any{typeid = typeid_from_type_info(ti)};
|
||||
a := any{typeid = typeid_of(ti)};
|
||||
switch _ in a {
|
||||
case int: write_string(buf, "int");
|
||||
case uint: write_string(buf, "uint");
|
||||
@@ -188,7 +188,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
||||
write_string(buf, "string");
|
||||
}
|
||||
case Type_Info_Boolean:
|
||||
a := any{typeid = typeid_from_type_info(ti)};
|
||||
a := any{typeid = typeid_of(ti)};
|
||||
switch _ in a {
|
||||
case bool: write_string(buf, "bool");
|
||||
case:
|
||||
@@ -629,7 +629,7 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
|
||||
|
||||
enum_value_to_string :: proc(v: any) -> (string, bool) {
|
||||
v.typeid = typeid_base(v.typeid);
|
||||
type_info := type_info_from_typeid(v.typeid);
|
||||
type_info := type_info_of(v.typeid);
|
||||
|
||||
switch e in type_info.variant {
|
||||
case: return "", false;
|
||||
@@ -653,7 +653,7 @@ enum_value_to_string :: proc(v: any) -> (string, bool) {
|
||||
return "", false;
|
||||
}
|
||||
|
||||
a := any{v.data, typeid_from_type_info(type_info_base(e.base))};
|
||||
a := any{v.data, typeid_of(type_info_base(e.base))};
|
||||
switch v in a {
|
||||
case rune: return get_str(v, e);
|
||||
case i8: return get_str(v, e);
|
||||
@@ -696,14 +696,14 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
return;
|
||||
}
|
||||
|
||||
type_info := type_info_from_typeid(v.typeid);
|
||||
type_info := type_info_of(v.typeid);
|
||||
switch e in type_info.variant {
|
||||
case: fmt_bad_verb(fi, verb);
|
||||
case Type_Info_Enum:
|
||||
switch verb {
|
||||
case: fmt_bad_verb(fi, verb);
|
||||
case 'd', 'f':
|
||||
fmt_arg(fi, any{v.data, typeid_from_type_info(type_info_base(e.base))}, verb);
|
||||
fmt_arg(fi, any{v.data, typeid_of(type_info_base(e.base))}, verb);
|
||||
case 's', 'v':
|
||||
str, ok := enum_value_to_string(v);
|
||||
if !ok do str = "!%(BAD ENUM VALUE)";
|
||||
@@ -719,7 +719,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
return;
|
||||
}
|
||||
|
||||
type_info := type_info_from_typeid(v.typeid);
|
||||
type_info := type_info_of(v.typeid);
|
||||
switch info in type_info.variant {
|
||||
case Type_Info_Named:
|
||||
switch b in info.base.variant {
|
||||
@@ -755,7 +755,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_string(fi.buf, "any{}");
|
||||
} else {
|
||||
data := rawptr(uintptr(v.data) + b.offsets[i]);
|
||||
id := typeid_from_type_info(t);
|
||||
id := typeid_of(t);
|
||||
fmt_arg(fi, any{data, id}, 'v');
|
||||
}
|
||||
|
||||
@@ -766,7 +766,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_byte(fi.buf, '}');
|
||||
|
||||
case:
|
||||
fmt_value(fi, any{v.data, typeid_from_type_info(info.base)}, verb);
|
||||
fmt_value(fi, any{v.data, typeid_of(info.base)}, verb);
|
||||
}
|
||||
|
||||
case Type_Info_Boolean: fmt_arg(fi, v, verb);
|
||||
@@ -790,7 +790,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
if i > 0 do write_string(fi.buf, ", ");
|
||||
|
||||
data := uintptr(v.data) + uintptr(i*info.elem_size);
|
||||
fmt_arg(fi, any{rawptr(data), typeid_from_type_info(info.elem)}, verb);
|
||||
fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
|
||||
}
|
||||
|
||||
case Type_Info_Dynamic_Array:
|
||||
@@ -801,7 +801,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
if i > 0 do write_string(fi.buf, ", ");
|
||||
|
||||
data := uintptr(array.data) + uintptr(i*info.elem_size);
|
||||
fmt_arg(fi, any{rawptr(data), typeid_from_type_info(info.elem)}, verb);
|
||||
fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
|
||||
}
|
||||
|
||||
case Type_Info_Slice:
|
||||
@@ -812,7 +812,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
if i > 0 do write_string(fi.buf, ", ");
|
||||
|
||||
data := uintptr(slice.data) + uintptr(i*info.elem_size);
|
||||
fmt_arg(fi, any{rawptr(data), typeid_from_type_info(info.elem)}, verb);
|
||||
fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
|
||||
}
|
||||
|
||||
case Type_Info_Map:
|
||||
@@ -843,13 +843,13 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_string(fi.buf, header.key.str);
|
||||
} else {
|
||||
fi := Fmt_Info{buf = fi.buf};
|
||||
fmt_arg(&fi, any{rawptr(&header.key.hash), typeid_from_type_info(info.key)}, 'v');
|
||||
fmt_arg(&fi, any{rawptr(&header.key.hash), typeid_of(info.key)}, 'v');
|
||||
}
|
||||
|
||||
write_string(fi.buf, "=");
|
||||
|
||||
value := data + entry_type.offsets[2];
|
||||
fmt_arg(fi, any{rawptr(value), typeid_from_type_info(info.value)}, 'v');
|
||||
fmt_arg(fi, any{rawptr(value), typeid_of(info.value)}, 'v');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -884,7 +884,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_string(fi.buf, "any{}");
|
||||
} else {
|
||||
data := uintptr(v.data) + info.offsets[i];
|
||||
id := typeid_from_type_info(t);
|
||||
id := typeid_of(t);
|
||||
fmt_arg(fi, any{rawptr(data), id}, 'v');
|
||||
}
|
||||
if hash do write_string(fi.buf, ",\n");
|
||||
@@ -892,7 +892,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
|
||||
case Type_Info_Union:
|
||||
tag_ptr := uintptr(v.data) + info.tag_offset;
|
||||
tag_any := any{rawptr(tag_ptr), typeid_from_type_info(info.tag_type)};
|
||||
tag_any := any{rawptr(tag_ptr), typeid_of(info.tag_type)};
|
||||
|
||||
tag: i64 = -1;
|
||||
switch i in tag_any {
|
||||
@@ -910,7 +910,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
if v.data == nil || tag == 0 {
|
||||
write_string(fi.buf, "nil");
|
||||
} else {
|
||||
id := typeid_from_type_info(info.variants[tag-1]);
|
||||
id := typeid_of(info.variants[tag-1]);
|
||||
fmt_arg(fi, any{v.data, id}, verb);
|
||||
}
|
||||
|
||||
@@ -958,7 +958,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
||||
fi.arg = arg;
|
||||
|
||||
if verb == 'T' {
|
||||
ti := type_info_from_typeid(arg.typeid);
|
||||
ti := type_info_of(arg.typeid);
|
||||
switch a in arg {
|
||||
case ^Type_Info: ti = a;
|
||||
}
|
||||
@@ -1015,7 +1015,7 @@ sbprint :: proc(buf: ^String_Buffer, args: ...any) -> string {
|
||||
fi.buf = buf;
|
||||
|
||||
for arg, i in args {
|
||||
is_string := arg != nil && types.is_string(type_info_from_typeid(arg.typeid));
|
||||
is_string := arg != nil && types.is_string(type_info_of(arg.typeid));
|
||||
if i > 0 && !is_string && !prev_string {
|
||||
write_byte(buf, ' ');
|
||||
}
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ ptr_to_bytes :: proc "contextless" (ptr: ^$T, len := 1) -> []byte {
|
||||
}
|
||||
|
||||
any_to_bytes :: proc "contextless" (val: any) -> []byte {
|
||||
ti := type_info_from_typeid(val.typeid);
|
||||
ti := type_info_of(val.typeid);
|
||||
size := ti != nil ? ti.size : 0;
|
||||
return transmute([]byte)raw.Slice{val.data, size};
|
||||
}
|
||||
|
||||
@@ -3421,6 +3421,13 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
add_type_info_type(c, t);
|
||||
|
||||
if (is_operand_value(o) && is_type_typeid(t)) {
|
||||
// Okay
|
||||
} else if (o.mode != Addressing_Type) {
|
||||
error(ce->args[0], "Expected a type or typeid for 'type_info_of'");
|
||||
return false;
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = t_type_info_ptr;
|
||||
|
||||
@@ -3450,6 +3457,16 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
add_type_info_type(c, t);
|
||||
|
||||
t = base_type(t);
|
||||
if (is_operand_value(o) && are_types_identical(t, t_type_info_ptr)) {
|
||||
add_preload_dependency(c, "__typeid_of");
|
||||
} else if (o.mode != Addressing_Type) {
|
||||
gbString ts = type_to_string(o.type);
|
||||
error(ce->args[0], "Expected a type or type info for 'typeid_of', got %s", ts);
|
||||
gb_string_free(ts);
|
||||
return false;
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = t_typeid;
|
||||
break;
|
||||
|
||||
+21
-4
@@ -4209,13 +4209,30 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
}
|
||||
|
||||
case BuiltinProc_type_info_of: {
|
||||
Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
|
||||
return ir_type_info(proc, t);
|
||||
AstNode *arg = ce->args[0];
|
||||
TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
|
||||
if (tav.mode == Addressing_Type) {
|
||||
Type *t = default_type(type_of_expr(proc->module->info, arg));
|
||||
return ir_type_info(proc, t);
|
||||
}
|
||||
GB_ASSERT(is_type_typeid(tav.type));
|
||||
irValue *id = ir_emit_bitcast(proc, ir_build_expr(proc, arg), t_uintptr);
|
||||
return ir_emit_array_ep(proc, ir_global_type_info_data, id);
|
||||
}
|
||||
|
||||
case BuiltinProc_typeid_of: {
|
||||
Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
|
||||
return ir_typeid(proc, t);
|
||||
AstNode *arg = ce->args[0];
|
||||
TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg);
|
||||
if (tav.mode == Addressing_Type) {
|
||||
Type *t = default_type(type_of_expr(proc->module->info, arg));
|
||||
return ir_typeid(proc, t);
|
||||
}
|
||||
Type *t = base_type(tav.type);
|
||||
GB_ASSERT(are_types_identical(t, t_type_info_ptr));
|
||||
|
||||
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||
args[0] = ir_emit_conv(proc, ir_build_expr(proc, arg), t_type_info_ptr);
|
||||
return ir_emit_global_call(proc, "__typeid_of", args);
|
||||
}
|
||||
|
||||
case BuiltinProc_len: {
|
||||
|
||||
Reference in New Issue
Block a user