This commit is contained in:
Ginger Bill
2016-09-07 15:15:10 +01:00
parent 61fcfd6f3d
commit 2c4193a242
8 changed files with 260 additions and 106 deletions
+28 -16
View File
@@ -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
View File
@@ -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
View File
@@ -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];