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
to_string() -> string => "injection scope for: {_target.qualified_name}"
104
si
105
si