diff options
| author | gingerBill <bill@gingerbill.org> | 2018-05-28 15:57:53 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2018-05-28 15:57:53 +0100 |
| commit | 642aa0bc4b47752d4ea52f97dec3d478470b597e (patch) | |
| tree | 12a086696c6dc2948ee169bacb4bb7fa50c4af99 /src/check_decl.cpp | |
| parent | 45b3067068a95f3440c4caab63525e3fd6722d00 (diff) | |
Refactor: use CheckerContext rather than Checker in type checking part
Diffstat (limited to 'src/check_decl.cpp')
| -rw-r--r-- | src/check_decl.cpp | 171 |
1 files changed, 84 insertions, 87 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp index acfb3140d..42b578605 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1,8 +1,8 @@ bool check_is_terminating(AstNode *node); -void check_stmt (Checker *c, AstNode *node, u32 flags); +void check_stmt (CheckerContext *ctx, AstNode *node, u32 flags); // NOTE(bill): 'content_name' is for debugging and error messages -Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String context_name) { +Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *operand, String context_name) { if (operand->mode == Addressing_Invalid || operand->type == t_invalid || e->type == t_invalid) { @@ -27,7 +27,7 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex if (e->type == nullptr) { error(operand->expr, "Cannot determine type from overloaded procedure '%.*s'", LIT(operand->proc_group->token.string)); } else { - check_assignment(c, operand, e->type, str_lit("variable assignment")); + check_assignment(ctx, operand, e->type, str_lit("variable assignment")); if (operand->mode != Addressing_Type) { return operand->type; } @@ -79,9 +79,9 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex e->type = t; } - e->parent_proc_decl = c->context.curr_proc_decl; + e->parent_proc_decl = ctx->curr_proc_decl; - check_assignment(c, operand, e->type, context_name); + check_assignment(ctx, operand, e->type, context_name); if (operand->mode == Addressing_Invalid) { return nullptr; } @@ -89,7 +89,7 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex return e->type; } -void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, Array<AstNode *> inits, String context_name) { +void check_init_variables(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<AstNode *> inits, String context_name) { if ((lhs == nullptr || lhs_count == 0) && inits.count == 0) { return; } @@ -97,9 +97,9 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, Array<AstNo // NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be // an extra allocation - auto operands = array_make<Operand>(c->allocator, 0, 2*lhs_count); + auto operands = array_make<Operand>(ctx->allocator, 0, 2*lhs_count); defer (array_free(&operands)); - check_unpack_arguments(c, lhs, lhs_count, &operands, inits, true); + check_unpack_arguments(ctx, lhs, lhs_count, &operands, inits, true); isize rhs_count = operands.count; for_array(i, operands) { @@ -111,9 +111,9 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, Array<AstNo isize max = gb_min(lhs_count, rhs_count); for (isize i = 0; i < max; i++) { Entity *e = lhs[i]; - DeclInfo *d = decl_info_of_entity(&c->info, e); + DeclInfo *d = decl_info_of_entity(&ctx->checker->info, e); Operand *o = &operands[i]; - check_init_variable(c, e, o, context_name); + check_init_variable(ctx, e, o, context_name); if (d != nullptr) { d->init_expr = o->expr; } @@ -123,7 +123,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, Array<AstNo } } -void check_init_constant(Checker *c, Entity *e, Operand *operand) { +void check_init_constant(CheckerContext *ctx, Entity *e, Operand *operand) { if (operand->mode == Addressing_Invalid || operand->type == t_invalid || e->type == t_invalid) { @@ -157,12 +157,12 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) { e->type = operand->type; } - check_assignment(c, operand, e->type, str_lit("constant declaration")); + check_assignment(ctx, operand, e->type, str_lit("constant declaration")); if (operand->mode == Addressing_Invalid) { return; } - e->parent_proc_decl = c->context.curr_proc_decl; + e->parent_proc_decl = ctx->curr_proc_decl; e->Constant.value = operand->value; } @@ -217,10 +217,10 @@ AstNode *remove_type_alias_clutter(AstNode *node) { } } -void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) { +void check_type_decl(CheckerContext *ctx, Entity *e, AstNode *type_expr, Type *def) { GB_ASSERT(e->type == nullptr); - DeclInfo *decl = decl_info_of_entity(&c->info, e); + DeclInfo *decl = decl_info_of_entity(&ctx->checker->info, e); if (decl != nullptr && decl->attributes.count > 0) { error(decl->attributes[0], "Attributes are not allowed on type declarations"); } @@ -238,9 +238,9 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) { } e->type = named; - check_type_path_push(c, e); - Type *bt = check_type_expr(c, te, named); - check_type_path_pop(c); + check_type_path_push(ctx, e); + Type *bt = check_type_expr(ctx, te, named); + check_type_path_pop(ctx); named->Named.base = base_type(bt); if (!is_distinct) { @@ -260,7 +260,7 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) { // } } -void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, Type *named_type) { +void check_const_decl(CheckerContext *ctx, Entity *e, AstNode *type_expr, AstNode *init, Type *named_type) { GB_ASSERT(e->type == nullptr); GB_ASSERT(e->kind == Entity_Constant); @@ -271,7 +271,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, e->flags |= EntityFlag_Visited; if (type_expr) { - Type *t = check_type(c, type_expr); + Type *t = check_type(ctx, type_expr); if (!is_type_constant_type(t)) { gbString str = type_to_string(t); error(type_expr, "Invalid constant type '%s'", str); @@ -287,11 +287,11 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, if (init != nullptr) { Entity *entity = nullptr; if (init->kind == AstNode_Ident) { - entity = check_ident(c, &operand, init, nullptr, e->type, true); + entity = check_ident(ctx, &operand, init, nullptr, e->type, true); } else if (init->kind == AstNode_SelectorExpr) { - entity = check_selector(c, &operand, init, e->type); + entity = check_selector(ctx, &operand, init, e->type); } else { - check_expr_or_type(c, &operand, init, e->type); + check_expr_or_type(ctx, &operand, init, e->type); } switch (operand.mode) { @@ -299,12 +299,12 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, e->kind = Entity_TypeName; e->type = nullptr; - DeclInfo *d = c->context.decl; + DeclInfo *d = ctx->decl; if (d->type_expr != nullptr) { error(e->token, "A type declaration cannot have an type parameter"); } d->type_expr = d->init_expr; - check_type_decl(c, e, d->type_expr, named_type); + check_type_decl(ctx, e, d->type_expr, named_type); return; } @@ -360,10 +360,10 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, } if (init != nullptr) { - check_expr_or_type(c, &operand, init, e->type); + check_expr_or_type(ctx, &operand, init, e->type); } - check_init_constant(c, e, &operand); + check_init_constant(ctx, e, &operand); if (operand.mode == Addressing_Invalid || base_type(operand.type) == t_invalid) { @@ -373,7 +373,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, } - DeclInfo *decl = decl_info_of_entity(&c->info, e); + DeclInfo *decl = decl_info_of_entity(&ctx->checker->info, e); if (decl != nullptr && decl->attributes.count > 0) { error(decl->attributes[0], "Attributes are not allowed on constant value declarations"); } @@ -433,7 +433,7 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) { return true; } -void init_entity_foreign_library(Checker *c, Entity *e) { +void init_entity_foreign_library(CheckerContext *ctx, Entity *e) { AstNode *ident = nullptr; Entity **foreign_library = nullptr; @@ -456,7 +456,7 @@ void init_entity_foreign_library(Checker *c, Entity *e) { error(ident, "foreign library names must be an identifier"); } else { String name = ident->Ident.token.string; - Entity *found = scope_lookup_entity(c->context.scope, name); + Entity *found = scope_lookup_entity(ctx->scope, name); if (found == nullptr) { if (is_blank_ident(name)) { error(ident, "'_' cannot be used as a value type"); @@ -469,18 +469,18 @@ void init_entity_foreign_library(Checker *c, Entity *e) { // TODO(bill): Extra stuff to do with library names? *foreign_library = found; found->LibraryName.used = true; - add_entity_use(c, ident, found); + add_entity_use(ctx, ident, found); } } } -String handle_link_name(Checker *c, Token token, String link_name, String link_prefix) { +String handle_link_name(CheckerContext *ctx, Token token, String link_name, String link_prefix) { if (link_prefix.len > 0) { if (link_name.len > 0) { error(token, "'link_name' and 'link_prefix' cannot be used together"); } else { isize len = link_prefix.len + token.string.len; - u8 *name = gb_alloc_array(c->allocator, u8, len+1); + u8 *name = gb_alloc_array(ctx->allocator, u8, len+1); gb_memmove(name, &link_prefix[0], link_prefix.len); gb_memmove(name+link_prefix.len, &token.string[0], token.string.len); name[len] = 0; @@ -491,7 +491,7 @@ String handle_link_name(Checker *c, Token token, String link_name, String link_p return link_name; } -void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { +void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { GB_ASSERT(e->type == nullptr); if (d->proc_lit->kind != AstNode_ProcLit) { // TOOD(bill): Better error message @@ -508,14 +508,13 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { e->type = proc_type; ast_node(pl, ProcLit, d->proc_lit); - check_open_scope(c, pl->type); - defer (check_close_scope(c)); + check_open_scope(ctx, pl->type); + defer (check_close_scope(ctx)); - auto prev_context = c->context; - c->context.allow_polymorphic_types = true; - check_procedure_type(c, proc_type, pl->type); - c->context = prev_context; + auto tmp_ctx = *ctx; + tmp_ctx.allow_polymorphic_types = true; + check_procedure_type(&tmp_ctx, proc_type, pl->type); TypeProc *pt = &proc_type->Proc; @@ -526,11 +525,11 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { AttributeContext ac = make_attribute_context(e->Procedure.link_prefix); if (d != nullptr) { - check_decl_attributes(c, d->attributes, proc_decl_attribute, &ac); + check_decl_attributes(ctx, d->attributes, proc_decl_attribute, &ac); } e->deprecated_message = ac.deprecated_message; - ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix); + ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix); if (e->pkg != nullptr && e->token.string == "main") { if (pt->param_count != 0 || @@ -545,10 +544,10 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { } pt->calling_convention = ProcCC_Contextless; if (e->pkg->kind == Package_Init) { - if (c->info.entry_point != nullptr) { + if (ctx->checker->info.entry_point != nullptr) { error(e->token, "Redeclaration of the entry pointer procedure 'main'"); } else { - c->info.entry_point = e; + ctx->checker->info.entry_point = e; } } } @@ -576,11 +575,11 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { error(pl->body, "A procedure with a '#c_vararg' field cannot have a body and must be foreign"); } - d->scope = c->context.scope; + d->scope = ctx->scope; GB_ASSERT(pl->body->kind == AstNode_BlockStmt); if (!pt->is_polymorphic) { - check_procedure_later(c, c->context.file, e->token, d, proc_type, pl->body, pl->tags); + check_procedure_later(ctx->checker, ctx->file, e->token, d, proc_type, pl->body, pl->tags); } } else if (!is_foreign) { if (e->Procedure.is_export) { @@ -608,9 +607,9 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { e->Procedure.is_foreign = true; e->Procedure.link_name = name; - init_entity_foreign_library(c, e); + init_entity_foreign_library(ctx, e); - auto *fp = &c->info.foreigns; + auto *fp = &ctx->checker->info.foreigns; HashKey key = hash_string(name); Entity **found = map_get(fp, key); if (found) { @@ -642,7 +641,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { name = e->Procedure.link_name; } if (e->Procedure.link_name.len > 0 || is_export) { - auto *fp = &c->info.foreigns; + auto *fp = &ctx->checker->info.foreigns; HashKey key = hash_string(name); Entity **found = map_get(fp, key); if (found) { @@ -662,7 +661,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { } } -void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, Array<AstNode *> init_expr_list) { +void check_var_decl(CheckerContext *ctx, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, Array<AstNode *> init_expr_list) { GB_ASSERT(e->type == nullptr); GB_ASSERT(e->kind == Entity_Variable); @@ -675,18 +674,18 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count AttributeContext ac = make_attribute_context(e->Variable.link_prefix); ac.init_expr_list_count = init_expr_list.count; - DeclInfo *decl = decl_info_of_entity(&c->info, e); + DeclInfo *decl = decl_info_of_entity(&ctx->checker->info, e); if (decl != nullptr) { - check_decl_attributes(c, decl->attributes, var_decl_attribute, &ac); + check_decl_attributes(ctx, decl->attributes, var_decl_attribute, &ac); } - ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix); + ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix); e->Variable.thread_local_model = ac.thread_local_model; String context_name = str_lit("variable declaration"); if (type_expr != nullptr) { - e->type = check_type(c, type_expr); + e->type = check_type(ctx, type_expr); } if (e->type != nullptr) { if (is_type_polymorphic(base_type(e->type))) { @@ -707,7 +706,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count if (init_expr_list.count > 0) { error(e->token, "A foreign variable declaration cannot have a default value"); } - init_entity_foreign_library(c, e); + init_entity_foreign_library(ctx, e); } if (ac.link_name.len > 0) { e->Variable.link_name = ac.link_name; @@ -718,7 +717,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count if (e->Variable.link_name.len > 0) { name = e->Variable.link_name; } - auto *fp = &c->info.foreigns; + auto *fp = &ctx->checker->info.foreigns; HashKey key = hash_string(name); Entity **found = map_get(fp, key); if (found) { @@ -750,17 +749,17 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count } } - check_init_variables(c, entities, entity_count, init_expr_list, context_name); + check_init_variables(ctx, entities, entity_count, init_expr_list, context_name); } -void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) { +void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, DeclInfo *d) { GB_ASSERT(pg_entity->kind == Entity_ProcGroup); auto *pge = &pg_entity->ProcGroup; String proc_group_name = pg_entity->token.string; ast_node(pg, ProcGroup, d->init_expr); - pge->entities = array_make<Entity*>(c->allocator, 0, pg->args.count); + pge->entities = array_make<Entity*>(ctx->allocator, 0, pg->args.count); // NOTE(bill): This must be set here to prevent cycles in checking if someone // places the entity within itself @@ -775,9 +774,9 @@ void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) { Entity *e = nullptr; Operand o = {}; if (arg->kind == AstNode_Ident) { - e = check_ident(c, &o, arg, nullptr, nullptr, true); + e = check_ident(ctx, &o, arg, nullptr, nullptr, true); } else if (arg->kind == AstNode_SelectorExpr) { - e = check_selector(c, &o, arg, nullptr); + e = check_selector(ctx, &o, arg, nullptr); } if (e == nullptr) { error(arg, "Expected a valid entity name in procedure group, got %.*s", LIT(ast_node_strings[arg->kind])); @@ -865,7 +864,7 @@ void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) { } -void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { +void check_entity_decl(CheckerContext *ctx, Entity *e, DeclInfo *d, Type *named_type) { if (e->state == EntityState_Resolved) { return; } @@ -893,7 +892,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { #endif if (d == nullptr) { - d = decl_info_of_entity(&c->info, e); + d = decl_info_of_entity(&ctx->checker->info, e); if (d == nullptr) { // TODO(bill): Err here? e->type = t_invalid; @@ -904,43 +903,41 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { } } - CheckerContext prev = c->context; - c->context.scope = d->scope; - c->context.decl = d; - c->context.type_level = 0; + CheckerContext c = *ctx; + c.scope = d->scope; + c.decl = d; + c.type_level = 0; - e->parent_proc_decl = c->context.curr_proc_decl; + e->parent_proc_decl = c.curr_proc_decl; e->state = EntityState_InProgress; switch (e->kind) { case Entity_Variable: - check_var_decl(c, e, d->entities, d->entity_count, d->type_expr, d->init_expr_list); + check_var_decl(&c, e, d->entities, d->entity_count, d->type_expr, d->init_expr_list); break; case Entity_Constant: - check_const_decl(c, e, d->type_expr, d->init_expr, named_type); + check_const_decl(&c, e, d->type_expr, d->init_expr, named_type); break; case Entity_TypeName: { - check_type_decl(c, e, d->type_expr, named_type); + check_type_decl(&c, e, d->type_expr, named_type); break; } case Entity_Procedure: - check_proc_decl(c, e, d); + check_proc_decl(&c, e, d); break; case Entity_ProcGroup: - check_proc_group_decl(c, e, d); + check_proc_group_decl(&c, e, d); break; } e->state = EntityState_Resolved; - c->context = prev; - #undef TIME_SECTION } -void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) { +void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *type, AstNode *body) { if (body == nullptr) { return; } @@ -954,14 +951,14 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod proc_name = str_lit("(anonymous-procedure)"); } - CheckerContext old_context = c->context; - defer (c->context = old_context); + CheckerContext new_ctx = *ctx_; + CheckerContext *ctx = &new_ctx; - c->context.scope = decl->scope; - c->context.decl = decl; - c->context.proc_name = proc_name; - c->context.curr_proc_decl = decl; - c->context.curr_proc_sig = type; + ctx->scope = decl->scope; + ctx->decl = decl; + ctx->proc_name = proc_name; + ctx->curr_proc_decl = decl; + ctx->curr_proc_sig = type; GB_ASSERT(type->kind == Type_Proc); if (type->Proc.param_count > 0) { @@ -981,7 +978,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod if (t->kind == Type_Struct) { Scope *scope = t->Struct.scope; if (scope == nullptr) { - scope = scope_of_node(&c->info, t->Struct.node); + scope = scope_of_node(&ctx->checker->info, t->Struct.node); } GB_ASSERT(scope != nullptr); for_array(i, scope->elements.entries) { @@ -991,7 +988,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod uvar->Variable.is_immutable = is_immutable; if (is_value) uvar->flags |= EntityFlag_Value; - Entity *prev = scope_insert_entity(c->context.scope, uvar); + Entity *prev = scope_insert_entity(ctx->scope, uvar); if (prev != nullptr) { error(e->token, "Namespace collision while 'using' '%.*s' of: %.*s", LIT(name), LIT(prev->token.string)); break; @@ -1006,7 +1003,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod } ast_node(bs, BlockStmt, body); - check_stmt_list(c, bs->stmts, Stmt_CheckScopeDecls); + check_stmt_list(ctx, bs->stmts, Stmt_CheckScopeDecls); if (type->Proc.result_count > 0) { if (!check_is_terminating(body)) { if (token.kind == Token_Ident) { @@ -1017,7 +1014,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod } } - check_scope_usage(c, c->context.scope); + check_scope_usage(ctx->checker, ctx->scope); if (decl->parent != nullptr) { // NOTE(bill): Add the dependencies from the procedure literal (lambda) |