STUDIO HAZE · topaz
Topaz source
Open by house policy. Topaz is our own language.
Topaz 5.20 · 56 files
compiler/crates/topaz_self_frontend/topaz/checker/bodies_captures.tpz
Topaz · 31517 B · Original file
1
// Function-body checking, initialization order, and closure capture derivation.2
// Expression recursion enters through CheckerService; this leaf owns body3
// sequencing and returns indexes used by the checker facade.5
import types {6
PreviewResolvedReference,7
PreviewTypedCall,8
PreviewTypedCapture,9
ResolveResult,10
SyntaxNode,11
}12
import checker.model {13
CaptureTarget,14
CheckerService,15
CheckerState,16
FunctionDefinition,17
ModuleSyntax,18
TYPE_BOUND_INDEX_STRIDE,19
constructor,20
emptyType,21
functionType,22
primitive,23
}24
import checker.type_algebra {25
flattenType,26
hasHole,27
joinedTypes,28
projectionType,29
stripProjectionTypes,30
}31
import checker.syntax_index {32
addDiagnostic,33
addNode,34
attribute,35
bindSymbol,36
boolAttribute,37
child,38
children,39
containsString,40
declarationFor,41
definitionNameKey,42
emptyStringIntMap,43
moduleIdentityAt,44
referenceFor,45
referenceTargetsPendingFunction,46
replaceNodeType,47
scopeFor,48
scopeKey,49
spanKey,50
text,51
typedNodeIndex,52
unwrapExport,53
}54
import checker.protocols_methods { functionDeclaration }55
import checker.members_capabilities { bindingIndex }56
import checker.patterns { patternBindingNodes }57
import checker.call_facts { checkExpressionExpected }58
import checker.expression_core { blockTerminates }59
import checker.expression_control { inferExpression }60
import checker.statements {61
checkBlock,62
checkBlockExpected,63
checkStatement,64
constantExpressionShape,65
foldConstantInteger,66
precheckTopLevelBindings,67
}69
function checkRecordDefaults(service: CheckerService, state: CheckerState, module: ModuleSyntax) -> () {70
for statement in module.root.children {71
let item = unwrapExport(statement)72
if item.kind == "statement/record" {73
for field in children(item, "fields") {74
match child(field, "default") {75
case Some(found) => {76
let _ = inferExpression(77
service,78
state,79
module.moduleIndex,80
module.source,81
found,82
)83
}84
case None => ()85
}86
}87
}88
}89
()90
}92
function checkFunctionDefault(93
state: CheckerState,94
moduleIndex: int,95
node: SyntaxNode,96
) -> () {97
if !constantExpressionShape(node) {98
addDiagnostic(99
state,100
moduleIndex,101
"TPZ5001",102
"`const` initializers must be constant expressions (§4)",103
"",104
node,105
)106
return ()107
}108
let _ = foldConstantInteger(state, moduleIndex, node)109
()110
}112
function callsPendingReturnSince(113
state: CheckerState,114
firstCall: int,115
) -> bool {116
let mut index = firstCall117
while index < state.calls.length {118
match state.calls.get(index) {119
case Some(call) => match referenceFor(120
state,121
call.moduleIndex,122
call.calleeLo,123
call.calleeHi,124
) {125
case Some(reference) => if referenceTargetsPendingFunction(126
state,127
reference,128
) {129
return true130
}131
case None => ()132
}133
case None => ()134
}135
index += 1136
}137
false138
}140
export function checkFunctionDeclaration(141
service: CheckerService,142
state: CheckerState,143
module: ModuleSyntax,144
declaration: SyntaxNode,145
) -> () {146
let nameNode = match child(declaration, "name") {147
case Some(found) => found148
case None => declaration149
}150
let mut exported = false151
for published in state.resolved.exports {152
if published.moduleIndex == module.moduleIndex && published.namespace == "value" &&153
published.declarationLo == nameNode.lo && published.declarationHi == nameNode.hi {154
exported = true155
}156
}157
let mut seenBounds: Array<string> = []158
for bound in children(declaration, "typeParameterBounds") {159
let protocol = text(module.source, bound)160
if exported && protocol != "Eq" && protocol != "Order" && protocol != "Show" && protocol != "JSON" {161
addDiagnostic(state, module.moduleIndex, "TPZ5524",162
"exported functions cannot expose module-local protocol bound `{protocol}`", "", bound)163
}164
let key = "{bound.index / TYPE_BOUND_INDEX_STRIDE}:{protocol}"165
if containsString(seenBounds, key) {166
addDiagnostic(state, module.moduleIndex, "TPZ5523",167
"protocol bound `{protocol}` is repeated for the same type parameter", "", bound)168
} else {169
seenBounds.push(key)170
}171
}172
let definitionIndex = match state.functionIndexes.get(spanKey(173
module.moduleIndex,174
nameNode.lo,175
nameNode.hi,176
)) {177
case Some(index) => index178
case None => -1179
}180
match state.functions.get(definitionIndex) {181
case Some(definition) => {182
let mut fixedIndex = 0183
for parameter in children(declaration, "parameters") {184
let name = match child(parameter, "name") {185
case Some(found) => found186
case None => parameter187
}188
let parameterType = if boolAttribute(parameter, "variadic") {189
constructor("Array", [match definition.variadic.get(0) {190
case Some(found) => found191
case None => emptyType("unknown")192
}])193
} else {194
match definition.parameterTypes.get(fixedIndex) {195
case Some(found) => found196
case None => emptyType("unknown")197
}198
}199
if !boolAttribute(parameter, "variadic") {200
fixedIndex += 1201
}202
bindSymbol(203
state,204
module.moduleIndex,205
name.lo,206
name.hi,207
text(module.source, name),208
parameterType,209
false,210
)211
addNode(state, module.moduleIndex, "binding", name, parameterType)212
match child(parameter, "default") {213
case Some(found) => {214
let _ = checkExpressionExpected(215
service,216
state,217
module.moduleIndex,218
module.source,219
found,220
parameterType,221
)222
checkFunctionDefault(state, module.moduleIndex, found)223
}224
case None => ()225
}226
}227
match child(declaration, "body") {228
case Some(body) => {229
let inferredResult = definition.result.kind == "unknown"230
let firstCall = state.calls.length231
let mut activeFunctions = state.activeFunctions232
activeFunctions.push(definitionIndex)233
let mut loopFloors = state.loopFloors234
loopFloors.push(state.loopFrames.length)235
let mut expectedReturns = state.expectedReturns236
expectedReturns.push(definition.result)237
let mut returnJoins = state.returnJoins238
returnJoins.push([])239
let bodyResult = if inferredResult {240
checkBlock(241
service,242
state,243
module.moduleIndex,244
module.source,245
body,246
)247
} else {248
checkBlockExpected(249
service,250
state,251
module.moduleIndex,252
module.source,253
body,254
definition.result,255
)256
}257
let mut returns = match returnJoins.get(returnJoins.length - 1) {258
case Some(found) => found259
case None => []260
}261
returnJoins.pop()262
expectedReturns.pop()263
loopFloors.pop()264
activeFunctions.pop()265
if inferredResult {266
match child(body, "tail") {267
case Some(_) => returns.push(bodyResult)268
case None => if !blockTerminates(body) {269
returns.push(primitive("unit"))270
}271
}272
let mut result = if returns.length == 0 {273
primitive("unit")274
} else {275
let mut unresolved = false276
for found in returns {277
if hasHole(found) {278
unresolved = true279
}280
}281
if unresolved {282
emptyType("unknown")283
} else {284
joinedTypes(state, returns, true)285
}286
}287
if projectionType(result) {288
addDiagnostic(289
state,290
module.moduleIndex,291
"TPZ5022",292
"cannot infer a return type for `{definition.name}`: it returns a destructured generic value with no nameable type — annotate the return type",293
"",294
nameNode,295
)296
result = stripProjectionTypes(result)297
}298
if result.kind == "unknown" &&299
callsPendingReturnSince(state, firstCall) {300
addDiagnostic(301
state,302
module.moduleIndex,303
"TPZ5022",304
"`{definition.name}` is (mutually) recursive: declare its return type (§7)",305
"",306
nameNode,307
)308
}309
let mut pending = state.pendingFunctions310
pending[definitionIndex] = false311
let patched = FunctionDefinition {312
...definition,313
result: result,314
}315
let mut functions = state.functions316
functions[definitionIndex] = patched317
let functionValue = functionType(318
definition.parameterTypes,319
definition.variadic,320
result,321
)322
bindSymbol(323
state,324
module.moduleIndex,325
nameNode.lo,326
nameNode.hi,327
definition.name,328
functionValue,329
false,330
)331
replaceNodeType(332
state,333
module.moduleIndex,334
"declaration",335
nameNode,336
functionValue,337
)338
}339
}340
case None => ()341
}342
// Publish the declaration fact after checking its body. Signatures used343
// during recursion are already available in symbols and functions.344
addNode(345
state,346
module.moduleIndex,347
"declaration",348
nameNode,349
functionType(350
definition.parameterTypes,351
definition.variadic,352
definition.result,353
),354
)355
}356
case None => ()357
}358
()359
}361
function staticTopLevelItem(item: SyntaxNode) -> bool {362
item.kind == "statement/function" ||363
item.kind == "statement/impl" ||364
item.kind == "statement/record" ||365
item.kind == "statement/enum" ||366
item.kind == "statement/newtype" ||367
item.kind == "statement/type-alias" ||368
item.kind == "statement/protocol" ||369
item.kind == "statement/const" ||370
item.kind == "statement/import"371
}373
function checkImplBodies(374
service: CheckerService,375
state: CheckerState,376
module: ModuleSyntax,377
statement: SyntaxNode,378
) -> () {379
let item = unwrapExport(statement)380
if item.kind != "statement/impl" {381
return ()382
}383
for method in children(item, "methods") {384
match child(method, "declaration") {385
case Some(declaration) => checkFunctionDeclaration(386
service,387
state,388
module,389
declaration,390
)391
case None => ()392
}393
}394
()395
}397
function topLevelRuntimeBindingIndexes(398
module: ModuleSyntax,399
) -> Map<int, int> {400
let mut indexes: Map<int, int> = Map.new()401
let mut index = 0402
for statement in module.root.children {403
let item = unwrapExport(statement)404
match functionDeclaration(item) {405
case Some(declaration) => match child(declaration, "name") {406
case Some(name) => indexes.insert(name.lo, index)407
case None => ()408
}409
case None => if item.kind == "statement/let" {410
match child(item, "pattern") {411
case Some(pattern) => for binding in patternBindingNodes(pattern) {412
indexes.insert(binding.lo, index)413
}414
case None => ()415
}416
} else {417
()418
}419
}420
index += 1421
}422
indexes423
}425
function initializationReferenceViolation(426
state: CheckerState,427
module: ModuleSyntax,428
runtimeBindingIndexes: Map<int, int>,429
cutoff: int,430
node: SyntaxNode,431
) -> bool {432
match referenceFor(state, module.moduleIndex, node.lo, node.hi) {433
case Some(reference) => if reference.targetModuleIndex == module.moduleIndex {434
match runtimeBindingIndexes.get(reference.targetLo) {435
case Some(target) => target >= cutoff436
case None => false437
}438
} else {439
false440
}441
case None => false442
}443
}445
function initializationChildIsImmediate(446
parent: SyntaxNode,447
found: SyntaxNode,448
) -> bool {449
// Conditional children are delayed under the same DIRECT rule as branch,450
// arm, loop, lambda, function, defer, and concurrent bodies.451
let kind = parent.kind452
if kind == "statement/function" || kind == "statement/defer" ||453
kind == "statement/break" || kind == "statement/continue" ||454
kind == "expression/lambda" || kind == "expression/loop" {455
return false456
}457
if kind == "statement/while" || kind == "expression/if" {458
return found.field == "condition"459
}460
if kind == "expression/match" {461
return found.field == "scrutinee"462
}463
if kind == "expression/for" || kind == "comprehension-clause/for" {464
return found.field == "iterator"465
}466
if kind == "expression/comprehension" {467
return found.field == "clauses" && found.index == 0 &&468
found.kind == "comprehension-clause/for"469
}470
if kind == "expression/concurrent" {471
return found.field == "timeout"472
}473
if kind == "expression/binary" && found.field == "right" {474
let operator = attribute(parent, "operator")475
return operator != "and" && operator != "or" && operator != "coalesce"476
}477
if kind == "expression/call" && found.field == "arguments" {478
match child(parent, "callee") {479
case Some(callee) => return callee.kind != "expression/optional-access"480
case None => ()481
}482
}483
if kind == "statement/let" || kind == "statement/const" ||484
kind == "statement/return" {485
return found.field == "value"486
}487
if kind == "statement/assign" {488
return found.field == "target" || found.field == "value"489
}490
if kind == "statement/using" {491
return found.field == "value" || found.field == "body"492
}493
if kind.startsWith("statement/") {494
return kind == "statement/expression"495
}496
true497
}499
function initializationViolation(500
state: CheckerState,501
module: ModuleSyntax,502
runtimeBindingIndexes: Map<int, int>,503
cutoff: int,504
node: SyntaxNode,505
) -> Option<SyntaxNode> {506
if node.kind == "expression/identifier" {507
return if initializationReferenceViolation(508
state,509
module,510
runtimeBindingIndexes,511
cutoff,512
node,513
) {514
Some(node)515
} else {516
None517
}518
}519
for found in node.children {520
if initializationChildIsImmediate(node, found) {521
match initializationViolation(522
state,523
module,524
runtimeBindingIndexes,525
cutoff,526
found,527
) {528
case Some(violation) => return Some(violation)529
case None => ()530
}531
}532
}533
None534
}536
function reportInitializationViolation(537
state: CheckerState,538
module: ModuleSyntax,539
violation: Option<SyntaxNode>,540
) -> () {541
match violation {542
case Some(found) => addDiagnostic(543
state,544
module.moduleIndex,545
"TPZ5002",546
"`{text(module.source, found)}` is not bound",547
"",548
found,549
)550
case None => ()551
}552
}554
function checkTopLevelInitializationOrder(555
state: CheckerState,556
module: ModuleSyntax,557
) -> () {558
let runtimeBindingIndexes = topLevelRuntimeBindingIndexes(module)559
let mut cutoff = 0560
for statement in module.root.children {561
let item = unwrapExport(statement)562
if item.kind == "statement/let" {563
match child(item, "value") {564
case Some(found) => reportInitializationViolation(565
state,566
module,567
initializationViolation(568
state,569
module,570
runtimeBindingIndexes,571
cutoff,572
found,573
),574
)575
case None => ()576
}577
} else if item.kind == "statement/using" {578
match child(item, "value") {579
case Some(found) => reportInitializationViolation(580
state,581
module,582
initializationViolation(583
state,584
module,585
runtimeBindingIndexes,586
cutoff,587
found,588
),589
)590
case None => ()591
}592
match child(item, "body") {593
case Some(found) => reportInitializationViolation(594
state,595
module,596
initializationViolation(597
state,598
module,599
runtimeBindingIndexes,600
cutoff,601
found,602
),603
)604
case None => ()605
}606
} else if item.kind == "statement/assign" {607
for field in ["target", "value"] {608
match child(item, field) {609
case Some(found) => reportInitializationViolation(610
state,611
module,612
initializationViolation(613
state,614
module,615
runtimeBindingIndexes,616
cutoff,617
found,618
),619
)620
case None => ()621
}622
}623
} else if item.kind == "statement/while" {624
match child(item, "condition") {625
case Some(found) => reportInitializationViolation(626
state,627
module,628
initializationViolation(629
state,630
module,631
runtimeBindingIndexes,632
cutoff,633
found,634
),635
)636
case None => ()637
}638
} else if item.kind == "statement/expression" ||639
item.kind == "statement/return" {640
for found in item.children {641
reportInitializationViolation(642
state,643
module,644
initializationViolation(645
state,646
module,647
runtimeBindingIndexes,648
cutoff,649
found,650
),651
)652
}653
}654
cutoff += 1655
}656
()657
}659
function checkModuleBodies(service: CheckerService, state: CheckerState, module: ModuleSyntax) -> () {660
checkRecordDefaults(service, state, module)661
for statement in module.root.children {662
checkImplBodies(service, state, module, statement)663
match functionDeclaration(unwrapExport(statement)) {664
case Some(declaration) => checkFunctionDeclaration(665
service,666
state,667
module,668
declaration,669
)670
case None => if !staticTopLevelItem(unwrapExport(statement)) {671
checkStatement(672
service,673
state,674
module.moduleIndex,675
module.source,676
statement,677
)678
}679
}680
}681
checkTopLevelInitializationOrder(state, module)682
()683
}685
export function checkFunctionBodies(service: CheckerService, state: CheckerState) -> () {686
// The resolver supplies dependency order, so inferred exported bindings687
// are available before a consumer checks its own initializers.688
let ordered = state.modules689
for module in ordered {690
precheckTopLevelBindings(service, state, module)691
}692
for module in ordered {693
checkModuleBodies(service, state, module)694
}695
()696
}698
function captureScopeAncestors(699
state: CheckerState,700
indexes: Map<string, Set<int>>,701
moduleIndex: int,702
ordinal: int,703
) -> Set<int> {704
let key = scopeKey(moduleIndex, ordinal)705
match indexes.get(key) {706
case Some(found) => return found707
case None => ()708
}709
let mut ancestors: Set<int> = set {}710
let mut current = ordinal711
while current >= 0 {712
ancestors.add(current)713
match scopeFor(state, moduleIndex, current) {714
case Some(scope) => {715
current = scope.parentOrdinal716
}717
case None => {718
current = -1719
}720
}721
}722
let mut target = indexes723
target.insert(key, ancestors)724
ancestors725
}727
function namespaceCaptureTarget(728
state: CheckerState,729
reference: PreviewResolvedReference,730
) -> Option<CaptureTarget> {731
let segments = reference.name.split(".")732
if segments.length < 2 {733
return None734
}735
let alias = match segments.get(0) {736
case Some(found) => found737
case None => return None738
}739
let index = match state.namespaceImportIndexes.get(740
definitionNameKey(reference.moduleIndex, alias),741
) {742
case Some(found) => found743
case None => return None744
}745
let declaration = match state.resolved.declarations.get(index) {746
case Some(found) => found747
case None => return None748
}749
let unknown = emptyType("unknown")750
Some(CaptureTarget {751
declaration: declaration,752
name: declaration.name,753
typeValue: flattenType(unknown),754
ambient: true,755
})756
}758
function captureTargetForReference(759
state: CheckerState,760
reference: PreviewResolvedReference,761
) -> Option<CaptureTarget> {762
if reference.namespace != "value" {763
return None764
}765
if reference.role == "namespace-member" {766
return namespaceCaptureTarget(state, reference)767
}768
if reference.targetModuleIndex != reference.moduleIndex {769
return None770
}771
let bindingIndex = typedNodeIndex(772
state,773
reference.targetModuleIndex,774
"binding",775
reference.targetLo,776
reference.targetHi,777
)778
let declarationIndex = typedNodeIndex(779
state,780
reference.targetModuleIndex,781
"declaration",782
reference.targetLo,783
reference.targetHi,784
)785
let declaredIndex = if bindingIndex > declarationIndex {786
bindingIndex787
} else {788
declarationIndex789
}790
let observedIndex = if declaredIndex >= 0 {791
declaredIndex792
} else {793
typedNodeIndex(794
state,795
reference.moduleIndex,796
"expression",797
reference.lo,798
reference.hi,799
)800
}801
let typedNode = match state.nodes.get(observedIndex) {802
case Some(found) => found803
case None => return None804
}805
let declaration = match declarationFor(806
state,807
reference.targetModuleIndex,808
reference.targetLo,809
reference.targetHi,810
) {811
case Some(found) => found812
case None => return None813
}814
Some(CaptureTarget {815
declaration: declaration,816
name: reference.name,817
typeValue: typedNode.typeValue,818
ambient: typedNode.ambient,819
})820
}822
function capturesForReference(823
state: CheckerState,824
scopeAncestorIndexes: Map<string, Set<int>>,825
reference: PreviewResolvedReference,826
) -> Array<PreviewTypedCapture> {827
let mut captures: Array<PreviewTypedCapture> = []828
let target = match captureTargetForReference(state, reference) {829
case Some(found) => found830
case None => return captures831
}832
let declarationAncestors = captureScopeAncestors(833
state,834
scopeAncestorIndexes,835
reference.moduleIndex,836
target.declaration.scopeOrdinal,837
)838
let mut current = reference.scopeOrdinal839
while current >= 0 {840
match scopeFor(state, reference.moduleIndex, current) {841
case Some(scope) => {842
if (scope.kind == "function" || scope.kind == "lambda") &&843
!declarationAncestors.contains(scope.ordinal) {844
captures.push(PreviewTypedCapture {845
moduleIndex: reference.moduleIndex,846
closureLo: scope.lo,847
closureHi: scope.hi,848
referenceLo: reference.lo,849
referenceHi: reference.hi,850
declarationLo: target.declaration.lo,851
declarationHi: target.declaration.hi,852
name: target.name,853
typeValue: target.typeValue,854
ambient: target.ambient,855
})856
}857
current = scope.parentOrdinal858
}859
case None => {860
current = -1861
}862
}863
}864
captures865
}867
function capturesAreSame(868
left: PreviewTypedCapture,869
right: PreviewTypedCapture,870
) -> bool {871
left.moduleIndex == right.moduleIndex &&872
left.closureLo == right.closureLo &&873
left.closureHi == right.closureHi &&874
left.referenceLo == right.referenceLo &&875
left.referenceHi == right.referenceHi &&876
left.declarationLo == right.declarationLo &&877
left.declarationHi == right.declarationHi &&878
left.name == right.name879
}881
function sortAndDeduplicateCaptures(state: CheckerState) -> () {882
let mut target = state.captures883
target.sortBy((capture) => capture.name)884
target.sortBy((capture) => capture.declarationHi)885
target.sortBy((capture) => capture.declarationLo)886
target.sortBy((capture) => capture.referenceHi)887
target.sortBy((capture) => capture.referenceLo)888
target.sortBy((capture) => capture.closureHi)889
target.sortBy((capture) => capture.closureLo)890
target.sortBy((capture) => capture.moduleIndex)891
target.sortBy((capture) => moduleIdentityAt(state, capture.moduleIndex))892
let mut index = 1893
while index < target.length {894
let previous = match target.get(index - 1) {895
case Some(value) => value896
case None => return ()897
}898
let current = match target.get(index) {899
case Some(value) => value900
case None => return ()901
}902
if capturesAreSame(previous, current) {903
target.removeAt(index)904
} else {905
index += 1906
}907
}908
}910
export function deriveCaptures(state: CheckerState) -> () {911
let mut scopeAncestorIndexes: Map<string, Set<int>> = Map.new()912
let mut captures = state.captures913
for reference in state.resolved.references {914
for capture in capturesForReference(915
state,916
scopeAncestorIndexes,917
reference,918
) {919
captures.push(capture)920
}921
}922
sortAndDeduplicateCaptures(state)923
()924
}926
function lispexRuleFactoryCallIndexes(927
calls: Array<PreviewTypedCall>,928
) -> Map<string, Array<int>> {929
let mut indexes: Map<string, Array<int>> = Map.new()930
let mut index = 0931
for call in calls {932
if call.arguments.length == 0 &&933
call.targetIdentity.startsWith("topaz.lispex-rule-handle/v1:") {934
let key = definitionNameKey(call.moduleIndex, call.targetIdentity)935
match indexes.get(key) {936
case Some(found) => {937
let mut targets = found938
targets.push(index)939
}940
case None => indexes.insert(key, [index])941
}942
}943
index += 1944
}945
indexes946
}948
export function diagnoseLispexRuleFactoryEscapes(state: CheckerState) -> () {949
let callIndexes = lispexRuleFactoryCallIndexes(state.calls)950
for reference in state.resolved.references {951
if reference.namespace != "value" ||952
reference.targetModule != "std.lispex.rules" ||953
reference.targetName == "" {954
continue955
}956
let expected = "topaz.lispex-rule-handle/v1:{reference.targetName}"957
let mut direct = false958
match callIndexes.get(definitionNameKey(reference.moduleIndex, expected)) {959
case Some(indexes) => for index in indexes {960
match state.calls.get(index) {961
case Some(call) => if reference.lo >= call.calleeLo &&962
reference.hi <= call.calleeHi {963
direct = true964
}965
case None => ()966
}967
}968
case None => ()969
}970
if !direct {971
addDiagnostic(972
state,973
reference.moduleIndex,974
"TPZ5500",975
"a generated Lispex rule factory may only appear as the direct callee of a zero-argument call",976
"",977
SyntaxNode {978
kind: "identifier",979
lo: reference.lo,980
hi: reference.hi,981
field: "",982
index: 0,983
attributes: [],984
children: [],985
},986
)987
}988
}989
()990
}992
record DeclarationIndexes {993
spans: Map<string, int>,994
valuesByModule: Map<string, Array<int>>,995
namespaceImports: Map<string, int>,996
}998
export record CheckerIndexes {999
declarations: Map<string, int>,1000
valueDeclarationsByModule: Map<string, Array<int>>,1001
namespaceImports: Map<string, int>,1002
references: Map<string, int>,1003
scopes: Map<string, int>,1004
}1006
function declarationIndexes(resolved: ResolveResult) -> DeclarationIndexes {1007
let mut spans = emptyStringIntMap()1008
let mut valuesByModule: Map<string, Array<int>> = Map.new()1009
let mut namespaceImports = emptyStringIntMap()1010
let mut index = 01011
for declaration in resolved.declarations {1012
let span = spanKey(declaration.moduleIndex, declaration.lo, declaration.hi)1013
match spans.get(span) {1014
case Some(_) => ()1015
case None => spans.insert(span, index)1016
}1017
if declaration.namespace == "value" {1018
let key = "{declaration.moduleIndex}"1019
match valuesByModule.get(key) {1020
case Some(found) => {1021
let mut targets = found1022
targets.push(index)1023
}1024
case None => valuesByModule.insert(key, [index])1025
}1026
}1027
if declaration.namespace == "module" &&1028
declaration.declarationKind == "namespace-import" {1029
let name = definitionNameKey(declaration.moduleIndex, declaration.name)1030
match namespaceImports.get(name) {1031
case Some(_) => ()1032
case None => namespaceImports.insert(name, index)1033
}1034
}1035
index += 11036
}1037
DeclarationIndexes {1038
spans: spans,1039
valuesByModule: valuesByModule,1040
namespaceImports: namespaceImports,1041
}1042
}1044
function referenceSpanIndexes(resolved: ResolveResult) -> Map<string, int> {1045
let mut indexes = emptyStringIntMap()1046
let mut index = 01047
for reference in resolved.references {1048
let key = spanKey(reference.moduleIndex, reference.lo, reference.hi)1049
match indexes.get(key) {1050
case Some(_) => ()1051
case None => indexes.insert(key, index)1052
}1053
index += 11054
}1055
indexes1056
}1058
function scopeOrdinalIndexes(resolved: ResolveResult) -> Map<string, int> {1059
let mut indexes = emptyStringIntMap()1060
let mut index = 01061
for scope in resolved.scopes {1062
let key = scopeKey(scope.moduleIndex, scope.ordinal)1063
match indexes.get(key) {1064
case Some(_) => ()1065
case None => indexes.insert(key, index)1066
}1067
index += 11068
}1069
indexes1070
}1072
export function checkerIndexes(resolved: ResolveResult) -> CheckerIndexes {1073
let declarations = declarationIndexes(resolved)1074
CheckerIndexes {1075
declarations: declarations.spans,1076
valueDeclarationsByModule: declarations.valuesByModule,1077
namespaceImports: declarations.namespaceImports,1078
references: referenceSpanIndexes(resolved),1079
scopes: scopeOrdinalIndexes(resolved),1080
}1081
}1083
export function initialCheckerState(1084
resolved: ResolveResult,1085
modules: Array<ModuleSyntax>,1086
indexes: CheckerIndexes,1087
) -> CheckerState {1088
CheckerState {1089
resolved: resolved,1090
modules: modules,1091
declarationIndexes: indexes.declarations,1092
valueDeclarationIndexesByModule: indexes.valueDeclarationsByModule,1093
namespaceImportIndexes: indexes.namespaceImports,1094
referenceIndexes: indexes.references,1095
scopeIndexes: indexes.scopes,1096
symbolIndexes: emptyStringIntMap(),1097
nodeIndexes: emptyStringIntMap(),1098
callIndexes: emptyStringIntMap(),1099
functionIndexes: emptyStringIntMap(),1100
functionNameIndexes: emptyStringIntMap(),1101
receiverMethodIndexes: emptyStringIntMap(),1102
protocolIndexes: emptyStringIntMap(),1103
conformanceIndexes: emptyStringIntMap(),1104
conformanceTypeIndexes: emptyStringIntMap(),1105
recordIndexes: emptyStringIntMap(),1106
enumIndexes: emptyStringIntMap(),1107
newtypeIndexes: emptyStringIntMap(),1108
aliasIndexes: emptyStringIntMap(),1109
symbols: [],1110
records: [],1111
enums: [],1112
newtypes: [],1113
aliases: [],1114
functions: [],1115
receiverMethods: [],1116
protocols: [],1117
pendingFunctions: [],1118
functionAliases: emptyStringIntMap(),1119
conformances: [],1120
typeParameters: [],1121
activeFunctions: [],1122
expectedReturns: [],1123
returnJoins: [],1124
expectedExpressions: [],1125
bareBindingExpressions: [],1126
literalJoinContexts: [],1127
branchJoinContexts: [],1128
statementExpressionContexts: [],1129
typeCapabilitySuppressions: [],1130
loopFrames: [],1131
loopFloors: [],1132
pipeValues: [],1133
nodes: [],1134
calls: [],1135
captures: [],1136
diagnostics: [],1137
inferenceSolutions: Map.new(),1138
nextInference: 0,1139
}1140
}SHA256 cc512c8ffbff50688063ea9078fd6afaa80670d55795e844aa7d7376e2a2b613