diff options
Diffstat (limited to 'src/checker/expr.cpp')
| -rw-r--r-- | src/checker/expr.cpp | 113 |
1 files changed, 49 insertions, 64 deletions
diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index b8919c0bb..e55efd56d 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -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; |