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/resolver/scopes_walk.tpz
Topaz · 29101 B · Original file
1
// Lexical scope construction and resolved-reference traversal.2
// Module tables define cross-file bindings, while this leaf owns local scopes,3
// declarations, captures, and reference observations.5
import raw { keywordKind }6
import types {7
PreviewResolvedDeclaration,8
PreviewResolvedExport,9
PreviewResolvedReference,10
PreviewResolvedScope,11
SyntaxNode,12
}13
import unicode { didYouMean }14
import resolver.model_facts {15
Binding,16
LocalScope,17
ModuleTable,18
ReferenceResolution,19
ResolverWalkContext,20
boolAttribute,21
child,22
children,23
diagnostic,24
isNone,25
text,26
}27
import resolver.modules_tables {28
bindingForStatement,29
catalogTable,30
collectPatternBindings,31
effectiveNamespace,32
exportedBinding,33
exportedNames,34
tableBinding,35
}37
function localBinding(scopes: Array<LocalScope>, name: string, namespace: string) -> Option<Binding> {38
let mut index = scopes.length39
while index > 0 {40
index -= 141
let scope = scopes[index]42
let bindings = if namespace == "type" { scope.types } else { scope.values }43
match bindings.get(name) {44
case Some(binding) => return Some(binding)45
case None => ()46
}47
}48
None49
}51
function currentScope(scopes: Array<LocalScope>) -> int {52
if scopes.length == 0 {53
return 054
}55
scopes[scopes.length - 1].ordinal56
}58
export function addDeclaration(59
output: Array<PreviewResolvedDeclaration>,60
binding: Binding,61
namespace: string,62
exported: bool,63
) -> () {64
let mut target = output65
target.push(PreviewResolvedDeclaration {66
moduleIndex: binding.moduleIndex,67
scopeOrdinal: binding.scopeOrdinal,68
name: binding.name,69
namespace: namespace,70
declarationKind: binding.declarationKind,71
lo: binding.lo,72
hi: binding.hi,73
exported: exported,74
targetModule: binding.targetModule,75
targetName: binding.targetName,76
})77
}79
function addLocalBinding(80
scopes: Array<LocalScope>,81
declarations: Array<PreviewResolvedDeclaration>,82
binding: Binding,83
) -> () {84
let mut activeScopes = scopes85
let scope = activeScopes[activeScopes.length - 1]86
if binding.namespace == "type" {87
let mut types = scope.types88
types.insert(binding.name, binding)89
} else {90
let mut values = scope.values91
values.insert(binding.name, binding)92
}93
addDeclaration(94
declarations,95
binding,96
binding.namespace,97
binding.exported,98
)99
}101
export function appendModuleExports(102
output: Array<PreviewResolvedExport>,103
moduleIndexValue: int,104
table: ModuleTable,105
) -> () {106
let mut target = output107
for name in exportedNames(table, "") {108
match exportedBinding(table, name) {109
case Some(exported) => {110
let binding = table.bindings[exported.bindingIndex]111
target.push(PreviewResolvedExport {112
moduleIndex: moduleIndexValue,113
name: name,114
namespace: exported.namespace,115
declarationLo: binding.lo,116
declarationHi: binding.hi,117
})118
}119
case None => ()120
}121
}122
()123
}125
function unresolvedReference(namespace: string) -> ReferenceResolution {126
ReferenceResolution {127
referenceNamespace: namespace,128
targetModuleIndex: -1,129
targetLo: 0,130
targetHi: 0,131
targetNamespace: "",132
targetModule: "",133
targetName: "",134
}135
}137
function appendReference(138
context: ResolverWalkContext,139
scopes: Array<LocalScope>,140
name: string,141
role: string,142
lo: int,143
hi: int,144
resolved: ReferenceResolution,145
) -> () {146
let mut output = context.referenceOutput147
output.push(PreviewResolvedReference {148
moduleIndex: context.moduleIndex,149
scopeOrdinal: currentScope(scopes),150
name: name,151
namespace: resolved.referenceNamespace,152
role: role,153
lo: lo,154
hi: hi,155
targetModuleIndex: resolved.targetModuleIndex,156
targetLo: resolved.targetLo,157
targetHi: resolved.targetHi,158
targetNamespace: resolved.targetNamespace,159
targetModule: resolved.targetModule,160
targetName: resolved.targetName,161
})162
}164
function localReferenceResolution(165
context: ResolverWalkContext,166
scopes: Array<LocalScope>,167
name: string,168
namespace: string,169
) -> Option<ReferenceResolution> {170
match localBinding(scopes, name, namespace) {171
case Some(target) => Some(ReferenceResolution {172
referenceNamespace: namespace,173
targetModuleIndex: context.moduleIndex,174
targetLo: target.lo,175
targetHi: target.hi,176
targetNamespace: target.namespace,177
targetModule: context.table.identity,178
targetName: name,179
})180
case None => None181
}182
}184
function moduleReferenceResolution(185
context: ResolverWalkContext,186
found: Binding,187
name: string,188
namespace: string,189
role: string,190
) -> ReferenceResolution {191
if found.declarationKind == "selected-import" {192
return ReferenceResolution {193
referenceNamespace: namespace,194
targetModuleIndex: context.moduleIndex,195
targetLo: found.lo,196
targetHi: found.hi,197
targetNamespace: if role == "type" {198
namespace199
} else {200
effectiveNamespace(found, context.tables)201
},202
targetModule: if role == "type" {203
context.table.identity204
} else {205
found.targetModule206
},207
targetName: if role == "type" { name } else { found.targetName },208
}209
} else if found.declarationKind == "namespace-import" {210
return ReferenceResolution {211
referenceNamespace: "module",212
targetModuleIndex: context.moduleIndex,213
targetLo: found.lo,214
targetHi: found.hi,215
targetNamespace: found.namespace,216
targetModule: found.targetModule,217
targetName: "",218
}219
}220
ReferenceResolution {221
referenceNamespace: namespace,222
targetModuleIndex: context.moduleIndex,223
targetLo: found.lo,224
targetHi: found.hi,225
targetNamespace: found.namespace,226
targetModule: context.table.identity,227
targetName: name,228
}229
}231
function reference(232
context: ResolverWalkContext,233
scopes: Array<LocalScope>,234
name: string,235
namespace: string,236
role: string,237
lo: int,238
hi: int,239
) -> Option<Binding> {240
let mut moduleBinding: Option<Binding> = None241
let resolved = match localReferenceResolution(242
context,243
scopes,244
name,245
namespace,246
) {247
case Some(value) => value248
case None => match tableBinding(context.table, name) {249
case Some(binding) => {250
moduleBinding = Some(binding)251
moduleReferenceResolution(252
context,253
binding,254
name,255
namespace,256
role,257
)258
}259
case None => unresolvedReference(namespace)260
}261
}262
appendReference(context, scopes, name, role, lo, hi, resolved)263
moduleBinding264
}266
function namespaceMemberResolution(267
context: ResolverWalkContext,268
binding: Binding,269
member: string,270
namespace: string,271
field: SyntaxNode,272
) -> ReferenceResolution {273
let targetTable = match catalogTable(context.tables, binding.targetModule) {274
case Some(found) => found275
case None => return unresolvedReference(namespace)276
}277
let targetBinding = tableBinding(targetTable, member)278
let targetExport = exportedBinding(targetTable, member)279
let targetNamespace = match targetExport {280
case Some(exported) => exported.namespace281
case None => ""282
}283
let memberExported = !isNone(targetExport)284
let keywordNamed = namespace == "value" &&285
keywordKind(member).startsWith("keyword/")286
if keywordNamed {287
diagnostic(288
context.diagnostics,289
context.moduleIndex,290
"TPZ3013",291
"namespace members are exported declarations and cannot be keyword-named (`{binding.name}.{member}`)",292
field.lo,293
field.hi,294
)295
} else if !memberExported {296
let mut recordDefaultPrivateValue = false297
if namespace == "value" && context.recordDefaultStack.length > 0 {298
match targetBinding {299
case Some(privateBinding) => if privateBinding.declarationKind == "let" &&300
!privateBinding.mutable && !privateBinding.exported {301
recordDefaultPrivateValue = true302
}303
case None => ()304
}305
}306
if !recordDefaultPrivateValue {307
let hint = didYouMean(308
member,309
exportedNames(targetTable, namespace),310
)311
diagnostic(312
context.diagnostics,313
context.moduleIndex,314
"TPZ3009",315
"`{member}` is not exported by `{binding.targetModule}`{hint}",316
field.lo,317
field.hi,318
)319
}320
}321
let target = match targetBinding {322
case Some(found) => found323
case None => return unresolvedReference(namespace)324
}325
if !keywordNamed && memberExported && namespace == "value" &&326
targetNamespace == "type" {327
diagnostic(328
context.diagnostics,329
context.moduleIndex,330
"TPZ3013",331
"`{member}` is an exported type alias of `{binding.targetModule}`, not a value; use it in type position",332
field.lo,333
field.hi,334
)335
} else if !keywordNamed && memberExported && namespace == "type" &&336
targetNamespace != "type" {337
diagnostic(338
context.diagnostics,339
context.moduleIndex,340
"TPZ3013",341
"`{member}` is exported by `{binding.targetModule}` but is not a type alias",342
field.lo,343
field.hi,344
)345
}346
ReferenceResolution {347
referenceNamespace: namespace,348
targetModuleIndex: target.moduleIndex,349
targetLo: target.lo,350
targetHi: target.hi,351
targetNamespace: if namespace == "type" || targetNamespace == "type" {352
"type"353
} else {354
"value"355
},356
targetModule: binding.targetModule,357
targetName: member,358
}359
}361
function namespaceMember(362
context: ResolverWalkContext,363
scopes: Array<LocalScope>,364
object: SyntaxNode,365
field: SyntaxNode,366
namespace: string,367
role: string,368
) -> bool {369
let head = text(context.source, object)370
if match localBinding(scopes, head, "value") {371
case Some(_) => true372
case None => false373
} {374
return false375
}376
let binding = match tableBinding(context.table, head) {377
case Some(found) => found378
case None => return false379
}380
if binding.declarationKind != "namespace-import" {381
return false382
}383
let member = text(context.source, field)384
let resolved = namespaceMemberResolution(385
context,386
binding,387
member,388
namespace,389
field,390
)391
appendReference(392
context,393
scopes,394
"{head}.{member}",395
role,396
field.lo,397
field.hi,398
resolved,399
)400
true401
}403
function pushScope(404
moduleIndexValue: int,405
owner: SyntaxNode,406
kind: string,407
scopes: Array<LocalScope>,408
nextScope: Array<int>,409
output: Array<PreviewResolvedScope>,410
) -> int {411
let ordinal = nextScope[0]412
let mut nextScopeBox = nextScope413
nextScopeBox[0] = ordinal + 1414
let mut rows = output415
rows.push(PreviewResolvedScope {416
moduleIndex: moduleIndexValue,417
ordinal: ordinal,418
parentOrdinal: currentScope(scopes),419
kind: kind,420
lo: owner.lo,421
hi: owner.hi,422
})423
let mut active = scopes424
active.push(LocalScope {425
ordinal: ordinal,426
values: Map.new(),427
types: Map.new(),428
})429
ordinal430
}432
function popScope(scopes: Array<LocalScope>) -> () {433
let mut activeScopes = scopes434
match activeScopes.pop() {435
case Some(_) => ()436
case None => ()437
}438
}440
function bindPattern(441
moduleIndexValue: int,442
pattern: SyntaxNode,443
source: Bytes,444
declarationKind: string,445
scopes: Array<LocalScope>,446
declarations: Array<PreviewResolvedDeclaration>,447
) -> () {448
let mut names: Array<SyntaxNode> = []449
collectPatternBindings(pattern, source, names)450
for name in names {451
addLocalBinding(scopes, declarations, Binding {452
moduleIndex: moduleIndexValue,453
scopeOrdinal: currentScope(scopes),454
name: text(source, name),455
namespace: "value",456
declarationKind: declarationKind,457
lo: name.lo,458
hi: name.hi,459
exported: false,460
targetModule: "",461
targetName: "",462
mutable: false,463
})464
}465
()466
}468
function walkProtocolStatement(469
context: ResolverWalkContext,470
node: SyntaxNode,471
scopes: Array<LocalScope>,472
) -> () {473
match child(node, "name") {474
case Some(name) => {475
let protocolName = text(context.source, name)476
let alreadyBound = match localBinding(scopes, protocolName, "type") {477
case Some(binding) => binding.scopeOrdinal == currentScope(scopes) &&478
binding.lo == name.lo && binding.hi == name.hi479
case None => false480
}481
if !alreadyBound {482
let mut declarations = context.declarationOutput483
declarations.push(PreviewResolvedDeclaration {484
moduleIndex: context.moduleIndex,485
scopeOrdinal: currentScope(scopes),486
name: protocolName,487
namespace: "type",488
declarationKind: "protocol",489
lo: name.lo,490
hi: name.hi,491
exported: false,492
targetModule: "",493
targetName: "",494
})495
}496
}497
case None => ()498
}499
for method in children(node, "methods") {500
for parameter in children(method, "parameters") {501
match child(parameter, "type") {502
case Some(parameterType) => walkNode(context, parameterType, scopes)503
case None => ()504
}505
}506
match child(method, "returnType") {507
case Some(returnType) => walkNode(context, returnType, scopes)508
case None => ()509
}510
}511
()512
}514
function walkUsingStatement(515
context: ResolverWalkContext,516
node: SyntaxNode,517
scopes: Array<LocalScope>,518
) -> () {519
match child(node, "value") {520
case Some(value) => walkNode(context, value, scopes)521
case None => ()522
}523
match child(node, "body") {524
case Some(body) => {525
pushScope(526
context.moduleIndex,527
body,528
"using",529
scopes,530
context.nextScope,531
context.scopeOutput,532
)533
match child(node, "name") {534
case Some(name) => addLocalBinding(535
scopes,536
context.declarationOutput,537
Binding {538
moduleIndex: context.moduleIndex,539
scopeOrdinal: currentScope(scopes),540
name: text(context.source, name),541
namespace: "value",542
declarationKind: "using",543
lo: name.lo,544
hi: name.hi,545
exported: false,546
targetModule: "",547
targetName: "",548
mutable: false,549
},550
)551
case None => ()552
}553
walkNode(context, body, scopes)554
popScope(scopes)555
}556
case None => ()557
}558
()559
}561
function walkComprehensionExpression(562
context: ResolverWalkContext,563
node: SyntaxNode,564
scopes: Array<LocalScope>,565
) -> () {566
let mut opened = 0567
for clause in children(node, "clauses") {568
if clause.kind == "comprehension-clause/for" {569
match child(clause, "iterator") {570
case Some(iterator) => walkNode(context, iterator, scopes)571
case None => ()572
}573
match child(clause, "pattern") {574
case Some(pattern) => {575
pushScope(576
context.moduleIndex,577
pattern,578
"comprehension",579
scopes,580
context.nextScope,581
context.scopeOutput,582
)583
bindPattern(584
context.moduleIndex,585
pattern,586
context.source,587
"pattern",588
scopes,589
context.declarationOutput,590
)591
walkNode(context, pattern, scopes)592
opened += 1593
}594
case None => ()595
}596
} else {597
for part in clause.children {598
walkNode(context, part, scopes)599
}600
}601
}602
for found in node.children {603
if found.field == "body" || found.field == "bodyKey" ||604
found.field == "bodyValue" {605
walkNode(context, found, scopes)606
}607
}608
while opened > 0 {609
popScope(scopes)610
opened -= 1611
}612
()613
}615
function openPatternScope(616
context: ResolverWalkContext,617
pattern: SyntaxNode,618
scopes: Array<LocalScope>,619
) -> () {620
walkNode(context, pattern, scopes)621
pushScope(622
context.moduleIndex,623
pattern,624
"pattern",625
scopes,626
context.nextScope,627
context.scopeOutput,628
)629
bindPattern(630
context.moduleIndex,631
pattern,632
context.source,633
"pattern",634
scopes,635
context.declarationOutput,636
)637
()638
}640
function walkMatchCase(641
context: ResolverWalkContext,642
node: SyntaxNode,643
scopes: Array<LocalScope>,644
) -> () {645
let mut opened = false646
match child(node, "pattern") {647
case Some(pattern) => {648
openPatternScope(context, pattern, scopes)649
opened = true650
}651
case None => ()652
}653
for found in node.children {654
if found.field != "pattern" {655
walkNode(context, found, scopes)656
}657
}658
if opened {659
popScope(scopes)660
}661
()662
}664
function walkForExpression(665
context: ResolverWalkContext,666
node: SyntaxNode,667
scopes: Array<LocalScope>,668
) -> () {669
match child(node, "iterator") {670
case Some(iterator) => walkNode(context, iterator, scopes)671
case None => ()672
}673
let mut opened = false674
match child(node, "pattern") {675
case Some(pattern) => {676
openPatternScope(context, pattern, scopes)677
opened = true678
}679
case None => ()680
}681
for found in node.children {682
if found.field != "iterator" && found.field != "pattern" {683
walkNode(context, found, scopes)684
}685
}686
if opened {687
popScope(scopes)688
}689
()690
}692
function resolveAssignmentIdentifier(693
context: ResolverWalkContext,694
target: SyntaxNode,695
scopes: Array<LocalScope>,696
) -> () {697
let name = text(context.source, target)698
let binding = match reference(699
context,700
scopes,701
name,702
"value",703
"write",704
target.lo,705
target.hi,706
) {707
case Some(found) => found708
case None => return ()709
}710
if binding.declarationKind == "selected-import" {711
diagnostic(712
context.diagnostics,713
context.moduleIndex,714
"TPZ3015",715
"`{name}` is an imported binding and cannot be assigned",716
target.lo,717
target.hi,718
)719
} else if binding.declarationKind == "namespace-import" {720
diagnostic(721
context.diagnostics,722
context.moduleIndex,723
"TPZ3012",724
"`{name}` is a namespace, not a value; it may appear only as `{name}.member`",725
target.lo,726
target.hi,727
)728
}729
()730
}732
function rejectNamespaceAssignment(733
context: ResolverWalkContext,734
target: SyntaxNode,735
scopes: Array<LocalScope>,736
) -> bool {737
if target.kind != "expression/member" {738
return false739
}740
let object = match child(target, "object") {741
case Some(found) => found742
case None => return false743
}744
if object.kind != "expression/identifier" {745
return false746
}747
let name = text(context.source, object)748
if !isNone(localBinding(scopes, name, "value")) {749
return false750
}751
let binding = match tableBinding(context.table, name) {752
case Some(found) => found753
case None => return false754
}755
if binding.declarationKind != "namespace-import" {756
return false757
}758
let member = match child(target, "field") {759
case Some(field) => text(context.source, field)760
case None => ""761
}762
diagnostic(763
context.diagnostics,764
context.moduleIndex,765
"TPZ3015",766
"`{name}.{member}` is an exported binding viewed through a namespace and cannot be assigned",767
target.lo,768
target.hi,769
)770
true771
}773
function walkAssignmentStatement(774
context: ResolverWalkContext,775
node: SyntaxNode,776
scopes: Array<LocalScope>,777
) -> () {778
match child(node, "target") {779
case Some(target) => if target.kind == "expression/identifier" {780
resolveAssignmentIdentifier(context, target, scopes)781
} else if !rejectNamespaceAssignment(context, target, scopes) {782
walkNode(context, target, scopes)783
}784
case None => ()785
}786
match child(node, "value") {787
case Some(value) => walkNode(context, value, scopes)788
case None => ()789
}790
()791
}793
function resolveNamedTypeReference(794
context: ResolverWalkContext,795
node: SyntaxNode,796
scopes: Array<LocalScope>,797
) -> () {798
match child(node, "name") {799
case Some(name) => {800
reference(801
context,802
scopes,803
text(context.source, name),804
"type",805
"type",806
name.lo,807
name.hi,808
)809
()810
}811
case None => ()812
}813
()814
}816
function resolveQualifiedTypeReference(817
context: ResolverWalkContext,818
node: SyntaxNode,819
scopes: Array<LocalScope>,820
) -> () {821
match child(node, "namespace") {822
case Some(namespaceNode) => match child(node, "name") {823
case Some(name) => if !namespaceMember(824
context,825
scopes,826
namespaceNode,827
name,828
"type",829
"type",830
) {831
diagnostic(832
context.diagnostics,833
context.moduleIndex,834
"TPZ3013",835
"the head of a qualified type must be a namespace binding; `{text(context.source, namespaceNode)}` is not one here",836
namespaceNode.lo,837
namespaceNode.hi,838
)839
}840
case None => ()841
}842
case None => ()843
}844
()845
}847
function resolveValueIdentifier(848
context: ResolverWalkContext,849
node: SyntaxNode,850
scopes: Array<LocalScope>,851
) -> () {852
let name = text(context.source, node)853
let binding = match reference(854
context,855
scopes,856
name,857
"value",858
"read",859
node.lo,860
node.hi,861
) {862
case Some(found) => found863
case None => return ()864
}865
if binding.declarationKind == "namespace-import" {866
diagnostic(867
context.diagnostics,868
context.moduleIndex,869
"TPZ3012",870
"`{name}` is a namespace, not a value; it may appear only as `{name}.member`",871
node.lo,872
node.hi,873
)874
}875
()876
}878
function resolveNamespaceMemberReference(879
context: ResolverWalkContext,880
node: SyntaxNode,881
scopes: Array<LocalScope>,882
) -> bool {883
if node.kind != "expression/member" {884
return false885
}886
match child(node, "object") {887
case Some(object) => match child(node, "field") {888
case Some(field) => object.kind == "expression/identifier" &&889
namespaceMember(890
context,891
scopes,892
object,893
field,894
"value",895
"namespace-member",896
)897
case None => false898
}899
case None => false900
}901
}903
function walkCallableSignature(904
context: ResolverWalkContext,905
node: SyntaxNode,906
scopes: Array<LocalScope>,907
) -> () {908
if node.kind != "function-declaration" &&909
node.kind != "expression/lambda" {910
return ()911
}912
for parameter in children(node, "parameters") {913
for part in parameter.children {914
if part.field == "type" || part.field == "default" {915
walkNode(context, part, scopes)916
}917
}918
}919
match child(node, "returnType") {920
case Some(returnType) => walkNode(context, returnType, scopes)921
case None => ()922
}923
()924
}926
function openNodeScope(927
context: ResolverWalkContext,928
node: SyntaxNode,929
scopes: Array<LocalScope>,930
) -> bool {931
let kind = match node.kind {932
case "function-declaration" => "function"933
case "expression/lambda" => "lambda"934
case "block" => "block"935
case _ => ""936
}937
if kind == "" {938
return false939
}940
let ordinal = pushScope(941
context.moduleIndex,942
node,943
kind,944
scopes,945
context.nextScope,946
context.scopeOutput,947
)948
if node.kind == "function-declaration" ||949
node.kind == "expression/lambda" {950
for parameter in children(node, "parameters") {951
match child(parameter, "name") {952
case Some(name) => addLocalBinding(953
scopes,954
context.declarationOutput,955
Binding {956
moduleIndex: context.moduleIndex,957
scopeOrdinal: ordinal,958
name: text(context.source, name),959
namespace: "value",960
declarationKind: "parameter",961
lo: name.lo,962
hi: name.hi,963
exported: false,964
targetModule: "",965
targetName: "",966
mutable: false,967
},968
)969
case None => ()970
}971
}972
}973
true974
}976
function prebindChildDeclaration(977
context: ResolverWalkContext,978
childNode: SyntaxNode,979
scopes: Array<LocalScope>,980
) -> () {981
if scopes.length == 0 {982
return ()983
}984
for candidate in bindingForStatement(985
context.moduleIndex,986
childNode,987
context.source,988
false,989
) {990
if candidate.declarationKind != "let" &&991
candidate.declarationKind != "const" &&992
candidate.declarationKind != "namespace-import" &&993
candidate.declarationKind != "selected-import" {994
addLocalBinding(995
scopes,996
context.declarationOutput,997
Binding {998
moduleIndex: context.moduleIndex,999
scopeOrdinal: currentScope(scopes),1000
name: candidate.name,1001
namespace: candidate.namespace,1002
declarationKind: candidate.declarationKind,1003
lo: candidate.lo,1004
hi: candidate.hi,1005
exported: false,1006
targetModule: "",1007
targetName: "",1008
mutable: candidate.mutable,1009
},1010
)1011
}1012
}1013
()1014
}1016
function bindStatementAfterWalk(1017
context: ResolverWalkContext,1018
node: SyntaxNode,1019
scopes: Array<LocalScope>,1020
) -> () {1021
if node.kind == "statement/let" {1022
match child(node, "pattern") {1023
case Some(pattern) => {1024
let mut names: Array<SyntaxNode> = []1025
collectPatternBindings(pattern, context.source, names)1026
for name in names {1027
addLocalBinding(1028
scopes,1029
context.declarationOutput,1030
Binding {1031
moduleIndex: context.moduleIndex,1032
scopeOrdinal: currentScope(scopes),1033
name: text(context.source, name),1034
namespace: "value",1035
declarationKind: "let",1036
lo: name.lo,1037
hi: name.hi,1038
exported: false,1039
targetModule: "",1040
targetName: "",1041
mutable: boolAttribute(node, "mutable"),1042
},1043
)1044
}1045
}1046
case None => ()1047
}1048
} else if node.kind == "statement/const" && scopes.length > 0 {1049
match child(node, "name") {1050
case Some(name) => addLocalBinding(1051
scopes,1052
context.declarationOutput,1053
Binding {1054
moduleIndex: context.moduleIndex,1055
scopeOrdinal: currentScope(scopes),1056
name: text(context.source, name),1057
namespace: "value",1058
declarationKind: "const",1059
lo: name.lo,1060
hi: name.hi,1061
exported: false,1062
targetModule: "",1063
targetName: "",1064
mutable: false,1065
},1066
)1067
case None => ()1068
}1069
}1070
()1071
}1073
function walkNodeChildren(1074
context: ResolverWalkContext,1075
node: SyntaxNode,1076
scopes: Array<LocalScope>,1077
) -> () {1078
if node.kind == "block" {1079
for statement in children(node, "statements") {1080
if statement.kind == "statement/function" {1081
prebindChildDeclaration(context, statement, scopes)1082
}1083
}1084
}1085
for found in node.children {1086
if found.kind == "identifier" {1087
continue1088
}1089
if node.kind == "expression/call" && found.field == "typeArguments" {1090
continue1091
}1092
if (node.kind == "function-declaration" ||1093
node.kind == "expression/lambda") &&1094
(found.field == "parameters" || found.field == "returnType") {1095
continue1096
}1097
if !(node.kind == "block" && found.kind == "statement/function") {1098
prebindChildDeclaration(context, found, scopes)1099
}1100
let recordDefault = node.kind == "record-field-declaration" &&1101
found.field == "default"1102
if recordDefault {1103
let mut stack = context.recordDefaultStack1104
stack.push(true)1105
}1106
walkNode(context, found, scopes)1107
if recordDefault {1108
let mut stack = context.recordDefaultStack1109
stack.pop()1110
}1111
bindStatementAfterWalk(context, found, scopes)1112
}1113
()1114
}1116
export function walkNode(1117
context: ResolverWalkContext,1118
nodeValue: SyntaxNode,1119
scopes: Array<LocalScope>,1120
) -> () {1121
let mut activeScopes = scopes1122
if nodeValue.kind == "identifier" {1123
return ()1124
}1125
if nodeValue.kind == "statement/protocol" {1126
walkProtocolStatement(context, nodeValue, activeScopes)1127
return ()1128
}1129
if nodeValue.kind == "statement/using" {1130
walkUsingStatement(context, nodeValue, activeScopes)1131
return ()1132
}1133
if nodeValue.kind == "expression/comprehension" {1134
walkComprehensionExpression(context, nodeValue, activeScopes)1135
return ()1136
}1137
if nodeValue.kind == "match-case" {1138
walkMatchCase(context, nodeValue, activeScopes)1139
return ()1140
}1141
if nodeValue.kind == "expression/for" {1142
walkForExpression(context, nodeValue, activeScopes)1143
return ()1144
}1145
if nodeValue.kind == "statement/assign" {1146
walkAssignmentStatement(context, nodeValue, scopes)1147
return ()1148
}1149
if nodeValue.kind == "type/named" {1150
resolveNamedTypeReference(context, nodeValue, scopes)1151
} else if nodeValue.kind == "pattern/nominal-record" {1152
resolveNamedTypeReference(context, nodeValue, scopes)1153
} else if nodeValue.kind == "type/qualified" {1154
resolveQualifiedTypeReference(context, nodeValue, scopes)1155
} else if nodeValue.kind == "expression/identifier" {1156
resolveValueIdentifier(context, nodeValue, scopes)1157
} else if resolveNamespaceMemberReference(context, nodeValue, scopes) {1158
return ()1159
}1161
walkCallableSignature(context, nodeValue, scopes)1162
let opened = openNodeScope(context, nodeValue, activeScopes)1163
walkNodeChildren(context, nodeValue, activeScopes)1164
if opened {1165
popScope(activeScopes)1166
}1167
}SHA256 7ca10a9b0f96e19e723d3450a616420820c562e6d646013090ddf508622a59fb