Skip to content
← Back

src/ir/emitter/srm_member_order.ghul

1
namespace IR.Emitter is
2
use Semantic.Symbols.Symbol
3
use Semantic.Symbols.Scope
4
use Semantic.Symbols.Classy
5
use Semantic.Symbols.Function
6
use Semantic.Symbols.Field
7
use Semantic.Symbols.Property
8
use Semantic.Symbols.FUNCTION_GROUP
9
use Semantic.Symbols.TYPE_GROUP
10
use Semantic.Symbols.NAMESPACE
11
12
// One type in the emitted assembly.
13
//
14
// Most are declared: a class, struct, trait, union or variant the
15
// source wrote, and a symbol the emitter can read everything from.
16
// A namespace holding global functions or variables has no such
17
// symbol - `$globals` is a naming convention the back end applies,
18
// not a declaration - so the namespace stands in for its carrier and
19
// supplies the same answers.
20
class SRM_EMITTED_TYPE is
21
declared: Classy?
22
globals_of: NAMESPACE?
23
24
init(declared: Classy) is
25
self.declared = declared
26
si
27
28
init(globals_of: NAMESPACE) is
29
self.globals_of = globals_of
30
si
31
32
is_globals_carrier: bool => globals_of?
33
34
// The metadata name, which for an arity sibling carries the `N
35
// suffix that keeps the pair apart.
36
name: string =>
37
if let d = declared then d.il_metadata_name else Semantic.DotNet.GLOBALS_CARRIER.name fi
38
39
// The scope whose members become this type's members, and whose
40
// owner supplies the metadata namespace. For a carrier both are
41
// the namespace itself.
42
scope: Scope => if let d = declared then d else globals_of! fi
43
44
owning_namespace: Scope? =>
45
if let d = declared then d.owner else globals_of! fi
46
si
47
48
// The order in which types and their members are written to
49
// metadata.
50
//
51
// Two separate passes read this: one to assign row numbers before
52
// any body is encoded, and one to write the rows afterwards. They
53
// must produce the same sequence or every pre-computed handle names
54
// the wrong row, so both go through here rather than iterating a
55
// scope directly.
56
//
57
// A scope stores its members in a map keyed by name, so iterating it
58
// yields neither declaration order nor an order that is obviously
59
// stable against unrelated edits. Sorting on source position
60
// recovers declaration order, which a struct's sequential layout
61
// depends on, and gives the same answer however the map chose to
62
// enumerate. Overloads share one name, so a scope yields a
63
// FUNCTION_GROUP where the tables want one row per function; the
64
// group is flattened here.
65
class SRM_MEMBER_ORDER is
66
// Every type the assembly defines. Imported types are reachable
67
// from the same root and are excluded: they are referenced,
68
// never defined, here.
69
types(root: Scope) -> Collections.List[SRM_EMITTED_TYPE] static is
70
let declared = Collections.LIST[Classy]()
71
let namespaces = Collections.LIST[NAMESPACE]()
72
73
_collect(root, declared, namespaces, Collections.SET[Classy]())
74
75
_sort_by_declaration(declared)
76
_sort_by_declaration(namespaces)
77
78
let result = Collections.LIST[SRM_EMITTED_TYPE]()
79
80
for type in declared do
81
result.add(SRM_EMITTED_TYPE(type))
82
od
83
84
// Closure frames are types in the emitted assembly, but no
85
// scope holds them: a frame's owner is the enclosing
86
// namespace, and nothing declares it there. Declaring one
87
// would make `$frame_0` a name that resolution, completion
88
// and symbol search could all see, so they are collected
89
// from the closures that own them instead. A closure is
90
// declared into the function the literal was written in,
91
// and is itself a scope that can hold further closures.
92
for frame in _frames(declared, namespaces) do
93
result.add(SRM_EMITTED_TYPE(frame))
94
od
95
96
// Carriers last, so that adding a global to a namespace
97
// cannot renumber any declared type's members.
98
for `namespace in namespaces do
99
if _has_globals(`namespace) then
100
result.add(SRM_EMITTED_TYPE(`namespace))
101
fi
102
od
103
104
return result
105
si
106
107
// A type's scope can reach back to a type already collected -
108
// a union names itself from each of its variants - so a type is
109
// descended into once.
110
_collect(
111
scope: Scope,
112
declared: Collections.LIST[Classy],
113
namespaces: Collections.LIST[NAMESPACE],
114
seen: Collections.SET[Classy]
115
) static is
116
for symbol in scope.symbols do
117
if symbol.is_reflected then
118
continue
119
fi
120
121
if let `namespace: NAMESPACE = symbol then
122
namespaces.add(`namespace)
123
124
_collect(`namespace, declared, namespaces, seen)
125
elif let group: TYPE_GROUP = symbol then
126
// Same-name types at different argument counts are
127
// one symbol in the scope and separate types in the
128
// assembly, so the group is descended into rather
129
// than emitted.
130
for type in group.classies do
131
_collect_type(type, declared, namespaces, seen)
132
od
133
elif let type: Classy = symbol then
134
_collect_type(type, declared, namespaces, seen)
135
fi
136
od
137
si
138
139
_collect_type(
140
type: Classy,
141
declared: Collections.LIST[Classy],
142
namespaces: Collections.LIST[NAMESPACE],
143
seen: Collections.SET[Classy]
144
) static is
145
if seen.contains(type) then
146
return
147
fi
148
149
seen.add(type)
150
declared.add(type)
151
152
// A union's variants are declared into the union's own
153
// scope rather than into the namespace, and are types in
154
// their own right in the emitted assembly.
155
_collect(type, declared, namespaces, seen)
156
si
157
158
_frames(
159
declared: Collections.LIST[Classy],
160
namespaces: Collections.LIST[NAMESPACE]
161
) -> Collections.List[Classy] static is
162
let result = Collections.LIST[Classy]()
163
164
for type in declared do
165
_collect_frames(type, result)
166
od
167
168
for `namespace in namespaces do
169
_collect_frames(`namespace, result)
170
od
171
172
_sort_by_declaration(result)
173
174
return result
175
si
176
177
_collect_frames(scope: Scope, into: Collections.LIST[Classy]) static is
178
for symbol in scope.symbols do
179
if let group: FUNCTION_GROUP = symbol then
180
for function in group.functions do
181
_collect_frames_from_function(function, into)
182
od
183
elif let function: Function = symbol then
184
_collect_frames_from_function(function, into)
185
fi
186
od
187
si
188
189
_collect_frames_from_function(function: Function, into: Collections.LIST[Classy]) static is
190
// A generator or async function compiles into a state
191
// machine whose frame is a type of its own, reached from
192
// the function rather than from any scope.
193
if let state_machine = Semantic.Symbols.state_machine_for(function) then
194
if let frame = state_machine.frame then
195
into.add(frame)
196
fi
197
fi
198
199
if let async_state_machine = Semantic.Symbols.async_state_machine_for(function) then
200
if let frame = async_state_machine.frame then
201
into.add(frame)
202
fi
203
fi
204
205
for symbol in function.symbols do
206
if let closure: Semantic.Symbols.Closure = symbol then
207
if let frame = closure.frame then
208
into.add(frame)
209
fi
210
211
// A closure body can declare closures of its own.
212
_collect_frames_from_function(closure, into)
213
fi
214
od
215
si
216
217
_has_globals(`namespace: NAMESPACE) -> bool static =>
218
fields(SRM_EMITTED_TYPE(`namespace)).count > 0 \/
219
methods(SRM_EMITTED_TYPE(`namespace)).count > 0
220
221
fields(type: SRM_EMITTED_TYPE) -> Collections.List[Field] static is
222
let result = Collections.LIST[Field]()
223
224
for symbol in type.scope.symbols do
225
// A scope holds members it does not declare: pulling a
226
// super's symbols down adds them here, and a member
227
// whose owner is elsewhere belongs to that owner's rows,
228
// not to these. A member with no overloads arrives as
229
// itself and is answered for here; one with overloads
230
// arrives inside a group, which is dealt with below.
231
if !_is_owned_by(symbol, type) then
232
continue
233
fi
234
235
if symbol.is_reflected then
236
continue
237
fi
238
239
if let `field: Field = symbol then
240
result.add(`field)
241
fi
242
od
243
244
// A memoized stateless delegate caches in a static field
245
// built on demand while expressions were compiled. It is a
246
// real symbol but is declared into no scope, so it is
247
// collected from the closures that own it - and it lands on
248
// the enclosing class, or on the namespace's carrier for a
249
// global one, which is not always where the closure is
250
// written.
251
_collect_delegate_caches(type, result)
252
253
_sort_by_declaration(result)
254
255
return result
256
si
257
258
_collect_delegate_caches(type: SRM_EMITTED_TYPE, into: Collections.LIST[Field]) static is
259
let closures = Collections.LIST[Semantic.Symbols.Closure]()
260
261
// A cache field lands on the enclosing class, or on the
262
// namespace's carrier when the closure is a global anonymous
263
// function - and a class method can hold one of those - so
264
// the search starts from the owning namespace rather than
265
// from the type, and the owner check below selects.
266
_collect_closures(type.owning_namespace ?? type.scope, closures, Collections.SET[Scope]())
267
268
for closure in closures do
269
if !closure.has_delegate_cache_field then
270
continue
271
fi
272
273
let `field = closure.delegate_cache_field
274
275
if _is_owned_by(`field, type) then
276
into.add(`field)
277
fi
278
od
279
si
280
281
_collect_closures(
282
scope: Scope,
283
into: Collections.LIST[Semantic.Symbols.Closure],
284
seen: Collections.SET[Scope]
285
) static is
286
if seen.contains(scope) then
287
return
288
fi
289
290
seen.add(scope)
291
292
for symbol in scope.symbols do
293
if let group: FUNCTION_GROUP = symbol then
294
for function in group.functions do
295
_collect_closures(function, into, seen)
296
od
297
elif let closure: Semantic.Symbols.Closure = symbol then
298
into.add(closure)
299
300
_collect_closures(closure, into, seen)
301
else
302
_collect_closures(symbol, into, seen)
303
fi
304
od
305
si
306
307
// The properties a type declares, in the order their rows are
308
// written.
309
//
310
// Unlike the field and method runs this order is not agreed
311
// across the two passes: nothing outside the property's own rows
312
// names it, so the rows and the map that points at them are both
313
// written in the same iteration and cannot disagree.
314
//
315
// Sorted all the same. A scope enumerates by name-keyed map
316
// order, so without this an unrelated edit elsewhere in the same
317
// scope reorders the emitted rows while nothing about the
318
// properties has changed — which the planned byte-comparison of
319
// two bootstrap assemblies would read as a difference.
320
properties(type: SRM_EMITTED_TYPE) -> Collections.List[Property] static is
321
let result = Collections.LIST[Property]()
322
323
for symbol in type.scope.symbols do
324
if !_is_owned_by(symbol, type) then
325
continue
326
fi
327
328
if symbol.is_reflected then
329
continue
330
fi
331
332
if let property: Property = symbol then
333
result.add(property)
334
fi
335
od
336
337
_sort_by_declaration(result)
338
339
return result
340
si
341
342
methods(type: SRM_EMITTED_TYPE) -> Collections.List[Function] static is
343
let result = Collections.LIST[Function]()
344
345
// An enum emits no methods. Its ordering operator is innate,
346
// compiled at each call site against the underlying value,
347
// and its symbol carries no body — emitting a row for it
348
// yields a method with no code, which makes the whole type
349
// fail to load.
350
if isa Semantic.Symbols.ENUM_STRUCT(type.declared) then
351
return result
352
fi
353
354
// A frame's closure method belongs to the frame in the
355
// emitted assembly but is declared elsewhere, so the walk
356
// over the frame's own symbols does not reach it.
357
if let frame: Semantic.Symbols.FRAME = type.declared then
358
result.add(frame.closure)
359
fi
360
361
for symbol in type.scope.symbols do
362
// A scope holds members it does not declare: pulling a
363
// super's symbols down adds them here, and a member
364
// whose owner is elsewhere belongs to that owner's rows,
365
// not to these. A member with no overloads arrives as
366
// itself and is answered for here; one with overloads
367
// arrives inside a group, which is dealt with below.
368
if !_is_owned_by(symbol, type) then
369
continue
370
fi
371
372
if symbol.is_reflected then
373
continue
374
fi
375
376
if let group: FUNCTION_GROUP = symbol then
377
// The group is the subclass's own, but it holds the
378
// functions it inherits alongside the ones declared
379
// here, and those still belong to the type that
380
// declared them. Checking the group answers for the
381
// group, not for what is in it.
382
for function in group.functions do
383
if _is_owned_by(function, type) /\ _is_emitted(function) then
384
result.add(function)
385
fi
386
od
387
elif let function: Function = symbol then
388
if _is_emitted(function) then
389
result.add(function)
390
fi
391
fi
392
od
393
394
_collect_anonymous_functions(type, result)
395
396
_sort_by_declaration(result)
397
398
return result
399
si
400
401
// A function literal with no frame is emitted onto the type that
402
// encloses it - as a static method when it captures nothing, as
403
// an instance one when all it captures is `self` - but it is
404
// declared into the function it was written in. `owner` points
405
// at the emitted home without the symbol store there holding it,
406
// so the walk over that home's own symbols does not reach one.
407
// Same shape as a closure frame, and as the cache field a
408
// memoized one stores itself in.
409
_collect_anonymous_functions(
410
type: SRM_EMITTED_TYPE,
411
into: Collections.LIST[Function]
412
) static is
413
let closures = Collections.LIST[Semantic.Symbols.Closure]()
414
415
_collect_closures(type.owning_namespace ?? type.scope, closures, Collections.SET[Scope]())
416
417
for closure in closures do
418
if !closure.frame? /\ _is_owned_by(closure, type) then
419
into.add(closure)
420
fi
421
od
422
si
423
424
// Whether a member is emitted onto this type.
425
//
426
// A member's owner is sometimes the namespace symbol and
427
// sometimes the scope standing for it, and the two are distinct
428
// objects, so comparing owners directly answers false for a
429
// member that does belong here. Both sides are resolved to the
430
// namespace before comparing.
431
// An `impl` or `partial` block's scope stands for the type it
432
// injects into in the same way, so it is resolved here too: a
433
// closure written in an injected member is emitted onto the
434
// target, not onto the block.
435
// An innate is a call site's instruction sequence wearing a
436
// symbol, not a method: it has no body to encode, and the
437
// declaration it stands for is emitted separately by whichever
438
// type actually declares it. A compilation that declares its own
439
// intrinsics gets one registered into `Ghul.Intrinsics` for every
440
// intrinsic it declares, all of them owned by that namespace - so
441
// the ownership test above admits them and only this turns them
442
// away.
443
_is_emitted(function: Function) -> bool static => !function.is_innate
444
445
_is_owned_by(member: Symbol, type: SRM_EMITTED_TYPE) -> bool static =>
446
_emitted_home(member.owner) == _emitted_home(type.scope)
447
448
_emitted_home(scope: Scope?) -> Scope? static =>
449
if let injection: Semantic.INJECTION_SCOPE = scope then
450
injection.target
451
else
452
_as_namespace(scope) ?? scope
453
fi
454
455
_as_namespace(scope: Scope?) -> Scope? static =>
456
if let declared: NAMESPACE = scope then
457
declared
458
elif let namespace_scope: Semantic.NAMESPACE_SCOPE = scope then
459
namespace_scope.containing_namespace
460
else
461
null
462
fi
463
464
// Overloads declared on one line, and synthesised members that
465
// share the internal location, would otherwise order
466
// arbitrarily; name and then description break the tie so the
467
// sequence is reproducible.
468
_sort_by_declaration[T: Symbol](symbols: Collections.LIST[T]) static is
469
symbols.sort(
470
(left: T, right: T) -> int is
471
let by_file = left.location.file_name <> right.location.file_name
472
473
if by_file != 0 then
474
return by_file
475
fi
476
477
let by_position = left.location.start - right.location.start
478
479
if by_position != 0 then
480
return by_position
481
fi
482
483
let by_name = left.name <> right.name
484
485
if by_name != 0 then
486
return by_name
487
fi
488
489
return left.description <> right.description
490
si)
491
si
492
si
493
si