aboutsummaryrefslogtreecommitdiff
path: root/src/check_stmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/check_stmt.cpp')
-rw-r--r--src/check_stmt.cpp195
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;