aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-09-21 23:18:28 +0100
committerGinger Bill <bill@gingerbill.org>2017-09-21 23:18:28 +0100
commitc43d66c286c0cf622402bd1e21f2bbc7de2a6b49 (patch)
tree71a723ef4583645ff20415c376272065f06e882b /src
parent95fb5fa46cfb3c90d6d69027f090364333d8f821 (diff)
Use comma for struct field separators (disallow nesting)
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp187
-rw-r--r--src/check_stmt.cpp21
-rw-r--r--src/checker.cpp56
-rw-r--r--src/parser.cpp7
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) {