mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-19 04:12:22 -07:00
any type
This commit is contained in:
+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;
|
||||
|
||||
Reference in New Issue
Block a user