Appearance
| 1 | namespace Semantic is | |
| 2 | use System.Text.StringBuilder; | |
| 3 | ||
| 4 | use Types.Type; | |
| 5 | use Symbols.Symbol; | |
| 6 | ||
| 7 | // Scope for the body of an `impl` or `partial` block, which declares | |
| 8 | // members into a target type that can be declared somewhere else | |
| 9 | // entirely. The target's own members and type parameters are found | |
| 10 | // first, exactly as inside the target's declaration body; any other | |
| 11 | // name resolves from the block's write site - its enclosing namespace | |
| 12 | // and `use` imports - rather than from the target's declaring scope. | |
| 13 | class INJECTION_SCOPE: Scope, ClosureContext is | |
| 14 | _target: Symbols.Classy; | |
| 15 | _lexical: Scope; | |
| 16 | _closures: Collections.SET[Symbols.Closure]?; | |
| 17 | ||
| 18 | target: Symbols.Classy => _target; | |
| 19 | ||
| 20 | underlying_scope: Scope => _target; | |
| 21 | ||
| 22 | name: string => _target.name; | |
| 23 | qualified_name: string => _target.qualified_name; | |
| 24 | ||
| 25 | symbols: Collections.Iterable[Symbol] => _target.symbols; | |
| 26 | ||
| 27 | type: Type? => _target.type; | |
| 28 | ||
| 29 | unspecialized_symbol: Symbol? => _target.unspecialized_symbol; | |
| 30 | ||
| 31 | is_trait: bool => _target.is_trait; | |
| 32 | is_classy: bool => _target.is_classy; | |
| 33 | is_union: bool => _target.is_union; | |
| 34 | is_variant: bool => _target.is_variant; | |
| 35 | is_closed_root: bool => _target.is_closed_root; | |
| 36 | is_unit_variant: bool => _target.is_unit_variant; | |
| 37 | is_instance_context: bool => _target.is_instance_context; | |
| 38 | ||
| 39 | // Closures declared inside an injected member are tracked on this | |
| 40 | // scope rather than the target so the block emits them itself, once | |
| 41 | // their bodies have been walked. Emitting them from the target's | |
| 42 | // primary definition would run before the block's bodies are | |
| 43 | // generated, leaving the closure methods bodyless. Without this | |
| 44 | // ClosureContext the closure-context search skips the injection | |
| 45 | // scope and registers the closure on the enclosing namespace. | |
| 46 | add_closure(closure: Symbols.Closure) is | |
| 47 | if !_closures? then | |
| 48 | _closures = Collections.SET[Symbols.Closure](); | |
| 49 | fi | |
| 50 | ||
| 51 | if !_closures.contains(closure) then | |
| 52 | _closures.add(closure); | |
| 53 | fi | |
| 54 | si | |
| 55 | ||
| 56 | get_closures() -> Collections.Iterable[Symbols.Closure] => | |
| 57 | if _closures? then _closures else Collections.LIST[Symbols.Closure](0) fi; | |
| 58 | ||
| 59 | init(target: Symbols.Classy, lexical: Scope) is | |
| 60 | _target = target; | |
| 61 | _lexical = lexical; | |
| 62 | si | |
| 63 | ||
| 64 | qualify(name: string) -> string => _target.qualify(name); | |
| 65 | ||
| 66 | find_direct(name: string) -> Symbol? => _target.find_direct(name); | |
| 67 | ||
| 68 | find_member(name: string) -> Symbol? => _target.find_member(name); | |
| 69 | ||
| 70 | find_enclosing(name: string) -> Symbol? is | |
| 71 | let result = _target.find_direct(name); | |
| 72 | ||
| 73 | if result? then | |
| 74 | if !isa Symbols.FUNCTION_GROUP(result) then | |
| 75 | return result; | |
| 76 | fi | |
| 77 | ||
| 78 | let outer = _lexical.find_enclosing(name); | |
| 79 | ||
| 80 | if !outer? \/ !isa Symbols.FUNCTION_GROUP(outer) then | |
| 81 | return result; | |
| 82 | fi | |
| 83 | ||
| 84 | return result.merged_over(outer); | |
| 85 | fi | |
| 86 | ||
| 87 | return _lexical.find_enclosing(name); | |
| 88 | si | |
| 89 | ||
| 90 | find_direct_matches(prefix: string, matches: Collections.MutableMap[string,Symbol]) is | |
| 91 | _target.find_direct_matches(prefix, matches); | |
| 92 | si | |
| 93 | ||
| 94 | find_member_matches(prefix: string, matches: Collections.MutableMap[string,Symbol]) is | |
| 95 | _target.find_member_matches(prefix, matches); | |
| 96 | si | |
| 97 | ||
| 98 | find_enclosing_matches(prefix: string, matches: Collections.MutableMap[string,Symbol]) is | |
| 99 | _target.find_direct_matches(prefix, matches); | |
| 100 | _lexical.find_enclosing_matches(prefix, matches); | |
| 101 | si | |
| 102 | ||
| 103 | gen_dotted_name(buffer: StringBuilder, qualifying: Scope) is | |
| 104 | _target.gen_dotted_name(buffer, qualifying); | |
| 105 | si | |
| 106 | ||
| 107 | gen_dot(buffer: StringBuilder) is | |
| 108 | _target.gen_dot(buffer); | |
| 109 | si | |
| 110 | ||
| 111 | gen_reference(buffer: StringBuilder) is | |
| 112 | _target.gen_reference(buffer); | |
| 113 | si | |
| 114 | ||
| 115 | gen_type(buffer: StringBuilder) is | |
| 116 | _target.gen_type(buffer); | |
| 117 | si | |
| 118 | ||
| 119 | to_string() -> string => "injection scope for: {_target.qualified_name}"; | |
| 120 | si | |
| 121 | si |