diff options
| author | gingerBill <bill@gingerbill.org> | 2017-12-09 18:11:36 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2017-12-09 18:11:36 +0000 |
| commit | 3703ca4df47134e0c274cf5096d14c9323331ff0 (patch) | |
| tree | a01aab633bf3d25aba33357cb8d181537e9c841b /src/check_stmt.cpp | |
| parent | 41b8281c7355eea7c4a2022027769df8a519ae7a (diff) | |
Explicit procedure group; Remove implicit procedure overloading
Diffstat (limited to 'src/check_stmt.cpp')
| -rw-r--r-- | src/check_stmt.cpp | 313 |
1 files changed, 156 insertions, 157 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 6dd2bcdaa..17d50fb6d 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -30,7 +30,7 @@ void check_stmt_list(Checker *c, Array<AstNode *> stmts, u32 flags) { if (i+1 < max) { switch (n->kind) { case AstNode_ReturnStmt: - error(n, "Statements after this 'return' are never executed"); + error(n, "Statements after this 'return' are never execu"); break; case AstNode_BranchStmt: @@ -182,7 +182,7 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) { return nullptr; } if (rhs->type == t_invalid && - rhs->mode != Addressing_Overload && + rhs->mode != Addressing_ProcGroup && rhs->mode != Addressing_Builtin) { return nullptr; } @@ -203,17 +203,16 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) { bool used = false; if (lhs->mode == Addressing_Invalid || - (lhs->type == t_invalid && lhs->mode != Addressing_Overload)) { + (lhs->type == t_invalid && lhs->mode != Addressing_ProcGroup)) { return nullptr; } - if (rhs->mode == Addressing_Overload) { - isize overload_count = rhs->overload_count; - Entity **procs = rhs->overload_entities; - GB_ASSERT(procs != nullptr && overload_count > 0); + if (rhs->mode == Addressing_ProcGroup) { + Array<Entity *> procs = proc_group_entities(c, *rhs); + GB_ASSERT(procs.count > 0); // NOTE(bill): These should be done - for (isize i = 0; i < overload_count; i++) { + for_array(i, procs) { Type *t = base_type(procs[i]->type); if (t == t_invalid) { continue; @@ -232,8 +231,7 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) { // HACK TODO(bill): Should the entities be freed as it's technically a leak rhs->mode = Addressing_Value; rhs->type = e->type; - rhs->overload_count = 0; - rhs->overload_entities = nullptr; + rhs->proc_group = nullptr; } } else { if (node->kind == AstNode_Ident) { @@ -1680,176 +1678,177 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { case_end; case_ast_node(vd, ValueDecl, node); - if (!vd->is_mutable) { - break; - } - Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count); - isize entity_count = 0; - - for_array(i, vd->names) { - AstNode *name = vd->names[i]; - Entity *entity = nullptr; - if (name->kind != AstNode_Ident) { - error(name, "A variable declaration must be an identifier"); - } else { - Token token = name->Ident.token; - String str = token.string; - Entity *found = nullptr; - // NOTE(bill): Ignore assignments to '_' - if (!is_blank_ident(str)) { - found = current_scope_lookup_entity(c->context.scope, str); - } - if (found == nullptr) { - entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false); - entity->identifier = name; - - AstNode *fl = c->context.foreign_context.curr_library; - if (fl != nullptr) { - GB_ASSERT(fl->kind == AstNode_Ident); - entity->Variable.is_foreign = true; - entity->Variable.foreign_library_ident = fl; - } + if (vd->is_mutable) { + Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count); + isize entity_count = 0; + + for_array(i, vd->names) { + AstNode *name = vd->names[i]; + Entity *entity = nullptr; + if (name->kind != AstNode_Ident) { + error(name, "A variable declaration must be an identifier"); } else { - TokenPos pos = found->token.pos; - error(token, - "Redeclaration of '%.*s' in this scope\n" - "\tat %.*s(%td:%td)", - LIT(str), LIT(pos.file), pos.line, pos.column); - entity = found; + Token token = name->Ident.token; + String str = token.string; + Entity *found = nullptr; + // NOTE(bill): Ignore assignments to '_' + if (!is_blank_ident(str)) { + found = current_scope_lookup_entity(c->context.scope, str); + } + if (found == nullptr) { + entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false); + entity->identifier = name; + + AstNode *fl = c->context.foreign_context.curr_library; + if (fl != nullptr) { + GB_ASSERT(fl->kind == AstNode_Ident); + entity->Variable.is_foreign = true; + entity->Variable.foreign_library_ident = fl; + } + } else { + TokenPos pos = found->token.pos; + error(token, + "Redeclaration of '%.*s' in this scope\n" + "\tat %.*s(%td:%td)", + LIT(str), LIT(pos.file), pos.line, pos.column); + entity = found; + } + } + if (entity == nullptr) { + entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name)); + } + entity->parent_proc_decl = c->context.curr_proc_decl; + entities[entity_count++] = entity; + } + + Type *init_type = nullptr; + if (vd->type != nullptr) { + init_type = check_type(c, vd->type, nullptr); + if (init_type == nullptr) { + init_type = t_invalid; + } else if (is_type_polymorphic(base_type(init_type))) { + gbString str = type_to_string(init_type); + error(vd->type, "Invalid use of a polymorphic type '%s' in variable declaration", str); + gb_string_free(str); + init_type = t_invalid; + } else if (is_type_empty_union(init_type)) { + gbString str = type_to_string(init_type); + error(vd->type, "An empty union '%s' cannot be instantiated in variable declaration", str); + gb_string_free(str); + init_type = t_invalid; } } - if (entity == nullptr) { - entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name)); - } - entity->parent_proc_decl = c->context.curr_proc_decl; - entities[entity_count++] = entity; - } - - Type *init_type = nullptr; - if (vd->type != nullptr) { - init_type = check_type(c, vd->type, nullptr); - if (init_type == nullptr) { - init_type = t_invalid; - } else if (is_type_polymorphic(base_type(init_type))) { - gbString str = type_to_string(init_type); - error(vd->type, "Invalid use of a polymorphic type '%s' in variable declaration", str); - gb_string_free(str); - init_type = t_invalid; - } else if (is_type_empty_union(init_type)) { - gbString str = type_to_string(init_type); - error(vd->type, "An empty union '%s' cannot be instantiated in variable declaration", str); - gb_string_free(str); - init_type = t_invalid; - } - } - // TODO NOTE(bill): This technically checks things multple times - AttributeContext ac = make_attribute_context(c->context.foreign_context.link_prefix); - check_decl_attributes(c, vd->attributes, var_decl_attribute, &ac); + // TODO NOTE(bill): This technically checks things multple times + AttributeContext ac = make_attribute_context(c->context.foreign_context.link_prefix); + check_decl_attributes(c, vd->attributes, var_decl_attribute, &ac); - for (isize i = 0; i < entity_count; i++) { - Entity *e = entities[i]; - GB_ASSERT(e != nullptr); - if (e->flags & EntityFlag_Visited) { - e->type = t_invalid; - continue; - } - e->flags |= EntityFlag_Visited; + for (isize i = 0; i < entity_count; i++) { + Entity *e = entities[i]; + GB_ASSERT(e != nullptr); + if (e->flags & EntityFlag_Visited) { + e->type = t_invalid; + continue; + } + e->flags |= EntityFlag_Visited; - if (e->type == nullptr) { - e->type = init_type; - } - ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix); - e->Variable.thread_local_model = ac.thread_local_model; + if (e->type == nullptr) { + e->type = init_type; + } + ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix); + e->Variable.thread_local_model = ac.thread_local_model; - if (ac.link_name.len > 0) { - e->Variable.link_name = ac.link_name; + if (ac.link_name.len > 0) { + e->Variable.link_name = ac.link_name; + } } - } - - check_arity_match(c, vd); - check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration")); - for (isize i = 0; i < entity_count; i++) { - Entity *e = entities[i]; - if (e->Variable.is_foreign) { - if (vd->values.count > 0) { - error(e->token, "A foreign variable declaration cannot have a default value"); - } + check_arity_match(c, vd); + check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration")); - String name = e->token.string; - if (e->Variable.link_name.len > 0) { - name = e->Variable.link_name; - } + for (isize i = 0; i < entity_count; i++) { + Entity *e = entities[i]; + if (e->Variable.is_foreign) { + if (vd->values.count > 0) { + error(e->token, "A foreign variable declaration cannot have a default value"); + } - if (vd->values.count > 0) { - error(e->token, "A foreign variable declaration cannot have a default value"); - } - init_entity_foreign_library(c, e); + String name = e->token.string; + if (e->Variable.link_name.len > 0) { + name = e->Variable.link_name; + } - auto *fp = &c->info.foreigns; - HashKey key = hash_string(name); - Entity **found = map_get(fp, key); - if (found) { - Entity *f = *found; - TokenPos pos = f->token.pos; - Type *this_type = base_type(e->type); - Type *other_type = base_type(f->type); - if (!are_types_identical(this_type, other_type)) { - error(e->token, - "Foreign entity '%.*s' previously declared elsewhere with a different type\n" - "\tat %.*s(%td:%td)", - LIT(name), LIT(pos.file), pos.line, pos.column); + if (vd->values.count > 0) { + error(e->token, "A foreign variable declaration cannot have a default value"); + } + init_entity_foreign_library(c, e); + + auto *fp = &c->info.foreigns; + HashKey key = hash_string(name); + Entity **found = map_get(fp, key); + if (found) { + Entity *f = *found; + TokenPos pos = f->token.pos; + Type *this_type = base_type(e->type); + Type *other_type = base_type(f->type); + if (!are_types_identical(this_type, other_type)) { + error(e->token, + "Foreign entity '%.*s' previously declared elsewhere with a different type\n" + "\tat %.*s(%td:%td)", + LIT(name), LIT(pos.file), pos.line, pos.column); + } + } else { + map_set(fp, key, e); } - } else { - map_set(fp, key, e); } - } - add_entity(c, c->context.scope, e->identifier, e); - } - - if (vd->is_using != 0) { - Token token = ast_node_token(node); - if (vd->type != nullptr && entity_count > 1) { - error(token, "'using' can only be applied to one variable of the same type"); - // TODO(bill): Should a 'continue' happen here? + add_entity(c, c->context.scope, e->identifier, e); } - for (isize entity_index = 0; entity_index < entity_count; entity_index++) { - Entity *e = entities[entity_index]; - if (e == nullptr) { - continue; + if (vd->is_using != 0) { + Token token = ast_node_token(node); + if (vd->type != nullptr && entity_count > 1) { + error(token, "'using' can only be applied to one variable of the same type"); + // TODO(bill): Should a 'continue' happen here? } - if (e->kind != Entity_Variable) { - continue; - } - bool is_immutable = e->Variable.is_immutable; - String name = e->token.string; - Type *t = base_type(type_deref(e->type)); - - if (is_blank_ident(name)) { - error(token, "'using' cannot be applied variable declared as '_'"); - } else if (is_type_struct(t) || is_type_raw_union(t)) { - Scope *scope = scope_of_node(&c->info, t->Struct.node); - for_array(i, scope->elements.entries) { - Entity *f = scope->elements.entries[i].value; - if (f->kind == Entity_Variable) { - Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type); - uvar->Variable.is_immutable = is_immutable; - Entity *prev = scope_insert_entity(c->context.scope, uvar); - if (prev != nullptr) { - error(token, "Namespace collision while 'using' '%.*s' of: %.*s", LIT(name), LIT(prev->token.string)); - return; + + for (isize entity_index = 0; entity_index < entity_count; entity_index++) { + Entity *e = entities[entity_index]; + if (e == nullptr) { + continue; + } + if (e->kind != Entity_Variable) { + continue; + } + bool is_immutable = e->Variable.is_immutable; + String name = e->token.string; + Type *t = base_type(type_deref(e->type)); + + if (is_blank_ident(name)) { + error(token, "'using' cannot be applied variable declared as '_'"); + } else if (is_type_struct(t) || is_type_raw_union(t)) { + Scope *scope = scope_of_node(&c->info, t->Struct.node); + for_array(i, scope->elements.entries) { + Entity *f = scope->elements.entries[i].value; + if (f->kind == Entity_Variable) { + Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type); + uvar->Variable.is_immutable = is_immutable; + Entity *prev = scope_insert_entity(c->context.scope, uvar); + if (prev != nullptr) { + error(token, "Namespace collision while 'using' '%.*s' of: %.*s", LIT(name), LIT(prev->token.string)); + return; + } } } + } else { + // NOTE(bill): skip the rest to remove extra errors + error(token, "'using' can only be applied to variables of type struct or raw_union"); + return; } - } else { - // NOTE(bill): skip the rest to remove extra errors - error(token, "'using' can only be applied to variables of type struct or raw_union"); - return; } } + } else { + // constant value declarations } case_end; } |