diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-09-21 23:18:28 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-09-21 23:18:28 +0100 |
| commit | c43d66c286c0cf622402bd1e21f2bbc7de2a6b49 (patch) | |
| tree | 71a723ef4583645ff20415c376272065f06e882b /src | |
| parent | 95fb5fa46cfb3c90d6d69027f090364333d8f821 (diff) | |
Use comma for struct field separators (disallow nesting)
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.cpp | 187 | ||||
| -rw-r--r-- | src/check_stmt.cpp | 21 | ||||
| -rw-r--r-- | src/checker.cpp | 56 | ||||
| -rw-r--r-- | src/parser.cpp | 7 |
4 files changed, 177 insertions, 94 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d33cee97b..8c38d7441 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -986,8 +986,8 @@ void check_struct_field_decl(Checker *c, AstNode *decl, Array<Entity *> *fields, } // Returns filled field_count -Array<Entity *> check_fields(Checker *c, AstNode *node, Array<AstNode *> decls, - isize init_field_capacity, String context) { +Array<Entity *> check_struct_fields(Checker *c, AstNode *node, Array<AstNode *> params, + isize init_field_capacity, String context) { gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); defer (gb_temp_arena_memory_end(tmp)); @@ -998,30 +998,152 @@ Array<Entity *> check_fields(Checker *c, AstNode *node, Array<AstNode *> decls, map_init(&entity_map, c->tmp_allocator, 2*init_field_capacity); - if (node != nullptr) { - GB_ASSERT(node->kind != AstNode_UnionType); + GB_ASSERT(node->kind == AstNode_StructType); + + isize variable_count = 0; + for_array(i, params) { + AstNode *field = params[i]; + if (ast_node_expect(field, AstNode_Field)) { + ast_node(f, Field, field); + variable_count += gb_max(f->names.count, 1); + } } - check_collect_entities(c, decls); - for_array(i, c->context.scope->elements.entries) { - Entity *e = c->context.scope->elements.entries[i].value; - DeclInfo *d = nullptr; - switch (e->kind) { - default: continue; - case Entity_Constant: - case Entity_TypeName: - d = decl_info_of_entity(&c->info, e); - if (d != nullptr) { - check_entity_decl(c, e, d, nullptr); + i32 field_src_index = 0; + for_array(i, params) { + AstNode *param = params[i]; + if (param->kind != AstNode_Field) { + continue; + } + ast_node(p, Field, param); + AstNode *type_expr = p->type; + Type *type = nullptr; + AstNode *default_value = unparen_expr(p->default_value); + ExactValue value = {}; + bool default_is_nil = false; + bool detemine_type_from_operand = false; + + + if (type_expr == nullptr) { + Operand o = {}; + check_expr_or_type(c, &o, default_value); + if (is_operand_nil(o)) { + default_is_nil = true; + } else if (o.mode != Addressing_Constant) { + error(default_value, "Default parameter must be a constant"); + } else { + value = o.value; + } + + type = default_type(o.type); + } else { + type = check_type(c, type_expr); + + if (default_value != nullptr) { + Operand o = {}; + check_expr_with_type_hint(c, &o, default_value, type); + + if (is_operand_nil(o)) { + default_is_nil = true; + } else if (o.mode != Addressing_Constant) { + error(default_value, "Default parameter must be a constant"); + } else { + value = o.value; + } + + check_is_assignable_to(c, &o, type); + } + + if (is_type_polymorphic(type)) { + type = nullptr; } - break; } - } + if (type == nullptr) { + error(params[i], "Invalid parameter type"); + type = t_invalid; + } + if (is_type_untyped(type)) { + if (is_type_untyped_undef(type)) { + error(params[i], "Cannot determine parameter type from ---"); + } else { + error(params[i], "Cannot determine parameter type from a nil"); + } + type = t_invalid; + } + if (is_type_empty_union(type)) { + gbString str = type_to_string(type); + error(params[i], "Invalid use of an empty union `%s`", str); + gb_string_free(str); + type = t_invalid; + } + + bool is_using = (p->flags&FieldFlag_using) != 0; + + for_array(j, p->names) { + AstNode *name = p->names[j]; + if (!ast_node_expect(name, AstNode_Ident)) { + continue; + } - for_array(decl_index, decls) { - check_struct_field_decl(c, decls[decl_index], &fields, &entity_map, node, context, context == "struct"); + Token name_token = name->Ident.token; + + Entity *field = nullptr; + field = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, field_src_index); + field->Variable.default_value = value; + field->Variable.default_is_nil = default_is_nil; + + add_entity(c, c->context.scope, name, field); + array_add(&fields, field); + + field_src_index += 1; + } + + Entity *using_index_expr = nullptr; + + if (is_using && p->names.count > 0) { + Type *first_type = fields[fields.count-1]->type; + Type *t = base_type(type_deref(first_type)); + + if (!is_type_struct(t) && !is_type_raw_union(t) && !is_type_bit_field(t) && + p->names.count >= 1 && + p->names[0]->kind == AstNode_Ident) { + Token name_token = p->names[0]->Ident.token; + if (is_type_indexable(t)) { + bool ok = true; + for_array(emi, entity_map.entries) { + Entity *e = entity_map.entries[emi].value; + if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { + if (is_type_indexable(e->type)) { + if (e->identifier != p->names[0]) { + ok = false; + using_index_expr = e; + break; + } + } + } + } + if (ok) { + using_index_expr = fields[fields.count-1]; + } else { + fields[fields.count-1]->flags &= ~EntityFlag_Using; + error(name_token, "Previous `using` for an index expression `%.*s`", LIT(name_token.string)); + } + } else { + gbString type_str = type_to_string(first_type); + error(name_token, "`using` cannot be applied to the field `%.*s` of type `%s`", LIT(name_token.string), type_str); + gb_string_free(type_str); + continue; + } + } + + populate_using_entity_map(c, node, type, &entity_map); + } } + // for_array(decl_index, params) { + // check_struct_field_decl(c, params[decl_index], &fields, &entity_map, node, context, context == "struct"); + // } + return fields; } @@ -1278,7 +1400,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera Array<Entity *> fields = {}; if (!is_polymorphic) { - fields = check_fields(c, node, st->fields, min_field_count, context); + fields = check_struct_fields(c, node, st->fields, min_field_count, context); } struct_type->Struct.scope = c->context.scope; @@ -1392,31 +1514,6 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) { } } -// void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) { -// GB_ASSERT(node->kind == AstNode_RawUnionType); -// GB_ASSERT(is_type_raw_union(union_type)); -// ast_node(ut, RawUnionType, node); - -// 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; -// } -// } - -// union_type->Struct.names = make_names_field_for_struct(c, c->context.scope); - -// auto fields = check_fields(c, node, ut->fields, min_field_count, str_lit("raw_union")); - -// union_type->Struct.scope = c->context.scope; -// union_type->Struct.fields = fields.data; -// union_type->Struct.field_count = fields.count; -// } - - void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) { ast_node(et, EnumType, node); GB_ASSERT(is_type_enum(enum_type)); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index d6c8f654d..9235d6055 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -472,24 +472,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo switch (e->kind) { case Entity_TypeName: { Type *t = base_type(e->type); - if (t->kind == Type_Struct) { - Scope *s = t->Struct.scope; - if (s != nullptr) { - for_array(i, s->elements.entries) { - Entity *f = s->elements.entries[i].value; - if (f->kind != Entity_Variable) { - Entity *found = scope_insert_entity(c->context.scope, f); - if (found != nullptr) { - gbString expr_str = expr_to_string(expr); - error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string)); - gb_string_free(expr_str); - return false; - } - f->using_parent = e; - } - } - } - } else if (t->kind == Type_Enum) { + if (t->kind == Type_Enum) { for (isize i = 0; i < t->Enum.field_count; i++) { Entity *f = t->Enum.fields[i]; Entity *found = scope_insert_entity(c->context.scope, f); @@ -502,7 +485,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo f->using_parent = e; } } else { - error(us->token, "`using` can be only applied to struct type entities"); + error(us->token, "`using` can be only applied to enum type entities"); } } break; diff --git a/src/checker.cpp b/src/checker.cpp index 7758d7803..dd53a7902 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1595,17 +1595,17 @@ Entity *find_core_entity(Checker *c, String name) { return e; } -Entity *find_sub_core_entity(TypeStruct *parent, String name) { - GB_ASSERT(parent->scope->parent->is_global); - Entity *e = current_scope_lookup_entity(parent->scope, name); +Type *find_core_type(Checker *c, String name) { + Entity *e = current_scope_lookup_entity(c->global_scope, name); if (e == nullptr) { compiler_error("Could not find type declaration for `%.*s`\n" "Is `_preload.odin` missing from the `core` directory relative to odin.exe?", LIT(name)); // NOTE(bill): This will exit the program as it's cannot continue without it! } - return e; + return e->type; } + void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type); void init_preload(Checker *c) { @@ -1617,7 +1617,7 @@ void init_preload(Checker *c) { GB_ASSERT(is_type_struct(type_info_entity->type)); TypeStruct *tis = &base_type(type_info_entity->type)->Struct; - Entity *type_info_enum_value = find_sub_core_entity(tis, str_lit("Enum_Value")); + Entity *type_info_enum_value = find_core_entity(c, str_lit("Type_Info_Enum_Value")); t_type_info_enum_value = type_info_enum_value->type; t_type_info_enum_value_ptr = make_type_pointer(c->allocator, t_type_info_enum_value); @@ -1627,31 +1627,27 @@ void init_preload(Checker *c) { Entity *type_info_variant = tis->fields_in_src_order[2]; Type *tiv_type = type_info_variant->type; GB_ASSERT(is_type_union(tiv_type)); - TypeUnion *tiv = &tiv_type->Union; - - if (tiv->variants.count != 20) { - compiler_error("Invalid `Type_Info` layout"); - } - t_type_info_named = tiv->variants[ 0]; - t_type_info_integer = tiv->variants[ 1]; - t_type_info_rune = tiv->variants[ 2]; - t_type_info_float = tiv->variants[ 3]; - t_type_info_complex = tiv->variants[ 4]; - t_type_info_string = tiv->variants[ 5]; - t_type_info_boolean = tiv->variants[ 6]; - t_type_info_any = tiv->variants[ 7]; - t_type_info_pointer = tiv->variants[ 8]; - t_type_info_procedure = tiv->variants[ 9]; - t_type_info_array = tiv->variants[10]; - t_type_info_dynamic_array = tiv->variants[11]; - t_type_info_slice = tiv->variants[12]; - t_type_info_vector = tiv->variants[13]; - t_type_info_tuple = tiv->variants[14]; - t_type_info_struct = tiv->variants[15]; - t_type_info_union = tiv->variants[16]; - t_type_info_enum = tiv->variants[17]; - t_type_info_map = tiv->variants[18]; - t_type_info_bit_field = tiv->variants[19]; + + t_type_info_named = find_core_type(c, str_lit("Type_Info_Named")); + t_type_info_integer = find_core_type(c, str_lit("Type_Info_Integer")); + t_type_info_rune = find_core_type(c, str_lit("Type_Info_Rune")); + t_type_info_float = find_core_type(c, str_lit("Type_Info_Float")); + t_type_info_complex = find_core_type(c, str_lit("Type_Info_Complex")); + t_type_info_string = find_core_type(c, str_lit("Type_Info_String")); + t_type_info_boolean = find_core_type(c, str_lit("Type_Info_Boolean")); + t_type_info_any = find_core_type(c, str_lit("Type_Info_Any")); + t_type_info_pointer = find_core_type(c, str_lit("Type_Info_Pointer")); + t_type_info_procedure = find_core_type(c, str_lit("Type_Info_Procedure")); + t_type_info_array = find_core_type(c, str_lit("Type_Info_Array")); + t_type_info_dynamic_array = find_core_type(c, str_lit("Type_Info_Dynamic_Array")); + t_type_info_slice = find_core_type(c, str_lit("Type_Info_Slice")); + t_type_info_vector = find_core_type(c, str_lit("Type_Info_Vector")); + t_type_info_tuple = find_core_type(c, str_lit("Type_Info_Tuple")); + t_type_info_struct = find_core_type(c, str_lit("Type_Info_Struct")); + t_type_info_union = find_core_type(c, str_lit("Type_Info_Union")); + t_type_info_enum = find_core_type(c, str_lit("Type_Info_Enum")); + t_type_info_map = find_core_type(c, str_lit("Type_Info_Map")); + t_type_info_bit_field = find_core_type(c, str_lit("Type_Info_Bit_Field")); t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named); t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer); diff --git a/src/parser.cpp b/src/parser.cpp index 730f16d06..37412c157 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -130,6 +130,7 @@ enum FieldFlag { FieldFlag_c_vararg = 1<<3, FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg, + FieldFlag_Struct = FieldFlag_using, }; enum StmtAllowFlag { @@ -3478,6 +3479,11 @@ AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) { isize total_name_count = 0; + AstNode *params = parse_field_list(f, &total_name_count, FieldFlag_Struct, Token_CloseBrace, true, false); + if (name_count_) *name_count_ = total_name_count; + return params; + +#if 0 while (f->curr_token.kind != Token_CloseBrace && f->curr_token.kind != Token_EOF) { AstNode *decl = parse_stmt(f); @@ -3508,6 +3514,7 @@ AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) { if (name_count_) *name_count_ = total_name_count; return ast_field_list(f, start_token, decls); +#endif } AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters, bool allow_type_token) { |