mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
any type
This commit is contained in:
+39
-4
@@ -4,7 +4,7 @@
|
||||
|
||||
print_type_info_kind :: proc(info: ^Type_Info) {
|
||||
using Type_Info
|
||||
match type i : info {
|
||||
match type info -> i {
|
||||
case Named: print_string("Named\n")
|
||||
case Integer: print_string("Integer\n")
|
||||
case Float: print_string("Float\n")
|
||||
@@ -23,6 +23,37 @@ print_type_info_kind :: proc(info: ^Type_Info) {
|
||||
}
|
||||
}
|
||||
|
||||
println :: proc(args: ..any) {
|
||||
for i := 0; i < len(args); i++ {
|
||||
arg := args[i]
|
||||
|
||||
if i > 0 {
|
||||
print_string(" ")
|
||||
}
|
||||
|
||||
using Type_Info
|
||||
match type arg.type_info -> i {
|
||||
case Named: print_string("Named")
|
||||
case Integer: print_string("Integer")
|
||||
case Float: print_string("Float")
|
||||
case String: print_string("String")
|
||||
case Boolean: print_string("Boolean")
|
||||
case Pointer: print_string("Pointer")
|
||||
case Procedure: print_string("Procedure")
|
||||
case Array: print_string("Array")
|
||||
case Slice: print_string("Slice")
|
||||
case Vector: print_string("Vector")
|
||||
case Struct: print_string("Struct")
|
||||
case Union: print_string("Union")
|
||||
case Raw_Union: print_string("RawUnion")
|
||||
case Enum: print_string("Enum")
|
||||
default: print_string("void")
|
||||
}
|
||||
}
|
||||
|
||||
print_nl()
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
i: int
|
||||
s: struct {
|
||||
@@ -30,7 +61,11 @@ main :: proc() {
|
||||
}
|
||||
p := ^s
|
||||
|
||||
print_type_info_kind(type_info(i))
|
||||
print_type_info_kind(type_info(s))
|
||||
print_type_info_kind(type_info(p))
|
||||
a: any = i
|
||||
|
||||
println(137, "Hello", 1.23)
|
||||
|
||||
// print_type_info_kind(a.type_info)
|
||||
// print_type_info_kind(type_info(s))
|
||||
// print_type_info_kind(type_info(p))
|
||||
}
|
||||
|
||||
+2
-10
@@ -18,11 +18,11 @@ Type_Info :: union {
|
||||
base: ^Type_Info
|
||||
}
|
||||
Integer: struct {
|
||||
bits: int
|
||||
size: int // in bytes
|
||||
signed: bool
|
||||
}
|
||||
Float: struct {
|
||||
bits: int
|
||||
size: int // in bytes
|
||||
}
|
||||
String: struct {}
|
||||
Boolean: struct {}
|
||||
@@ -49,14 +49,6 @@ Type_Info :: union {
|
||||
}
|
||||
}
|
||||
|
||||
Any :: struct {
|
||||
type_info: ^Type_Info
|
||||
// pointer to the data stored
|
||||
data: rawptr
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
assume :: proc(cond: bool) #foreign "llvm.assume"
|
||||
|
||||
|
||||
+28
-16
@@ -389,23 +389,7 @@ void add_global_constant(gbAllocator a, String name, Type *type, ExactValue valu
|
||||
}
|
||||
|
||||
|
||||
Type *t_type_info = NULL;
|
||||
Type *t_type_info_ptr = NULL;
|
||||
|
||||
Type *t_type_info_named = NULL;
|
||||
Type *t_type_info_integer = NULL;
|
||||
Type *t_type_info_float = NULL;
|
||||
Type *t_type_info_string = NULL;
|
||||
Type *t_type_info_boolean = NULL;
|
||||
Type *t_type_info_pointer = NULL;
|
||||
Type *t_type_info_procedure = NULL;
|
||||
Type *t_type_info_array = NULL;
|
||||
Type *t_type_info_slice = NULL;
|
||||
Type *t_type_info_vector = NULL;
|
||||
Type *t_type_info_struct = NULL;
|
||||
Type *t_type_info_union = NULL;
|
||||
Type *t_type_info_raw_union = NULL;
|
||||
Type *t_type_info_enum = NULL;
|
||||
|
||||
|
||||
void init_universal_scope(void) {
|
||||
@@ -857,6 +841,7 @@ void check_parsed_files(Checker *c) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto check_global_entity = [](Checker *c, EntityKind kind) {
|
||||
gb_for_array(i, c->info.entities.entries) {
|
||||
auto *entry = &c->info.entities.entries[i];
|
||||
@@ -869,6 +854,33 @@ void check_parsed_files(Checker *c) {
|
||||
};
|
||||
|
||||
check_global_entity(c, Entity_TypeName);
|
||||
|
||||
if (t_type_info == NULL) {
|
||||
String type_info_str = make_string("Type_Info");
|
||||
Entity **found = map_get(&c->global_scope->elements, hash_string(type_info_str));
|
||||
GB_ASSERT_MSG(found != NULL, "Internal Compiler Error: Could not find type declaration for `Type_Info`");
|
||||
Entity *e = *found;
|
||||
t_type_info = e->type;
|
||||
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
||||
|
||||
auto *record = &get_base_type(e->type)->Record;
|
||||
GB_ASSERT(record->field_count == 15);
|
||||
t_type_info_named = record->fields[ 1]->type;
|
||||
t_type_info_integer = record->fields[ 2]->type;
|
||||
t_type_info_float = record->fields[ 3]->type;
|
||||
t_type_info_string = record->fields[ 4]->type;
|
||||
t_type_info_boolean = record->fields[ 5]->type;
|
||||
t_type_info_pointer = record->fields[ 6]->type;
|
||||
t_type_info_procedure = record->fields[ 7]->type;
|
||||
t_type_info_array = record->fields[ 8]->type;
|
||||
t_type_info_slice = record->fields[ 9]->type;
|
||||
t_type_info_vector = record->fields[10]->type;
|
||||
t_type_info_struct = record->fields[11]->type;
|
||||
t_type_info_union = record->fields[12]->type;
|
||||
t_type_info_raw_union = record->fields[13]->type;
|
||||
t_type_info_enum = record->fields[14]->type;
|
||||
}
|
||||
|
||||
check_global_entity(c, Entity_Constant);
|
||||
check_global_entity(c, Entity_Procedure);
|
||||
check_global_entity(c, Entity_Variable);
|
||||
|
||||
+49
-64
@@ -45,6 +45,44 @@ b32 check_is_assignable_to_using_subtype(Type *dst, Type *src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void add_type_info_type(Checker *c, Type *t) {
|
||||
if (t == NULL) {
|
||||
return;
|
||||
}
|
||||
t = default_type(t);
|
||||
if (map_get(&c->info.type_info_types, hash_pointer(t)) != NULL) {
|
||||
// Types have already been added
|
||||
return;
|
||||
}
|
||||
|
||||
map_set(&c->info.type_info_types, hash_pointer(t), t);
|
||||
Type *bt = get_base_type(t);
|
||||
switch (bt->kind) {
|
||||
case Type_Named: add_type_info_type(c, bt->Named.base); break;
|
||||
case Type_Array: add_type_info_type(c, bt->Array.elem); break;
|
||||
case Type_Slice: add_type_info_type(c, bt->Slice.elem); break;
|
||||
case Type_Vector: add_type_info_type(c, bt->Vector.elem); break;
|
||||
case Type_Pointer: add_type_info_type(c, bt->Pointer.elem); break;
|
||||
case Type_Record: {
|
||||
switch (bt->Record.kind) {
|
||||
case TypeRecord_Enum:
|
||||
add_type_info_type(c, bt->Record.enum_base);
|
||||
break;
|
||||
default:
|
||||
for (isize i = 0; i < bt->Record.field_count; i++) {
|
||||
Entity *f = bt->Record.fields[i];
|
||||
add_type_info_type(c, f->type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
// TODO(bill): Type info for procedures and tuples
|
||||
// TODO(bill): Remove duplicate identical types efficiently
|
||||
}
|
||||
|
||||
|
||||
b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argument = false) {
|
||||
if (operand->mode == Addressing_Invalid ||
|
||||
type == t_invalid) {
|
||||
@@ -110,6 +148,13 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (dst == t_any) {
|
||||
// NOTE(bill): Anything can cast to `Any`
|
||||
add_type_info_type(c, s);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_argument) {
|
||||
// NOTE(bill): Polymorphism for subtyping
|
||||
if (check_is_assignable_to_using_subtype(type, src)) {
|
||||
@@ -133,11 +178,13 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
|
||||
if (is_type_untyped(operand->type)) {
|
||||
Type *target_type = type;
|
||||
|
||||
if (type == NULL)
|
||||
if (type == NULL || is_type_any(type)) {
|
||||
target_type = default_type(operand->type);
|
||||
}
|
||||
convert_to_typed(c, operand, target_type);
|
||||
if (operand->mode == Addressing_Invalid)
|
||||
if (operand->mode == Addressing_Invalid) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1900,42 +1947,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_type_info_type(Checker *c, Type *t) {
|
||||
if (t == NULL) {
|
||||
return;
|
||||
}
|
||||
t = default_type(t);
|
||||
if (map_get(&c->info.type_info_types, hash_pointer(t)) != NULL) {
|
||||
// Types have already been added
|
||||
return;
|
||||
}
|
||||
|
||||
map_set(&c->info.type_info_types, hash_pointer(t), t);
|
||||
Type *bt = get_base_type(t);
|
||||
switch (bt->kind) {
|
||||
case Type_Named: add_type_info_type(c, bt->Named.base); break;
|
||||
case Type_Array: add_type_info_type(c, bt->Array.elem); break;
|
||||
case Type_Slice: add_type_info_type(c, bt->Slice.elem); break;
|
||||
case Type_Vector: add_type_info_type(c, bt->Vector.elem); break;
|
||||
case Type_Pointer: add_type_info_type(c, bt->Pointer.elem); break;
|
||||
case Type_Record: {
|
||||
switch (bt->Record.kind) {
|
||||
case TypeRecord_Enum:
|
||||
add_type_info_type(c, bt->Record.enum_base);
|
||||
break;
|
||||
default:
|
||||
for (isize i = 0; i < bt->Record.field_count; i++) {
|
||||
Entity *f = bt->Record.fields[i];
|
||||
add_type_info_type(c, f->type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
// TODO(bill): Type info for procedures and tuples
|
||||
// TODO(bill): Remove duplicate identical types efficiently
|
||||
}
|
||||
|
||||
b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) {
|
||||
GB_ASSERT(call->kind == AstNode_CallExpr);
|
||||
ast_node(ce, CallExpr, call);
|
||||
@@ -2690,32 +2701,6 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
|
||||
|
||||
case BuiltinProc_type_info: {
|
||||
if (t_type_info == NULL) {
|
||||
String type_info_str = make_string("Type_Info");
|
||||
Entity **found = map_get(&c->global_scope->elements, hash_string(type_info_str));
|
||||
GB_ASSERT_MSG(found != NULL, "Internal Compiler Error: Could not find type declaration for `Type_Info`");
|
||||
Entity *e = *found;
|
||||
t_type_info = e->type;
|
||||
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
||||
|
||||
auto *record = &get_base_type(e->type)->Record;
|
||||
GB_ASSERT(record->field_count == 15);
|
||||
t_type_info_named = record->fields[ 1]->type;
|
||||
t_type_info_integer = record->fields[ 2]->type;
|
||||
t_type_info_float = record->fields[ 3]->type;
|
||||
t_type_info_string = record->fields[ 4]->type;
|
||||
t_type_info_boolean = record->fields[ 5]->type;
|
||||
t_type_info_pointer = record->fields[ 6]->type;
|
||||
t_type_info_procedure = record->fields[ 7]->type;
|
||||
t_type_info_array = record->fields[ 8]->type;
|
||||
t_type_info_slice = record->fields[ 9]->type;
|
||||
t_type_info_vector = record->fields[10]->type;
|
||||
t_type_info_struct = record->fields[11]->type;
|
||||
t_type_info_union = record->fields[12]->type;
|
||||
t_type_info_raw_union = record->fields[13]->type;
|
||||
t_type_info_enum = record->fields[14]->type;
|
||||
}
|
||||
|
||||
add_type_info_type(c, operand->type);
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = t_type_info_ptr;
|
||||
|
||||
+62
-1
@@ -19,6 +19,9 @@ enum BasicKind {
|
||||
Basic_uint,
|
||||
Basic_rawptr,
|
||||
Basic_string,
|
||||
|
||||
Basic_any,
|
||||
|
||||
Basic_UntypedBool,
|
||||
Basic_UntypedInteger,
|
||||
Basic_UntypedFloat,
|
||||
@@ -26,6 +29,7 @@ enum BasicKind {
|
||||
Basic_UntypedString,
|
||||
Basic_UntypedRune,
|
||||
|
||||
|
||||
Basic_Count,
|
||||
|
||||
Basic_byte = Basic_u8,
|
||||
@@ -306,6 +310,7 @@ gb_global Type basic_types[] = {
|
||||
{0, Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}},
|
||||
{0, Type_Basic, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}},
|
||||
{0, Type_Basic, {Basic_string, BasicFlag_String, STR_LIT("string")}},
|
||||
{0, Type_Basic, {Basic_any, 0, STR_LIT("any")}},
|
||||
{0, Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}},
|
||||
{0, Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}},
|
||||
{0, Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}},
|
||||
@@ -337,6 +342,7 @@ gb_global Type *t_int = &basic_types[Basic_int];
|
||||
gb_global Type *t_uint = &basic_types[Basic_uint];
|
||||
gb_global Type *t_rawptr = &basic_types[Basic_rawptr];
|
||||
gb_global Type *t_string = &basic_types[Basic_string];
|
||||
gb_global Type *t_any = &basic_types[Basic_any];
|
||||
gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
|
||||
gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
|
||||
gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
|
||||
@@ -346,6 +352,25 @@ gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
|
||||
gb_global Type *t_byte = &basic_type_aliases[Basic_byte];
|
||||
gb_global Type *t_rune = &basic_type_aliases[Basic_rune];
|
||||
|
||||
gb_global Type *t_type_info = NULL;
|
||||
gb_global Type *t_type_info_ptr = NULL;
|
||||
|
||||
gb_global Type *t_type_info_named = NULL;
|
||||
gb_global Type *t_type_info_integer = NULL;
|
||||
gb_global Type *t_type_info_float = NULL;
|
||||
gb_global Type *t_type_info_string = NULL;
|
||||
gb_global Type *t_type_info_boolean = NULL;
|
||||
gb_global Type *t_type_info_pointer = NULL;
|
||||
gb_global Type *t_type_info_procedure = NULL;
|
||||
gb_global Type *t_type_info_array = NULL;
|
||||
gb_global Type *t_type_info_slice = NULL;
|
||||
gb_global Type *t_type_info_vector = NULL;
|
||||
gb_global Type *t_type_info_struct = NULL;
|
||||
gb_global Type *t_type_info_union = NULL;
|
||||
gb_global Type *t_type_info_raw_union = NULL;
|
||||
gb_global Type *t_type_info_enum = NULL;
|
||||
|
||||
|
||||
|
||||
b32 is_type_named(Type *t) {
|
||||
if (t->kind == Type_Basic)
|
||||
@@ -488,6 +513,11 @@ Type *get_enum_base_type(Type *t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
b32 is_type_any(Type *t) {
|
||||
t = get_base_type(t);
|
||||
return (t->kind == Type_Basic && t->Basic.kind == Basic_any);
|
||||
}
|
||||
|
||||
|
||||
|
||||
b32 is_type_comparable(Type *t) {
|
||||
@@ -675,6 +705,9 @@ void selection_add_index(Selection *s, isize index) {
|
||||
gb_array_append(s->index, index);
|
||||
}
|
||||
|
||||
gb_global Entity *entity_any_type_info = NULL;
|
||||
gb_global Entity *entity_any_data = NULL;
|
||||
|
||||
Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection sel = empty_selection) {
|
||||
GB_ASSERT(type_ != NULL);
|
||||
|
||||
@@ -686,11 +719,39 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se
|
||||
b32 is_ptr = type != type_;
|
||||
type = get_base_type(type);
|
||||
|
||||
if (type->kind == Type_Basic) {
|
||||
if (type->Basic.kind == Basic_any) {
|
||||
String type_info_str = make_string("type_info");
|
||||
String data_str = make_string("data_str");
|
||||
if (entity_any_type_info == NULL) {
|
||||
Token token = {Token_Identifier};
|
||||
token.string = type_info_str;
|
||||
entity_any_type_info = make_entity_field(gb_heap_allocator(), NULL, token, t_type_info_ptr, false);
|
||||
}
|
||||
if (entity_any_data == NULL) {
|
||||
Token token = {Token_Identifier};
|
||||
token.string = data_str;
|
||||
entity_any_data = make_entity_field(gb_heap_allocator(), NULL, token, t_type_info_ptr, false);
|
||||
}
|
||||
|
||||
if (are_strings_equal(field_name, type_info_str)) {
|
||||
selection_add_index(&sel, 0);
|
||||
sel.entity = entity_any_type_info;
|
||||
return sel;
|
||||
} else if (are_strings_equal(field_name, data_str)) {
|
||||
selection_add_index(&sel, 1);
|
||||
sel.entity = entity_any_data;
|
||||
return sel;
|
||||
}
|
||||
}
|
||||
|
||||
return sel;
|
||||
}
|
||||
|
||||
if (type->kind != Type_Record) {
|
||||
return sel;
|
||||
}
|
||||
if (is_type) {
|
||||
|
||||
if (is_type_union(type)) {
|
||||
for (isize i = 0; i < type->Record.field_count; i++) {
|
||||
Entity *f = type->Record.fields[i];
|
||||
|
||||
@@ -153,6 +153,13 @@ void ssa_print_type(ssaFileBuffer *f, BaseTypeSizes s, Type *t) {
|
||||
case Basic_string: ssa_fprintf(f, "%%..string"); break;
|
||||
case Basic_uint: ssa_fprintf(f, "i%lld", word_bits); break;
|
||||
case Basic_int: ssa_fprintf(f, "i%lld", word_bits); break;
|
||||
case Basic_any:
|
||||
ssa_fprintf(f, "{");
|
||||
ssa_print_type(f, s, t_type_info_ptr);
|
||||
ssa_fprintf(f, ", ");
|
||||
ssa_print_type(f, s, t_rawptr);
|
||||
ssa_fprintf(f, "}");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Type_Array:
|
||||
|
||||
+71
-8
@@ -1053,9 +1053,26 @@ ssaValue *ssa_emit_deep_field_gep(ssaProcedure *proc, Type *type, ssaValue *e, S
|
||||
if (is_type_raw_union(type)) {
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ssa_emit_conv(proc, e, make_type_pointer(proc->module->allocator, type));
|
||||
} else {
|
||||
} else if (type->kind == Type_Record) {
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ssa_emit_struct_gep(proc, e, index, make_type_pointer(proc->module->allocator, type));
|
||||
} else if (type->kind == Type_Basic) {
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_any: {
|
||||
if (index == 0) {
|
||||
type = t_type_info_ptr;
|
||||
} else if (index == 1) {
|
||||
type = t_rawptr;
|
||||
}
|
||||
e = ssa_emit_struct_gep(proc, e, index, make_type_pointer(proc->module->allocator, type));
|
||||
} break;
|
||||
|
||||
default:
|
||||
GB_PANIC("un-gep-able type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
GB_PANIC("un-gep-able type");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1079,9 +1096,26 @@ ssaValue *ssa_emit_deep_field_ev(ssaProcedure *proc, Type *type, ssaValue *e, Se
|
||||
if (is_type_raw_union(type)) {
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ssa_emit_conv(proc, e, make_type_pointer(proc->module->allocator, type));
|
||||
} else {
|
||||
} else if (type->kind == Type_Record) {
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ssa_emit_struct_ev(proc, e, index, type);
|
||||
} else if (type->kind == Type_Basic) {
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_any: {
|
||||
if (index == 0) {
|
||||
type = t_type_info_ptr;
|
||||
} else if (index == 1) {
|
||||
type = t_rawptr;
|
||||
}
|
||||
e = ssa_emit_struct_ev(proc, e, index, type);
|
||||
} break;
|
||||
|
||||
default:
|
||||
GB_PANIC("un-ev-able type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
GB_PANIC("un-ev-able type");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1303,12 +1337,17 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
|
||||
}
|
||||
|
||||
if (value->kind == ssaValue_Constant) {
|
||||
if (dst->kind == Type_Basic) {
|
||||
if (is_type_any(dst)) {
|
||||
Type *dt = default_type(src);
|
||||
ssaValue *default_value = ssa_add_local_generated(proc, dt);
|
||||
ssa_emit_store(proc, default_value, value);
|
||||
return ssa_emit_conv(proc, ssa_emit_load(proc, default_value), t_any, is_argument);
|
||||
} else if (dst->kind == Type_Basic) {
|
||||
ExactValue ev = value->Constant.value;
|
||||
if (is_type_float(dst)) {
|
||||
ev = exact_value_to_float(ev);
|
||||
} else if (is_type_string(dst)) {
|
||||
//
|
||||
// Handled elsewhere
|
||||
} else if (is_type_integer(dst)) {
|
||||
ev = exact_value_to_integer(ev);
|
||||
} else if (is_type_pointer(dst)) {
|
||||
@@ -1487,6 +1526,33 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
|
||||
return v;
|
||||
}
|
||||
|
||||
if (is_type_any(dst)) {
|
||||
ssaValue **found = map_get(&proc->module->members, hash_string(make_string("__type_info_data")));
|
||||
GB_ASSERT(found != NULL);
|
||||
ssaValue *type_info_data = *found;
|
||||
CheckerInfo *info = proc->module->info;
|
||||
|
||||
|
||||
ssaValue *result = ssa_add_local_generated(proc, t_any);
|
||||
|
||||
// NOTE(bill): Make copy on stack so I can reference it later
|
||||
ssaValue *data = ssa_add_local_generated(proc, src_type);
|
||||
ssa_emit_store(proc, data, value);
|
||||
data = ssa_emit_conv(proc, data, t_rawptr);
|
||||
|
||||
|
||||
MapFindResult fr = map__find(&info->type_info_types, hash_pointer(src_type));
|
||||
GB_ASSERT(fr.entry_index >= 0);
|
||||
ssaValue *ti = ssa_emit_struct_gep(proc, type_info_data, fr.entry_index, t_type_info_ptr);
|
||||
|
||||
ssaValue *gep0 = ssa_emit_struct_gep(proc, result, v_zero32, make_type_pointer(proc->module->allocator, t_type_info_ptr));
|
||||
ssaValue *gep1 = ssa_emit_struct_gep(proc, result, v_one32, make_type_pointer(proc->module->allocator, t_rawptr));
|
||||
ssa_emit_store(proc, gep0, ti);
|
||||
ssa_emit_store(proc, gep1, data);
|
||||
|
||||
return ssa_emit_load(proc, result);
|
||||
}
|
||||
|
||||
|
||||
gb_printf_err("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t));
|
||||
gb_printf_err("Not Identical %s != %s\n", type_to_string(src), type_to_string(dst));
|
||||
@@ -3194,10 +3260,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
ssaBlock *default_block = NULL;
|
||||
|
||||
isize case_count = body->list_count;
|
||||
isize i = 0;
|
||||
for (AstNode *clause = body->list;
|
||||
clause != NULL;
|
||||
clause = clause->next, i++) {
|
||||
for (AstNode *clause = body->list; clause != NULL; clause = clause->next) {
|
||||
ast_node(cc, CaseClause, clause);
|
||||
|
||||
if (cc->list == NULL) {
|
||||
|
||||
+2
-3
@@ -2297,9 +2297,9 @@ AstNode *parse_match_stmt(AstFile *f) {
|
||||
Token open, close;
|
||||
|
||||
if (allow_token(f, Token_type)) {
|
||||
tag = parse_expr(f, true);
|
||||
expect_token(f, Token_ArrowRight);
|
||||
AstNode *var = parse_identifier(f);
|
||||
expect_token(f, Token_Colon);
|
||||
tag = parse_simple_stmt(f);
|
||||
|
||||
open = expect_token(f, Token_OpenBrace);
|
||||
AstNode *list = NULL;
|
||||
@@ -2315,7 +2315,6 @@ AstNode *parse_match_stmt(AstFile *f) {
|
||||
close = expect_token(f, Token_CloseBrace);
|
||||
body = make_block_stmt(f, list, list_count, open, close);
|
||||
|
||||
tag = convert_stmt_to_expr(f, tag, make_string("type match expression"));
|
||||
return make_type_match_stmt(f, token, tag, var, body);
|
||||
} else {
|
||||
if (f->cursor[0].kind != Token_OpenBrace) {
|
||||
|
||||
Reference in New Issue
Block a user