Skip to content
← Back

src/syntax/process/compile-expressions/compile_generic_application.ghul

1
namespace Syntax.Process is
2
use Logging
3
use Source
4
5
use Semantic.Types.Type
6
7
use IR.Values
8
9
use Ghul.Pipes
10
11
// Compiles the type-argument-application family of expressions:
12
// ambiguous expressions and generic applications (the
13
// resolved-to-type / resolved-to-function forms). Split out of
14
// COMPILE_EXPRESSIONS, which delegates the matching visit / pre
15
// methods here. The bodies live in their `pre` methods — they
16
// re-walk children and suppress the default traversal — so the
17
// visitor's `visit` overrides for those stay empty.
18
class COMPILE_GENERIC_APPLICATION is
19
_logger: Logger
20
_symbol_use_locations: Semantic.SYMBOL_USE_LOCATIONS
21
_symbol_loader: Semantic.SYMBOL_LOADER
22
_unit_variant_constructor: Semantic.UNIT_VARIANT_CONSTRUCTOR
23
_visitor: ScopedVisitor
24
_function_reference_resolver: Semantic.FUNCTION_REFERENCE_RESOLVER
25
_shadowed_callable_finder: Semantic.SHADOWED_CALLABLE_FINDER
26
27
init(
28
logger: Logger,
29
symbol_table: Semantic.SYMBOL_TABLE,
30
symbol_use_locations: Semantic.SYMBOL_USE_LOCATIONS,
31
symbol_loader: Semantic.SYMBOL_LOADER,
32
innate_symbol_lookup: Semantic.Lookups.InnateSymbolLookup,
33
overload_resolver: Semantic.OVERLOAD_RESOLVER,
34
unit_variant_constructor: Semantic.UNIT_VARIANT_CONSTRUCTOR,
35
visitor: ScopedVisitor
36
) is
37
super.init()
38
39
_logger = logger
40
_symbol_use_locations = symbol_use_locations
41
_symbol_loader = symbol_loader
42
_unit_variant_constructor = unit_variant_constructor
43
_visitor = visitor
44
45
_shadowed_callable_finder = Semantic.SHADOWED_CALLABLE_FINDER(logger, symbol_table)
46
47
_function_reference_resolver =
48
Semantic.FUNCTION_REFERENCE_RESOLVER(
49
logger,
50
symbol_table,
51
symbol_loader,
52
innate_symbol_lookup,
53
overload_resolver
54
)
55
si
56
57
pre_ambiguous_expression(ambiguous_expression: Trees.Expressions.AMBIGUOUS_EXPRESSION) -> bool is
58
if ambiguous_expression.result == Trees.Expressions.AmbiguousExpressionResult.INDEX then
59
if let ambiguous_expression.value? /\ value.is_need_store then
60
ambiguous_expression.index.compile_expressions_state.value = value
61
fi
62
63
ambiguous_expression.index.walk(_visitor)
64
65
ambiguous_expression.compile_expressions_state.value = ambiguous_expression.index.value
66
67
return true
68
fi
69
70
let arg = ambiguous_expression.type_arguments.elements[0]
71
72
arg.walk(_visitor)
73
74
let symbol: Semantic.Symbols.Symbol? mut = _
75
76
if ambiguous_expression.left? then
77
ambiguous_expression.left.walk(_visitor)
78
79
if ambiguous_expression.left!.value? then
80
symbol = ambiguous_expression.left!.value!.type!.find_member(ambiguous_expression.identifier.name)
81
82
// find member will not report an error for not found
83
if !symbol? then
84
_logger.error(ambiguous_expression.identifier.location, "member {ambiguous_expression.identifier.name} not found in {ambiguous_expression.left!.value!.type}")
85
fi
86
fi
87
else
88
symbol = _find_applicable(ambiguous_expression.identifier)
89
fi
90
91
if !symbol? then
92
return true
93
fi
94
95
_symbol_use_locations.add_symbol_use(ambiguous_expression.identifier.location, symbol)
96
97
let result_type: Semantic.Types.Type? mut = _
98
let result_symbol: Semantic.Symbols.Symbol? mut = _
99
100
if symbol.is_type then
101
ambiguous_expression.result = Trees.Expressions.AmbiguousExpressionResult.TYPE
102
result_type =
103
specialize_type(
104
ambiguous_expression.location,
105
symbol,
106
ambiguous_expression.type_arguments
107
)
108
elif symbol.is_function \/ symbol.is_function_group then
109
ambiguous_expression.result = Trees.Expressions.AmbiguousExpressionResult.FUNCTION
110
result_symbol =
111
specialize_symbol(
112
ambiguous_expression.location,
113
symbol,
114
ambiguous_expression.type_arguments
115
)
116
else
117
_logger.error(ambiguous_expression.location, "cannot apply type arguments here")
118
return true
119
fi
120
121
let result = ambiguous_expression.result
122
123
if result == Trees.Expressions.AmbiguousExpressionResult.UNKNOWN then
124
// we didn't resolve what this was in the resolve type expressions phase
125
// don't report another error here, just produce a propagating error value:
126
ambiguous_expression.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), ambiguous_expression.location)
127
elif result == Trees.Expressions.AmbiguousExpressionResult.INDEX then
128
// if the ambiguous expression resolved to an indexer
129
// call then walk that
130
ambiguous_expression.index.walk(_visitor)
131
132
// our value is whatever value the index expression produced
133
ambiguous_expression.compile_expressions_state.value = ambiguous_expression.index.value
134
elif result == Trees.Expressions.AmbiguousExpressionResult.TYPE then
135
if symbol.is_unit_variant then
136
let lowered = _unit_variant_constructor.try_load(ambiguous_expression.location, symbol, result_type, ambiguous_expression)
137
138
if lowered? then
139
_symbol_use_locations.add_symbol_use(ambiguous_expression.identifier.location, lowered.constructor)
140
ambiguous_expression.compile_expressions_state.value = lowered.value
141
return true
142
fi
143
fi
144
145
ambiguous_expression.compile_expressions_state.value = TYPE_EXPRESSION(result_type!, ambiguous_expression.location)
146
elif result == Trees.Expressions.AmbiguousExpressionResult.FUNCTION then
147
if !result_symbol? then
148
// try_specialize already reported why; propagate an error value
149
ambiguous_expression.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), ambiguous_expression.location)
150
return true
151
fi
152
153
let left_value: Value? =
154
if ambiguous_expression.left? then
155
ambiguous_expression.left.value
156
else
157
null
158
fi
159
160
// A name applied to type arguments and then used as a
161
// value is a function reference at that instantiation,
162
// so it takes the same route to a function value as a
163
// bare name does. A call target declines, and its own
164
// path calls the symbol directly.
165
ambiguous_expression.compile_expressions_state.value =
166
_function_reference_resolver.try_load(
167
ambiguous_expression.location,
168
result_symbol,
169
left_value,
170
ambiguous_expression.expected_type,
171
ambiguous_expression.is_call_target
172
) ??
173
result_symbol.load(ambiguous_expression.location, left_value, _symbol_loader)
174
else
175
assert false else "result variant is something unexpected {result}"
176
fi
177
178
return true
179
si
180
181
pre_generic_application(generic_application: Trees.Expressions.GENERIC_APPLICATION) -> bool is
182
generic_application.type_arguments.walk(_visitor)
183
184
let symbol: Semantic.Symbols.Symbol? mut = _
185
186
if generic_application.left? then
187
generic_application.left.walk(_visitor)
188
189
if generic_application.left!.value? then
190
symbol = generic_application.left!.value!.type!.find_member(generic_application.identifier.name)
191
192
// find member will not report an error for not found
193
if !symbol? then
194
_logger.error(generic_application.identifier.location, "member {generic_application.identifier.name} not found in {generic_application.left!.value!.type}")
195
fi
196
fi
197
else
198
// find will report an error for not found
199
symbol = _find_applicable(generic_application.identifier)
200
fi
201
202
if !symbol? then
203
return true
204
fi
205
206
_symbol_use_locations.add_symbol_use(generic_application.identifier.location, symbol)
207
208
let result_type: Semantic.Types.Type? mut = _
209
let result_symbol: Semantic.Symbols.Symbol? mut = _
210
211
if symbol.is_type then
212
generic_application.result = Trees.Expressions.AmbiguousExpressionResult.TYPE
213
214
result_type =
215
specialize_type(
216
generic_application.location,
217
symbol,
218
generic_application.type_arguments
219
)
220
elif symbol.is_function \/ symbol.is_function_group then
221
generic_application.result = Trees.Expressions.AmbiguousExpressionResult.FUNCTION
222
223
result_symbol =
224
specialize_symbol(
225
generic_application.location,
226
symbol,
227
generic_application.type_arguments
228
)
229
else
230
_logger.error(generic_application.location, "cannot apply type arguments here")
231
return true
232
fi
233
234
let result = generic_application.result
235
236
if result == Trees.Expressions.AmbiguousExpressionResult.UNKNOWN then
237
// we didn't resolve what this was in the resolve type expressions phase
238
// don't report another error here, just produce a propagating error value:
239
generic_application.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), generic_application.location)
240
elif result == Trees.Expressions.AmbiguousExpressionResult.TYPE then
241
if symbol.is_unit_variant then
242
let lowered = _unit_variant_constructor.try_load(generic_application.location, symbol, result_type, generic_application)
243
244
if lowered? then
245
_symbol_use_locations.add_symbol_use(generic_application.identifier.location, lowered.constructor)
246
generic_application.compile_expressions_state.value = lowered.value
247
return true
248
fi
249
fi
250
251
generic_application.compile_expressions_state.value = TYPE_EXPRESSION(result_type!, generic_application.location)
252
elif result == Trees.Expressions.AmbiguousExpressionResult.FUNCTION then
253
if !result_symbol? then
254
// try_specialize already reported why; propagate an error value
255
generic_application.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), generic_application.location)
256
return true
257
fi
258
259
let left_value: Value? =
260
if generic_application.left? then
261
generic_application.left.value
262
else
263
null
264
fi
265
266
// A name applied to type arguments and then used as a
267
// value is a function reference at that instantiation,
268
// so it takes the same route to a function value as a
269
// bare name does. A call target declines, and its own
270
// path calls the symbol directly.
271
generic_application.compile_expressions_state.value =
272
_function_reference_resolver.try_load(
273
generic_application.location,
274
result_symbol,
275
left_value,
276
generic_application.expected_type,
277
generic_application.is_call_target
278
) ??
279
result_symbol.load(generic_application.location, left_value, _symbol_loader)
280
else
281
assert false else "result is something unexpected {result}"
282
fi
283
284
return true
285
si
286
287
_expand_alias(location: Source.LOCATION, alias: Semantic.Symbols.TYPE_ALIAS, arguments: Trees.TypeExpressions.LIST) -> Semantic.Types.Type is
288
if alias.argument_count != arguments.elements.count then
289
if alias.argument_count == 0 then
290
_logger.error(location, "type alias {alias.name} takes no type arguments")
291
else
292
_logger.error(location, "expected {alias.argument_count} type arguments but found {arguments.elements.count}")
293
fi
294
295
return Semantic.Types.ERROR()
296
fi
297
298
let target = alias.target_type
299
300
if !target? then
301
return Semantic.Types.ERROR()
302
fi
303
304
let actual_arguments = Collections.LIST[Semantic.Types.Type]()
305
306
for a in arguments do
307
a.check_is_not_void(_logger, "cannot use void type here")
308
309
actual_arguments.add(a.type ?? Semantic.Types.ERROR())
310
od
311
312
return target.specialize(alias.argument_map(actual_arguments))
313
si
314
315
specialize_type(location: Source.LOCATION, symbol: Semantic.Symbols.Symbol, arguments: Trees.TypeExpressions.LIST) -> Semantic.Types.Type is
316
let resolved_symbol: Semantic.Symbols.Symbol mut = symbol
317
let group = cast Semantic.Symbols.TYPE_GROUP?(symbol)
318
319
if group? then
320
let match = group.find_by_generic_arguments_count(arguments.elements.count)
321
322
if !match? then
323
let counts = group.generic_arguments_counts |> map(a -> string => "{a}") |> join(" or ")
324
_logger.error(location, "expected {counts} type arguments but found {arguments.elements.count}")
325
return Semantic.Types.ERROR()
326
fi
327
328
resolved_symbol = match
329
fi
330
331
// An alias stands for its target, so applying one to type
332
// arguments is applying its target to them, substituted the
333
// way resolve-type-expressions substitutes them where the
334
// alias is written as a type.
335
if let alias = cast Semantic.Symbols.TYPE_ALIAS?(resolved_symbol) then
336
return _expand_alias(location, alias, arguments)
337
fi
338
339
if !isa Semantic.Symbols.Classy(resolved_symbol) then
340
_logger.error(location, "cannot supply type arguments here")
341
return Semantic.Types.ERROR()
342
fi
343
344
for a in arguments do
345
a.check_is_not_void(_logger, "cannot use void type here")
346
347
let t = a.type
348
349
if t? /\ t.is_named /\ cast Semantic.Types.NAMED?(t)!.symbol.is_unsafe_constraints then
350
_logger.warn(a.location, "unchecked-constraints", "type {t} has unchecked constraints")
351
fi
352
od
353
354
let classy = resolved_symbol
355
356
let actual_arguments = arguments |> map(
357
// FIXME type inference issue
358
a -> Type => if a.type? then a.type else Semantic.Types.ERROR() fi
359
) |> collect()
360
361
let result = Semantic.Types.GENERIC(location, classy, actual_arguments)
362
363
classy.check_argument_constraints(location, _logger, actual_arguments)
364
365
if resolved_symbol.is_unsafe_constraints then
366
_logger.warn(location, "unchecked-constraints", "type {result} has unchecked constraints")
367
fi
368
369
return result
370
si
371
372
// A name applied to type arguments can only mean a type or a function.
373
// When the nearest symbol by that name is neither - a local variable,
374
// say - the callable one further out is what the application means,
375
// as it is for a bare call, and the same warning says so.
376
_find_applicable(identifier: Trees.Identifiers.Identifier) -> Semantic.Symbols.Symbol? is
377
let symbol = _visitor.find(identifier)
378
379
if !symbol? \/ symbol.is_type \/ identifier.qualifier? then
380
return symbol
381
fi
382
383
return _shadowed_callable_finder.find(identifier.location, identifier.name, symbol) ?? symbol
384
si
385
386
specialize_symbol(location: Source.LOCATION, symbol: Semantic.Symbols.Symbol, arguments: Trees.TypeExpressions.LIST) -> Semantic.Symbols.Symbol? is
387
return
388
symbol.try_specialize(
389
location,
390
_logger,
391
arguments.elements |>
392
map(t => t.type!) |> collect()
393
)
394
si
395
si
396
si