Skip to content
← Back

src/semantic/symbols/method.ghul

1
namespace Semantic.Symbols is
2
use IO.Std;
3
4
use System.Text.StringBuilder;
5
6
use Collections.Iterable;
7
use Collections.LIST;
8
9
use IoC;
10
use Logging;
11
use Source;
12
13
use IR.Values.Value;
14
15
use Types.Type;
16
17
class Method: Function abstract is
18
is_constructor: bool => self.il_name_override =~ "'.ctor'";
19
20
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
21
super.init(location, span, owner, name, enclosing_scope);
22
si
23
24
gen_dot(buffer: System.Text.StringBuilder) is
25
buffer.append("::");
26
si
27
28
// Underscore access policy for the state-machine method kinds
29
// (generator / async). Those are already distinct method kinds and so
30
// cannot be the dedicated PRIVATE_/PROTECTED_ classes; they consult the
31
// name and policy here instead. Regular methods use the dedicated kinds
32
// chosen in Classy._make_instance_method / _make_static_method.
33
_is_underscore_non_public: bool =>
34
name.starts_with('_') /\
35
IoC.CONTAINER.instance.build_flags.underscore_access != Compiler.UnderscoreAccess.LEGACY;
36
37
_gen_underscore_access(buffer: StringBuilder) is
38
if _is_underscore_non_public then
39
buffer.append("assembly ");
40
else
41
buffer.append("public ");
42
fi
43
si
44
45
// Shared by every default-trait-method kind: the plain one and the
46
// generator / async ones, which extend the state-machine method
47
// classes instead and so cannot inherit it.
48
_check_ineffective_trait_override(into: Classy, overrider: Function, logger: Logger) is
49
// Property accessors flow through handle_property_overridee, which
50
// raises this diagnostic at the property level. Skip the accessor
51
// here so we don't double-fire with the mangled `$get_*`/`$set_*`
52
// name.
53
if name.starts_with('$') then
54
return;
55
fi
56
57
if let owner_classy: Classy = owner then
58
INEFFECTIVE_TRAIT_OVERRIDE_CHECKER()
59
.check(into, overrider.location, overrider.to_string(), self, name, owner_classy, logger);
60
fi
61
si
62
63
_underscore_is_accessible_to(accessor: Classy?) -> bool is
64
if !_is_underscore_non_public then
65
return true;
66
fi
67
68
let o = cast Classy?(owner);
69
70
if IoC.CONTAINER.instance.build_flags.underscore_access == Compiler.UnderscoreAccess.PRIVATE then
71
return accessor? /\ o? /\ o == accessor;
72
fi
73
74
return accessor? /\ o? /\ o.type? /\ accessor.type? /\ o.type.is_assignable_from(accessor.type);
75
si
76
si
77
78
class INSTANCE_METHOD: Method is
79
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
80
_describe_function(context, !is_constructor);
81
82
describe_kind(context: DESCRIBE_CONTEXT) -> string? =>
83
if is_constructor then "constructor" else "{pure_prefix}{access_prefix}method" fi;
84
85
symbol_kind: SymbolKind => SymbolKind.METHOD;
86
completion_kind: CompletionKind => CompletionKind.METHOD;
87
88
is_instance: bool => true;
89
is_virtual: bool => true;
90
91
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
92
super.init(location, span, owner, name, enclosing_scope);
93
si
94
95
declare_closure(location: LOCATION, name: string, owner: Scope, enclosing: Scope, is_recursive: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol =>
96
declare_closure_symbol(location, Symbols.INSTANCE_CLOSURE(location, owner, name, enclosing, is_recursive));
97
98
declare_async_closure(location: LOCATION, name: string, owner: Scope, enclosing: Scope, is_recursive: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol =>
99
declare_closure_symbol(location, Symbols.INSTANCE_ASYNC_CLOSURE(location, owner, name, enclosing, is_recursive));
100
101
load(location: LOCATION, from: Value?, loader: SYMBOL_LOADER) -> Value => loader.load_instance_method(location, from, self);
102
103
load_self(location: LOCATION, loader: SYMBOL_LOADER) -> Value is
104
let context = IoC.CONTAINER.instance.symbol_table.current_instance_context;
105
106
return IR.Values.Load.REFERENCE_SELF(context!, context.type);
107
si
108
109
call(location: Source.LOCATION, from: Value?, arguments: Collections.List[Value], type: Type?, caller: FUNCTION_CALLER) -> Value is
110
return caller.call_instance_method(location, from, self, arguments, self.arguments, type);
111
si
112
113
try_override(into: Classy, overridee: Function, logger: Logging.Logger) is
114
overridee.try_instance_override_me(into, self, logger);
115
si
116
117
try_instance_override_me(into: Classy, overrider: Function, logger: Logger) is
118
let return_type_matches = overrider.ensure_return_type_matches(into, self, true, logger);
119
120
overrider.ensure_arguments_accept_optionals(into, self, true, logger);
121
122
let il_name_matches = overrider.ensure_il_name_matches(into, self, "override", logger);
123
124
overrider.add_overridee(self);
125
self.add_overrider(overrider);
126
si
127
128
try_struct_override_me(into: Classy, overrider: Function, logger: Logger) is
129
let return_type_matches = overrider.ensure_return_type_matches(into, self, true, logger);
130
131
overrider.ensure_arguments_accept_optionals(into, self, true, logger);
132
133
let il_name_matches = overrider.ensure_il_name_matches(into, self, "override", logger);
134
135
overrider.add_overridee(self);
136
self.add_overrider(overrider);
137
si
138
139
try_abstract_override_me(into: Classy, overrider: Function, logger: Logger) is
140
// An imported interface is free to redeclare an inherited
141
// member abstractly even when the inherited one carries a
142
// default implementation. The assembly it came from settled
143
// that already, and nobody compiling against it can change it.
144
if overrider.is_reflected then
145
logger.info(overrider.location, "hides {self}");
146
147
return;
148
fi
149
150
logger.error(overrider.location, "cannot override abstract method {self}");
151
si
152
153
gen_calling_convention(buffer: StringBuilder) is
154
buffer.append("instance ");
155
si
156
157
gen_flags(buffer: StringBuilder) is
158
if name =~ "init" then
159
buffer
160
.append("hidebysig specialname ");
161
elif is_internal then
162
buffer
163
.append("virtual hidebysig specialname ");
164
else
165
buffer
166
.append("virtual hidebysig ");
167
fi
168
si
169
si
170
171
// An underscore-prefixed instance method under the PROTECTED policy: a
172
// normal virtual method that a subclass in the same assembly can override,
173
// but nothing outside the assembly can see.
174
class PROTECTED_METHOD: INSTANCE_METHOD is
175
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
176
super.init(location, span, owner, name, enclosing_scope);
177
si
178
179
gen_access(buffer: StringBuilder) is
180
buffer.append("assembly ");
181
si
182
183
is_accessible_to(accessor: Classy?) -> bool =>
184
accessor? /\
185
let o = cast Classy?(owner) in
186
o? /\ o.type? /\ accessor.type? /\ o.type.is_assignable_from(accessor.type);
187
188
access_prefix: string => "protected ";
189
si
190
191
// An underscore-prefixed instance method under the PRIVATE policy: an
192
// implementation detail of its declaring type. Not virtual, so a same-named
193
// method in a subclass is a distinct method rather than an override, and
194
// calls resolve statically.
195
class PRIVATE_METHOD: INSTANCE_METHOD is
196
is_virtual: bool => false;
197
198
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
199
super.init(location, span, owner, name, enclosing_scope);
200
si
201
202
gen_access(buffer: StringBuilder) is
203
buffer.append("assembly ");
204
si
205
206
gen_flags(buffer: StringBuilder) is
207
if is_internal then
208
buffer.append("hidebysig specialname ");
209
else
210
buffer.append("hidebysig ");
211
fi
212
si
213
214
try_override(into: Classy, overridee: Function, logger: Logging.Logger) is
215
si
216
217
is_accessible_to(accessor: Classy?) -> bool =>
218
accessor? /\ cast Classy?(owner) == accessor;
219
220
access_prefix: string => "private ";
221
si
222
223
class STRUCT_METHOD: INSTANCE_METHOD is
224
// STRUCT_METHOD inherits describe / describe_kind from
225
// INSTANCE_METHOD unchanged.
226
symbol_kind: SymbolKind => SymbolKind.METHOD;
227
completion_kind: CompletionKind => CompletionKind.METHOD;
228
229
override: Function public;
230
231
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
232
super.init(location, span, owner, name, enclosing_scope);
233
si
234
235
load(location: LOCATION, from: Value?, loader: SYMBOL_LOADER) -> Value => loader.load_struct_method(location, from, self);
236
237
load_self(location: LOCATION, loader: SYMBOL_LOADER) -> Value is
238
let context = IoC.CONTAINER.instance.symbol_table.current_instance_context;
239
240
return IR.Values.Load.REFERENCE_SELF(context!, context.type);
241
si
242
243
call(location: Source.LOCATION, from: Value?, arguments: Collections.List[Value], type: Type?, caller: FUNCTION_CALLER) -> Value =>
244
caller.call_struct_method(location, from, self, arguments, self.arguments, type);
245
246
try_override(into: Classy, overridee: Function, logger: Logging.Logger) =>
247
overridee.try_struct_override_me(into, self, logger);
248
249
try_struct_override_me(into: Classy, overrider: Function, logger: Logger) =>
250
logger.error(overrider.location, "cannot override struct method {self}");
251
252
try_instance_override_me(into: Classy, overrider: Function, logger: Logger) =>
253
logger.error(overrider.location, "cannot override struct method {self}");
254
255
try_abstract_override_me(into: Classy, overrider: Function, logger: Logger) =>
256
logger.error(overrider.location, "cannot override struct method {self}");
257
258
gen_calling_convention(buffer: StringBuilder) is
259
buffer.append("instance ");
260
si
261
262
gen_flags(buffer: StringBuilder) is
263
if name !~ "init" then
264
buffer
265
.append("final virtual hidebysig ");
266
elif is_internal then
267
buffer
268
.append("hidebysig specialname ");
269
else
270
buffer
271
.append("hidebysig specialname ");
272
fi
273
si
274
si
275
276
class ABSTRACT_METHOD: INSTANCE_METHOD is
277
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
278
_describe_function(context, true);
279
280
describe_kind(context: DESCRIBE_CONTEXT) -> string? =>
281
"{pure_prefix}abstract method";
282
283
is_abstract: bool => true;
284
285
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
286
super.init(location, span, owner, name, enclosing_scope);
287
si
288
289
call(location: Source.LOCATION, from: Value?, arguments: Collections.List[Value], type: Type?, caller: FUNCTION_CALLER) -> Value => caller.call_abstract_method(location, from, self, arguments, self.arguments, type);
290
291
try_pull_down_into(
292
into: Classy,
293
other_overridee_symbols: Collections.Iterable[Symbol],
294
logger: Logging.Logger
295
) is
296
if !into.is_trait /\ !into.is_reflected then
297
logger.error(into.location, "must implement {self}");
298
fi
299
300
into.add_member(self);
301
si
302
303
try_override(into: Classy, overridee: Function, logger: Logging.Logger) =>
304
overridee.try_abstract_override_me(into, self, logger);
305
306
try_instance_override_me(into: Classy, overrider: Function, logger: Logger) is
307
let return_type_matches = overrider.ensure_return_type_matches(into, self, false, logger);
308
309
overrider.ensure_arguments_accept_optionals(into, self, false, logger);
310
311
let il_name_matches = overrider.ensure_il_name_matches(into, self, "implement", logger);
312
313
overrider.add_overridee(self);
314
self.add_overrider(overrider);
315
si
316
317
try_struct_override_me(into: Classy, overrider: Function, logger: Logger) is
318
let return_type_matches = overrider.ensure_return_type_matches(into, self, false, logger);
319
320
overrider.ensure_arguments_accept_optionals(into, self, false, logger);
321
322
let il_name_matches = overrider.ensure_il_name_matches(into, self, "implement", logger);
323
324
overrider.add_overridee(self);
325
self.add_overrider(overrider);
326
si
327
328
try_abstract_override_me(into: Classy, overrider: Function, logger: Logger) =>
329
logger.info(overrider.location, "hides {self}");
330
331
gen_calling_convention(buffer: StringBuilder) is
332
buffer.append("instance ");
333
si
334
335
gen_flags(buffer: StringBuilder) is
336
if is_internal then
337
buffer
338
.append("virtual hidebysig specialname abstract ");
339
else
340
buffer
341
.append("virtual hidebysig abstract ");
342
fi
343
si
344
si
345
346
class DEFAULT_TRAIT_METHOD: INSTANCE_METHOD is
347
describe_kind(context: DESCRIBE_CONTEXT) -> string? =>
348
"{pure_prefix}default trait method";
349
350
is_default_trait_method: bool => true;
351
352
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
353
super.init(location, span, owner, name, enclosing_scope);
354
si
355
356
try_instance_override_me(into: Classy, overrider: Function, logger: Logger) is
357
super.try_instance_override_me(into, overrider, logger);
358
359
_check_ineffective_trait_override(into, overrider, logger);
360
si
361
si
362
363
class STATIC_METHOD: Method is
364
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
365
_describe_function(context, true);
366
367
describe_kind(context: DESCRIBE_CONTEXT) -> string? =>
368
"{pure_prefix}{access_prefix}class method";
369
symbol_kind: SymbolKind => SymbolKind.METHOD;
370
completion_kind: CompletionKind => CompletionKind.METHOD;
371
372
override: Function public;
373
374
// Set for a reflected static virtual/abstract interface member -
375
// the only shape of static method the CLR allows to be
376
// dispatched through an as-yet-unresolved type parameter.
377
is_static_interface_virtual: bool public;
378
is_virtual: bool => is_static_interface_virtual;
379
380
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
381
super.init(location, span, owner, name, enclosing_scope);
382
si
383
384
declare_closure(location: LOCATION, name: string, owner: Scope, enclosing: Scope, is_recursive: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol =>
385
declare_closure_symbol(location, Symbols.STATIC_CLOSURE(location, owner, name, enclosing, is_recursive));
386
387
declare_async_closure(location: LOCATION, name: string, owner: Scope, enclosing: Scope, is_recursive: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol =>
388
declare_closure_symbol(location, Symbols.STATIC_ASYNC_CLOSURE(location, owner, name, enclosing, is_recursive));
389
390
load(location: LOCATION, from: Value?, loader: SYMBOL_LOADER) -> Value => loader.load_static_method(self);
391
392
call(location: Source.LOCATION, from: Value?, arguments: Collections.List[Value], type: Type?, caller: FUNCTION_CALLER) -> Value is
393
if is_static_interface_virtual /\ from? /\ from.type? /\ from.type!.is_type_variable then
394
return caller.call_static_interface_method(self, from.type!, arguments, self.arguments, type);
395
fi
396
397
return caller.call_static_method(self, arguments, self.arguments, type);
398
si
399
400
try_override(into: Classy, overridee: Function, logger: Logging.Logger) is
401
// This is arguably not an issue as the hidden instance remains available via super.method()
402
if !is_internal /\ overridee.is_instance then
403
logger.warn(self.location, "hides-inherited", "static method hides {overridee}");
404
fi
405
si
406
407
// Don't believe it makes sense to report an instance methods hiding a static method
408
// as the static method remains available via CLASS.method()
409
try_instance_override_me(into: Classy, overrider: Function, logger: Logger) is
410
si
411
412
try_struct_override_me(into: Classy, overrider: Function, logger: Logger) is
413
si
414
415
try_abstract_override_me(into: Classy, overrider: Function, logger: Logger) is
416
si
417
418
gen_flags(buffer: StringBuilder) is
419
if is_internal then
420
buffer
421
.append("hidebysig specialname static ");
422
else
423
buffer
424
.append("hidebysig static ");
425
fi
426
si
427
428
gen_body_header(context: IR.CONTEXT) is
429
gen_entrypoint(context);
430
si
431
si
432
433
// Underscore-prefixed static methods under the PROTECTED / PRIVATE
434
// policies. Static methods are already non-virtual, so only the emitted
435
// accessibility differs from STATIC_METHOD.
436
class PROTECTED_STATIC_METHOD: STATIC_METHOD is
437
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
438
super.init(location, span, owner, name, enclosing_scope);
439
si
440
441
gen_access(buffer: StringBuilder) is
442
buffer.append("assembly ");
443
si
444
445
is_accessible_to(accessor: Classy?) -> bool =>
446
accessor? /\
447
let o = cast Classy?(owner) in
448
o? /\ o.type? /\ accessor.type? /\ o.type.is_assignable_from(accessor.type);
449
450
access_prefix: string => "protected ";
451
si
452
453
class PRIVATE_STATIC_METHOD: STATIC_METHOD is
454
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
455
super.init(location, span, owner, name, enclosing_scope);
456
si
457
458
gen_access(buffer: StringBuilder) is
459
buffer.append("assembly ");
460
si
461
462
is_accessible_to(accessor: Classy?) -> bool =>
463
accessor? /\ cast Classy?(owner) == accessor;
464
465
access_prefix: string => "private ";
466
si
467
468
// A static constructor: `init() static`. Emitted as the owning
469
// type's `.cctor`, which the CLR runs once before the type is first
470
// used. It takes no parameters and no receiver; a parameterised
471
// static init is rejected during declare-symbols.
472
class STATIC_CONSTRUCTOR: STATIC_METHOD is
473
is_static_constructor: bool => true;
474
475
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
476
_describe_function(context, false);
477
478
describe_kind(context: DESCRIBE_CONTEXT) -> string? => "static constructor";
479
480
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
481
super.init(location, span, owner, name, enclosing_scope);
482
483
// Function.init overrode il_name to '.ctor' for the "init"
484
// name; the static constructor is the CLR's '.cctor'.
485
il_name_override = "'.cctor'";
486
si
487
488
gen_access(buffer: StringBuilder) is
489
buffer.append("private ");
490
si
491
492
gen_flags(buffer: StringBuilder) is
493
buffer.append("hidebysig specialname rtspecialname static ");
494
si
495
496
gen_body_header(context: IR.CONTEXT) is
497
si
498
si
499
si