diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 3299a330b..525a13ce0 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -240,7 +240,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti CheckerContext nctx = *c; Scope *scope = create_scope(base_entity->scope, a); - scope->is_proc = true; + scope->flags |= ScopeFlag_Proc; nctx.scope = scope; nctx.allow_polymorphic_types = true; if (nctx.polymorphic_scope == nullptr) { @@ -2578,7 +2578,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ // NOTE(bill): Builtin's are in the universal scope which is part of every scopes hierarchy // This means that we should just ignore the found result through it is_declared = false; - } else if (entity->scope->is_global && !import_scope->is_global) { + } else if ((entity->scope->flags&ScopeFlag_Global) == ScopeFlag_Global && (import_scope->flags&ScopeFlag_Global) == 0) { is_declared = false; } } @@ -3305,7 +3305,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_type_info_of: { // proc type_info_of(Type) -> ^Type_Info - if (c->scope->is_global) { + if (c->scope->flags&ScopeFlag_Global) { compiler_error("'type_info_of' Cannot be declared within the runtime package due to how the internals of the compiler works"); } @@ -3340,7 +3340,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_typeid_of: { // proc typeid_of(Type) -> typeid - if (c->scope->is_global) { + if (c->scope->flags&ScopeFlag_Global) { compiler_error("'typeid_of' Cannot be declared within the runtime package due to how the internals of the compiler works"); } diff --git a/src/check_type.cpp b/src/check_type.cpp index bbb67667e..931117f79 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -608,7 +608,7 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast enum_type->Enum.is_export = et->is_export; if (et->is_export) { Scope *parent = ctx->scope->parent; - if (parent->is_file) { + if (parent->flags&ScopeFlag_File) { // NOTE(bill): Use package scope parent = parent->parent; } diff --git a/src/checker.cpp b/src/checker.cpp index a0049137f..44bde3b73 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -141,8 +141,8 @@ int import_graph_node_cmp(ImportGraphNode **data, isize i, isize j) { GB_ASSERT(x->scope != y->scope); - bool xg = x->scope->is_global; - bool yg = y->scope->is_global; + bool xg = (x->scope->flags&ScopeFlag_Global) != 0; + bool yg = (y->scope->flags&ScopeFlag_Global) != 0; if (xg != yg) return xg ? -1 : +1; if (xg && yg) return x->pkg->id < y->pkg->id ? +1 : -1; if (x->dep_count < y->dep_count) return -1; @@ -237,7 +237,7 @@ Scope *create_scope_from_file(CheckerContext *c, AstFile *f) { array_reserve(&s->delayed_imports, f->imports.count); array_reserve(&s->delayed_directives, f->directive_count); - s->is_file = true; + s->flags |= ScopeFlag_File; s->file = f; f->scope = s; @@ -254,22 +254,20 @@ Scope *create_scope_from_package(CheckerContext *c, AstPackage *pkg) { isize init_elements_capacity = 2*decl_count; Scope *s = create_scope(builtin_scope, c->allocator, init_elements_capacity); - s->is_pkg = true; + s->flags |= ScopeFlag_Pkg; s->pkg = pkg; pkg->scope = s; - if (pkg->fullpath == c->checker->parser->init_fullpath) { - s->is_init = true; - } else { - s->is_init = pkg->kind == Package_Init; + if (pkg->fullpath == c->checker->parser->init_fullpath || pkg->kind == Package_Init) { + s->flags |= ScopeFlag_Init; } if (pkg->kind == Package_Runtime) { - s->is_global = true; + s->flags |= ScopeFlag_Global; } - if (s->is_init || s->is_global) { - s->has_been_imported = true; + if (s->flags & (ScopeFlag_Init|ScopeFlag_Global)) { + s->flags |= ScopeFlag_HasBeenImported; } return s; @@ -317,12 +315,12 @@ void check_open_scope(CheckerContext *c, Ast *node) { add_scope(c, node, scope); switch (node->kind) { case Ast_ProcType: - scope->is_proc = true; + scope->flags |= ScopeFlag_Proc; break; case Ast_StructType: case Ast_EnumType: case Ast_UnionType: - scope->is_struct = true; + scope->flags |= ScopeFlag_Type; break; } c->scope = scope; @@ -357,7 +355,7 @@ void scope_lookup_parent(Scope *scope, String name, Scope **scope_, Entity **ent continue; } if (e->kind == Entity_Variable && - !e->scope->is_file) { + !(e->scope->flags&ScopeFlag_File)) { continue; } } @@ -367,10 +365,10 @@ void scope_lookup_parent(Scope *scope, String name, Scope **scope_, Entity **ent return; } - if (s->is_proc) { + if (s->flags&ScopeFlag_Proc) { gone_thru_proc = true; } - if (s->is_pkg) { + if (s->flags&ScopeFlag_Pkg) { gone_thru_package = true; } } @@ -534,7 +532,7 @@ void init_universal(void) { builtin_pkg->kind = Package_Normal; builtin_scope = create_scope(nullptr, a); - builtin_scope->is_pkg = true; + builtin_scope->flags |= ScopeFlag_Pkg | ScopeFlag_Global; builtin_scope->pkg = builtin_pkg; builtin_pkg->scope = builtin_scope; @@ -907,7 +905,7 @@ void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, Dec if (e->scope != nullptr) { Scope *scope = e->scope; - if (scope->is_file && is_entity_kind_exported(e->kind)) { + if ((scope->flags&ScopeFlag_File) && is_entity_kind_exported(e->kind)) { AstPackage *pkg = scope->file->pkg; GB_ASSERT(pkg->scope == scope->parent); GB_ASSERT(c->pkg == pkg); @@ -1947,7 +1945,7 @@ void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array *attr default: return; } - if (!(ctx->scope->is_file && ctx->scope->file->pkg->kind == Package_Runtime)) { + if (!((ctx->scope->flags&ScopeFlag_File) && ctx->scope->file->pkg->kind == Package_Runtime)) { return; } @@ -2004,7 +2002,7 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { ast_node(vd, ValueDecl, decl); if (vd->is_mutable) { - if (!c->scope->is_file) { + if (!(c->scope->flags&ScopeFlag_File)) { // NOTE(bill): local scope -> handle later and in order return; } @@ -2080,7 +2078,7 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { d->type_expr = init; d->init_expr = init; } else if (init->kind == Ast_ProcLit) { - if (c->scope->is_struct) { + if (c->scope->flags&ScopeFlag_Type) { error(name, "Procedure declarations are not allowed within a struct"); continue; } @@ -2171,7 +2169,7 @@ void check_collect_entities(CheckerContext *c, Array const &nodes) { for_array(decl_index, nodes) { Ast *decl = nodes[decl_index]; if (!is_ast_decl(decl) && !is_ast_when_stmt(decl)) { - if (c->scope->is_file && decl->kind == Ast_ExprStmt) { + if ((c->scope->flags&ScopeFlag_File) != 0 && decl->kind == Ast_ExprStmt) { Ast *expr = decl->ExprStmt.expr; if (expr->kind == Ast_CallExpr && expr->CallExpr.proc->kind == Ast_BasicDirective) { if (c->collect_delayed_decls) { @@ -2196,7 +2194,7 @@ void check_collect_entities(CheckerContext *c, Array const &nodes) { case_end; case_ast_node(id, ImportDecl, decl); - if (!c->scope->is_file) { + if ((c->scope->flags&ScopeFlag_File) == 0) { error(decl, "import declarations are only allowed in the file scope"); // NOTE(bill): _Should_ be caught by the parser // TODO(bill): Better error handling if it isn't @@ -2208,7 +2206,7 @@ void check_collect_entities(CheckerContext *c, Array const &nodes) { case_end; case_ast_node(fl, ForeignImportDecl, decl); - if (!c->scope->is_file) { + if ((c->scope->flags&ScopeFlag_File) == 0) { error(decl, "%.*s declarations are only allowed in the file scope", LIT(fl->token.string)); // NOTE(bill): _Should_ be caught by the parser // TODO(bill): Better error handling if it isn't @@ -2222,7 +2220,7 @@ void check_collect_entities(CheckerContext *c, Array const &nodes) { case_end; default: - if (c->scope->is_file) { + if (c->scope->flags&ScopeFlag_File) { error(decl, "Only declarations are allowed at file scope"); } break; @@ -2231,7 +2229,7 @@ void check_collect_entities(CheckerContext *c, Array const &nodes) { // NOTE(bill): 'when' stmts need to be handled after the other as the condition may refer to something // declared after this stmt in source - if (!c->scope->is_file || c->collect_delayed_decls) { + if ((c->scope->flags&ScopeFlag_File) == 0 || c->collect_delayed_decls) { for_array(i, nodes) { Ast *node = nodes[i]; switch (node->kind) { @@ -2257,7 +2255,7 @@ void check_all_global_entities(Checker *c) { CheckerContext ctx = c->init_ctx; - GB_ASSERT(d->scope->is_file); + GB_ASSERT(d->scope->flags&ScopeFlag_File); AstFile *file = d->scope->file; add_curr_ast_file(&ctx, file); AstPackage *pkg = file->pkg; @@ -2522,7 +2520,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { Token token = id->relpath; Scope *parent_scope = ctx->scope; - GB_ASSERT(parent_scope->is_file); + GB_ASSERT(parent_scope->flags&ScopeFlag_File); auto *pkgs = &ctx->checker->info.packages; @@ -2546,7 +2544,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { scope = pkg->scope; } } - GB_ASSERT(scope->is_pkg); + GB_ASSERT(scope->flags&ScopeFlag_Pkg); if (ptr_set_exists(&parent_scope->imported, scope)) { @@ -2580,8 +2578,8 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { } if (id->is_using) { - if (parent_scope->is_global) { - error(id->import_name, "'builtin' package imports cannot use using"); + if (parent_scope->flags & ScopeFlag_Global) { + error(id->import_name, "built-in package imports cannot use using"); return; } @@ -2597,7 +2595,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { } } - scope->has_been_imported = true; + scope->flags |= ScopeFlag_HasBeenImported; } @@ -2608,7 +2606,7 @@ void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { ast_node(fl, ForeignImportDecl, decl); Scope *parent_scope = ctx->scope; - GB_ASSERT(parent_scope->is_file); + GB_ASSERT(parent_scope->flags&ScopeFlag_File); String fullpath = fl->fullpath; String library_name = path_to_entity_name(fl->library_name.string, fullpath); @@ -2743,7 +2741,7 @@ bool collect_file_decls_from_when_stmt(CheckerContext *ctx, AstWhenStmt *ws) { } bool collect_file_decls(CheckerContext *ctx, Array const &decls) { - GB_ASSERT(ctx->scope->is_file); + GB_ASSERT(ctx->scope->flags&ScopeFlag_File); if (collect_checked_packages_from_decl_list(ctx->checker, decls)) { return true; @@ -2893,7 +2891,7 @@ void check_import_entities(Checker *c) { bool new_files = false; for_array(i, package_order) { ImportGraphNode *node = package_order[i]; - GB_ASSERT(node->scope->is_pkg); + GB_ASSERT(node->scope->flags&ScopeFlag_Pkg); AstPackage *pkg = node->scope->pkg; if (!ptr_set_exists(&c->checked_packages, pkg)) { continue; @@ -2943,7 +2941,7 @@ void check_import_entities(Checker *c) { for_array(i, package_order) { ImportGraphNode *node = package_order[i]; - GB_ASSERT(node->scope->is_pkg); + GB_ASSERT(node->scope->flags&ScopeFlag_Pkg); AstPackage *pkg = node->scope->pkg; for_array(i, pkg->files) { @@ -3160,7 +3158,7 @@ void check_parsed_files(Checker *c) { HashKey key = hash_string(p->fullpath); map_set(&c->info.packages, key, p); - if (scope->is_init) { + if (scope->flags&ScopeFlag_Init) { c->info.init_scope = scope; } if (p->kind == Package_Runtime) { @@ -3269,7 +3267,7 @@ void check_parsed_files(Checker *c) { if (!build_context.is_dll) { Scope *s = c->info.init_scope; GB_ASSERT(s != nullptr); - GB_ASSERT(s->is_init); + GB_ASSERT(s->flags&ScopeFlag_Init); Entity *e = scope_lookup_current(s, str_lit("main")); if (e == nullptr) { Token token = {}; diff --git a/src/checker.hpp b/src/checker.hpp index 3dc47f8c8..74023dd83 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -211,25 +211,31 @@ struct ProcInfo { +enum ScopeFlag { + ScopeFlag_Pkg = 1<<1, + ScopeFlag_Global = 1<<2, + ScopeFlag_File = 1<<3, + ScopeFlag_Init = 1<<4, + ScopeFlag_Proc = 1<<5, + ScopeFlag_Type = 1<<6, + + + ScopeFlag_HasBeenImported = 1<<10, // This is only applicable to file scopes +}; + struct Scope { - Ast * node; - Scope * parent; - Scope * prev, *next; - Scope * first_child; - Scope * last_child; - Map elements; // Key: String + Ast * node; + Scope * parent; + Scope * prev, *next; + Scope * first_child; + Scope * last_child; + Map elements; // Key: String - Array delayed_directives; - Array delayed_imports; - PtrSet imported; - bool is_proc; - bool is_global; - bool is_pkg; - bool is_file; - bool is_init; - bool is_struct; - bool has_been_imported; // This is only applicable to file scopes + Array delayed_directives; + Array delayed_imports; + PtrSet imported; + i32 flags; // ScopeFlag union { AstPackage *pkg; AstFile * file; diff --git a/src/ir.cpp b/src/ir.cpp index 92169f48f..5b97a79d2 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8312,13 +8312,13 @@ void ir_gen_tree(irGen *s) { if (e->kind == Entity_Variable) { global_variable_max_count++; } else if (e->kind == Entity_Procedure && !is_global) { - if (e->scope->is_init && name == "main") { + if ((e->scope->flags&ScopeFlag_Init) && name == "main") { GB_ASSERT(e == entry_point); // entry_point = e; } if (e->Procedure.is_export || (e->Procedure.link_name.len > 0) || - (e->scope->is_file && e->Procedure.link_name.len > 0)) { + ((e->scope->flags&ScopeFlag_File) && e->Procedure.link_name.len > 0)) { if (!has_dll_main && name == "DllMain") { has_dll_main = true; } else if (!has_win_main && name == "WinMain") { @@ -8345,7 +8345,7 @@ void ir_gen_tree(irGen *s) { Entity *e = d->entity; - if (!e->scope->is_file) { + if ((e->scope->flags & ScopeFlag_File) == 0) { continue; } @@ -8400,12 +8400,12 @@ void ir_gen_tree(irGen *s) { DeclInfo *decl = e->decl_info; Scope * scope = e->scope; - if (!scope->is_file) { + if ((scope->flags & ScopeFlag_File) == 0) { continue; } Scope *package_scope = scope->parent; - GB_ASSERT(package_scope->is_pkg); + GB_ASSERT(package_scope->flags & ScopeFlag_Pkg); switch (e->kind) { case Entity_Variable: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 880e9d5ef..88b172d7f 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -863,8 +863,7 @@ void ir_print_value(irFileBuffer *f, irModule *m, irValue *value, Type *type_hin Scope *scope = e->scope; bool in_global_scope = false; if (scope != nullptr) { - // TODO(bill): Fix this rule. What should it be? - in_global_scope = scope->is_global || scope->is_init; + in_global_scope = (scope->flags & ScopeFlag_Global) != 0; } ir_print_encoded_global(f, ir_get_global_name(m, value), in_global_scope); break; @@ -1753,8 +1752,7 @@ void print_llvm_ir(irGen *ir) { bool in_global_scope = false; if (scope != nullptr) { // TODO(bill): Fix this rule. What should it be? - in_global_scope = scope->is_global || scope->is_init; - // in_global_scope = value->Global.name_is_not_mangled; + in_global_scope = (scope->flags & ScopeFlag_Global) != 0; } ir_print_encoded_global(f, ir_get_global_name(m, v), in_global_scope);