Skip to content
← Back

src/semantic/scope/injection_scope.ghul

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