Skip to content
← Back

src/semantic/symbols/classy.ghul

1
namespace Semantic.Symbols is
2
use IO.Std
3
4
use System.Text.StringBuilder
5
6
use Collections.SET
7
8
use Ghul.Pipes
9
10
use IoC
11
use Logging
12
use Source
13
14
use IR.Values.Value
15
16
use Types.Type
17
18
class Classy: ScopedWithEnclosingScope, ClosureContext abstract is
19
// The unspecialized builder an async function returning this type
20
// drives, resolved from its AsyncMethodBuilderAttribute - read at
21
// import for a reflected type, from the attribute pragma during
22
// resolve-type-expressions for a source-declared one. Null for
23
// everything that is not a task-like.
24
async_builder: Types.Type? public
25
26
// Whether the type is visible outside its declaring assembly.
27
// Mirrors gen_access: an underscore-prefixed type under the
28
// private or protected policy is assembly-internal.
29
is_public_readable: bool => (
30
let policy = IoC.CONTAINER.instance.build_flags.underscore_access
31
32
!(name.starts_with('_') /\
33
(policy == Compiler.UnderscoreAccess.PRIVATE \/ policy == Compiler.UnderscoreAccess.PROTECTED))
34
)
35
36
_ancestors: Collections.LIST[Type]
37
_implementors: Collections.LIST[Symbol]?
38
_enclosing_symbols: Collections.MAP[string,Symbol]
39
_closures: Collections.SET[Closure]?
40
41
// Parameters for a generic that does not declare them into its
42
// own scope, minted lazily and cached here so every reference to
43
// the same parameter — a member's formal and a substitution
44
// map's key alike — carries one symbol. Type substitution
45
// matches on symbol identity, so a fresh symbol per request
46
// would silently miss.
47
_positional_type_parameters: Collections.LIST[GenericArgument]?
48
49
_are_overrides_resolved: bool
50
51
// The reversible record of what this class's pull-down did, so
52
// reset_pulled_down_symbols can undo it exactly. Null until the
53
// class resolves its overrides, and for classes marked resolved
54
// without a pull-down (reflected imports).
55
_inheritance_journal: INHERITANCE_JOURNAL?
56
57
type: Type?
58
set_type(value: Type) is type = value; si
59
60
span: LOCATION
61
62
// Incremental body re-walk override: also shift the declaration
63
// span when the retained interface symbol is relocated.
64
set_span(span_location: LOCATION) is
65
span = span_location
66
si
67
68
_depth: int
69
depth: int is
70
if _depth > 0 then
71
return _depth
72
fi
73
74
_depth = _calc_depth()
75
return _depth
76
si
77
78
argument_names: Collections.List[string]
79
argument_variances: Collections.List[Types.TypeVariance]? public
80
argument_constraint_kinds: Collections.List[TypeParameterConstraintKind] public
81
argument_has_constructor_constraint: Collections.List[bool] public
82
// Parallel to argument_names: the type bound (`where T : SomeBase`)
83
// one list of bounds per type parameter, empty when that parameter
84
// is unbounded. Populated at import for .NET-defined generics whose
85
// parameter symbols don't live in the symbol's own scope;
86
// ghūl-declared generics keep the bounds on the parameter symbol
87
// itself.
88
argument_type_bounds: Collections.List[Collections.List[Type]] public
89
90
// True when this type has its own accessible parameterless
91
// constructor — a zero-argument `init` for a ghūl-declared type,
92
// a public parameterless `.ctor` for an imported one. Used to
93
// check an `init` type-parameter constraint. Set when the type
94
// is declared / imported, since a ghūl constructor's signature
95
// is not resolved early enough to inspect at constraint-check
96
// time.
97
has_parameterless_constructor: bool public
98
99
// The constructor synthesised from this type's primary-constructor
100
// header, when it has one. Recorded by declare-symbols so a hover
101
// on the declaration can show the primary parameters; null for a
102
// type without a primary header (secondary constructors are not
103
// recorded here).
104
primary_constructor: Function? public
105
106
// Set by TYPE_GROUP when the type joins a group of same-named
107
// sibling types distinguished by generic-argument count.
108
// Triggers `\`N` suffixing in IL emission so .NET sees distinct
109
// names — lone types (no siblings) emit unchanged so the
110
// universal compiler-source path is byte-identical.
111
has_argument_count_siblings: bool public
112
113
is_generic: bool => argument_names.count > 0
114
115
get_argument_variance(index: int) -> Types.TypeVariance =>
116
if !argument_variances? \/ index < 0 \/ index >= argument_variances.count then
117
Types.TypeVariance.INVARIANT
118
else
119
argument_variances[index]
120
fi
121
122
// FIXME: not safe to expose unspecialized ancestors
123
ancestors: Collections.List[Type] => _ancestors
124
125
implementors: Collections.Iterable[Symbol]? => _implementors
126
127
il_assembly_name: string? public
128
129
// The reflected full name of an imported type - reflection's own
130
// spelling, with nesting joined by '+' - captured when the symbol
131
// is loaded, and null for a type declared in source. A
132
// custom-attribute blob names a typeof argument in this form, so
133
// it is kept as read rather than reconstructed from the IL name,
134
// whose nesting separator differs.
135
dotnet_full_name: string? public
136
137
is_workspace_visible: bool => true
138
is_capture_context: bool => true
139
is_type: bool => true
140
is_classy: bool => true
141
is_instance_context: bool => false
142
143
// True when extension across assembly boundaries is permitted -
144
// subclassing for a class, implementing or deriving for a trait.
145
// Resolved explicitly at declare-symbols time (from the `open`
146
// modifier) for ghūl-declared classes and traits, and at import
147
// time (from the presence of the `[Ghul.Internal.CLOSED_ATTRIBUTE]`
148
// marker) for imported ones. With neither path having set the
149
// state, `_is_open_by_default` decides.
150
_is_open: bool
151
_is_open_set: bool
152
153
is_open: bool =>
154
if _is_open_set then _is_open
155
else _is_open_by_default
156
fi
157
158
// True when the type is declared `pure`: its instance members
159
// must be pure (proven store-free or declared), with only
160
// constructors, statics and assign accessors exempt. Set from
161
// the `pure` modifier during declare-symbols. Not carried across
162
// assemblies: member-level PURE_ATTRIBUTE crosses already, and
163
// the pure-override contract binds implementors member-wise.
164
_is_pure: bool
165
166
is_pure: bool => _is_pure
167
168
mark_pure() is
169
_is_pure = true
170
si
171
172
// The answer for a kind whose open/closed state is never set
173
// explicitly. False for structs, unions, variants and the
174
// synthesised kinds - none of them can be extended from outside
175
// their declaring assembly. Structs cannot be subclassed at all;
176
// a union's only subclasses are its own compiler-generated
177
// variants, and members reach a union or a single variant only
178
// through same-assembly partial and impl blocks. `CLASS` and
179
// `TRAIT` override this with `is_reflected`, so that an
180
// imported type carrying no marker is treated as open (it was
181
// built by a compiler that does not emit one) while a
182
// ghūl-declared one resolves from the `open` modifier.
183
_is_open_by_default: bool => false
184
185
// True when the source says `open`. A submission's classes and
186
// traits are open without saying so, since a later step of the
187
// session can extend them, and a rule about what the author
188
// wrote asks this rather than `is_open`.
189
is_declared_open: bool
190
191
mark_declared_open() is
192
is_declared_open = true
193
mark_open()
194
si
195
196
mark_open() is
197
_is_open = true
198
_is_open_set = true
199
si
200
201
mark_closed() is
202
_is_open = false
203
_is_open_set = true
204
si
205
206
// A .NET delegate type: set at import by walking the base chain
207
// to System.MulticastDelegate. A delegate member runs whatever
208
// its target is, so no reading of its shape vouches for what it
209
// writes, and the trust tiers decline it on this.
210
is_delegate: bool => _is_delegate
211
212
_is_delegate: bool
213
214
mark_delegate() is
215
_is_delegate = true
216
si
217
218
// True when this Classy itself cannot appear as a runtime type
219
// (only its subclasses can). Default false — traits/structs/
220
// unions/variants are never "abstract" in this sense for
221
// narrowing purposes (unions enumerate via variants; trait
222
// implementors aren't enumerable to begin with). `Symbols.CLASS`
223
// overrides this with a settable field, set from the `abstract`
224
// modifier during declare-symbols and from
225
// `TypeAttributes.Abstract` on import.
226
is_abstract: bool => false
227
228
// True when abstractness was inferred from a body-less instance
229
// method rather than written as the `abstract` modifier. Only a
230
// class can be abstract by inference; everything else answers
231
// false because nothing else infers it.
232
is_implicitly_abstract: bool => false
233
234
// The set of direct subclasses declared in the same assembly as
235
// this Classy. Used by the variant-complement narrowing path to
236
// enumerate a closed root's possible dynamic types. Returns an
237
// empty list when the root is open — callers gate on `is_open`
238
// before consulting this. Built from `implementors`, filtered
239
// to ghūl-declared CLASS subclasses (trait implementors and
240
// imported subclasses don't count for closure).
241
closed_subclasses: Collections.Iterable[Classy] is
242
let result = Collections.LIST[Classy]()
243
244
if !_implementors? then
245
return result
246
fi
247
248
for s in _implementors do
249
if isa CLASS(s) then
250
let sub = cast Classy(s)
251
if !sub.is_reflected then
252
result.add(sub)
253
fi
254
fi
255
od
256
257
return result
258
si
259
260
// True when this Classy is the root of a closed set of subtypes
261
// narrowing can complement against. Two shapes qualify: a union
262
// (variants are the closed set), and a ghūl-declared closed
263
// class (`closed_subclasses` is the closed set). Open classes,
264
// traits, structs, enums and imported types do not.
265
is_closed_root: bool =>
266
is_union \/ (is_class /\ !is_open)
267
268
// The subtypes that make up this closed root's in-set. Returns
269
// the variants for a union, the direct in-assembly subclasses
270
// for a closed class, an empty list otherwise. Callers gate on
271
// `is_closed_root` first; the empty fallback is a safety net.
272
closed_alternatives: Collections.Iterable[Classy] is
273
let result = Collections.LIST[Classy]()
274
275
if is_union then
276
for s in symbols do
277
if s.is_variant then
278
result.add(cast Classy?(s)!)
279
fi
280
od
281
282
return result
283
fi
284
285
if is_class /\ !is_open then
286
for s in closed_subclasses do
287
result.add(s)
288
od
289
fi
290
291
return result
292
si
293
294
is_derived_from_iterable_trait: bool
295
=> find_ancestor(IoC.CONTAINER.instance.innate_symbol_lookup.get_unspecialized_iterable_type())?
296
297
is_derived_from_iterator_trait: bool
298
=> find_ancestor(IoC.CONTAINER.instance.innate_symbol_lookup.get_unspecialized_iterator_type())?
299
300
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, argument_names: Collections.List[string], enclosing_scope: Scope) is
301
super.init(location, owner, name, enclosing_scope)
302
303
_ancestors = Collections.LIST[Type]()
304
_enclosing_symbols = Collections.MAP[string,Symbol]()
305
argument_constraint_kinds = Collections.LIST[TypeParameterConstraintKind](0)
306
argument_has_constructor_constraint = Collections.LIST[bool](0)
307
argument_type_bounds = Collections.LIST[Collections.LIST[Type]](0)
308
309
self.span = span
310
self.argument_names = argument_names
311
312
type = Types.NAMED(self)
313
si
314
315
get_ancestor(i: int) -> Type
316
=> ancestors[i].specialize(Collections.MAP[Symbol,Type]())
317
318
add_ancestor(ancestor: Type) is
319
assert ancestor? else "adding null ancestor to {name}"
320
321
_ancestors.add(ancestor)
322
si
323
324
_calc_depth() -> int => 0
325
326
// Distance from the root of the inheritance graph, counting
327
// implemented traits as well as the superclass chain: a
328
// concrete type reached only through the traits it implements
329
// has to rank below them.
330
_max_ancestor_depth() -> int =>
331
ancestors |> map(a => a.depth) |> reduce(0, (max, n) => if n > max then n else max fi)
332
333
add_implementor(symbol: Symbol) is
334
let implementors mut = _implementors
335
336
if !implementors? then
337
implementors = Collections.LIST[Symbol]()
338
_implementors = implementors
339
elif implementors.contains(symbol) then
340
return
341
fi
342
343
implementors.add(symbol)
344
345
if let journal = INHERITANCE_JOURNAL.current then
346
journal.record(InheritanceOp.IMPLEMENTOR_ADDED(self, symbol))
347
fi
348
si
349
350
remove_implementor(symbol: Symbol) is
351
let implementors = _implementors
352
353
if implementors? then
354
implementors.remove(symbol)
355
fi
356
si
357
358
push_ancestor(ancestor: Type) is
359
let na = Collections.LIST[Type]()
360
361
na.add(ancestor)
362
na.add_range(_ancestors)
363
364
_ancestors = na
365
si
366
367
add_closure(closure: Closure) is
368
if !_closures? then
369
_closures = Collections.SET[Closure]()
370
fi
371
372
if !_closures.contains(closure) then
373
_closures.add(closure)
374
fi
375
si
376
377
get_closures() -> Collections.Iterable[Closure] =>
378
if _closures? then _closures else Collections.LIST[Closure](0) fi
379
380
find_member(name: string) -> Symbol? => find_direct(name)
381
382
// The synthetic `$globals` class hosts namespace-level functions and
383
// fields in IL but is not user-spellable. Hide it from qualified
384
// names so HOVER and diagnostics show `NS.member` rather than
385
// `NS.$globals.member`.
386
qualified_name: string =>
387
if name =~ "$globals" /\ owner? then
388
owner.qualified_name
389
elif owner? then
390
owner.qualify(name)
391
else
392
name
393
fi
394
395
qualify(name: string) -> string =>
396
if self.name =~ "$globals" /\ owner? then
397
owner.qualify(name)
398
else
399
"{qualified_name}.{name}"
400
fi
401
402
// The unqualified name this type is emitted under. A generic
403
// that shares its name with an arity sibling carries the `N
404
// suffix .NET uses to tell such a pair apart: without it the
405
// two occupy one metadata name, and every consumer that finds a
406
// type by name - Type.GetType, a custom-attribute blob, another
407
// assembly importing this one - resolves whichever row it
408
// reaches first. A generic with no sibling keeps the bare name
409
// it has always been emitted under.
410
il_metadata_name: string =>
411
if has_argument_count_siblings /\ is_generic then
412
"{name}`{argument_names.count}"
413
else
414
name
415
fi
416
417
// The emitted fully-qualified name, unquoted: the owner chain
418
// joined with dots and this type's emitted name. This is the
419
// name a custom-attribute blob carries for a typeof(T)
420
// argument; the binary encoder reads it here rather than
421
// rendering the type and stripping the quotes back off. An
422
// `il_name_override` of the `[assembly]Full.Name` form an
423
// imported type carries is taken verbatim past the bracket.
424
il_qualified_name: string is
425
let iln = il_name_override
426
427
if iln? then
428
let parts = iln.split(['[',']'])
429
430
if parts.count == 3 then
431
return parts[2]
432
fi
433
434
if owner? /\ !iln.contains('.') then
435
return "{_owner_il_qualified_name}.{iln}"
436
fi
437
438
return iln
439
fi
440
441
// An owner that contributes no name of its own - the root
442
// namespace, or a scope that is not a namespace or a type -
443
// leaves nothing to separate, so the name stands alone
444
// rather than picking up a leading dot.
445
if owner? then
446
let qualifier = _owner_il_qualified_name
447
448
if qualifier.length > 0 then
449
return "{qualifier}.{il_metadata_name}"
450
fi
451
fi
452
453
return il_metadata_name
454
si
455
456
// The owner chain's qualified IL name. A type's owner is a
457
// namespace or an enclosing type. A namespace's `qualified_name`
458
// carries a leading-dot root marker and is left intact by
459
// `qualify` only for non-synthetic namespaces, so read it
460
// directly and strip the marker; an enclosing type recurses.
461
_owner_il_qualified_name: string =>
462
if let ns = cast NAMESPACE?(owner) then
463
let q = ns.qualified_name
464
if q.starts_with('.') then q.substring(1) else q fi
465
elif let enclosing = cast Classy?(owner) then
466
enclosing.il_qualified_name
467
else
468
""
469
fi
470
471
// The member store backs the find_enclosing memo below; any
472
// mutation invalidates it. Batch builds never mutate a class
473
// after its expressions compile, but an analysis-mode
474
// incremental edit replaces members on a retained class — a
475
// memoized name would keep resolving to the outgoing symbol's
476
// (emptied) function group, so calls through it stop resolving.
477
declare(location: LOCATION, symbol: Symbol, symbol_definition_listener: SymbolDefinitionListener?) is
478
_enclosing_symbols.clear()
479
super.declare(location, symbol, symbol_definition_listener)
480
si
481
482
remove_direct(name: string) is
483
_enclosing_symbols.clear()
484
super.remove_direct(name)
485
si
486
487
put_direct(name: string, symbol: Symbol) is
488
_enclosing_symbols.clear()
489
super.put_direct(name, symbol)
490
si
491
492
find_enclosing(name: string) -> Symbol? is
493
if _enclosing_symbols.contains_key(name) then
494
return _enclosing_symbols[name]
495
fi
496
497
let result = find_direct(name)
498
499
if result? then
500
if !isa FUNCTION_GROUP(result) then
501
_enclosing_symbols[name] = result
502
503
return result
504
fi
505
506
let outer = find_enclosing_only(name)
507
508
if !outer? \/ !isa FUNCTION_GROUP(outer) then
509
_enclosing_symbols[name] = result
510
511
return result
512
fi
513
514
let combined = result.merged_over(outer)
515
516
_enclosing_symbols[name] = combined
517
518
return combined
519
fi
520
521
return find_enclosing_only(name)
522
si
523
524
find_ancestor_matches(prefix: string, matches: Collections.MutableMap[string, Symbols.Symbol]) is
525
assert _are_overrides_resolved
526
527
for a in ancestors do
528
if let a.scope? then
529
scope.find_member_matches(prefix, matches)
530
fi
531
od
532
si
533
534
find_member_matches(prefix: string, matches: Collections.MutableMap[string, Symbols.Symbol]) is
535
assert _are_overrides_resolved
536
537
find_direct_matches(prefix, matches)
538
si
539
540
find_enclosing_matches(prefix: string, matches: Collections.MutableMap[string, Symbols.Symbol]) is
541
assert _are_overrides_resolved
542
543
find_member_matches(prefix, matches)
544
find_enclosing_only_matches(prefix, matches)
545
si
546
547
assert_symbols_pulled_down() is
548
if !_are_overrides_resolved then
549
pull_down_super_symbols()
550
fi
551
si
552
553
mark_overrides_resolved() is
554
_are_overrides_resolved = true
555
si
556
557
pull_down_super_symbols() is
558
if _are_overrides_resolved then
559
return
560
fi
561
562
_are_overrides_resolved = true
563
564
let journal = INHERITANCE_JOURNAL(self)
565
566
// A reflected class is import-lifetime and never reset, so its
567
// journal is discarded after the pull-down. It is still pushed
568
// while the pull-down runs: a recursive ancestor resolution
569
// must never record its own mutations into the journal of the
570
// class that happened to trigger it.
571
if !is_reflected then
572
_inheritance_journal = journal
573
fi
574
575
INHERITANCE_JOURNAL.push(journal)
576
577
try
578
for i in 0..ancestors.count do
579
let symbol = get_ancestor(i).symbol
580
581
symbol.pull_down_super_symbols()
582
symbol.add_implementor(self)
583
od
584
585
let resolver = SYMBOL_INHERITANCE_RESOLVER(self)
586
587
resolver.pull_down_super_symbols_into()
588
finally
589
INHERITANCE_JOURNAL.pop()
590
yrt
591
si
592
593
// Reverse this class's pull_down_super_symbols exactly: remove the
594
// pulled-down members, override links, implementor registrations
595
// and inherited IL-name / assign-accessor state it recorded, and
596
// clear the resolved flag so resolve-overrides can run again for
597
// this class against a retained symbol table.
598
reset_pulled_down_symbols() is
599
if !_are_overrides_resolved then
600
return
601
fi
602
603
_are_overrides_resolved = false
604
605
if let journal = _inheritance_journal then
606
journal.undo()
607
608
_inheritance_journal = null
609
fi
610
si
611
612
try_specialize(
613
location: LOCATION,
614
logger: Logger,
615
actual_type_arguments: Collections.List[Type]
616
) -> Symbol? is
617
if !is_generic then
618
logger.error(location, "cannot explicitly specialize non-generic type")
619
return null
620
elif actual_type_arguments.count != argument_names.count then
621
logger.error(location, "expected {argument_names.count} explicit generic type arguments")
622
return null
623
fi
624
625
check_argument_constraints(location, logger, actual_type_arguments)
626
627
return GENERIC(location, self, actual_type_arguments)
628
si
629
630
// This type applied to its own type parameters.
631
//
632
// It is what its members' receiver is from inside its own
633
// methods, and what a subtype of it extends. The open type a
634
// generic is declared as is not a type anything can name at run
635
// time, so a row or a reference that needs to name this one has
636
// to construct it. A non-generic type is already itself.
637
own_instantiation: Type is
638
if argument_names.count == 0 then
639
return type!
640
fi
641
642
let arguments = Collections.LIST[Type]()
643
644
for index in 0..argument_names.count do
645
let parameter = type_parameter_at(index)
646
647
assert parameter? else
648
"generic type '{name}' has no type parameter '{argument_names[index]}'"
649
650
arguments.add(parameter.type!)
651
od
652
653
return Types.GENERIC(LOCATION.internal, self, arguments)
654
si
655
656
// The symbol standing for the type parameter at `index`, or null
657
// when there is none to be had.
658
//
659
// A type that writes its parameters declares them into its own
660
// scope, so the name it wrote finds them. A closure frame is the
661
// exception: its parameters are the enclosing function's,
662
// reached at a position the lowering installs rather than
663
// redeclared, so it answers with those symbols instead.
664
type_parameter_at(index: int) -> Symbol? is
665
if index < 0 \/ index >= argument_names.count then
666
return null
667
fi
668
669
if let declared = find_direct(argument_names[index]) then
670
return declared
671
fi
672
673
// Several kinds of generic carry their parameters
674
// positionally without declaring them into their own scope:
675
// an imported one, the innate types the compiler registers
676
// itself, and a tuple. There is no name to find, so the
677
// position is the whole answer. The parameter minted for it
678
// is cached, because every request has to answer with the
679
// same symbol — type substitution matches on identity, and a
680
// fresh symbol each time would silently fail to match.
681
if !_positional_type_parameters? then
682
let parameters = Collections.LIST[GenericArgument](argument_names.count)
683
684
for i in 0..argument_names.count do
685
parameters.add(CLASSY_GENERIC_ARGUMENT(location, self, argument_names[i], i))
686
od
687
688
_positional_type_parameters = parameters
689
fi
690
691
return _positional_type_parameters[index]
692
si
693
694
// The kind constraint of the type parameter at `index`. Imported
695
// generics carry it in the `argument_constraint_kinds` list (the
696
// type-parameter symbols are not declared in scope); ghūl-declared
697
// generics carry it on the type-parameter symbol itself.
698
get_argument_constraint_kind(index: int) -> TypeParameterConstraintKind is
699
if index >= 0 /\ index < argument_constraint_kinds.count then
700
return argument_constraint_kinds[index]
701
fi
702
703
if index >= 0 /\ index < argument_names.count then
704
let argument = type_parameter_at(index)
705
706
if argument? then
707
return argument.constraint_kind
708
fi
709
fi
710
711
return TypeParameterConstraintKind.NONE
712
si
713
714
// Whether the type parameter at `index` carries a parameterless-
715
// constructor (`init`) constraint. Imported .NET generics carry
716
// it in `argument_has_constructor_constraint` (populated by
717
// symbol_factory at import time); ghūl-declared generics carry it
718
// on the type-parameter symbol itself (set by declare_symbols
719
// from the parsed `[T: init]` NTE flag).
720
get_argument_has_constructor_constraint(index: int) -> bool is
721
if index >= 0 /\ index < argument_has_constructor_constraint.count then
722
return argument_has_constructor_constraint[index]
723
fi
724
725
if index >= 0 /\ index < argument_names.count then
726
let argument = type_parameter_at(index)
727
728
if argument? then
729
return argument.has_constructor_constraint
730
fi
731
fi
732
733
return false
734
si
735
736
// The bounds (`[T: A /\ B]`) of the type parameter at `index`,
737
// empty when unbounded. Imported generics carry them in
738
// `argument_type_bounds`; ghūl-declared generics carry them on the
739
// type-parameter symbol as its ancestors, with the meaningless
740
// `object` default bound dropped.
741
get_argument_type_bounds(index: int) -> Collections.List[Type] is
742
if index >= 0 /\ index < argument_type_bounds.count then
743
return argument_type_bounds[index]
744
fi
745
746
if index >= 0 /\ index < argument_names.count then
747
let argument = type_parameter_at(index)
748
749
if argument? /\ argument.is_type_variable then
750
let result = Collections.LIST[Type](0)
751
752
for ancestor in argument.ancestors do
753
if !ancestor.is_object then
754
result.add(ancestor)
755
fi
756
od
757
758
return result
759
fi
760
fi
761
762
return Collections.LIST[Type](0)
763
si
764
765
check_argument_constraints(
766
location: LOCATION,
767
logger: Logger,
768
actual_type_arguments: Collections.List[Type]
769
) is
770
GENERIC_CONSTRAINT_CHECKER().check_arguments(
771
location,
772
logger,
773
self,
774
argument_names,
775
actual_type_arguments
776
)
777
si
778
779
check_argument_type_bounds(
780
location: LOCATION,
781
logger: Logger,
782
actual_type_arguments: Collections.List[Type]
783
) is
784
GENERIC_CONSTRAINT_CHECKER().check_argument_type_bounds(
785
location,
786
logger,
787
self,
788
argument_names,
789
actual_type_arguments
790
)
791
si
792
793
check_argument_kinds(
794
location: LOCATION,
795
logger: Logger,
796
actual_type_arguments: Collections.List[Type]
797
) is
798
GENERIC_CONSTRAINT_CHECKER().check_argument_kinds(
799
location,
800
logger,
801
self,
802
argument_names,
803
actual_type_arguments
804
)
805
si
806
807
// True when this type declares an explicit static constructor
808
// (`init() static`). Such a type must not be emitted with
809
// `beforefieldinit`, which would let the CLR run the `.cctor`
810
// at an unspecified point before first use rather than
811
// precisely before it.
812
has_static_constructor: bool is
813
if let group: Symbols.FUNCTION_GROUP = find_direct("init") then
814
for f in group.functions do
815
if f.is_static_constructor then
816
return true
817
fi
818
od
819
fi
820
821
return false
822
si
823
824
// Shared head rendering for the classy kinds. Produces
825
// `<keyword> <name>[<type params>]`, optionally followed by the
826
// primary constructor arguments, so a hover on a declaration shows
827
// the shape you would write. The concrete kinds supply their
828
// keyword and whether a constructor applies.
829
// The name part already carries the type parameters through
830
// `render_name` (`render_type_argument_suffix`), so the head is just
831
// keyword + name + optional primary constructor arguments.
832
_describe_classy_head(keyword: string, include_constructor: bool) -> SignaturePart is
833
let parts = Collections.LIST[SignaturePart]()
834
parts.add(PARTS.literal(keyword))
835
parts.add(PARTS.name(self))
836
if include_constructor then
837
parts.add(_describe_constructor_arguments())
838
fi
839
return SignaturePart.SEQUENCE(parts)
840
si
841
842
// A generic classy always renders its formal type parameters.
843
render_type_argument_suffix() -> string is
844
if argument_names.count == 0 then
845
return ""
846
fi
847
let result = System.Text.StringBuilder()
848
result.append('[')
849
let first mut = true
850
for name in argument_names do
851
if !first then
852
result.append(',')
853
fi
854
first = false
855
result.append(name)
856
od
857
result.append(']')
858
return result.to_string()
859
si
860
861
_describe_constructor_arguments() -> SignaturePart is
862
let constructor = primary_constructor
863
if !constructor? \/ constructor.arguments.count == 0 then
864
return PARTS.nil()
865
fi
866
let items = Collections.LIST[SignaturePart]()
867
for i in 0..constructor.arguments.count do
868
items.add(PARTS.sequence([
869
PARTS.literal("{constructor.argument_names[i]}: "),
870
PARTS.type_ref(constructor.arguments[i])
871
]))
872
od
873
return SignaturePart.WRAPPABLE("(", ",", false, ")", items)
874
si
875
876
_make_instance_method(location: LOCATION, span: LOCATION, name: string, is_underscore: bool, enclosing: Scope) -> Function is
877
if is_underscore then
878
let policy = IoC.CONTAINER.instance.build_flags.underscore_access
879
880
if policy == Compiler.UnderscoreAccess.PRIVATE then
881
return Symbols.PRIVATE_METHOD(location, span, self, name, enclosing)
882
elif policy == Compiler.UnderscoreAccess.PROTECTED then
883
return Symbols.PROTECTED_METHOD(location, span, self, name, enclosing)
884
fi
885
fi
886
887
return Symbols.INSTANCE_METHOD(location, span, self, name, enclosing)
888
si
889
890
_make_static_method(location: LOCATION, span: LOCATION, name: string, is_underscore: bool, enclosing: Scope) -> Function is
891
if name =~ "init" then
892
return Symbols.STATIC_CONSTRUCTOR(location, span, self, name, enclosing)
893
fi
894
895
if is_underscore then
896
let policy = IoC.CONTAINER.instance.build_flags.underscore_access
897
898
if policy == Compiler.UnderscoreAccess.PRIVATE then
899
return Symbols.PRIVATE_STATIC_METHOD(location, span, self, name, enclosing)
900
elif policy == Compiler.UnderscoreAccess.PROTECTED then
901
return Symbols.PROTECTED_STATIC_METHOD(location, span, self, name, enclosing)
902
fi
903
fi
904
905
return Symbols.STATIC_METHOD(location, span, self, name, enclosing)
906
si
907
si
908
909
class CLASS: Classy, Types.Typed is
910
short_description: string => "class {name}"
911
912
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
913
_describe_classy_head("class ", true)
914
915
describe_kind(context: DESCRIBE_CONTEXT) -> string? => "class"
916
917
symbol_kind: SymbolKind => SymbolKind.CLASS
918
completion_kind: CompletionKind => CompletionKind.CLASS
919
920
921
is_inheritable: bool => true
922
is_class: bool => true
923
is_object: bool
924
is_root_value_type: bool
925
is_root_array_type: bool
926
927
il_name_prefix: string => "class "
928
929
is_instance_context: bool => true
930
931
_is_open_by_default: bool => is_reflected
932
933
// Set from the `abstract` modifier during declare-symbols for
934
// ghūl-declared classes, and from `TypeAttributes.Abstract` at
935
// import time for reflected classes. An abstract class cannot
936
// be instantiated directly (constructor calls are rejected),
937
// and the closed-narrowing path excludes it from the
938
// complement universe so the narrow can reach subtype-only
939
// members.
940
//
941
// Beyond the explicit mark, a class is implicitly abstract
942
// when it carries any user-written body-less method — the
943
// user wrote a method without a body, clearly meaning it as
944
// a contract for subclasses to satisfy, and a bare instance
945
// of this class would throw on calling it. Today's ghūl
946
// synthesises a throw body for body-less ghūl-class methods
947
// rather than emitting them as real `ABSTRACT_METHOD`
948
// symbols, so the user-intent signal has to be captured
949
// explicitly via `mark_has_bodyless_method` during
950
// declare-symbols. (Inherited-but-unimplemented abstract
951
// methods aren't covered here — for those, the user should
952
// either override or mark the class explicitly `abstract`.)
953
_is_abstract: bool
954
_bodyless_method_count: int
955
956
_has_bodyless_method: bool => _bodyless_method_count > 0
957
958
is_abstract: bool =>
959
_is_abstract \/ _has_bodyless_method
960
961
is_implicitly_abstract: bool =>
962
_has_bodyless_method /\ !_is_abstract
963
964
mark_has_bodyless_method() is
965
_bodyless_method_count = _bodyless_method_count + 1
966
si
967
968
// Called when one of them turns out to override an implemented
969
// member, so it carries a throwing body rather than being a
970
// contract, and stops counting towards the class's abstractness.
971
unmark_has_bodyless_method() is
972
if _bodyless_method_count > 0 then
973
_bodyless_method_count = _bodyless_method_count - 1
974
fi
975
si
976
977
mark_abstract() is
978
_is_abstract = true
979
si
980
981
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, arguments: Collections.List[string], enclosing_scope: Scope) is
982
super.init(location, span, owner, name, arguments, enclosing_scope)
983
984
self.span = span
985
si
986
987
mark_is_object() is
988
is_object = true
989
si
990
991
mark_is_root_value_type() is
992
is_root_value_type = true
993
si
994
995
mark_is_root_array_type() is
996
is_root_array_type = true
997
si
998
999
_calc_depth() -> int =>
1000
if is_object then
1001
0
1002
else
1003
_max_ancestor_depth() + 1
1004
fi
1005
1006
load(location: LOCATION, from: Value?, loader: SYMBOL_LOADER) -> Value => loader.load_class(self)
1007
1008
declare_type(location: LOCATION, name: string, index: int, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1009
let result = Symbols.CLASSY_GENERIC_ARGUMENT(location, self, name, index)
1010
1011
declare(location, result, symbol_definition_listener)
1012
1013
return result
1014
si
1015
1016
declare_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, is_property_accessor: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1017
let result: Function mut
1018
1019
if is_static then
1020
result = _make_static_method(location, span, name, is_private, enclosing)
1021
elif !has_body /\ !is_property_accessor then
1022
// A method the user wrote with no body at all is a
1023
// contract for a subclass to satisfy: it has nothing
1024
// to run, so the class is abstract and a concrete
1025
// subclass owes an implementation. A property's
1026
// accessor is not one of these - a body-less accessor
1027
// reads or writes the backing field.
1028
result = Symbols.ABSTRACT_METHOD(location, span, self, name, enclosing)
1029
else
1030
result = _make_instance_method(location, span, name, is_private, enclosing)
1031
fi
1032
1033
declare_function_group(location, result, symbol_definition_listener)
1034
1035
return result
1036
si
1037
1038
declare_generator_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1039
let result: Function mut
1040
1041
if is_static then
1042
result = Symbols.STATIC_GENERATOR_METHOD(location, span, self, name, enclosing)
1043
else
1044
result = Symbols.INSTANCE_GENERATOR_METHOD(location, span, self, name, enclosing)
1045
fi
1046
1047
declare_function_group(location, result, symbol_definition_listener)
1048
1049
return result
1050
si
1051
1052
declare_async_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1053
let result: Function mut
1054
1055
if is_static then
1056
result = Symbols.STATIC_ASYNC_METHOD(location, span, self, name, enclosing)
1057
else
1058
result = Symbols.INSTANCE_ASYNC_METHOD(location, span, self, name, enclosing)
1059
fi
1060
1061
declare_function_group(location, result, symbol_definition_listener)
1062
1063
return result
1064
si
1065
1066
declare_innate(location: LOCATION, name: string, innate_name: string, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1067
let result = Symbols.INNATE_METHOD(location, self, name, enclosing, innate_name)
1068
1069
declare_function_group(location, result, symbol_definition_listener)
1070
1071
return result
1072
si
1073
1074
declare_variable(location: LOCATION, name: string, is_static: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1075
let result: Variable mut
1076
1077
if is_static then
1078
result = Symbols.STATIC_FIELD(location, self, name)
1079
else
1080
result = Symbols.INSTANCE_FIELD(location, self, name)
1081
fi
1082
1083
declare(location, result, symbol_definition_listener)
1084
1085
return result
1086
si
1087
1088
declare_property(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, is_assignable: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1089
let result: Property mut
1090
1091
if is_static then
1092
result = Symbols.STATIC_PROPERTY(location, span, self, name, is_assignable, is_private)
1093
else
1094
result = Symbols.INSTANCE_PROPERTY(location, span, self, name, is_assignable, is_private)
1095
fi
1096
1097
declare(location, result, symbol_definition_listener)
1098
1099
return result
1100
si
1101
1102
si
1103
1104
class TRAIT: Classy, Types.Typed is
1105
short_description: string => "trait {name}"
1106
1107
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
1108
_describe_classy_head("trait ", false)
1109
1110
describe_kind(context: DESCRIBE_CONTEXT) -> string? => "trait"
1111
1112
symbol_kind: SymbolKind => SymbolKind.INTERFACE
1113
completion_kind: CompletionKind => CompletionKind.INTERFACE
1114
1115
1116
is_inheritable: bool => true
1117
is_trait: bool => true
1118
1119
_is_open_by_default: bool => is_reflected
1120
1121
il_name_prefix: string => "class "
1122
1123
is_instance_context: bool => true
1124
1125
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, arguments: Collections.List[string], enclosing_scope: Scope) is
1126
super.init(location, span, owner, name, arguments, enclosing_scope)
1127
si
1128
1129
_calc_depth() -> int => _max_ancestor_depth() + 1
1130
1131
declare_type(location: LOCATION, name: string, index: int, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1132
let result = Symbols.CLASSY_GENERIC_ARGUMENT(location, self, name, index)
1133
1134
declare(location, result, symbol_definition_listener)
1135
1136
return result
1137
si
1138
1139
load(location: LOCATION, from: IR.Values.Value?, loader: SYMBOL_LOADER) -> IR.Values.Value is
1140
return loader.load_trait(self)
1141
si
1142
1143
declare_innate(location: LOCATION, name: string, innate_name: string, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1144
let result = Symbols.INNATE_FUNCTION(location, self, name, enclosing, innate_name)
1145
1146
declare_function_group(location, result, symbol_definition_listener)
1147
1148
return result
1149
si
1150
1151
declare_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, is_property_accessor: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1152
let result: Function mut
1153
1154
if is_static then
1155
IoC.CONTAINER.instance.logger.error(location, "cannot declare static method in trait")
1156
result = _make_static_method(location, span, name, is_private, enclosing)
1157
elif has_body then
1158
result = Symbols.DEFAULT_TRAIT_METHOD(location, span, self, name, enclosing)
1159
else
1160
result = Symbols.ABSTRACT_METHOD(location, span, self, name, enclosing)
1161
fi
1162
1163
declare_function_group(location, result, symbol_definition_listener)
1164
1165
return result
1166
si
1167
1168
declare_generator_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1169
let result: Function mut
1170
1171
if is_static then
1172
IoC.CONTAINER.instance.logger.error(location, "cannot declare static method in trait")
1173
result = Symbols.STATIC_GENERATOR_METHOD(location, span, self, name, enclosing)
1174
else
1175
result = Symbols.DEFAULT_TRAIT_GENERATOR_METHOD(location, span, self, name, enclosing)
1176
fi
1177
1178
declare_function_group(location, result, symbol_definition_listener)
1179
1180
return result
1181
si
1182
1183
declare_async_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1184
let result: Function mut
1185
1186
if is_static then
1187
IoC.CONTAINER.instance.logger.error(location, "cannot declare static method in trait")
1188
result = Symbols.STATIC_ASYNC_METHOD(location, span, self, name, enclosing)
1189
else
1190
result = Symbols.DEFAULT_TRAIT_ASYNC_METHOD(location, span, self, name, enclosing)
1191
fi
1192
1193
declare_function_group(location, result, symbol_definition_listener)
1194
1195
return result
1196
si
1197
1198
declare_property(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, is_assignable: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1199
let result: Property mut
1200
1201
if is_static then
1202
IoC.CONTAINER.instance.logger.error(location, "cannot declare static property in trait")
1203
result = Symbols.STATIC_PROPERTY(location, span, self, name, is_assignable, is_private)
1204
else
1205
result = Symbols.INSTANCE_PROPERTY(location, span, self, name, is_assignable, is_private)
1206
fi
1207
1208
declare(location, result, symbol_definition_listener)
1209
1210
return result
1211
si
1212
1213
si
1214
1215
class STRUCT: Classy, Types.Typed is
1216
short_description: string => "struct {name}"
1217
1218
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
1219
_describe_classy_head("struct ", true)
1220
1221
describe_kind(context: DESCRIBE_CONTEXT) -> string? => "struct"
1222
1223
symbol_kind: SymbolKind => SymbolKind.STRUCT
1224
completion_kind: CompletionKind => CompletionKind.STRUCT
1225
1226
1227
is_value_type: bool => true
1228
1229
il_name_prefix: string => "valuetype "
1230
1231
is_instance_context: bool => true
1232
1233
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, arguments: Collections.List[string], enclosing_scope: Scope) is
1234
super.init(location, span, owner, name, arguments, enclosing_scope)
1235
si
1236
1237
_calc_depth() -> int => 2 // object -> value type -> struct
1238
1239
load(location: LOCATION, from: IR.Values.Value?, loader: SYMBOL_LOADER) -> IR.Values.Value is
1240
return loader.load_struct(self)
1241
si
1242
1243
// FIXME: most of these can be folded into Classy:
1244
1245
declare_type(location: LOCATION, name: string, index: int, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1246
let result = Symbols.CLASSY_GENERIC_ARGUMENT(location, self, name, index)
1247
1248
declare(location, result, symbol_definition_listener)
1249
1250
return result
1251
si
1252
1253
declare_innate(location: LOCATION, name: string, innate_name: string, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1254
let result = Symbols.INNATE_METHOD(location, self, name, enclosing, innate_name)
1255
1256
declare_function_group(location, result, symbol_definition_listener)
1257
1258
return result
1259
si
1260
1261
declare_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, is_property_accessor: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1262
let result: Function mut
1263
1264
if is_static then
1265
result = _make_static_method(location, span, name, is_private, enclosing)
1266
else
1267
result = Symbols.STRUCT_METHOD(location, span, self, name, enclosing)
1268
fi
1269
1270
declare_function_group(location, result, symbol_definition_listener)
1271
1272
return result
1273
si
1274
1275
declare_variable(location: LOCATION, name: string, is_static: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1276
let result: Variable mut
1277
1278
if is_static then
1279
result = Symbols.STATIC_FIELD(location, self, name)
1280
else
1281
result = Symbols.STRUCT_FIELD(location, self, name)
1282
fi
1283
1284
declare(location, result, symbol_definition_listener)
1285
1286
return result
1287
si
1288
1289
declare_property(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, is_assignable: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1290
let result: Property mut
1291
1292
if is_static then
1293
result = Symbols.STATIC_PROPERTY(location, span, self, name, is_assignable, is_private)
1294
else
1295
result = Symbols.INSTANCE_PROPERTY(location, span, self, name, is_assignable, is_private)
1296
fi
1297
1298
declare(location, result, symbol_definition_listener)
1299
1300
return result
1301
si
1302
1303
si
1304
1305
class UNION: Classy, Types.Typed is
1306
short_description: string => "union {name}"
1307
1308
describe(context: DESCRIBE_CONTEXT) -> SignaturePart is
1309
let parts = Collections.LIST[SignaturePart]()
1310
parts.add(_describe_classy_head("union ", false))
1311
1312
// A union's traits are not visible from its body - variants
1313
// only - and an impl block can add one from another file
1314
// entirely, so the hover lists them.
1315
let first mut = true
1316
for a in ancestors do
1317
if !a.is_trait then
1318
continue
1319
fi
1320
1321
parts.add(PARTS.literal(if first then ": " else ", " fi))
1322
parts.add(PARTS.type_ref(a))
1323
first = false
1324
od
1325
1326
return SignaturePart.SEQUENCE(parts)
1327
si
1328
1329
describe_kind(context: DESCRIBE_CONTEXT) -> string? => "union"
1330
1331
symbol_kind: SymbolKind => SymbolKind.CLASS
1332
completion_kind: CompletionKind => CompletionKind.CLASS
1333
1334
1335
il_name_prefix: string => "class "
1336
1337
is_union: bool => true
1338
is_instance_context: bool => true
1339
1340
// The variant `?` and `!` target. `compile_access` reads
1341
// this to lower `u?` to `isa Default(u)` and `u!` to a cast
1342
// (plus single-field projection). Source unions get this
1343
// set during declare_members; cross-assembly unions get it
1344
// via the `DEFAULT_VARIANT_ATTRIBUTE` marker read in
1345
// `SYMBOL_FACTORY.materialize_variant`. When null — a
1346
// source union with no default, or a cross-asm union from
1347
// an older compiler that predates the marker — `?` short-
1348
// circuits to a bare null check and `!` to a plain
1349
// non-null assert.
1350
default_variant: VARIANT? public
1351
1352
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, arguments: Collections.List[string], enclosing_scope: Scope) is
1353
super.init(location, span, owner, name, arguments, enclosing_scope)
1354
si
1355
1356
_calc_depth() -> int => 1 // object -> union
1357
1358
load(location: LOCATION, from: IR.Values.Value?, loader: SYMBOL_LOADER) -> IR.Values.Value =>
1359
loader.load_union(self)
1360
1361
// FIXME: most of these can be folded into Classy:
1362
declare_type(location: LOCATION, name: string, index: int, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1363
let result = Symbols.CLASSY_GENERIC_ARGUMENT(location, self, name, index)
1364
1365
declare(location, result, symbol_definition_listener)
1366
1367
return result
1368
si
1369
1370
declare_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, is_property_accessor: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1371
let result: Function mut
1372
1373
if is_static then
1374
result = _make_static_method(location, span, name, is_private, enclosing)
1375
else
1376
result = _make_instance_method(location, span, name, is_private, enclosing)
1377
fi
1378
1379
declare_function_group(location, result, symbol_definition_listener)
1380
1381
return result
1382
si
1383
1384
declare_generator_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1385
let result: Function mut
1386
1387
if is_static then
1388
result = Symbols.STATIC_GENERATOR_METHOD(location, span, self, name, enclosing)
1389
else
1390
result = Symbols.INSTANCE_GENERATOR_METHOD(location, span, self, name, enclosing)
1391
fi
1392
1393
declare_function_group(location, result, symbol_definition_listener)
1394
1395
return result
1396
si
1397
1398
declare_async_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1399
let result: Function mut
1400
1401
if is_static then
1402
result = Symbols.STATIC_ASYNC_METHOD(location, span, self, name, enclosing)
1403
else
1404
result = Symbols.INSTANCE_ASYNC_METHOD(location, span, self, name, enclosing)
1405
fi
1406
1407
declare_function_group(location, result, symbol_definition_listener)
1408
1409
return result
1410
si
1411
1412
declare_property(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, is_assignable: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1413
let result: Property mut
1414
1415
if is_static then
1416
result = Symbols.STATIC_PROPERTY(location, span, self, name, is_assignable, is_private)
1417
else
1418
result = Symbols.INSTANCE_PROPERTY(location, span, self, name, is_assignable, is_private)
1419
fi
1420
1421
declare(location, result, symbol_definition_listener)
1422
1423
return result
1424
si
1425
1426
// Supports the backing fields the auto-property lowering
1427
// synthesises for primary-constructor parameters. User-written
1428
// fields inside a union body aren't reachable from the parser,
1429
// so this is exercised only for synthesised members.
1430
declare_variable(location: LOCATION, name: string, is_static: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1431
let result: Variable mut
1432
1433
if is_static then
1434
result = Symbols.STATIC_FIELD(location, self, name)
1435
else
1436
result = Symbols.INSTANCE_FIELD(location, self, name)
1437
fi
1438
1439
declare(location, result, symbol_definition_listener)
1440
1441
return result
1442
si
1443
1444
declare_variant(location: LOCATION, span: LOCATION, name: string, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1445
let result = Symbols.VARIANT(location, span, self, name, argument_names, enclosing)
1446
1447
declare(location, result, symbol_definition_listener)
1448
1449
return result
1450
si
1451
1452
si
1453
1454
class VARIANT: Classy, Types.Typed is
1455
_field_names: Collections.LIST[string]
1456
1457
short_description: string => "variant {name}"
1458
1459
// No `variant` keyword: a variant has no standalone declaration
1460
// syntax outside its union, so the head is just the union-qualified
1461
// name plus any fields, and the kind is carried by `describe_kind`.
1462
describe(context: DESCRIBE_CONTEXT) -> SignaturePart is
1463
let parts = Collections.LIST[SignaturePart]()
1464
parts.add(PARTS.name(self))
1465
if _field_names.count > 0 then
1466
let items = Collections.LIST[SignaturePart]()
1467
for name in _field_names do
1468
let member = find_member(name)
1469
if member? then
1470
items.add(PARTS.sequence([
1471
PARTS.literal("{member.name}: "),
1472
PARTS.type_ref(member.type!)
1473
]))
1474
fi
1475
od
1476
parts.add(SignaturePart.WRAPPABLE("(", ",", false, ")", items))
1477
fi
1478
return SignaturePart.SEQUENCE(parts)
1479
si
1480
1481
describe_kind(context: DESCRIBE_CONTEXT) -> string? => "variant"
1482
1483
symbol_kind: SymbolKind => SymbolKind.CLASS
1484
completion_kind: CompletionKind => CompletionKind.CLASS
1485
1486
1487
il_name_prefix: string => "class "
1488
1489
is_variant: bool => true
1490
is_unit_variant: bool => _field_names.count == 0
1491
is_instance_context: bool => true
1492
can_accept_actual_type_arguments: bool => true
1493
1494
// Total field count (own + inherited). `own_field_count`
1495
// excludes inherited primary fields; this property includes
1496
// them so the single-field unwrap projection considers the
1497
// variant's full surface — a `BOX(payload: T, ..)` against
1498
// a union with primary params is multi-field overall and
1499
// unwraps to the variant itself, not the lone own field.
1500
field_count: int => _field_names.count
1501
1502
// True for the variant the union nominated as its default —
1503
// either via the `default` modifier, or as the lone non-unit
1504
// variant fallback. Set by declare_symbols from the AST flag.
1505
is_default: bool public
1506
1507
// Own-field count (own + inherited-primary kept in
1508
// `_field_names`; `own_field_count` excludes the inherited
1509
// ones so the implicit-default rule "exactly one non-unit
1510
// variant" measures variants by what they declare themselves
1511
// — a variant whose only fields come from the union's
1512
// primary-constructor splice is still a unit variant for
1513
// that rule.
1514
own_field_count: int public
1515
1516
field_descriptions: string =>
1517
if _field_names.count == 0 then
1518
""
1519
else
1520
"({_field_names |> map(name => let member = find_member(name)! in "{member.name}: {member.type}") |> join(", ")})"
1521
fi
1522
1523
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, arguments: Collections.List[string], enclosing_scope: Scope) is
1524
super.init(location, span, owner, name, arguments, enclosing_scope)
1525
1526
_field_names = Collections.LIST[string]()
1527
si
1528
1529
_calc_depth() -> int => 2 // object -> union -> variant
1530
1531
get_destructure_member_name(index: int) -> string? =>
1532
if index < _field_names.count then
1533
_field_names[index]
1534
else
1535
null
1536
fi
1537
1538
load(location: LOCATION, from: IR.Values.Value?, loader: SYMBOL_LOADER) -> IR.Values.Value =>
1539
loader.load_variant(self)
1540
1541
// FIXME: most of these can be folded into Classy:
1542
declare_type(location: LOCATION, name: string, index: int, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1543
let result = Symbols.CLASSY_GENERIC_ARGUMENT(location, self, name, index)
1544
1545
declare(location, result, symbol_definition_listener)
1546
1547
return result
1548
si
1549
1550
declare_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, is_property_accessor: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1551
let result: Function mut
1552
1553
if is_static then
1554
result = _make_static_method(location, span, name, is_private, enclosing)
1555
else
1556
result = _make_instance_method(location, span, name, is_private, enclosing)
1557
fi
1558
1559
declare_function_group(location, result, symbol_definition_listener)
1560
1561
return result
1562
si
1563
1564
declare_generator_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1565
let result: Function mut
1566
1567
if is_static then
1568
result = Symbols.STATIC_GENERATOR_METHOD(location, span, self, name, enclosing)
1569
else
1570
result = Symbols.INSTANCE_GENERATOR_METHOD(location, span, self, name, enclosing)
1571
fi
1572
1573
declare_function_group(location, result, symbol_definition_listener)
1574
1575
return result
1576
si
1577
1578
declare_async_function(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, has_body: bool, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1579
let result: Function mut
1580
1581
if is_static then
1582
result = Symbols.STATIC_ASYNC_METHOD(location, span, self, name, enclosing)
1583
else
1584
result = Symbols.INSTANCE_ASYNC_METHOD(location, span, self, name, enclosing)
1585
fi
1586
1587
declare_function_group(location, result, symbol_definition_listener)
1588
1589
return result
1590
si
1591
1592
declare_innate(location: LOCATION, name: string, innate_name: string, enclosing: Scope, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1593
let result = Symbols.INNATE_METHOD(location, self, name, enclosing, innate_name)
1594
1595
declare_function_group(location, result, symbol_definition_listener)
1596
1597
return result
1598
si
1599
1600
declare_variable(location: LOCATION, name: string, is_static: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1601
let result = Symbols.VARIANT_FIELD(location, self, name)
1602
1603
_field_names.add(name)
1604
own_field_count = own_field_count + 1
1605
1606
declare(location, result, symbol_definition_listener)
1607
1608
return result
1609
si
1610
1611
// Used by the reflection layer: when a cross-assembly
1612
// variant's symbol is materialized, its fields are added
1613
// via `add_member` (which doesn't touch `_field_names`).
1614
// Positional destructure (`let (v, r) = step`) consults
1615
// `_field_names` via `get_destructure_member_name(index)`,
1616
// so reflected variants need this list populated in source
1617
// order. The reflection caller iterates the variant's
1618
// instance fields in their .NET-metadata declaration order
1619
// (which matches source order in practice) and calls this
1620
// for each.
1621
register_reflected_field_name(name: string) is
1622
_field_names.add(name)
1623
own_field_count = own_field_count + 1
1624
si
1625
1626
// Called by declare_members for variant fields produced by
1627
// expanding a `..` splice against the enclosing union's
1628
// primary-constructor parameters. No VARIANT_FIELD is created
1629
// — the union base owns the storage — but the name still
1630
// contributes to the variant's arity (`is_unit_variant`,
1631
// positional destructure, field-description rendering).
1632
register_inherited_primary_field_name(name: string) is
1633
_field_names.add(name)
1634
si
1635
1636
declare_property(location: LOCATION, span: LOCATION, name: string, is_static: bool, is_private: bool, is_assignable: bool, symbol_definition_listener: SymbolDefinitionListener?) -> Symbol is
1637
let result: Property mut
1638
1639
if is_static then
1640
result = Symbols.STATIC_PROPERTY(location, span, self, name, is_assignable, is_private)
1641
else
1642
result = Symbols.INSTANCE_PROPERTY(location, span, self, name, is_assignable, is_private)
1643
fi
1644
1645
declare(location, result, symbol_definition_listener)
1646
1647
return result
1648
si
1649
1650
specialize(arguments: Collections.List[Type]) -> Symbol is
1651
return GENERIC(location, self, arguments)
1652
si
1653
1654
si
1655
1656
class ENUM_STRUCT: STRUCT is
1657
_next_value: int
1658
1659
next_value: int is
1660
let result = _next_value
1661
1662
_next_value = _next_value + 1
1663
1664
return result
1665
si
1666
1667
// The type an imported enum was declared over - `enum Wide :
1668
// long`. Absent for a ghūl-declared enum, which is always
1669
// int32-backed, and every reader of an enum value treats the
1670
// absent record as int32.
1671
underlying_type: Types.Type? public
1672
1673
// Whether a value of this enum is read wider than int32. Only
1674
// an enum imported with a 64-bit underlying type is, so every
1675
// other enum - including any that recorded nothing - is not.
1676
is_wider_than_int32(lookup: Lookups.InnateSymbolLookup) -> bool is
1677
if let declared = underlying_type then
1678
return
1679
declared.matches(lookup.get_long_type()) \/
1680
declared.matches(lookup.get_ulong_type())
1681
fi
1682
1683
return false
1684
si
1685
1686
short_description: string => "enum {name}"
1687
1688
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
1689
PARTS.sequence([PARTS.literal("enum "), PARTS.name(self)])
1690
1691
describe_kind(context: DESCRIBE_CONTEXT) -> string? => "enum"
1692
1693
symbol_kind: SymbolKind => SymbolKind.ENUM
1694
completion_kind: CompletionKind => CompletionKind.ENUM
1695
1696
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, enclosing_scope: Scope) is
1697
super.init(location, span, owner, name, Collections.LIST[string](), enclosing_scope)
1698
si
1699
1700
load(location: LOCATION, from: IR.Values.Value?, loader: SYMBOL_LOADER) -> IR.Values.Value is
1701
return loader.load_struct(self)
1702
si
1703
1704
declare_enum_member(location: LOCATION, name: string, value: string? mut, symbol_definition_listener: SymbolDefinitionListener?) is
1705
if !value? then
1706
value = "{next_value}"
1707
fi
1708
1709
let result = Symbols.ENUM_STRUCT_MEMBER(location, self, name, value)
1710
1711
declare(location, result, symbol_definition_listener)
1712
si
1713
1714
si
1715
1716
class VOID_STRUCT: STRUCT is
1717
is_void: bool => true
1718
1719
init(location: LOCATION, span: LOCATION, owner: Scope, name: string, arguments: Collections.List[string], enclosing_scope: Scope) is
1720
super.init(location, span, owner, name, arguments, enclosing_scope)
1721
si
1722
1723
load(location: LOCATION, from: IR.Values.Value?, loader: SYMBOL_LOADER) -> IR.Values.Value is
1724
IoC.CONTAINER.instance.logger.error(location, "cannot use void value here")
1725
1726
return loader.load_struct(self)
1727
si
1728
si
1729
1730
class FRAME: Classy is
1731
_next_id: int static
1732
1733
_closure: Closure
1734
_constructor: Method?
1735
_captures: Collections.LIST[Field]
1736
1737
// The closure whose captures this frame holds. Its method is a
1738
// member of the frame in the emitted assembly, but it is
1739
// declared into the function the literal was written in, so a
1740
// walk over the frame's own symbols does not find it.
1741
closure: Closure => _closure
1742
1743
next_id: int static is
1744
let result = _next_id
1745
1746
_next_id = _next_id + 1
1747
1748
return result
1749
si
1750
1751
init(owner: Scope, closure: Closure) is
1752
let owner_owner: Scope mut
1753
1754
if isa Symbol(owner) then
1755
let owner_symbol = owner
1756
1757
owner_owner = owner_symbol.owner!
1758
else
1759
owner_owner = owner
1760
fi
1761
1762
super.init(LOCATION.internal, LOCATION.internal, owner_owner, "$frame_{next_id}", System.Array.empty[string](), owner)
1763
1764
assert closure.captured_values?
1765
1766
_closure = closure
1767
_captures = Collections.LIST[Field](closure.captured_values!.count)
1768
1769
set_type(Types.NAMED(self))
1770
si
1771
1772
declare() is
1773
let symbol_definition_listener = IoC.CONTAINER.instance.symbol_definition_locations
1774
1775
if !_constructor? then
1776
declare_constructor(symbol_definition_listener)
1777
1778
type = Types.NAMED(self)
1779
else
1780
// Iterative-inference body retry: a field's type may
1781
// have been refreshed by Closure.find_or_add_capture
1782
// when the source variable's type resolved between
1783
// iterations. The constructor's argument types are a
1784
// snapshot from the first declare() call — refresh
1785
// them so the frame ctor's IL signature matches the
1786
// resolved field types instead of the iter-1
1787
// placeholder.
1788
refresh_constructor_argument_types()
1789
fi
1790
si
1791
1792
declare_constructor(symbol_definition_listener: SymbolDefinitionListener?) is
1793
let constructor = Symbols.INSTANCE_METHOD(LOCATION.internal, LOCATION.internal, self, "init", self)
1794
1795
let argument_names = Collections.LIST[string]()
1796
let arguments = Collections.LIST[Type]()
1797
1798
for `field in symbols |> filter(s => s.is_variable /\ s.name !~ "$recurse") |> map(s => cast Variable?(s)!) do
1799
argument_names.add(`field.name)
1800
// Defensive: a frame field captured during a closure-load
1801
// for a forward-referenced variable (e.g. mutual recursion
1802
// between two let-bound lambdas) may not yet have its
1803
// type set. set_arguments asserts no null entries, so
1804
// default to ERROR. The upstream "variable is not
1805
// defined here" diagnostic is already emitted; the IL
1806
// signature emission stage produces a `/* error type */`
1807
// comment harmlessly.
1808
arguments.add(if `field.type? then `field.type else Types.ERROR() fi)
1809
od
1810
1811
constructor.set_arguments(argument_names, arguments)
1812
1813
constructor.set_void_return_type()
1814
1815
declare(LOCATION.internal, constructor, symbol_definition_listener)
1816
1817
_constructor = constructor
1818
si
1819
1820
refresh_constructor_argument_types() is
1821
let argument_names = Collections.LIST[string]()
1822
let arguments = Collections.LIST[Type]()
1823
1824
for `field in symbols |> filter(s => s.is_variable /\ s.name !~ "$recurse") |> map(s => cast Variable?(s)!) do
1825
argument_names.add(`field.name)
1826
arguments.add(if `field.type? then `field.type else Types.ERROR() fi)
1827
od
1828
1829
_constructor!.set_arguments(argument_names, arguments)
1830
si
1831
1832
get_captured(name: string) -> Field? is
1833
for c in _captures do
1834
if c.name =~ name then
1835
return c
1836
fi
1837
od
1838
return null
1839
si
1840
1841
declare_captured(name: string, type: Type?, symbol_definition_listener: SymbolDefinitionListener?) -> Field is
1842
// type may be null during early inference iterations — the
1843
// body-retry loop walks again once the source's type resolves,
1844
// and the field's type is set on the later walk. Mirrors the
1845
// pre-strict-mode behaviour where Type was passed through
1846
// unchecked.
1847
let `field = Symbols.INSTANCE_FIELD(LOCATION.internal, self, name)
1848
1849
declare(location, `field, symbol_definition_listener)
1850
1851
if type? then
1852
`field.set_type(type)
1853
fi
1854
1855
_captures.add(`field)
1856
1857
return `field
1858
si
1859
1860
declare_recurse(symbol_definition_listener: SymbolDefinitionListener?) -> Field is
1861
let `field = Symbols.INSTANCE_FIELD(LOCATION.internal, self, "$recurse")
1862
1863
`field.is_recurse_capture = true
1864
1865
declare(location, `field, symbol_definition_listener)
1866
1867
`field.set_type(_closure.type!)
1868
1869
_captures.add(`field)
1870
1871
return `field
1872
si
1873
1874
try_update_recurse_type(type: Type) is
1875
let `field = get_captured("$recurse")
1876
1877
if `field? then
1878
`field.set_type(type)
1879
fi
1880
si
1881
1882
// The enclosing function's type-parameter symbols, in the order
1883
// this frame's own parameters mirror them. A frame does not
1884
// redeclare them: the closure installs an emitted position on
1885
// each for as long as its body is being emitted, which is what
1886
// makes them render at the frame's index rather than at their
1887
// own.
1888
_type_parameters: Collections.List[Symbol]?
1889
1890
type_parameter_at(index: int) -> Symbol? is
1891
if let self._type_parameters? /\ index >= 0 /\ index < _type_parameters.count then
1892
return _type_parameters[index]
1893
fi
1894
1895
return super.type_parameter_at(index)
1896
si
1897
1898
set_type_arguments(arguments: Collections.Iterable[Symbol]) is
1899
let symbols = arguments |> collect_list()
1900
1901
_type_parameters = symbols
1902
self.argument_names = symbols |> map(a => a.name) |> collect()
1903
si
1904
1905
gen_all(context: IR.CONTEXT, symbol_loader: SYMBOL_LOADER) is
1906
gen_constructor(context, symbol_loader)
1907
si
1908
1909
gen_constructor(context: IR.CONTEXT, symbol_loader: SYMBOL_LOADER) is
1910
let internal = LOCATION.internal
1911
1912
// The constructor is encoded into a body of its own.
1913
// Without one its row carries no code at all, which is
1914
// not a constructor a runtime will accept: the image is
1915
// rejected outright, before any type in it is loaded.
1916
let assembly_emitter = context.srm_assembly_emitter
1917
let enclosing = context.current_srm_body_emitter
1918
let body_emitter = IR.Emitter.SRM_METHOD_BODY_EMITTER()
1919
1920
context.current_srm_body_emitter = body_emitter
1921
1922
try
1923
for c in _captures |> filter(c => c.name !~ "$recurse") do
1924
let argument = LOCAL_ARGUMENT(internal, _constructor!, c.name)
1925
argument.set_type(c.type!)
1926
1927
c.store(
1928
internal,
1929
IR.Values.Load.REFERENCE_SELF(self),
1930
argument.load(LOCATION.internal, null, symbol_loader),
1931
symbol_loader,
1932
true
1933
).gen(context)
1934
od
1935
catch ex: System.Exception
1936
IoC.CONTAINER.instance.logger.exception(
1937
location, ex, "error generating closure frame constructor")
1938
yrt
1939
1940
body_emitter.ret()
1941
1942
assembly_emitter.handles.set_body_offset(
1943
_constructor!, body_emitter.flush(assembly_emitter))
1944
assembly_emitter.handles.set_il_outputs(
1945
_constructor!, body_emitter.il_outputs)
1946
1947
context.current_srm_body_emitter = enclosing
1948
1949
si
1950
1951
get_create_instance(
1952
actual_arguments: Collections.List[Value],
1953
type_arguments: Collections.List[Type]?
1954
) -> IR.Values.Value? is
1955
declare()
1956
1957
try
1958
return
1959
if type_arguments? then
1960
let specialized_self = GENERIC(location, self, type_arguments)
1961
let ctor = cast Function?(specialized_self.find_member("init"))!
1962
1963
IR.Values.NEW(specialized_self.type, ctor, actual_arguments)
1964
else
1965
IR.Values.NEW(type!, _constructor!, actual_arguments)
1966
fi
1967
catch ex: System.Exception
1968
CONTAINER.instance.logger.exception(self.location, ex, "trying to generate frame instance")
1969
yrt
1970
return null
1971
si
1972
1973
si
1974
1975
class ENUM_STRUCT_MEMBER: Symbol, Types.Typed is
1976
_enum: ENUM_STRUCT => cast ENUM_STRUCT?(owner)!
1977
1978
type: Type => _enum.type!
1979
1980
// The literal exactly as written, kept for diagnostics.
1981
value: string
1982
1983
// The number it denotes, absent when `value` is not an integer
1984
// in int32's range. `value` is the source token verbatim, so it
1985
// can carry digit grouping, a radix prefix and a type suffix,
1986
// none of which a consumer can emit: an enum member's value has
1987
// to reach metadata as a number, not as the text that was
1988
// written for it.
1989
//
1990
// Absent rather than zero, because zero is a legitimate enum
1991
// value. A reflected member of an enum wider than int32 arrives
1992
// unreadable and is ordinary - `[Flags] enum : uint` with the
1993
// high bit set reaches here as "2147483648".
1994
numeric_value: int?
1995
1996
// The value as a consumer should emit it: the number where there
1997
// is one, and otherwise the text untouched.
1998
emitted_value: string =>
1999
if let number = numeric_value then "{number}" else value fi
2000
2001
short_description: string => name
2002
2003
describe(context: DESCRIBE_CONTEXT) -> SignaturePart =>
2004
PARTS.sequence([
2005
PARTS.name(self),
2006
PARTS.literal(" = {value}")
2007
])
2008
2009
describe_kind(context: DESCRIBE_CONTEXT) -> string? => "enum member"
2010
2011
symbol_kind: SymbolKind => SymbolKind.ENUM_MEMBER
2012
completion_kind: CompletionKind => CompletionKind.ENUM_MEMBER
2013
2014
init(location: LOCATION, owner: ENUM_STRUCT, name: string, value: string) is
2015
super.init(location, owner, name)
2016
2017
self.value = value
2018
2019
numeric_value = _parse_value(value)
2020
si
2021
2022
// Reports nothing. A source member that arrives unreadable has
2023
// already been rejected, and a reflected one is passed through
2024
// untouched, so there is nothing here to diagnose.
2025
//
2026
// The suffix rule is the numeric literal classifier's, so this
2027
// reads a literal the way the rest of the compiler does.
2028
_parse_value(text: string) -> int? static is
2029
let stripped =
2030
Syntax.Process.NUMERIC_LITERAL_CLASSIFIER.strip_suffix(
2031
text.replace("_", ""))
2032
2033
let negative = stripped.starts_with("-")
2034
let digits mut = if negative then stripped.substring(1) else stripped fi
2035
2036
let radix mut = 10
2037
2038
if digits.starts_with("0x") \/ digits.starts_with("0X") then
2039
radix = 16
2040
digits = digits.substring(2)
2041
fi
2042
2043
let result mut = 0L
2044
let parsed mut = digits.length > 0
2045
2046
if parsed then
2047
try
2048
result = System.Convert.to_int64(digits, radix)
2049
catch ex: System.Exception
2050
parsed = false
2051
yrt
2052
fi
2053
2054
if negative then
2055
result = -result
2056
fi
2057
2058
if !parsed \/ result > 2147483647L \/ result < -2147483648L then
2059
return null
2060
fi
2061
2062
return cast int(result)
2063
si
2064
2065
specialize(type_map: Collections.Map[string,Symbols.Symbol], owner: GENERIC) -> Symbol
2066
=> self
2067
2068
load(location: LOCATION, from: Value?, loader: SYMBOL_LOADER) -> Value is
2069
let result = loader.load_enum_struct_member(self)
2070
2071
return result
2072
si
2073
2074
si
2075
si