Skip to content
← Back

src/semantic/symbols/generic_argument.ghul

1
namespace Semantic.Symbols is
2
use IO.Std
3
4
use System.Text.StringBuilder
5
6
use IoC
7
use Logging
8
use Source
9
10
use Types.Type
11
12
class GenericArgument: Scoped, Types.SettableTyped is
13
type: Type?
14
set_type(value: Type) is type = value; si
15
16
// NOTE this is neccessary, because values of generic argument types
17
// need to be boxed before they can be treated as instances of System.Object
18
is_value_type: bool => true
19
20
is_type: bool => true
21
is_type_variable: bool => true
22
23
_ancestor_types: Collections.List[Type]
24
_constraint_kind: TypeParameterConstraintKind
25
_has_constructor_constraint: bool
26
27
index: int
28
29
30
// The declared bounds (`[T: A /\ B]`), empty when unbounded. An
31
// unbounded parameter carries `object` as its single bound, set by
32
// resolve-explicit-types.
33
ancestors: Collections.List[Type] => _ancestor_types
34
35
set_ancestor_types(ancestor_types: Collections.List[Type]) is
36
_ancestor_types = ancestor_types
37
si
38
39
constraint_kind: TypeParameterConstraintKind => _constraint_kind
40
41
set_constraint_kind(kind: TypeParameterConstraintKind) is
42
_constraint_kind = kind
43
si
44
45
has_constructor_constraint: bool => _has_constructor_constraint
46
47
set_has_constructor_constraint(value: bool) is
48
_has_constructor_constraint = value
49
si
50
51
_is_argument_pack: bool
52
53
// Declared `[T..]`: the parameter stands for the arguments of an
54
// N-ary call, held as a positional tuple. Nothing about the
55
// parameter itself changes - it binds to that tuple like any
56
// other type argument. The flag licenses the front end to adapt
57
// an N-ary function into a slot that mentions it.
58
is_argument_pack: bool => _is_argument_pack
59
60
set_is_argument_pack(value: bool) is
61
_is_argument_pack = value
62
si
63
64
symbol_kind: SymbolKind => SymbolKind.TYPE_PARAMETER
65
completion_kind: CompletionKind => CompletionKind.TYPE_PARAMETER
66
67
short_description: string => description
68
69
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
70
PARTS.literal(name)
71
72
describe_kind(context: DESCRIBE_CONTEXT) -> string? => "type variable"
73
74
init(location: LOCATION, owner: Scope, name: string, type: Type) is
75
super.init(location, owner, name)
76
77
_ancestor_types = Collections.LIST[Type](0)
78
79
self.type = type
80
si
81
82
get_ancestor(i: int) -> Type
83
=> ancestors[i]
84
85
find_member(name: string) -> Symbol? =>
86
GENERIC_ARGUMENT_MEMBER_LOOKUP(_ancestor_types).find_member(name)
87
88
find_member_matches(prefix: string, matches: Collections.MutableMap[string, Symbol]) is
89
for ancestor_type in _ancestor_types do
90
if let scope = ancestor_type.scope then
91
scope.find_member_matches(prefix, matches)
92
fi
93
od
94
si
95
96
// A function rather than a position, because a closure's answer
97
// depends on whether it has a frame by the time its body is
98
// emitted, which is not settled when the override is installed.
99
//
100
// Held against the parameter rather than against this symbol: a
101
// frozen or specialized copy is a different object standing for
102
// the same parameter, and all of them have to read back what any
103
// one of them installed. See TYPE_PARAMETER_POSITIONS.
104
set_emitted_position(position: (() -> TYPE_PARAMETER_POSITION)?) is
105
IoC.CONTAINER.instance.type_parameter_positions.set(self, position)
106
si
107
108
// Read access — Closure.map_type_arguments / unmap_type_arguments
109
// need to save the previous override on entry and restore it on
110
// exit, so an outer install_body_emission_overrides (set by the
111
// enclosing generator) survives a nested closure's freeze cycle.
112
current_emitted_position: (() -> TYPE_PARAMETER_POSITION)? =>
113
IoC.CONTAINER.instance.type_parameter_positions.get(self)
114
115
emitted_position: TYPE_PARAMETER_POSITION? =>
116
if let position = current_emitted_position then position() else null fi
117
118
make_argument_type(argument: GenericArgument) -> Type
119
make_specialized(specialized_type: Type) -> Symbol
120
index_prefix() -> string
121
122
freeze() -> Symbol is
123
let result = cast GenericArgument?(memberwise_clone())!
124
125
// The clone stands for the same parameter as its source —
126
// same owner, same declared index — so it reads back
127
// whatever position is installed for that parameter, including
128
// one a state machine's `install_body_emission_overrides`
129
// installs after this clone is made.
130
result.type = make_argument_type(result)
131
132
return result
133
si
134
135
specialize(type_map: Collections.Map[Symbol,Type], owner: GENERIC) -> Symbol is
136
if type_map.contains_key(self) then
137
// FIXME the resulting argument could have the wrong index
138
let result = make_specialized(type_map[self])
139
140
result.set_is_argument_pack(_is_argument_pack)
141
142
return result
143
fi
144
145
return self
146
si
147
148
si
149
150
class CLASSY_GENERIC_ARGUMENT: GenericArgument is
151
init(location: LOCATION, owner: Scope, name: string, index: int) is
152
super.init(location, owner, name, Types.CLASSY_GENERIC_ARGUMENT(self))
153
154
self.index = index
155
si
156
157
init(location: LOCATION, owner: Scope, name: string, type: Type) is
158
super.init(location, owner, name, type)
159
160
self.type = type
161
si
162
163
make_argument_type(argument: GenericArgument) -> Type => Types.CLASSY_GENERIC_ARGUMENT(argument)
164
165
make_specialized(specialized_type: Type) -> Symbol =>
166
CLASSY_GENERIC_ARGUMENT(location, self, name, specialized_type)
167
168
index_prefix() -> string => "!"
169
si
170
171
// FIXME: should inherit from TYPE
172
class FUNCTION_GENERIC_ARGUMENT: GenericArgument is
173
is_local: bool => true
174
175
init(location: LOCATION, owner: Scope, name: string, index: int) is
176
super.init(location, owner, name, Types.FUNCTION_GENERIC_ARGUMENT(self))
177
178
self.index = index
179
si
180
181
init(location: LOCATION, owner: Scope, name: string, type: Type) is
182
super.init(location, owner, name, type)
183
184
self.type = type
185
si
186
187
make_argument_type(argument: GenericArgument) -> Type => Types.FUNCTION_GENERIC_ARGUMENT(argument)
188
189
make_specialized(specialized_type: Type) -> Symbol =>
190
FUNCTION_GENERIC_ARGUMENT(location, self, name, specialized_type)
191
192
index_prefix() -> string => "!!"
193
si
194
si