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_type: Type?;
24
_constraint_kind: TypeParameterConstraintKind;
25
_has_constructor_constraint: bool;
26
27
index: int;
28
29
_gen_type_override: ((Symbol, StringBuilder) -> void)?;
30
31
// FIXME: should ancestor be a type not a symbol? We could then just use Symbol.ancestors.
32
// We'll need multiple ancestors to support multiple constraints anyway
33
ancestors: Collections.List[Type] is
34
if _ancestor_type == null then
35
return Collections.LIST[Type](0);
36
fi
37
38
return [_ancestor_type];
39
si
40
41
set_ancestor_type(ancestor: Type) is
42
_ancestor_type = ancestor;
43
si
44
45
constraint_kind: TypeParameterConstraintKind => _constraint_kind;
46
47
set_constraint_kind(kind: TypeParameterConstraintKind) is
48
_constraint_kind = kind;
49
si
50
51
has_constructor_constraint: bool => _has_constructor_constraint;
52
53
set_has_constructor_constraint(value: bool) is
54
_has_constructor_constraint = value;
55
si
56
57
symbol_kind: SymbolKind => SymbolKind.TYPE_PARAMETER;
58
completion_kind: CompletionKind => CompletionKind.TYPE_PARAMETER;
59
60
short_description: string => description;
61
62
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
63
PARTS.literal(name);
64
65
describe_kind(context: DESCRIBE_CONTEXT) -> string? => "type variable";
66
67
init(location: LOCATION, owner: Scope, name: string, type: Type) is
68
super.init(location, owner, name);
69
70
self.type = type;
71
si
72
73
get_ancestor(i: int) -> Type
74
=> ancestors[i];
75
76
find_member(name: string) -> Symbol? =>
77
if _ancestor_type? then
78
_ancestor_type.find_member(name)
79
else
80
null
81
fi;
82
83
find_member_matches(prefix: string, matches: Collections.MutableMap[string, Symbol]) is
84
if let self._ancestor_type? then
85
_ancestor_type.scope!.find_member_matches(prefix, matches);
86
fi
87
si
88
89
gen_type_override(override: (Symbol, StringBuilder) -> void) is
90
_gen_type_override = override;
91
si
92
93
// Read access — Closure.map_type_arguments / unmap_type_arguments
94
// need to save the previous override on entry and restore it on
95
// exit, so an outer install_body_emission_overrides (set by the
96
// enclosing generator) survives a nested closure's freeze cycle.
97
current_gen_type_override: ((Symbol, StringBuilder) -> void)? =>
98
_gen_type_override;
99
100
gen_reference(buffer: StringBuilder) is
101
gen_type(buffer);
102
si
103
104
gen_class_name(buffer: StringBuilder) is
105
gen_type(buffer);
106
si
107
108
make_argument_type(argument: GenericArgument) -> Type;
109
make_specialized(specialized_type: Type) -> Symbol;
110
index_prefix() -> string;
111
112
freeze() -> Symbol is
113
let result = cast GenericArgument?(memberwise_clone())!;
114
115
// Keep `_gen_type_override` from the source — when a
116
// closure freezes type-arg references inside a
117
// generator's body, the state-machine's `install_body_
118
// emission_overrides` has rewritten the source symbol's
119
// gen_type to emit class-level `!N` on the state machine.
120
// Clearing the override here would put the frozen clone
121
// back on the default branch (the source's own index)
122
// and the resulting IL would reference the wrong class.
123
result.type = make_argument_type(result);
124
125
return result;
126
si
127
128
specialize(type_map: Collections.Map[string,Type], owner: GENERIC) -> Symbol is
129
if type_map.contains_key(name) then
130
// FIXME the resulting argument could have the wrong index
131
return make_specialized(type_map[name]);
132
fi
133
134
return self;
135
si
136
137
gen_type(buffer: StringBuilder) is
138
if _gen_type_override? then
139
_gen_type_override(self, buffer);
140
else
141
buffer
142
.append(index_prefix())
143
.append(index)
144
.append(' ');
145
fi
146
si
147
si
148
149
class CLASSY_GENERIC_ARGUMENT: GenericArgument is
150
init(location: LOCATION, owner: Scope, name: string, index: int) is
151
super.init(location, owner, name, Types.CLASSY_GENERIC_ARGUMENT(self));
152
153
self.index = index;
154
si
155
156
init(location: LOCATION, owner: Scope, name: string, type: Type) is
157
super.init(location, owner, name, type);
158
159
self.type = type;
160
si
161
162
make_argument_type(argument: GenericArgument) -> Type => Types.CLASSY_GENERIC_ARGUMENT(argument);
163
164
make_specialized(specialized_type: Type) -> Symbol =>
165
CLASSY_GENERIC_ARGUMENT(location, self, name, specialized_type);
166
167
index_prefix() -> string => "!";
168
si
169
170
// FIXME: should inherit from TYPE
171
class FUNCTION_GENERIC_ARGUMENT: GenericArgument is
172
is_local: bool => true;
173
174
init(location: LOCATION, owner: Scope, name: string, index: int) is
175
super.init(location, owner, name, Types.FUNCTION_GENERIC_ARGUMENT(self));
176
177
self.index = index;
178
si
179
180
init(location: LOCATION, owner: Scope, name: string, type: Type) is
181
super.init(location, owner, name, type);
182
183
self.type = type;
184
si
185
186
make_argument_type(argument: GenericArgument) -> Type => Types.FUNCTION_GENERIC_ARGUMENT(argument);
187
188
make_specialized(specialized_type: Type) -> Symbol =>
189
FUNCTION_GENERIC_ARGUMENT(location, self, name, specialized_type);
190
191
index_prefix() -> string => "!!";
192
si
193
si