diff options
Diffstat (limited to 'src/check_stmt.cpp')
| -rw-r--r-- | src/check_stmt.cpp | 195 |
1 files changed, 100 insertions, 95 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 65a6387f8..af5f5edeb 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1535,121 +1535,126 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { check_stmt(c, pa->body, mod_flags); case_end; - - case_ast_node(vd, ValueDecl, node); + case_ast_node(gd, GenDecl, node); GB_ASSERT(!c->context.scope->is_file); - if (vd->token.kind == Token_const) { - // NOTE(bill): Handled elsewhere - } else { - Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count); - isize entity_count = 0; - - if (vd->flags & VarDeclFlag_thread_local) { - vd->flags &= ~VarDeclFlag_thread_local; - error_node(node, "`thread_local` may only be applied to a variable declaration"); - } + for_array(i, gd->specs) { + AstNode *spec = gd->specs[i]; + switch (gd->token.kind) { + case Token_var: + case Token_let: { + ast_node(vd, ValueSpec, spec); + + Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count); + isize entity_count = 0; + + if (gd->flags & VarDeclFlag_thread_local) { + gd->flags &= ~VarDeclFlag_thread_local; + error_node(node, "`thread_local` may only be applied to a variable declaration"); + } - for_array(i, vd->names) { - AstNode *name = vd->names[i]; - Entity *entity = NULL; - if (name->kind != AstNode_Ident) { - error_node(name, "A variable declaration must be an identifier"); - } else { - Token token = name->Ident; - String str = token.string; - Entity *found = NULL; - // NOTE(bill): Ignore assignments to `_` - if (str != "_") { - found = current_scope_lookup_entity(c->context.scope, str); - } - if (found == NULL) { - entity = make_entity_variable(c->allocator, c->context.scope, token, NULL, (vd->flags&VarDeclFlag_immutable) != 0); - entity->identifier = name; + for_array(i, vd->names) { + AstNode *name = vd->names[i]; + Entity *entity = NULL; + if (name->kind != AstNode_Ident) { + error_node(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; + String str = token.string; + Entity *found = NULL; + // NOTE(bill): Ignore assignments to `_` + if (str != "_") { + found = current_scope_lookup_entity(c->context.scope, str); + } + if (found == NULL) { + entity = make_entity_variable(c->allocator, c->context.scope, token, NULL, (gd->flags&VarDeclFlag_immutable) != 0); + entity->identifier = name; + } 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 == NULL) { + 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; } - if (entity == NULL) { - 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 = NULL; - if (vd->type) { - init_type = check_type(c, vd->type, NULL); - if (init_type == NULL) { - init_type = t_invalid; + Type *init_type = NULL; + if (vd->type) { + init_type = check_type(c, vd->type, NULL); + if (init_type == NULL) { + init_type = t_invalid; + } } - } - for (isize i = 0; i < entity_count; i++) { - Entity *e = entities[i]; - GB_ASSERT(e != NULL); - 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 != NULL); + if (e->flags & EntityFlag_Visited) { + e->type = t_invalid; + continue; + } + e->flags |= EntityFlag_Visited; - if (e->type == NULL) { - e->type = init_type; + if (e->type == NULL) { + e->type = init_type; + } } - } - check_arity_match(c, vd); - check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration")); + 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++) { - add_entity(c, c->context.scope, entities[i]->identifier, entities[i]); - } - - if ((vd->flags & VarDeclFlag_using) != 0) { - Token token = ast_node_token(node); - if (vd->type != NULL && entity_count > 1) { - error(token, "`using` can only be applied to one variable of the same type"); - // TODO(bill): Should a `continue` happen here? + for (isize i = 0; i < entity_count; i++) { + add_entity(c, c->context.scope, entities[i]->identifier, entities[i]); } - for (isize entity_index = 0; entity_index < entity_count; entity_index++) { - Entity *e = entities[entity_index]; - if (e == NULL) { - continue; + if ((gd->flags & VarDeclFlag_using) != 0) { + Token token = ast_node_token(node); + if (vd->type != NULL && 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_type_struct(t) || is_type_raw_union(t)) { - Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node)); - GB_ASSERT(found != NULL); - for_array(i, (*found)->elements.entries) { - Entity *f = (*found)->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 != NULL) { - 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 == NULL) { + 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_type_struct(t) || is_type_raw_union(t)) { + Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node)); + GB_ASSERT(found != NULL); + for_array(i, (*found)->elements.entries) { + Entity *f = (*found)->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 != NULL) { + 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; } } + } break; } } case_end; |