1 /// Copyright: Copyright (c) 2017-2019 Andrey Penechko. 2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 3 /// Authors: Andrey Penechko. 4 module vox.fe.ast.decl.scope_; 5 6 import vox.all; 7 8 enum ScopeKind : ubyte { 9 no_scope, // scope created by @attr{} or by #version or #if or #foreach 10 local, // function 11 member, // struct, enum 12 global, // module 13 } 14 15 struct ScopeIndex 16 { 17 uint storageIndex; 18 bool isDefined() const { return storageIndex != 0; } 19 bool isUndefined() const { return storageIndex == 0; } 20 21 bool opCast(T : bool)() const { 22 return storageIndex != 0; 23 } 24 25 Scope* get_scope(CompilationContext* c) { return c.getAstScope(this); } 26 27 // null scope index is treated as empty scope and results in null AstIndex 28 AstIndex lookup_scope(Identifier id, CompilationContext* c) { 29 if (isUndefined) return AstIndex.init; 30 Scope* sc = c.getAstScope(this); 31 return sc.symbols.get(id, AstIndex.init); 32 } 33 void insert_scope(Identifier id, AstIndex nodeIndex, CompilationContext* c) { 34 assert(isDefined, "scope is undefined"); 35 Scope* sc = c.getAstScope(this); 36 sc.insert(id, nodeIndex, c); 37 } 38 } 39 40 /// 41 struct Scope 42 { 43 /// 44 AstNodeMap symbols; 45 /// Imported modules 46 AstNodes imports; 47 /// 48 ScopeIndex parentScope; 49 /// This node is owner of all the definitions inside of this scope 50 AstIndex owner; 51 /// 52 ScopeKind kind; 53 /// 54 string debugName; 55 56 /// Constructs and inserts symbol with id 57 void insert(Identifier id, AstIndex nodeIndex, CompilationContext* c) 58 { 59 AstNode* node = nodeIndex.get_node(c); 60 if (auto s = symbols.get(id, AstIndex.init)) 61 { 62 c.error(node.loc, 63 "declaration `%s` is already defined at %s", 64 c.idString(id), FmtSrcLoc(s.get_node(c).loc, c)); 65 } 66 symbols.put(c.arrayArena, id, nodeIndex); 67 } 68 } 69 70 void post_clone_scope(Scope* node, ref CloneState state) 71 { 72 // Scope.symbols/imports dont need fixing, because no symbols are registered at this point 73 state.fixScope(node.parentScope); 74 state.fixAstIndex(node.owner); 75 } 76 77 mixin template ScopeDeclNodeData(AstType _astType, int default_flags = 0, AstNodeState _init_state = AstNodeState.parse_done) { 78 mixin AstNodeData!(_astType, default_flags, _init_state); 79 /// Each node can be struct, function or variable 80 AstNodes declarations; 81 }