aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-08-11 23:58:49 +0100
committergingerBill <bill@gingerbill.org>2019-08-11 23:58:49 +0100
commit04036aba9c1eec05fe143d939ef93e017502f015 (patch)
tree0d9da264ef729dc01822a6be975cfb8f03fc531f /src
parentb08aa857b3c99c241e93ea3d0fbe36f712d96015 (diff)
`package reflect`; fix substring type bug; fix scoping rules for `using` on procedure parameter
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.cpp118
-rw-r--r--src/check_expr.cpp2
2 files changed, 76 insertions, 44 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index f3e0f70bc..cf3cb8e97 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -1074,6 +1074,11 @@ void check_entity_decl(CheckerContext *ctx, Entity *e, DeclInfo *d, Type *named_
}
+struct ProcUsingVar {
+ Entity *e;
+ Entity *uvar;
+};
+
void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *type, Ast *body) {
if (body == nullptr) {
@@ -1098,58 +1103,85 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
ctx->curr_proc_decl = decl;
ctx->curr_proc_sig = type;
- GB_ASSERT(type->kind == Type_Proc);
- if (type->Proc.param_count > 0) {
- TypeTuple *params = &type->Proc.params->Tuple;
- for_array(i, params->variables) {
- Entity *e = params->variables[i];
- if (e->kind != Entity_Variable) {
- continue;
- }
- if (!(e->flags & EntityFlag_Using)) {
- continue;
- }
- bool is_immutable = e->Variable.is_immutable;
- bool is_value = (e->flags & EntityFlag_Value) != 0 && !is_type_pointer(e->type);
- String name = e->token.string;
- Type *t = base_type(type_deref(e->type));
- if (t->kind == Type_Struct) {
- Scope *scope = t->Struct.scope;
- if (scope == nullptr) {
- scope = scope_of_node(t->Struct.node);
+ ast_node(bs, BlockStmt, body);
+
+ Array<ProcUsingVar> using_entities = {};
+ using_entities.allocator = heap_allocator();
+ defer (array_free(&using_entities));
+
+ {
+ GB_ASSERT(type->kind == Type_Proc);
+ if (type->Proc.param_count > 0) {
+ TypeTuple *params = &type->Proc.params->Tuple;
+ for_array(i, params->variables) {
+ Entity *e = params->variables[i];
+ if (e->kind != Entity_Variable) {
+ continue;
}
- GB_ASSERT(scope != nullptr);
- for_array(i, scope->elements.entries) {
- Entity *f = scope->elements.entries[i].value;
- if (f->kind == Entity_Variable) {
- Entity *uvar = alloc_entity_using_variable(e, f->token, f->type);
- uvar->Variable.is_immutable = is_immutable;
- if (is_value) uvar->flags |= EntityFlag_Value;
-
- Entity *prev = scope_insert(ctx->scope, uvar);
- if (prev != nullptr) {
- error(e->token, "Namespace collision while 'using' '%.*s' of: %.*s", LIT(name), LIT(prev->token.string));
- break;
+ if (!(e->flags & EntityFlag_Using)) {
+ continue;
+ }
+ bool is_immutable = e->Variable.is_immutable;
+ bool is_value = (e->flags & EntityFlag_Value) != 0 && !is_type_pointer(e->type);
+ String name = e->token.string;
+ Type *t = base_type(type_deref(e->type));
+ if (t->kind == Type_Struct) {
+ Scope *scope = t->Struct.scope;
+ if (scope == nullptr) {
+ scope = scope_of_node(t->Struct.node);
+ }
+ GB_ASSERT(scope != nullptr);
+ for_array(i, scope->elements.entries) {
+ Entity *f = scope->elements.entries[i].value;
+ if (f->kind == Entity_Variable) {
+ Entity *uvar = alloc_entity_using_variable(e, f->token, f->type);
+ uvar->Variable.is_immutable = is_immutable;
+ if (is_value) uvar->flags |= EntityFlag_Value;
+
+
+ ProcUsingVar puv = {e, uvar};
+ array_add(&using_entities, puv);
+
}
}
+ } else {
+ error(e->token, "'using' can only be applied to variables of type struct");
+ break;
}
- } else {
- error(e->token, "'using' can only be applied to variables of type struct");
- break;
}
}
}
- ast_node(bs, BlockStmt, body);
+
+ for_array(i, using_entities) {
+ Entity *e = using_entities[i].e;
+ Entity *uvar = using_entities[i].uvar;
+ Entity *prev = scope_insert(ctx->scope, uvar);
+ if (prev != nullptr) {
+ error(e->token, "Namespace collision while 'using' '%.*s' of: %.*s", LIT(e->token.string), LIT(prev->token.string));
+ break;
+ }
+ }
+
check_open_scope(ctx, body);
- check_stmt_list(ctx, bs->stmts, Stmt_CheckScopeDecls);
- if (type->Proc.result_count > 0) {
- if (!check_is_terminating(body)) {
- if (token.kind == Token_Ident) {
- error(bs->close, "Missing return statement at the end of the procedure '%.*s'", LIT(token.string));
- } else {
- // NOTE(bill): Anonymous procedure (lambda)
- error(bs->close, "Missing return statement at the end of the procedure");
+ {
+ for_array(i, using_entities) {
+ Entity *e = using_entities[i].e;
+ Entity *uvar = using_entities[i].uvar;
+ Entity *prev = scope_insert(ctx->scope, uvar);
+ // NOTE(bill): Don't err here
+ }
+
+ check_stmt_list(ctx, bs->stmts, Stmt_CheckScopeDecls);
+
+ if (type->Proc.result_count > 0) {
+ if (!check_is_terminating(body)) {
+ if (token.kind == Token_Ident) {
+ error(bs->close, "Missing return statement at the end of the procedure '%.*s'", LIT(token.string));
+ } else {
+ // NOTE(bill): Anonymous procedure (lambda)
+ error(bs->close, "Missing return statement at the end of the procedure");
+ }
}
}
}
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 99fe6695b..7a6e0f22d 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -7164,7 +7164,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
if (o->mode == Addressing_Constant) {
max_count = o->value.value_string.len;
}
- o->type = t_string;
+ o->type = type_deref(o->type);
}
break;