type_info_of allows typeid; typeid_of allows ^Type_Info; Otherwise only allow type

This commit is contained in:
gingerBill
2018-05-12 19:54:16 +01:00
parent 2ef22e86e0
commit 373a60b9ef
5 changed files with 77 additions and 46 deletions
+18 -21
View File
@@ -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
View File
@@ -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
View File
@@ -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};
}
+17
View File
@@ -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
View File
@@ -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: {