diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-07-10 22:32:21 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-07-10 22:32:21 +0100 |
| commit | fd8c4d58bb476f858b5238287b6e9911dd5c333c (patch) | |
| tree | 31e138edb4f51148838bd01e10402e51160547e8 /src/check_expr.cpp | |
| parent | ce4b7b8b7d54e889413cf2d43d85f2e4f4a0b007 (diff) | |
`union` type allow for any types and removes common fields
Diffstat (limited to 'src/check_expr.cpp')
| -rw-r--r-- | src/check_expr.cpp | 132 |
1 files changed, 22 insertions, 110 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index ebddbb0f3..7a0088f86 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -500,8 +500,8 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) { if (is_type_union(dst)) { for (isize i = 0; i < dst->Record.variant_count; i++) { - Entity *f = dst->Record.variants[i]; - if (are_types_identical(f->type, s)) { + Type *vt = dst->Record.variants[i]; + if (are_types_identical(vt, s)) { return 1; } } @@ -980,41 +980,17 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n ast_node(ut, UnionType, node); isize variant_count = ut->variants.count+1; - isize min_field_count = 0; - for_array(i, ut->fields) { - AstNode *field = ut->fields[i]; - switch (field->kind) { - case_ast_node(f, ValueDecl, field); - min_field_count += f->names.count; - case_end; - } - } gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); defer (gb_temp_arena_memory_end(tmp)); - Map<Entity *> entity_map = {}; // Key: String - map_init_with_reserve(&entity_map, c->tmp_allocator, 2*variant_count); - Entity *using_index_expr = nullptr; - Array<Entity *> variants = {}; - array_init(&variants, heap_allocator(), variant_count); - - array_add(&variants, make_entity_type_name(c->allocator, c->context.scope, empty_token, nullptr)); - - auto fields = check_fields(c, nullptr, ut->fields, min_field_count, str_lit("union")); - - for (isize i = 0; i < fields.count; i++) { - Entity *f = fields[i]; - String name = f->token.string; - map_set(&entity_map, hash_string(name), f); - } + Array<Type *> variants = {}; + array_init(&variants, c->allocator, variant_count); + array_add(&variants, t_invalid); union_type->Record.scope = c->context.scope; - union_type->Record.fields = fields.data; - union_type->Record.fields_in_src_order = fields.data; - union_type->Record.field_count = fields.count; union_type->Record.are_offsets_set = false; union_type->Record.is_ordered = true; { @@ -1023,75 +999,21 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n } for_array(i, ut->variants) { - AstNode *variant = ut->variants[i]; - if (variant->kind != AstNode_UnionField) { - continue; - } - ast_node(f, UnionField, variant); - Token name_token = f->name->Ident.token; - - Type *base_type = make_type_struct(c->allocator); - { - ast_node(fl, FieldList, f->list); - - // NOTE(bill): Copy the contents for the common fields for now - Array<AstNode *> list = {}; - array_init_count(&list, c->allocator, ut->fields.count+fl->list.count); - gb_memmove_array(list.data, ut->fields.data, ut->fields.count); - gb_memmove_array(list.data+ut->fields.count, fl->list.data, fl->list.count); - - isize list_count = 0; - for_array(j, list) { - if (list[j]->kind == AstNode_Field) { - list_count += list[j]->Field.names.count; - } else { - ast_node(f, ValueDecl, list[j]); - list_count += f->names.count; + AstNode *node = ut->variants[i]; + Type *t = check_type(c, node); + if (t != nullptr && t != t_invalid) { + bool ok = true; + for_array(j, variants) { + if (are_types_identical(t, variants[j])) { + ok = false; + gbString str = type_to_string(t); + error(node, "Duplicate variant type `%s`", str); + gb_string_free(str); + break; } } - - - Token token = name_token; - token.kind = Token_struct; - AstNode *dummy_struct = ast_struct_type(c->curr_ast_file, token, list, list_count, false, true, nullptr); - - check_open_scope(c, dummy_struct); - base_type->Record.names = make_names_field_for_record(c, c->context.scope); - auto fields = check_fields(c, dummy_struct, list, list_count, str_lit("variant")); - base_type->Record.is_packed = false; - base_type->Record.is_ordered = true; - base_type->Record.fields = fields.data; - base_type->Record.fields_in_src_order = fields.data; - base_type->Record.field_count = fields.count; - base_type->Record.node = dummy_struct; - base_type->Record.variant_parent = named_type != nullptr ? named_type : union_type; - base_type->Record.variant_index = variants.count; - - - type_set_offsets(c->allocator, base_type); - - check_close_scope(c); - } - - Type *type = make_type_named(c->allocator, name_token.string, base_type, nullptr); - Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, type); - type->Named.type_name = e; - add_entity(c, c->context.scope, f->name, e); - - if (name_token.string == "_") { - error(name_token, "`_` cannot be used a union subtype"); - continue; + if (ok) array_add(&variants, t); } - - HashKey key = hash_string(name_token.string); - if (map_get(&entity_map, key) != nullptr) { - // NOTE(bill): Scope checking already checks the declaration - error(name_token, "`%.*s` is already declared in this union", LIT(name_token.string)); - } else { - map_set(&entity_map, key, e); - array_add(&variants, e); - } - add_entity_use(c, f->name, e); } type_set_offsets(c->allocator, union_type); @@ -6889,28 +6811,17 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t bool src_is_ptr = is_type_pointer(o->type); - bool dst_is_ptr = is_type_pointer(t); Type *src = type_deref(o->type); - Type *dst = type_deref(t); + Type *dst = t; Type *bsrc = base_type(src); Type *bdst = base_type(dst); - if (src_is_ptr != dst_is_ptr) { - gbString src_type_str = type_to_string(o->type); - gbString dst_type_str = type_to_string(t); - error(o->expr, "Invalid type assertion types: `%s` and `%s`", src_type_str, dst_type_str); - gb_string_free(dst_type_str); - gb_string_free(src_type_str); - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } if (is_type_union(src)) { bool ok = false; for (isize i = 1; i < bsrc->Record.variant_count; i++) { - Entity *f = bsrc->Record.variants[i]; - if (are_types_identical(f->type, dst)) { + Type *vt = bsrc->Record.variants[i]; + if (are_types_identical(vt, dst)) { ok = true; break; } @@ -7088,6 +6999,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t case Type_Slice: valid = true; + o->type = type_deref(o->type); break; case Type_DynamicArray: @@ -7602,7 +7514,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) { case_ast_node(st, UnionType, node); str = gb_string_appendc(str, "union "); str = gb_string_appendc(str, "{"); - str = write_record_fields_to_string(str, st->fields); + str = write_record_fields_to_string(str, st->variants); str = gb_string_appendc(str, "}"); case_end; |