1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity average) 4 module dil.semantic.Scope; 5 6 import dil.semantic.Symbol, 7 dil.semantic.Symbols; 8 import dil.lexer.Identifier; 9 import common; 10 11 /// Models a hierarchy of environments. 12 class Scope 13 { 14 Scope parent; /// The surrounding scope, or null if this is the root scope. 15 16 ScopeSymbol symbol; /// The current symbol with the symbol table. 17 18 /// Constructs a Scope. 19 this(Scope parent, ScopeSymbol symbol) 20 { 21 this.parent = parent; 22 this.symbol = symbol; 23 } 24 25 /// Finds a symbol in this scope. 26 /// Params: 27 /// name = The name of the symbol. 28 Symbol lookup(Identifier* name) 29 { 30 return symbol.lookup(name); 31 } 32 33 /// Searches for a symbol in this scope and all enclosing scopes. 34 /// Params: 35 /// name = The name of the symbol. 36 Symbol search(Identifier* name) 37 { 38 Symbol symbol; 39 for (auto sc = this; sc; sc = sc.parent) 40 { 41 symbol = sc.lookup(name); 42 if (symbol !is null) 43 break; 44 } 45 return symbol; 46 } 47 48 /// Searches for a symbol in this scope and all enclosing scopes. 49 /// Params: 50 /// name = The name of the symbol. 51 /// ignoreSymbol = The symbol that must be skipped. 52 Symbol search(Identifier* name, Symbol ignoreSymbol) 53 { 54 Symbol symbol; 55 for (auto sc = this; sc; sc = sc.parent) 56 { 57 symbol = sc.lookup(name); 58 if (symbol !is null && symbol !is ignoreSymbol) 59 break; 60 } 61 return symbol; 62 } 63 64 /// Creates a new inner scope and returns that. 65 Scope enter(ScopeSymbol symbol) 66 { 67 return new Scope(this, symbol); 68 } 69 70 /// Destroys this scope and returns the outer scope. 71 Scope exit() 72 { 73 auto sc = parent; 74 parent = null; 75 symbol = null; 76 return sc; 77 } 78 79 /// Searches for a scope matching type sid. 80 Scope findScope(SYM sid) 81 { 82 auto s = this; 83 do 84 if (s.symbol.sid == sid) 85 break; 86 while ((s = s.parent) !is null); 87 return s; 88 } 89 90 /// Searches for the enclosing Class scope. 91 Scope classScope() 92 { 93 return findScope(SYM.Class); 94 } 95 96 /// Searches for the enclosing Module scope. 97 Scope moduleScope() 98 { 99 return findScope(SYM.Module); 100 } 101 }