goscript 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cmd/goscript/cmd_compile.go +28 -8
- package/cmd/goscript/cmd_compile_test.go +105 -6
- package/compiler/build-flags.go +9 -10
- package/compiler/gotest/runner_test.go +127 -0
- package/compiler/lowered-program.go +1 -0
- package/compiler/lowering.go +1325 -194
- package/compiler/lowering_bench_test.go +350 -0
- package/compiler/override-registry_test.go +43 -0
- package/compiler/package-graph.go +61 -4
- package/compiler/package-graph_test.go +30 -0
- package/compiler/semantic-model-types.go +8 -0
- package/compiler/semantic-model.go +447 -22
- package/compiler/semantic-model_test.go +138 -0
- package/compiler/skeleton_test.go +1436 -50
- package/compiler/typescript-emitter.go +47 -4
- package/dist/gs/builtin/builtin.d.ts +2 -2
- package/dist/gs/builtin/builtin.js +20 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.js +36 -9
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/slice.js +5 -0
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +1 -1
- package/dist/gs/builtin/type.js +80 -8
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.d.ts +7 -5
- package/dist/gs/bytes/bytes.gs.js +10 -4
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +3 -3
- package/dist/gs/compress/zlib/index.js +88 -26
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/crypto/sha1/index.d.ts +5 -0
- package/dist/gs/crypto/sha1/index.js +103 -0
- package/dist/gs/crypto/sha1/index.js.map +1 -0
- package/dist/gs/crypto/sha256/index.js +2 -5
- package/dist/gs/crypto/sha256/index.js.map +1 -1
- package/dist/gs/crypto/sha512/index.js +2 -5
- package/dist/gs/crypto/sha512/index.js.map +1 -1
- package/dist/gs/embed/index.d.ts +6 -0
- package/dist/gs/embed/index.js +210 -5
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +4 -4
- package/dist/gs/fmt/fmt.js +93 -19
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +118 -6
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.d.ts +45 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js +229 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js.map +1 -0
- package/dist/gs/io/fs/readdir.js +5 -3
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/io.d.ts +18 -11
- package/dist/gs/io/io.js +107 -44
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +26 -5
- package/dist/gs/math/bits/index.js +13 -24
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.js +7 -5
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +11 -1
- package/dist/gs/net/http/index.js +157 -11
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +6 -2
- package/dist/gs/os/types_js.gs.js +169 -8
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +1 -0
- package/dist/gs/reflect/type.js +80 -51
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +2 -2
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +2 -1
- package/dist/gs/sync/sync.js +37 -16
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/js/index.js +9 -0
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/testing/testing.js +8 -6
- package/dist/gs/testing/testing.js.map +1 -1
- package/gs/builtin/builtin.ts +25 -2
- package/gs/builtin/channel.ts +47 -9
- package/gs/builtin/runtime-contract.test.ts +78 -0
- package/gs/builtin/slice.ts +7 -0
- package/gs/builtin/type.ts +97 -8
- package/gs/bytes/bytes.gs.ts +19 -10
- package/gs/bytes/bytes.test.ts +17 -0
- package/gs/compress/zlib/index.test.ts +97 -0
- package/gs/compress/zlib/index.ts +117 -27
- package/gs/compress/zlib/meta.json +4 -1
- package/gs/context/context.test.ts +5 -1
- package/gs/crypto/sha1/index.test.ts +45 -0
- package/gs/crypto/sha1/index.ts +127 -0
- package/gs/crypto/sha1/meta.json +8 -0
- package/gs/crypto/sha256/index.test.ts +14 -2
- package/gs/crypto/sha256/index.ts +3 -6
- package/gs/crypto/sha512/index.test.ts +17 -2
- package/gs/crypto/sha512/index.ts +3 -6
- package/gs/embed/index.test.ts +87 -0
- package/gs/embed/index.ts +229 -5
- package/gs/fmt/fmt.test.ts +61 -3
- package/gs/fmt/fmt.ts +115 -22
- package/gs/fmt/meta.json +6 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +8 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +139 -11
- package/gs/github.com/aperturerobotics/util/conc/index.test.ts +1 -1
- package/gs/github.com/go-git/go-billy/v6/osfs/index.test.ts +110 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/index.ts +280 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/meta.json +8 -0
- package/gs/io/fs/readdir.test.ts +38 -0
- package/gs/io/fs/readdir.ts +7 -3
- package/gs/io/io.test.ts +135 -0
- package/gs/io/io.ts +143 -63
- package/gs/io/meta.json +7 -1
- package/gs/math/bits/index.ts +52 -28
- package/gs/net/http/httptest/index.test.ts +34 -2
- package/gs/net/http/httptest/index.ts +23 -8
- package/gs/net/http/index.test.ts +46 -0
- package/gs/net/http/index.ts +178 -12
- package/gs/os/file_unix_js.test.ts +52 -0
- package/gs/os/meta.json +4 -0
- package/gs/os/readdir.test.ts +56 -0
- package/gs/os/types_js.gs.ts +169 -8
- package/gs/os/zero_copy_posix.gs.ts +1 -2
- package/gs/reflect/deepequal.test.ts +10 -1
- package/gs/reflect/type.ts +91 -56
- package/gs/reflect/typefor.test.ts +31 -1
- package/gs/strings/meta.json +5 -2
- package/gs/strings/reader.test.ts +2 -2
- package/gs/strings/reader.ts +2 -2
- package/gs/sync/meta.json +2 -0
- package/gs/sync/sync.test.ts +41 -1
- package/gs/sync/sync.ts +41 -16
- package/gs/syscall/js/index.test.ts +18 -0
- package/gs/syscall/js/index.ts +12 -0
- package/gs/testing/testing.test.ts +32 -3
- package/gs/testing/testing.ts +13 -10
- package/package.json +1 -1
package/compiler/lowering.go
CHANGED
|
@@ -187,9 +187,6 @@ func (o *LoweringOwner) lowerFile(
|
|
|
187
187
|
})
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
|
-
for importSourcePath := range relevantImportFiles {
|
|
191
|
-
o.addGeneratedTypeImports(model, semPkg, importSourcePath, loweredFile, importAliases, importPaths, reservedImportAliases, seenImport)
|
|
192
|
-
}
|
|
193
190
|
implicitImportPaths := make([]string, 0, len(localRefs.implicitImports))
|
|
194
191
|
for pkgPath := range localRefs.implicitImports {
|
|
195
192
|
if pkgPath != "" && pkgPath != semPkg.pkgPath {
|
|
@@ -198,7 +195,19 @@ func (o *LoweringOwner) lowerFile(
|
|
|
198
195
|
}
|
|
199
196
|
slices.Sort(implicitImportPaths)
|
|
200
197
|
for _, pkgPath := range implicitImportPaths {
|
|
201
|
-
o.addGeneratedImportPath(
|
|
198
|
+
o.addGeneratedImportPath(
|
|
199
|
+
model,
|
|
200
|
+
pkgPath,
|
|
201
|
+
loweredFile,
|
|
202
|
+
importAliases,
|
|
203
|
+
importPaths,
|
|
204
|
+
reservedImportAliases,
|
|
205
|
+
seenImport,
|
|
206
|
+
!localRefs.implicitRuntime[pkgPath],
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
for importSourcePath := range relevantImportFiles {
|
|
210
|
+
o.addGeneratedTypeImports(model, semPkg, importSourcePath, loweredFile, importAliases, importPaths, reservedImportAliases, seenImport)
|
|
202
211
|
}
|
|
203
212
|
localImports := make([]loweredImport, 0, len(localRefs.aliases))
|
|
204
213
|
seenLocalImport := make(map[string]bool)
|
|
@@ -208,7 +217,13 @@ func (o *LoweringOwner) lowerFile(
|
|
|
208
217
|
}
|
|
209
218
|
seenLocalImport[alias] = true
|
|
210
219
|
source := localRefs.aliasSources[alias]
|
|
211
|
-
|
|
220
|
+
typeOnly := !localRefs.runtimeAliases[alias]
|
|
221
|
+
localImports = append(localImports, loweredImport{
|
|
222
|
+
alias: alias,
|
|
223
|
+
source: source,
|
|
224
|
+
sideEffect: !typeOnly,
|
|
225
|
+
typeOnly: typeOnly,
|
|
226
|
+
})
|
|
212
227
|
}
|
|
213
228
|
slices.SortFunc(localImports, func(a, b loweredImport) int {
|
|
214
229
|
return cmp.Compare(a.alias, b.alias)
|
|
@@ -308,7 +323,7 @@ func (o *LoweringOwner) addGeneratedTypeImports(
|
|
|
308
323
|
}
|
|
309
324
|
slices.Sort(pkgPaths)
|
|
310
325
|
for _, pkgPath := range pkgPaths {
|
|
311
|
-
o.addGeneratedImportPath(model, pkgPath, loweredFile, importAliases, importPaths, reservedImportAliases, seenImport)
|
|
326
|
+
o.addGeneratedImportPath(model, pkgPath, loweredFile, importAliases, importPaths, reservedImportAliases, seenImport, true)
|
|
312
327
|
}
|
|
313
328
|
}
|
|
314
329
|
|
|
@@ -320,6 +335,7 @@ func (o *LoweringOwner) addGeneratedImportPath(
|
|
|
320
335
|
importPaths map[string]string,
|
|
321
336
|
reservedImportAliases map[string]bool,
|
|
322
337
|
seenImport map[string]bool,
|
|
338
|
+
typeOnly bool,
|
|
323
339
|
) {
|
|
324
340
|
if !o.hasGeneratedImportPackage(model, pkgPath) {
|
|
325
341
|
return
|
|
@@ -340,7 +356,8 @@ func (o *LoweringOwner) addGeneratedImportPath(
|
|
|
340
356
|
loweredFile.imports = append(loweredFile.imports, loweredImport{
|
|
341
357
|
alias: alias,
|
|
342
358
|
source: source,
|
|
343
|
-
sideEffect:
|
|
359
|
+
sideEffect: !typeOnly,
|
|
360
|
+
typeOnly: typeOnly,
|
|
344
361
|
})
|
|
345
362
|
}
|
|
346
363
|
|
|
@@ -429,7 +446,9 @@ type localFileReferenceAnalysis struct {
|
|
|
429
446
|
reservedNames map[string]bool
|
|
430
447
|
aliases map[types.Object]string
|
|
431
448
|
aliasSources map[string]string
|
|
449
|
+
runtimeAliases map[string]bool
|
|
432
450
|
implicitImports map[string]bool
|
|
451
|
+
implicitRuntime map[string]bool
|
|
433
452
|
}
|
|
434
453
|
|
|
435
454
|
func (o *LoweringOwner) analyzeLocalFileReferences(
|
|
@@ -444,35 +463,68 @@ func (o *LoweringOwner) analyzeLocalFileReferences(
|
|
|
444
463
|
reservedNames: make(map[string]bool),
|
|
445
464
|
aliases: make(map[types.Object]string),
|
|
446
465
|
aliasSources: make(map[string]string),
|
|
466
|
+
runtimeAliases: make(map[string]bool),
|
|
447
467
|
implicitImports: make(map[string]bool),
|
|
468
|
+
implicitRuntime: make(map[string]bool),
|
|
448
469
|
}
|
|
449
470
|
seenObjects := make(map[types.Object]bool)
|
|
450
471
|
seenTypes := make(map[types.Type]bool)
|
|
451
472
|
var addTypeDeps func(typ types.Type)
|
|
452
|
-
var
|
|
453
|
-
|
|
454
|
-
|
|
473
|
+
var addRuntimeTypeDeps func(typ types.Type)
|
|
474
|
+
var addRuntimeTypeOwnerDeps func(typ types.Type)
|
|
475
|
+
var addObject func(obj types.Object, runtime bool)
|
|
476
|
+
addObject = func(obj types.Object, runtime bool) {
|
|
477
|
+
if obj == nil || obj.Pkg() == nil {
|
|
455
478
|
return
|
|
456
479
|
}
|
|
457
|
-
if
|
|
480
|
+
if obj.Pkg().Path() != semPkg.pkgPath {
|
|
481
|
+
if runtime {
|
|
482
|
+
analysis.implicitImports[obj.Pkg().Path()] = true
|
|
483
|
+
analysis.implicitRuntime[obj.Pkg().Path()] = true
|
|
484
|
+
}
|
|
458
485
|
return
|
|
459
486
|
}
|
|
460
|
-
seenObjects[obj] = true
|
|
461
487
|
declFile := declFiles[obj]
|
|
488
|
+
if declFile == "" {
|
|
489
|
+
if fn, ok := obj.(*types.Func); ok {
|
|
490
|
+
if decl := functionDeclForObject(semPkg, fn); decl != nil {
|
|
491
|
+
declFile = sourcePos(semPkg.source, decl.Pos()).file
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
462
495
|
if declFile != "" && declFile != sourcePath {
|
|
463
496
|
outputName := outputNames[declFile]
|
|
464
497
|
if outputName != "" {
|
|
465
498
|
alias := "__goscript_" + safeIdentifier(strings.TrimSuffix(outputName, ".gs.ts"))
|
|
466
499
|
analysis.aliases[obj] = alias
|
|
467
500
|
analysis.aliasSources[alias] = "./" + outputName
|
|
501
|
+
if runtime {
|
|
502
|
+
analysis.runtimeAliases[alias] = true
|
|
503
|
+
}
|
|
468
504
|
}
|
|
469
505
|
}
|
|
506
|
+
if runtime {
|
|
507
|
+
if alias := analysis.aliases[obj]; alias != "" {
|
|
508
|
+
analysis.runtimeAliases[alias] = true
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if seenObjects[obj] {
|
|
512
|
+
return
|
|
513
|
+
}
|
|
514
|
+
seenObjects[obj] = true
|
|
470
515
|
switch typed := obj.(type) {
|
|
471
516
|
case *types.TypeName:
|
|
472
517
|
addTypeDeps(typed.Type())
|
|
518
|
+
if named, ok := types.Unalias(typed.Type()).(*types.Named); ok {
|
|
519
|
+
if structType := structUnderlyingType(named); structType != nil {
|
|
520
|
+
for field := range structType.Fields() {
|
|
521
|
+
addRuntimeTypeDeps(field.Type())
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
473
525
|
if named, ok := types.Unalias(typed.Type()).(*types.Named); ok {
|
|
474
526
|
for method := range named.Methods() {
|
|
475
|
-
addObject(method)
|
|
527
|
+
addObject(method, false)
|
|
476
528
|
}
|
|
477
529
|
}
|
|
478
530
|
case *types.Var:
|
|
@@ -515,7 +567,7 @@ func (o *LoweringOwner) analyzeLocalFileReferences(
|
|
|
515
567
|
addTypeDeps(alias.Rhs())
|
|
516
568
|
return
|
|
517
569
|
}
|
|
518
|
-
addObject(alias.Obj())
|
|
570
|
+
addObject(alias.Obj(), false)
|
|
519
571
|
if args := alias.TypeArgs(); args != nil {
|
|
520
572
|
for t := range args.Types() {
|
|
521
573
|
addTypeDeps(t)
|
|
@@ -534,7 +586,7 @@ func (o *LoweringOwner) analyzeLocalFileReferences(
|
|
|
534
586
|
}
|
|
535
587
|
return
|
|
536
588
|
}
|
|
537
|
-
addObject(named.Obj())
|
|
589
|
+
addObject(named.Obj(), false)
|
|
538
590
|
if args := named.TypeArgs(); args != nil {
|
|
539
591
|
for t := range args.Types() {
|
|
540
592
|
addTypeDeps(t)
|
|
@@ -580,8 +632,93 @@ func (o *LoweringOwner) analyzeLocalFileReferences(
|
|
|
580
632
|
}
|
|
581
633
|
}
|
|
582
634
|
}
|
|
635
|
+
addRuntimeTypeDeps = func(typ types.Type) {
|
|
636
|
+
if typ == nil {
|
|
637
|
+
return
|
|
638
|
+
}
|
|
639
|
+
if alias, ok := typ.(*types.Alias); ok {
|
|
640
|
+
addObject(alias.Obj(), true)
|
|
641
|
+
if args := alias.TypeArgs(); args != nil {
|
|
642
|
+
for t := range args.Types() {
|
|
643
|
+
addRuntimeTypeDeps(t)
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
addRuntimeTypeDeps(alias.Rhs())
|
|
647
|
+
return
|
|
648
|
+
}
|
|
649
|
+
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
650
|
+
addObject(named.Obj(), true)
|
|
651
|
+
for method := range named.Methods() {
|
|
652
|
+
addObject(method, true)
|
|
653
|
+
}
|
|
654
|
+
methodSet := types.NewMethodSet(types.NewPointer(named))
|
|
655
|
+
for method := range methodSet.Methods() {
|
|
656
|
+
addObject(method.Obj(), true)
|
|
657
|
+
}
|
|
658
|
+
if args := named.TypeArgs(); args != nil {
|
|
659
|
+
for t := range args.Types() {
|
|
660
|
+
addRuntimeTypeDeps(t)
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return
|
|
664
|
+
}
|
|
665
|
+
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
666
|
+
case *types.Pointer:
|
|
667
|
+
addRuntimeTypeDeps(typed.Elem())
|
|
668
|
+
case *types.Slice:
|
|
669
|
+
addRuntimeTypeDeps(typed.Elem())
|
|
670
|
+
case *types.Array:
|
|
671
|
+
addRuntimeTypeDeps(typed.Elem())
|
|
672
|
+
case *types.Map:
|
|
673
|
+
addRuntimeTypeDeps(typed.Key())
|
|
674
|
+
addRuntimeTypeDeps(typed.Elem())
|
|
675
|
+
case *types.Chan:
|
|
676
|
+
addRuntimeTypeDeps(typed.Elem())
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
addRuntimeTypeOwnerDeps = func(typ types.Type) {
|
|
680
|
+
if typ == nil {
|
|
681
|
+
return
|
|
682
|
+
}
|
|
683
|
+
if alias, ok := typ.(*types.Alias); ok {
|
|
684
|
+
addObject(alias.Obj(), true)
|
|
685
|
+
if args := alias.TypeArgs(); args != nil {
|
|
686
|
+
for t := range args.Types() {
|
|
687
|
+
addRuntimeTypeOwnerDeps(t)
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
addRuntimeTypeOwnerDeps(alias.Rhs())
|
|
691
|
+
return
|
|
692
|
+
}
|
|
693
|
+
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
694
|
+
addObject(named.Obj(), true)
|
|
695
|
+
if args := named.TypeArgs(); args != nil {
|
|
696
|
+
for t := range args.Types() {
|
|
697
|
+
addRuntimeTypeOwnerDeps(t)
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
return
|
|
701
|
+
}
|
|
702
|
+
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
703
|
+
case *types.Pointer:
|
|
704
|
+
addRuntimeTypeOwnerDeps(typed.Elem())
|
|
705
|
+
case *types.Slice:
|
|
706
|
+
addRuntimeTypeOwnerDeps(typed.Elem())
|
|
707
|
+
case *types.Array:
|
|
708
|
+
addRuntimeTypeOwnerDeps(typed.Elem())
|
|
709
|
+
case *types.Map:
|
|
710
|
+
addRuntimeTypeOwnerDeps(typed.Key())
|
|
711
|
+
addRuntimeTypeOwnerDeps(typed.Elem())
|
|
712
|
+
case *types.Chan:
|
|
713
|
+
addRuntimeTypeOwnerDeps(typed.Elem())
|
|
714
|
+
}
|
|
715
|
+
}
|
|
583
716
|
inspect := func(node ast.Node) bool {
|
|
584
717
|
switch typed := node.(type) {
|
|
718
|
+
case *ast.ValueSpec:
|
|
719
|
+
if len(typed.Values) == 0 && typed.Type != nil {
|
|
720
|
+
addRuntimeTypeDeps(semPkg.source.TypesInfo.TypeOf(typed.Type))
|
|
721
|
+
}
|
|
585
722
|
case *ast.Ident:
|
|
586
723
|
if obj := semPkg.source.TypesInfo.Defs[typed]; obj != nil {
|
|
587
724
|
if _, ok := obj.(*types.PkgName); !ok {
|
|
@@ -591,18 +728,46 @@ func (o *LoweringOwner) analyzeLocalFileReferences(
|
|
|
591
728
|
}
|
|
592
729
|
}
|
|
593
730
|
}
|
|
594
|
-
|
|
731
|
+
if tv, ok := semPkg.source.TypesInfo.Types[typed]; ok && tv.IsValue() {
|
|
732
|
+
addObject(semPkg.source.TypesInfo.Uses[typed], true)
|
|
733
|
+
}
|
|
595
734
|
addTypeDeps(semPkg.source.TypesInfo.TypeOf(typed))
|
|
596
735
|
case *ast.SelectorExpr:
|
|
597
736
|
if selection := semPkg.source.TypesInfo.Selections[typed]; selection != nil {
|
|
598
|
-
|
|
737
|
+
switch selection.Kind() {
|
|
738
|
+
case types.FieldVal, types.MethodVal, types.MethodExpr:
|
|
739
|
+
addObject(selection.Obj(), true)
|
|
740
|
+
if selection.Kind() != types.FieldVal {
|
|
741
|
+
addRuntimeTypeOwnerDeps(selection.Recv())
|
|
742
|
+
}
|
|
743
|
+
default:
|
|
744
|
+
addObject(selection.Obj(), false)
|
|
745
|
+
}
|
|
599
746
|
addTypeDeps(selection.Obj().Type())
|
|
600
747
|
} else if obj := semPkg.source.TypesInfo.Uses[typed.Sel]; obj != nil {
|
|
748
|
+
if tv, ok := semPkg.source.TypesInfo.Types[typed]; ok && tv.IsValue() {
|
|
749
|
+
addObject(obj, true)
|
|
750
|
+
}
|
|
601
751
|
addTypeDeps(obj.Type())
|
|
602
752
|
}
|
|
603
753
|
if pointer, ok := types.Unalias(semPkg.source.TypesInfo.TypeOf(typed.X)).Underlying().(*types.Pointer); ok {
|
|
604
754
|
addTypeDeps(pointer.Elem())
|
|
605
755
|
}
|
|
756
|
+
case *ast.CompositeLit:
|
|
757
|
+
addRuntimeTypeDeps(semPkg.source.TypesInfo.TypeOf(typed))
|
|
758
|
+
addCompositeInterfaceValueDeps(semPkg.source.TypesInfo, typed, addRuntimeTypeDeps)
|
|
759
|
+
case *ast.CallExpr:
|
|
760
|
+
if ident, ok := ast.Unparen(typed.Fun).(*ast.Ident); ok && ident.Name == "new" {
|
|
761
|
+
for _, arg := range typed.Args {
|
|
762
|
+
addRuntimeTypeDeps(semPkg.source.TypesInfo.TypeOf(arg))
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if ident, ok := ast.Unparen(typed.Fun).(*ast.Ident); ok && ident.Name == "make" && len(typed.Args) != 0 {
|
|
766
|
+
addRuntimeTypeDeps(semPkg.source.TypesInfo.TypeOf(typed.Args[0]))
|
|
767
|
+
}
|
|
768
|
+
addReflectTypeForRuntimeDeps(semPkg.source.TypesInfo, typed, addRuntimeTypeDeps)
|
|
769
|
+
addInterfaceArgumentRuntimeDeps(semPkg.source.TypesInfo, typed, addRuntimeTypeDeps)
|
|
770
|
+
addRuntimeTypeDeps(semPkg.source.TypesInfo.TypeOf(typed.Fun))
|
|
606
771
|
}
|
|
607
772
|
return true
|
|
608
773
|
}
|
|
@@ -613,6 +778,162 @@ func (o *LoweringOwner) analyzeLocalFileReferences(
|
|
|
613
778
|
return analysis
|
|
614
779
|
}
|
|
615
780
|
|
|
781
|
+
func addInterfaceArgumentRuntimeDeps(
|
|
782
|
+
info *types.Info,
|
|
783
|
+
call *ast.CallExpr,
|
|
784
|
+
addRuntimeTypeDeps func(types.Type),
|
|
785
|
+
) {
|
|
786
|
+
if info == nil || call == nil {
|
|
787
|
+
return
|
|
788
|
+
}
|
|
789
|
+
signature, _ := types.Unalias(info.TypeOf(call.Fun)).(*types.Signature)
|
|
790
|
+
if signature == nil || signature.Params() == nil {
|
|
791
|
+
return
|
|
792
|
+
}
|
|
793
|
+
params := signature.Params()
|
|
794
|
+
for idx, arg := range call.Args {
|
|
795
|
+
paramIdx := idx
|
|
796
|
+
if signature.Variadic() && paramIdx >= params.Len()-1 {
|
|
797
|
+
paramIdx = params.Len() - 1
|
|
798
|
+
}
|
|
799
|
+
if paramIdx < 0 || paramIdx >= params.Len() {
|
|
800
|
+
continue
|
|
801
|
+
}
|
|
802
|
+
paramType := params.At(paramIdx).Type()
|
|
803
|
+
if signature.Variadic() && idx >= params.Len()-1 {
|
|
804
|
+
if slice, ok := types.Unalias(paramType).Underlying().(*types.Slice); ok {
|
|
805
|
+
paramType = slice.Elem()
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
if typeIsInterface(paramType) {
|
|
809
|
+
addRuntimeTypeDeps(info.TypeOf(arg))
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
func addReflectTypeForRuntimeDeps(
|
|
815
|
+
info *types.Info,
|
|
816
|
+
call *ast.CallExpr,
|
|
817
|
+
addRuntimeTypeDeps func(types.Type),
|
|
818
|
+
) {
|
|
819
|
+
if info == nil || call == nil || !isReflectTypeForExpr(info, call.Fun) {
|
|
820
|
+
return
|
|
821
|
+
}
|
|
822
|
+
switch typed := ast.Unparen(call.Fun).(type) {
|
|
823
|
+
case *ast.IndexExpr:
|
|
824
|
+
addRuntimeTypeDeps(info.TypeOf(typed.Index))
|
|
825
|
+
case *ast.IndexListExpr:
|
|
826
|
+
for _, index := range typed.Indices {
|
|
827
|
+
addRuntimeTypeDeps(info.TypeOf(index))
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
func isReflectTypeForExpr(info *types.Info, expr ast.Expr) bool {
|
|
833
|
+
var base ast.Expr
|
|
834
|
+
switch typed := ast.Unparen(expr).(type) {
|
|
835
|
+
case *ast.IndexExpr:
|
|
836
|
+
base = typed.X
|
|
837
|
+
case *ast.IndexListExpr:
|
|
838
|
+
base = typed.X
|
|
839
|
+
default:
|
|
840
|
+
return false
|
|
841
|
+
}
|
|
842
|
+
selector, ok := ast.Unparen(base).(*ast.SelectorExpr)
|
|
843
|
+
if !ok || selector.Sel.Name != "TypeFor" {
|
|
844
|
+
return false
|
|
845
|
+
}
|
|
846
|
+
ident, ok := ast.Unparen(selector.X).(*ast.Ident)
|
|
847
|
+
if !ok {
|
|
848
|
+
return false
|
|
849
|
+
}
|
|
850
|
+
pkgName, _ := info.Uses[ident].(*types.PkgName)
|
|
851
|
+
return pkgName != nil && pkgName.Imported() != nil && pkgName.Imported().Path() == "reflect"
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
func addCompositeInterfaceValueDeps(
|
|
855
|
+
info *types.Info,
|
|
856
|
+
lit *ast.CompositeLit,
|
|
857
|
+
addRuntimeTypeDeps func(types.Type),
|
|
858
|
+
) {
|
|
859
|
+
if info == nil || lit == nil {
|
|
860
|
+
return
|
|
861
|
+
}
|
|
862
|
+
typ := types.Unalias(info.TypeOf(lit))
|
|
863
|
+
if pointer, ok := typ.Underlying().(*types.Pointer); ok {
|
|
864
|
+
typ = types.Unalias(pointer.Elem())
|
|
865
|
+
}
|
|
866
|
+
switch typed := typ.Underlying().(type) {
|
|
867
|
+
case *types.Array:
|
|
868
|
+
addCompositeElementsRuntimeDeps(info, lit.Elts, typed.Elem(), addRuntimeTypeDeps)
|
|
869
|
+
case *types.Slice:
|
|
870
|
+
addCompositeElementsRuntimeDeps(info, lit.Elts, typed.Elem(), addRuntimeTypeDeps)
|
|
871
|
+
case *types.Map:
|
|
872
|
+
for _, elt := range lit.Elts {
|
|
873
|
+
keyValue, ok := elt.(*ast.KeyValueExpr)
|
|
874
|
+
if !ok {
|
|
875
|
+
continue
|
|
876
|
+
}
|
|
877
|
+
if typeIsInterface(typed.Key()) {
|
|
878
|
+
addRuntimeTypeDeps(info.TypeOf(keyValue.Key))
|
|
879
|
+
}
|
|
880
|
+
if typeIsInterface(typed.Elem()) {
|
|
881
|
+
addRuntimeTypeDeps(info.TypeOf(keyValue.Value))
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
case *types.Struct:
|
|
885
|
+
nextField := 0
|
|
886
|
+
for _, elt := range lit.Elts {
|
|
887
|
+
fieldIdx := nextField
|
|
888
|
+
value := elt
|
|
889
|
+
if keyValue, ok := elt.(*ast.KeyValueExpr); ok {
|
|
890
|
+
value = keyValue.Value
|
|
891
|
+
if ident, ok := keyValue.Key.(*ast.Ident); ok {
|
|
892
|
+
for idx := range typed.NumFields() {
|
|
893
|
+
if typed.Field(idx).Name() == ident.Name {
|
|
894
|
+
fieldIdx = idx
|
|
895
|
+
break
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
} else {
|
|
900
|
+
nextField++
|
|
901
|
+
}
|
|
902
|
+
if fieldIdx < 0 || fieldIdx >= typed.NumFields() {
|
|
903
|
+
continue
|
|
904
|
+
}
|
|
905
|
+
if typeIsInterface(typed.Field(fieldIdx).Type()) {
|
|
906
|
+
addRuntimeTypeDeps(info.TypeOf(value))
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
func addCompositeElementsRuntimeDeps(
|
|
913
|
+
info *types.Info,
|
|
914
|
+
elements []ast.Expr,
|
|
915
|
+
elemType types.Type,
|
|
916
|
+
addRuntimeTypeDeps func(types.Type),
|
|
917
|
+
) {
|
|
918
|
+
if !typeIsInterface(elemType) {
|
|
919
|
+
return
|
|
920
|
+
}
|
|
921
|
+
for _, elt := range elements {
|
|
922
|
+
if keyValue, ok := elt.(*ast.KeyValueExpr); ok {
|
|
923
|
+
elt = keyValue.Value
|
|
924
|
+
}
|
|
925
|
+
addRuntimeTypeDeps(info.TypeOf(elt))
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
func typeIsInterface(typ types.Type) bool {
|
|
930
|
+
if typ == nil {
|
|
931
|
+
return false
|
|
932
|
+
}
|
|
933
|
+
_, ok := types.Unalias(typ).Underlying().(*types.Interface)
|
|
934
|
+
return ok
|
|
935
|
+
}
|
|
936
|
+
|
|
616
937
|
func safeIdentifier(value string) string {
|
|
617
938
|
var b strings.Builder
|
|
618
939
|
for idx, r := range value {
|
|
@@ -803,7 +1124,7 @@ func isConstGenDecl(decl ast.Decl) bool {
|
|
|
803
1124
|
}
|
|
804
1125
|
|
|
805
1126
|
func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([]loweredDecl, []Diagnostic) {
|
|
806
|
-
|
|
1127
|
+
decls := make([]loweredDecl, 0, len(decl.Specs))
|
|
807
1128
|
var diagnostics []Diagnostic
|
|
808
1129
|
for _, spec := range decl.Specs {
|
|
809
1130
|
switch typed := spec.(type) {
|
|
@@ -868,8 +1189,8 @@ func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([
|
|
|
868
1189
|
lazy := ctx.topLevel && ctx.lazyPackageVars[obj]
|
|
869
1190
|
code := keyword + " " + declName + ": " + variableType + " = " + value
|
|
870
1191
|
if lazy {
|
|
871
|
-
keyword = "
|
|
872
|
-
code = "
|
|
1192
|
+
keyword = "var"
|
|
1193
|
+
code = "var " + declName + ": " + variableType
|
|
873
1194
|
}
|
|
874
1195
|
indexExport := ""
|
|
875
1196
|
if ctx.topLevel && name.Name != "_" {
|
|
@@ -881,19 +1202,27 @@ func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([
|
|
|
881
1202
|
decls = append(decls, loweredDecl{code: code, indexExport: indexExport})
|
|
882
1203
|
if lazy {
|
|
883
1204
|
getterName := packageVarGetterName(name.Name)
|
|
1205
|
+
initName := packageVarInitName(name.Name)
|
|
1206
|
+
initIndexExport := ""
|
|
1207
|
+
if ast.IsExported(name.Name) {
|
|
1208
|
+
initIndexExport = initName
|
|
1209
|
+
}
|
|
884
1210
|
getterCode := "export function " + getterName + "(): " + variableType + " {\n\t"
|
|
885
1211
|
if strings.Contains(value, "await ") {
|
|
886
|
-
|
|
887
|
-
initCode := "async function " + initName + "(): globalThis.Promise<void> {\n\t" +
|
|
1212
|
+
initCode := "export async function " + initName + "(): globalThis.Promise<void> {\n\t" +
|
|
888
1213
|
"if (((" + declName + ") as any) === undefined) {\n\t\t" +
|
|
889
1214
|
declName + " = " + value + "\n\t}\n}"
|
|
890
|
-
decls = append(decls, loweredDecl{code: initCode})
|
|
1215
|
+
decls = append(decls, loweredDecl{code: initCode, indexExport: initIndexExport})
|
|
891
1216
|
decls = append(decls, loweredDecl{packageInitCall: initName + "()"})
|
|
892
1217
|
getterCode += "if (((" + declName + ") as any) === undefined) {\n\t\t" +
|
|
893
1218
|
"throw new Error(" + strconv.Quote("goscript package variable "+name.Name+" read before initialization") + ")\n\t}\n"
|
|
894
1219
|
} else {
|
|
1220
|
+
initCode := "export function " + initName + "(): void {\n\t" +
|
|
1221
|
+
"if (((" + declName + ") as any) === undefined) {\n\t\t" +
|
|
1222
|
+
declName + " = " + value + "\n\t}\n}"
|
|
1223
|
+
decls = append(decls, loweredDecl{code: initCode, indexExport: initIndexExport})
|
|
895
1224
|
getterCode += "if (((" + declName + ") as any) === undefined) {\n\t\t" +
|
|
896
|
-
|
|
1225
|
+
initName + "()\n\t}\n"
|
|
897
1226
|
}
|
|
898
1227
|
getterCode += "\treturn " + declName + "\n}"
|
|
899
1228
|
getterIndexExport := ""
|
|
@@ -907,10 +1236,15 @@ func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([
|
|
|
907
1236
|
setterType := o.tsPackageVarSetterValueTypeFor(ctx, obj.Type())
|
|
908
1237
|
setterTarget := declName
|
|
909
1238
|
if ctx.model.needsVarRef[obj] {
|
|
910
|
-
|
|
1239
|
+
if lazy {
|
|
1240
|
+
setterTarget = packageVarGetterName(name.Name) + "().value"
|
|
1241
|
+
} else {
|
|
1242
|
+
setterTarget += ".value"
|
|
1243
|
+
}
|
|
911
1244
|
}
|
|
912
|
-
|
|
913
|
-
|
|
1245
|
+
setterValue := "__goscriptValue"
|
|
1246
|
+
setterCode := "export function " + setterName + "(" + setterValue + ": " + setterType + "): void {\n\t" +
|
|
1247
|
+
setterTarget + " = " + setterValue + "\n}"
|
|
914
1248
|
setterIndexExport := ""
|
|
915
1249
|
if ast.IsExported(name.Name) {
|
|
916
1250
|
setterIndexExport = setterName
|
|
@@ -964,6 +1298,9 @@ func initializerMayHaveRuntimeEffects(ctx lowerFileContext, expr ast.Expr) bool
|
|
|
964
1298
|
}
|
|
965
1299
|
switch typed := node.(type) {
|
|
966
1300
|
case *ast.CallExpr:
|
|
1301
|
+
if isEffectFreePackageInitializerCall(ctx, typed) {
|
|
1302
|
+
return true
|
|
1303
|
+
}
|
|
967
1304
|
if callTargetSignature(ctx, typed.Fun) != nil {
|
|
968
1305
|
hasEffects = true
|
|
969
1306
|
return false
|
|
@@ -979,11 +1316,93 @@ func initializerMayHaveRuntimeEffects(ctx lowerFileContext, expr ast.Expr) bool
|
|
|
979
1316
|
return hasEffects
|
|
980
1317
|
}
|
|
981
1318
|
|
|
1319
|
+
func isEffectFreePackageInitializerCall(ctx lowerFileContext, call *ast.CallExpr) bool {
|
|
1320
|
+
if call == nil {
|
|
1321
|
+
return false
|
|
1322
|
+
}
|
|
1323
|
+
if isEffectFreePackageInitializerBuiltin(ctx, call.Fun) {
|
|
1324
|
+
return true
|
|
1325
|
+
}
|
|
1326
|
+
if isReflectTypeOfCall(ctx, call) {
|
|
1327
|
+
return true
|
|
1328
|
+
}
|
|
1329
|
+
if isReflectTypeForCall(ctx, call) {
|
|
1330
|
+
return true
|
|
1331
|
+
}
|
|
1332
|
+
if isMathBigNewIntCall(ctx, call) {
|
|
1333
|
+
return true
|
|
1334
|
+
}
|
|
1335
|
+
selector, ok := ast.Unparen(call.Fun).(*ast.SelectorExpr)
|
|
1336
|
+
if !ok || selector.Sel.Name != "Elem" {
|
|
1337
|
+
return false
|
|
1338
|
+
}
|
|
1339
|
+
receiver, ok := ast.Unparen(selector.X).(*ast.CallExpr)
|
|
1340
|
+
return ok && isReflectTypeOfCall(ctx, receiver)
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
func isEffectFreePackageInitializerBuiltin(ctx lowerFileContext, expr ast.Expr) bool {
|
|
1344
|
+
ident, ok := expr.(*ast.Ident)
|
|
1345
|
+
if !ok {
|
|
1346
|
+
return false
|
|
1347
|
+
}
|
|
1348
|
+
if ident.Name != "make" && ident.Name != "new" {
|
|
1349
|
+
return false
|
|
1350
|
+
}
|
|
1351
|
+
_, ok = objectForIdent(ctx, ident).(*types.Builtin)
|
|
1352
|
+
return ok
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
func isReflectTypeOfCall(ctx lowerFileContext, call *ast.CallExpr) bool {
|
|
1356
|
+
selector, ok := ast.Unparen(call.Fun).(*ast.SelectorExpr)
|
|
1357
|
+
if !ok || selector.Sel.Name != "TypeOf" {
|
|
1358
|
+
return false
|
|
1359
|
+
}
|
|
1360
|
+
ident, ok := ast.Unparen(selector.X).(*ast.Ident)
|
|
1361
|
+
if !ok {
|
|
1362
|
+
return false
|
|
1363
|
+
}
|
|
1364
|
+
pkgName, _ := objectForIdent(ctx, ident).(*types.PkgName)
|
|
1365
|
+
return pkgName != nil && pkgName.Imported() != nil && pkgName.Imported().Path() == "reflect"
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
func isReflectTypeForCall(ctx lowerFileContext, call *ast.CallExpr) bool {
|
|
1369
|
+
fun := ast.Unparen(call.Fun)
|
|
1370
|
+
switch typed := fun.(type) {
|
|
1371
|
+
case *ast.IndexExpr:
|
|
1372
|
+
fun = ast.Unparen(typed.X)
|
|
1373
|
+
case *ast.IndexListExpr:
|
|
1374
|
+
fun = ast.Unparen(typed.X)
|
|
1375
|
+
}
|
|
1376
|
+
selector, ok := fun.(*ast.SelectorExpr)
|
|
1377
|
+
if !ok || selector.Sel.Name != "TypeFor" {
|
|
1378
|
+
return false
|
|
1379
|
+
}
|
|
1380
|
+
ident, ok := ast.Unparen(selector.X).(*ast.Ident)
|
|
1381
|
+
if !ok {
|
|
1382
|
+
return false
|
|
1383
|
+
}
|
|
1384
|
+
pkgName, _ := objectForIdent(ctx, ident).(*types.PkgName)
|
|
1385
|
+
return pkgName != nil && pkgName.Imported() != nil && pkgName.Imported().Path() == "reflect"
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
func isMathBigNewIntCall(ctx lowerFileContext, call *ast.CallExpr) bool {
|
|
1389
|
+
selector, ok := ast.Unparen(call.Fun).(*ast.SelectorExpr)
|
|
1390
|
+
if !ok || selector.Sel.Name != "NewInt" {
|
|
1391
|
+
return false
|
|
1392
|
+
}
|
|
1393
|
+
ident, ok := ast.Unparen(selector.X).(*ast.Ident)
|
|
1394
|
+
if !ok {
|
|
1395
|
+
return false
|
|
1396
|
+
}
|
|
1397
|
+
pkgName, _ := objectForIdent(ctx, ident).(*types.PkgName)
|
|
1398
|
+
return pkgName != nil && pkgName.Imported() != nil && pkgName.Imported().Path() == "math/big"
|
|
1399
|
+
}
|
|
1400
|
+
|
|
982
1401
|
func packageDeclFiles(semPkg *semanticPackage) map[types.Object]string {
|
|
983
1402
|
if semPkg == nil || semPkg.source == nil {
|
|
984
1403
|
return nil
|
|
985
1404
|
}
|
|
986
|
-
declFiles := make(map[types.Object]string)
|
|
1405
|
+
declFiles := make(map[types.Object]string, len(semPkg.declarations))
|
|
987
1406
|
for _, decl := range semPkg.declarations {
|
|
988
1407
|
if decl.object != nil && decl.position.file != "" {
|
|
989
1408
|
declFiles[decl.object] = decl.position.file
|
|
@@ -1012,6 +1431,7 @@ func (o *LoweringOwner) lazyPackageVars(semPkg *semanticPackage, declFiles map[t
|
|
|
1012
1431
|
for idx, obj := range semPkg.initOrder {
|
|
1013
1432
|
varOrder[obj] = idx
|
|
1014
1433
|
}
|
|
1434
|
+
funcRefs := packageVarsReferencedFromOtherFileTopLevelCalls(semPkg, declFiles)
|
|
1015
1435
|
lazy := make(map[types.Object]bool)
|
|
1016
1436
|
for idx, file := range semPkg.source.Syntax {
|
|
1017
1437
|
sourcePath := sourceFilePath(semPkg, idx, file)
|
|
@@ -1048,6 +1468,12 @@ func (o *LoweringOwner) lazyPackageVars(semPkg *semanticPackage, declFiles map[t
|
|
|
1048
1468
|
if valueIdx >= len(valueSpec.Values) &&
|
|
1049
1469
|
zeroValueReferencesOtherFileObject(semPkg, declFiles, sourcePath, obj.Type()) {
|
|
1050
1470
|
lazy[obj] = true
|
|
1471
|
+
continue
|
|
1472
|
+
}
|
|
1473
|
+
if funcRefs[obj] &&
|
|
1474
|
+
(valueIdx >= len(valueSpec.Values) ||
|
|
1475
|
+
!initializerMayHaveRuntimeEffects(lowerFileContext{semPkg: semPkg}, valueSpec.Values[valueIdx])) {
|
|
1476
|
+
lazy[obj] = true
|
|
1051
1477
|
}
|
|
1052
1478
|
}
|
|
1053
1479
|
}
|
|
@@ -1056,6 +1482,178 @@ func (o *LoweringOwner) lazyPackageVars(semPkg *semanticPackage, declFiles map[t
|
|
|
1056
1482
|
return lazy
|
|
1057
1483
|
}
|
|
1058
1484
|
|
|
1485
|
+
func packageVarsReferencedFromOtherFileTopLevelCalls(
|
|
1486
|
+
semPkg *semanticPackage,
|
|
1487
|
+
declFiles map[types.Object]string,
|
|
1488
|
+
) map[*types.Var]bool {
|
|
1489
|
+
refs := make(map[*types.Var]bool)
|
|
1490
|
+
if semPkg == nil || semPkg.source == nil || semPkg.source.TypesInfo == nil {
|
|
1491
|
+
return refs
|
|
1492
|
+
}
|
|
1493
|
+
var collectFuncRefs func(rootSource string, fn *types.Func, seen map[*types.Func]bool)
|
|
1494
|
+
collectFuncRefs = func(rootSource string, fn *types.Func, seen map[*types.Func]bool) {
|
|
1495
|
+
if fn == nil || seen[fn] {
|
|
1496
|
+
return
|
|
1497
|
+
}
|
|
1498
|
+
seen[fn] = true
|
|
1499
|
+
decl := functionDeclForObject(semPkg, fn)
|
|
1500
|
+
if decl == nil || decl.Body == nil {
|
|
1501
|
+
return
|
|
1502
|
+
}
|
|
1503
|
+
ast.Inspect(decl.Body, func(node ast.Node) bool {
|
|
1504
|
+
switch typed := node.(type) {
|
|
1505
|
+
case *ast.Ident:
|
|
1506
|
+
obj, _ := semPkg.source.TypesInfo.Uses[typed].(*types.Var)
|
|
1507
|
+
if obj == nil || obj.Pkg() == nil || obj.Pkg().Path() != semPkg.pkgPath {
|
|
1508
|
+
return true
|
|
1509
|
+
}
|
|
1510
|
+
if declFiles[obj] != "" && declFiles[obj] != rootSource {
|
|
1511
|
+
refs[obj] = true
|
|
1512
|
+
}
|
|
1513
|
+
case *ast.CallExpr:
|
|
1514
|
+
called := calledFunction(semPkg.source, typed.Fun)
|
|
1515
|
+
if called != nil && called.Pkg() != nil && called.Pkg().Path() == semPkg.pkgPath {
|
|
1516
|
+
collectFuncRefs(rootSource, called, seen)
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
return true
|
|
1520
|
+
})
|
|
1521
|
+
}
|
|
1522
|
+
for _, file := range semPkg.source.Syntax {
|
|
1523
|
+
sourcePath := sourcePos(semPkg.source, file.Pos()).file
|
|
1524
|
+
for _, decl := range file.Decls {
|
|
1525
|
+
switch typed := decl.(type) {
|
|
1526
|
+
case *ast.GenDecl:
|
|
1527
|
+
if typed.Tok != token.VAR {
|
|
1528
|
+
continue
|
|
1529
|
+
}
|
|
1530
|
+
for _, spec := range typed.Specs {
|
|
1531
|
+
valueSpec, ok := spec.(*ast.ValueSpec)
|
|
1532
|
+
if !ok {
|
|
1533
|
+
continue
|
|
1534
|
+
}
|
|
1535
|
+
for _, value := range valueSpec.Values {
|
|
1536
|
+
collectTopLevelRefs(semPkg, declFiles, refs, sourcePath, value, collectFuncRefs)
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
case *ast.FuncDecl:
|
|
1540
|
+
if typed.Name.Name == "init" && typed.Body != nil {
|
|
1541
|
+
collectTopLevelRefs(semPkg, declFiles, refs, sourcePath, typed.Body, collectFuncRefs)
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
return refs
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
func collectTopLevelRefs(
|
|
1550
|
+
semPkg *semanticPackage,
|
|
1551
|
+
declFiles map[types.Object]string,
|
|
1552
|
+
refs map[*types.Var]bool,
|
|
1553
|
+
sourcePath string,
|
|
1554
|
+
node ast.Node,
|
|
1555
|
+
collectFuncRefs func(string, *types.Func, map[*types.Func]bool),
|
|
1556
|
+
) {
|
|
1557
|
+
ast.Inspect(node, func(node ast.Node) bool {
|
|
1558
|
+
switch typed := node.(type) {
|
|
1559
|
+
case *ast.Ident:
|
|
1560
|
+
obj, _ := semPkg.source.TypesInfo.Uses[typed].(*types.Var)
|
|
1561
|
+
if obj == nil || obj.Pkg() == nil || obj.Pkg().Path() != semPkg.pkgPath {
|
|
1562
|
+
return true
|
|
1563
|
+
}
|
|
1564
|
+
if declFiles[obj] != "" && declFiles[obj] != sourcePath {
|
|
1565
|
+
refs[obj] = true
|
|
1566
|
+
}
|
|
1567
|
+
case *ast.CallExpr:
|
|
1568
|
+
called := calledFunction(semPkg.source, typed.Fun)
|
|
1569
|
+
if called == nil || called.Pkg() == nil || called.Pkg().Path() != semPkg.pkgPath {
|
|
1570
|
+
return true
|
|
1571
|
+
}
|
|
1572
|
+
collectFuncRefs(sourcePath, called, make(map[*types.Func]bool))
|
|
1573
|
+
}
|
|
1574
|
+
return true
|
|
1575
|
+
})
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
func (o *LoweringOwner) packageVarIsLazy(ctx lowerFileContext, obj *types.Var) bool {
|
|
1579
|
+
if obj == nil {
|
|
1580
|
+
return false
|
|
1581
|
+
}
|
|
1582
|
+
if ctx.lazyPackageVars[obj] {
|
|
1583
|
+
return true
|
|
1584
|
+
}
|
|
1585
|
+
if ctx.model == nil || obj.Pkg() == nil {
|
|
1586
|
+
return false
|
|
1587
|
+
}
|
|
1588
|
+
semPkg := ctx.model.packages[obj.Pkg().Path()]
|
|
1589
|
+
if semPkg == nil {
|
|
1590
|
+
return false
|
|
1591
|
+
}
|
|
1592
|
+
for lazyObj := range o.lazyPackageVars(semPkg, packageDeclFiles(semPkg)) {
|
|
1593
|
+
if lazyObj != nil && lazyObj.Name() == obj.Name() &&
|
|
1594
|
+
lazyObj.Pkg() != nil && lazyObj.Pkg().Path() == obj.Pkg().Path() {
|
|
1595
|
+
return true
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
return false
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
func (o *LoweringOwner) packageVarNameIsLazy(ctx lowerFileContext, pkgPath, name string) bool {
|
|
1602
|
+
if ctx.model == nil || pkgPath == "" || name == "" {
|
|
1603
|
+
return false
|
|
1604
|
+
}
|
|
1605
|
+
semPkg := ctx.model.packages[pkgPath]
|
|
1606
|
+
if semPkg == nil {
|
|
1607
|
+
return false
|
|
1608
|
+
}
|
|
1609
|
+
for lazyObj := range o.lazyPackageVars(semPkg, packageDeclFiles(semPkg)) {
|
|
1610
|
+
if lazyObj != nil && lazyObj.Name() == name {
|
|
1611
|
+
return true
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
return false
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
func (o *LoweringOwner) packageVarHasAsyncLazyInit(ctx lowerFileContext, obj types.Object) bool {
|
|
1618
|
+
varObj, _ := obj.(*types.Var)
|
|
1619
|
+
if varObj == nil || varObj.Pkg() == nil {
|
|
1620
|
+
return false
|
|
1621
|
+
}
|
|
1622
|
+
return o.packageVarNameHasAsyncLazyInit(ctx, varObj.Pkg().Path(), varObj.Name())
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
func (o *LoweringOwner) packageVarNameHasAsyncLazyInit(ctx lowerFileContext, pkgPath, name string) bool {
|
|
1626
|
+
if ctx.model == nil || pkgPath == "" || name == "" {
|
|
1627
|
+
return false
|
|
1628
|
+
}
|
|
1629
|
+
semPkg := ctx.model.packages[pkgPath]
|
|
1630
|
+
if semPkg == nil || semPkg.source == nil {
|
|
1631
|
+
return false
|
|
1632
|
+
}
|
|
1633
|
+
initCtx := lowerFileContext{model: ctx.model, semPkg: semPkg, topLevel: true}
|
|
1634
|
+
for _, file := range semPkg.source.Syntax {
|
|
1635
|
+
for _, decl := range file.Decls {
|
|
1636
|
+
genDecl, ok := decl.(*ast.GenDecl)
|
|
1637
|
+
if !ok || genDecl.Tok != token.VAR {
|
|
1638
|
+
continue
|
|
1639
|
+
}
|
|
1640
|
+
for _, spec := range genDecl.Specs {
|
|
1641
|
+
valueSpec, ok := spec.(*ast.ValueSpec)
|
|
1642
|
+
if !ok {
|
|
1643
|
+
continue
|
|
1644
|
+
}
|
|
1645
|
+
for idx, ident := range valueSpec.Names {
|
|
1646
|
+
if ident.Name != name || idx >= len(valueSpec.Values) {
|
|
1647
|
+
continue
|
|
1648
|
+
}
|
|
1649
|
+
return o.topLevelInitializerNeedsAwait(initCtx, valueSpec.Values[idx])
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
return false
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1059
1657
|
func initializerReferencesLaterPackageVar(
|
|
1060
1658
|
semPkg *semanticPackage,
|
|
1061
1659
|
varOrder map[types.Object]int,
|
|
@@ -1278,7 +1876,7 @@ func (o *LoweringOwner) lowerTupleValueSpec(
|
|
|
1278
1876
|
tupleExpr := tempName
|
|
1279
1877
|
if lazyTuple {
|
|
1280
1878
|
tupleGetterName := packageVarGetterName(tempName)
|
|
1281
|
-
decls = append(decls, loweredDecl{code: "
|
|
1879
|
+
decls = append(decls, loweredDecl{code: "var " + tempName + ": any = undefined as any"})
|
|
1282
1880
|
decls = append(decls, loweredDecl{code: "function " + tupleGetterName + "(): any {\n\t" +
|
|
1283
1881
|
"if (((" + tempName + ") as any) === undefined) {\n\t\t" +
|
|
1284
1882
|
tempName + " = " + right + "\n\t}\n\treturn " + tempName + "\n}"})
|
|
@@ -1303,8 +1901,8 @@ func (o *LoweringOwner) lowerTupleValueSpec(
|
|
|
1303
1901
|
code := keyword + " " + o.lowerIdent(ctx, name, true) + ": " + variableType + " = " + value
|
|
1304
1902
|
lazy := lazyTuple || ctx.topLevel && ctx.lazyPackageVars[obj]
|
|
1305
1903
|
if lazy {
|
|
1306
|
-
keyword = "
|
|
1307
|
-
code = "
|
|
1904
|
+
keyword = "var"
|
|
1905
|
+
code = "var " + o.lowerIdent(ctx, name, true) + ": " + variableType + " = undefined as unknown as " + variableType
|
|
1308
1906
|
}
|
|
1309
1907
|
indexExport := ""
|
|
1310
1908
|
if ctx.topLevel {
|
|
@@ -1364,6 +1962,13 @@ func lowerLargeIntegerConstantValue(value constant.Value) (string, bool) {
|
|
|
1364
1962
|
return value.ExactString(), true
|
|
1365
1963
|
}
|
|
1366
1964
|
|
|
1965
|
+
func lowerWideIntegerConstantValue(value constant.Value) (string, bool) {
|
|
1966
|
+
if value == nil || value.Kind() != constant.Int || constant.BitLen(value) <= 53 {
|
|
1967
|
+
return "", false
|
|
1968
|
+
}
|
|
1969
|
+
return value.ExactString(), true
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1367
1972
|
func lowerConstantStringByteSlice(ctx lowerFileContext, expr ast.Expr) (string, bool) {
|
|
1368
1973
|
value := ctx.semPkg.source.TypesInfo.Types[unwrapParenExpr(expr)].Value
|
|
1369
1974
|
if value == nil || value.Kind() != constant.String {
|
|
@@ -1397,46 +2002,229 @@ func goEmbedPatterns(groups ...*ast.CommentGroup) []string {
|
|
|
1397
2002
|
if !strings.HasPrefix(text, "go:embed") {
|
|
1398
2003
|
continue
|
|
1399
2004
|
}
|
|
1400
|
-
patterns = append(patterns, strings.Fields(strings.TrimSpace(strings.TrimPrefix(text, "go:embed")))...)
|
|
2005
|
+
patterns = append(patterns, strings.Fields(strings.TrimSpace(strings.TrimPrefix(text, "go:embed")))...)
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
return patterns
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
func (o *LoweringOwner) lowerGoEmbedValue(
|
|
2012
|
+
ctx lowerFileContext,
|
|
2013
|
+
typ types.Type,
|
|
2014
|
+
patterns []string,
|
|
2015
|
+
) (string, []Diagnostic) {
|
|
2016
|
+
if isEmbedFSType(typ) {
|
|
2017
|
+
return o.lowerGoEmbedFSValue(ctx, patterns)
|
|
2018
|
+
}
|
|
2019
|
+
if len(patterns) != 1 {
|
|
2020
|
+
return "", []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern list")}
|
|
2021
|
+
}
|
|
2022
|
+
cleanPattern, diagnostics := cleanGoEmbedFilePattern(ctx, patterns[0])
|
|
2023
|
+
if len(diagnostics) != 0 {
|
|
2024
|
+
return "", diagnostics
|
|
2025
|
+
}
|
|
2026
|
+
data, diagnostics := readGoEmbedFile(ctx, cleanPattern)
|
|
2027
|
+
if len(diagnostics) != 0 {
|
|
2028
|
+
return "", diagnostics
|
|
2029
|
+
}
|
|
2030
|
+
if isStringType(typ) {
|
|
2031
|
+
return strconv.Quote(string(data)), nil
|
|
2032
|
+
}
|
|
2033
|
+
if slice, ok := types.Unalias(typ).Underlying().(*types.Slice); ok && isByteType(slice.Elem()) {
|
|
2034
|
+
return byteSliceLiteral(data), nil
|
|
2035
|
+
}
|
|
2036
|
+
diag := loweringUnsupported("declaration", ctx.semPkg.pkgPath, "unsupported go:embed target type")
|
|
2037
|
+
diag.Detail = "target type: " + types.TypeString(typ, func(pkg *types.Package) string {
|
|
2038
|
+
if pkg == nil {
|
|
2039
|
+
return ""
|
|
2040
|
+
}
|
|
2041
|
+
return pkg.Path()
|
|
2042
|
+
})
|
|
2043
|
+
return "", []Diagnostic{diag}
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
func (o *LoweringOwner) lowerGoEmbedFSValue(ctx lowerFileContext, patterns []string) (string, []Diagnostic) {
|
|
2047
|
+
embedAlias := ctx.importPaths["embed"]
|
|
2048
|
+
if embedAlias == "" {
|
|
2049
|
+
return "", []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "unsupported go:embed FS import")}
|
|
2050
|
+
}
|
|
2051
|
+
if len(patterns) == 0 {
|
|
2052
|
+
return "", []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern list")}
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
filesByPath := make(map[string][]byte)
|
|
2056
|
+
for _, pattern := range patterns {
|
|
2057
|
+
files, diagnostics := expandGoEmbedPattern(ctx, pattern)
|
|
2058
|
+
if len(diagnostics) != 0 {
|
|
2059
|
+
return "", diagnostics
|
|
2060
|
+
}
|
|
2061
|
+
for _, file := range files {
|
|
2062
|
+
filesByPath[file.path] = file.data
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
paths := make([]string, 0, len(filesByPath))
|
|
2066
|
+
for path := range filesByPath {
|
|
2067
|
+
paths = append(paths, path)
|
|
2068
|
+
}
|
|
2069
|
+
slices.Sort(paths)
|
|
2070
|
+
entries := make([]string, 0, len(paths))
|
|
2071
|
+
for _, path := range paths {
|
|
2072
|
+
entries = append(entries, "["+strconv.Quote(path)+", "+byteSliceLiteral(filesByPath[path])+"]")
|
|
2073
|
+
}
|
|
2074
|
+
builtinAlias := o.runtimeOwner.BuiltinImport().Alias
|
|
2075
|
+
return builtinAlias + ".markAsStructValue(new " + embedAlias + ".FS(new Map<string, Uint8Array>([" + strings.Join(entries, ", ") + "])))", nil
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
type goEmbedFile struct {
|
|
2079
|
+
path string
|
|
2080
|
+
data []byte
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
func cleanGoEmbedFilePattern(ctx lowerFileContext, pattern string) (string, []Diagnostic) {
|
|
2084
|
+
cleanPattern, _, diagnostics := cleanGoEmbedPattern(ctx, pattern)
|
|
2085
|
+
if len(diagnostics) != 0 {
|
|
2086
|
+
return "", diagnostics
|
|
2087
|
+
}
|
|
2088
|
+
if strings.Contains(cleanPattern, "*") {
|
|
2089
|
+
return "", []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern")}
|
|
2090
|
+
}
|
|
2091
|
+
info, err := os.Stat(filepath.Join(filepath.Dir(ctx.sourcePath), filepath.FromSlash(cleanPattern)))
|
|
2092
|
+
if err != nil {
|
|
2093
|
+
return "", []Diagnostic{goEmbedReadDiagnostic(ctx, err)}
|
|
2094
|
+
}
|
|
2095
|
+
if info.IsDir() {
|
|
2096
|
+
return "", []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "unsupported go:embed directory target")}
|
|
2097
|
+
}
|
|
2098
|
+
return cleanPattern, nil
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
func cleanGoEmbedPattern(ctx lowerFileContext, pattern string) (string, bool, []Diagnostic) {
|
|
2102
|
+
pattern = strings.Trim(pattern, "`\"")
|
|
2103
|
+
all := false
|
|
2104
|
+
if strings.HasPrefix(pattern, "all:") {
|
|
2105
|
+
all = true
|
|
2106
|
+
pattern = strings.TrimPrefix(pattern, "all:")
|
|
2107
|
+
}
|
|
2108
|
+
cleanPattern := path.Clean(pattern)
|
|
2109
|
+
if pattern == "" ||
|
|
2110
|
+
path.IsAbs(pattern) ||
|
|
2111
|
+
cleanPattern == "." ||
|
|
2112
|
+
cleanPattern == ".." ||
|
|
2113
|
+
strings.HasPrefix(cleanPattern, "../") {
|
|
2114
|
+
return "", false, []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern")}
|
|
2115
|
+
}
|
|
2116
|
+
return cleanPattern, all, nil
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
func expandGoEmbedPattern(ctx lowerFileContext, pattern string) ([]goEmbedFile, []Diagnostic) {
|
|
2120
|
+
cleanPattern, all, diagnostics := cleanGoEmbedPattern(ctx, pattern)
|
|
2121
|
+
if len(diagnostics) != 0 {
|
|
2122
|
+
return nil, diagnostics
|
|
2123
|
+
}
|
|
2124
|
+
pkgDir := filepath.Dir(ctx.sourcePath)
|
|
2125
|
+
paths := []string{filepath.Join(pkgDir, filepath.FromSlash(cleanPattern))}
|
|
2126
|
+
if strings.Contains(cleanPattern, "*") {
|
|
2127
|
+
matches, err := filepath.Glob(filepath.Join(pkgDir, filepath.FromSlash(cleanPattern)))
|
|
2128
|
+
if err != nil {
|
|
2129
|
+
return nil, []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern")}
|
|
2130
|
+
}
|
|
2131
|
+
if len(matches) == 0 {
|
|
2132
|
+
return nil, []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "go:embed pattern matched no files")}
|
|
2133
|
+
}
|
|
2134
|
+
paths = matches
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
var files []goEmbedFile
|
|
2138
|
+
for _, path := range paths {
|
|
2139
|
+
collected, diagnostics := collectGoEmbedPath(ctx, pkgDir, path, all)
|
|
2140
|
+
if len(diagnostics) != 0 {
|
|
2141
|
+
return nil, diagnostics
|
|
2142
|
+
}
|
|
2143
|
+
files = append(files, collected...)
|
|
2144
|
+
}
|
|
2145
|
+
slices.SortFunc(files, func(a, b goEmbedFile) int {
|
|
2146
|
+
return cmp.Compare(a.path, b.path)
|
|
2147
|
+
})
|
|
2148
|
+
return files, nil
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
func collectGoEmbedPath(ctx lowerFileContext, pkgDir, absPath string, all bool) ([]goEmbedFile, []Diagnostic) {
|
|
2152
|
+
info, err := os.Stat(absPath)
|
|
2153
|
+
if err != nil {
|
|
2154
|
+
return nil, []Diagnostic{goEmbedReadDiagnostic(ctx, err)}
|
|
2155
|
+
}
|
|
2156
|
+
if !info.IsDir() {
|
|
2157
|
+
file, diagnostics := readGoEmbedAbsFile(ctx, pkgDir, absPath)
|
|
2158
|
+
if len(diagnostics) != 0 {
|
|
2159
|
+
return nil, diagnostics
|
|
2160
|
+
}
|
|
2161
|
+
return []goEmbedFile{file}, nil
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
var files []goEmbedFile
|
|
2165
|
+
if err := filepath.WalkDir(absPath, func(path string, entry os.DirEntry, err error) error {
|
|
2166
|
+
if err != nil {
|
|
2167
|
+
return err
|
|
2168
|
+
}
|
|
2169
|
+
if path != absPath && !all && (strings.HasPrefix(entry.Name(), ".") || strings.HasPrefix(entry.Name(), "_")) {
|
|
2170
|
+
if entry.IsDir() {
|
|
2171
|
+
return filepath.SkipDir
|
|
2172
|
+
}
|
|
2173
|
+
return nil
|
|
2174
|
+
}
|
|
2175
|
+
if entry.IsDir() {
|
|
2176
|
+
return nil
|
|
2177
|
+
}
|
|
2178
|
+
file, diagnostics := readGoEmbedAbsFile(ctx, pkgDir, path)
|
|
2179
|
+
if len(diagnostics) != 0 {
|
|
2180
|
+
return fmt.Errorf("%s", diagnostics[0].Detail)
|
|
1401
2181
|
}
|
|
2182
|
+
files = append(files, file)
|
|
2183
|
+
return nil
|
|
2184
|
+
}); err != nil {
|
|
2185
|
+
return nil, []Diagnostic{goEmbedReadDiagnostic(ctx, err)}
|
|
1402
2186
|
}
|
|
1403
|
-
|
|
2187
|
+
if len(files) == 0 {
|
|
2188
|
+
return nil, []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "go:embed directory matched no files")}
|
|
2189
|
+
}
|
|
2190
|
+
return files, nil
|
|
1404
2191
|
}
|
|
1405
2192
|
|
|
1406
|
-
func (
|
|
1407
|
-
ctx
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
) (string, []Diagnostic) {
|
|
1411
|
-
if len(patterns) != 1 {
|
|
1412
|
-
return "", []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern list")}
|
|
2193
|
+
func readGoEmbedFile(ctx lowerFileContext, cleanPattern string) ([]byte, []Diagnostic) {
|
|
2194
|
+
file, diagnostics := readGoEmbedAbsFile(ctx, filepath.Dir(ctx.sourcePath), filepath.Join(filepath.Dir(ctx.sourcePath), filepath.FromSlash(cleanPattern)))
|
|
2195
|
+
if len(diagnostics) != 0 {
|
|
2196
|
+
return nil, diagnostics
|
|
1413
2197
|
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
strings.HasPrefix(cleanPattern, "../") {
|
|
1422
|
-
return "", []Diagnostic{loweringUnsupported("declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern")}
|
|
2198
|
+
return file.data, nil
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
func readGoEmbedAbsFile(ctx lowerFileContext, pkgDir, absPath string) (goEmbedFile, []Diagnostic) {
|
|
2202
|
+
relPath, err := filepath.Rel(pkgDir, absPath)
|
|
2203
|
+
if err != nil {
|
|
2204
|
+
return goEmbedFile{}, []Diagnostic{goEmbedReadDiagnostic(ctx, err)}
|
|
1423
2205
|
}
|
|
1424
|
-
data, err := os.ReadFile(
|
|
2206
|
+
data, err := os.ReadFile(absPath)
|
|
1425
2207
|
if err != nil {
|
|
1426
|
-
return
|
|
1427
|
-
Severity: DiagnosticSeverityError,
|
|
1428
|
-
Code: "goscript/lowering:embed",
|
|
1429
|
-
Message: "failed to read go:embed file",
|
|
1430
|
-
Detail: ctx.semPkg.pkgPath + ": " + err.Error(),
|
|
1431
|
-
}}
|
|
2208
|
+
return goEmbedFile{}, []Diagnostic{goEmbedReadDiagnostic(ctx, err)}
|
|
1432
2209
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
2210
|
+
return goEmbedFile{path: filepath.ToSlash(relPath), data: data}, nil
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
func goEmbedReadDiagnostic(ctx lowerFileContext, err error) Diagnostic {
|
|
2214
|
+
return Diagnostic{
|
|
2215
|
+
Severity: DiagnosticSeverityError,
|
|
2216
|
+
Code: "goscript/lowering:embed",
|
|
2217
|
+
Message: "failed to read go:embed file",
|
|
2218
|
+
Detail: ctx.semPkg.pkgPath + ": " + err.Error(),
|
|
1435
2219
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
func isEmbedFSType(typ types.Type) bool {
|
|
2223
|
+
named, _ := types.Unalias(typ).(*types.Named)
|
|
2224
|
+
if named == nil || named.Obj() == nil || named.Obj().Pkg() == nil {
|
|
2225
|
+
return false
|
|
1438
2226
|
}
|
|
1439
|
-
return
|
|
2227
|
+
return named.Obj().Pkg().Path() == "embed" && named.Obj().Name() == "FS"
|
|
1440
2228
|
}
|
|
1441
2229
|
|
|
1442
2230
|
func byteSliceLiteral(data []byte) string {
|
|
@@ -1493,12 +2281,13 @@ func (o *LoweringOwner) lowerTypeSpec(ctx lowerFileContext, spec *ast.TypeSpec)
|
|
|
1493
2281
|
if signature, ok := named.Underlying().(*types.Signature); ok {
|
|
1494
2282
|
loweredType = o.tsAsyncCompatibleFunctionTypeFor(ctx, signature)
|
|
1495
2283
|
}
|
|
1496
|
-
|
|
2284
|
+
typeName := safeIdentifier(semType.name)
|
|
2285
|
+
code := "type " + typeName + " = " + loweredType
|
|
1497
2286
|
typeIndexExport := ""
|
|
1498
2287
|
if ctx.topLevel {
|
|
1499
2288
|
code = "export " + code
|
|
1500
2289
|
if ast.IsExported(semType.name) {
|
|
1501
|
-
typeIndexExport =
|
|
2290
|
+
typeIndexExport = typeName
|
|
1502
2291
|
}
|
|
1503
2292
|
}
|
|
1504
2293
|
return loweredDecl{code: code, typeIndexExport: typeIndexExport}, nil
|
|
@@ -1506,12 +2295,13 @@ func (o *LoweringOwner) lowerTypeSpec(ctx lowerFileContext, spec *ast.TypeSpec)
|
|
|
1506
2295
|
|
|
1507
2296
|
func (o *LoweringOwner) lowerInterfaceType(ctx lowerFileContext, semType *semanticType, iface *types.Interface) loweredDecl {
|
|
1508
2297
|
iface.Complete()
|
|
1509
|
-
|
|
2298
|
+
typeName := safeIdentifier(semType.name)
|
|
2299
|
+
code := "type " + typeName + " = " + o.tsInterfaceType(ctx, iface)
|
|
1510
2300
|
typeIndexExport := ""
|
|
1511
2301
|
if ctx.topLevel {
|
|
1512
2302
|
code = "export " + code
|
|
1513
2303
|
if ast.IsExported(semType.name) {
|
|
1514
|
-
typeIndexExport =
|
|
2304
|
+
typeIndexExport = typeName
|
|
1515
2305
|
}
|
|
1516
2306
|
}
|
|
1517
2307
|
code = code + "\n\n" + o.runtimeOwner.QualifiedHelper(RuntimeHelperRegisterInterfaceType) +
|
|
@@ -1599,9 +2389,10 @@ func (o *LoweringOwner) lowerStructType(ctx lowerFileContext, semType *semanticT
|
|
|
1599
2389
|
lowered := &loweredStruct{
|
|
1600
2390
|
exported: ctx.topLevel,
|
|
1601
2391
|
indexExported: ctx.topLevel && ast.IsExported(semType.name),
|
|
1602
|
-
name: semType.name,
|
|
2392
|
+
name: safeIdentifier(semType.name),
|
|
1603
2393
|
typeName: runtimeNamedTypeName(semType.named),
|
|
1604
2394
|
cloneMethod: "clone",
|
|
2395
|
+
fields: make([]loweredStructField, 0, len(semType.fields)),
|
|
1605
2396
|
}
|
|
1606
2397
|
for idx, field := range semType.fields {
|
|
1607
2398
|
structValue := isStructValueType(field.typ)
|
|
@@ -1628,9 +2419,12 @@ func (o *LoweringOwner) lowerStructType(ctx lowerFileContext, semType *semanticT
|
|
|
1628
2419
|
|
|
1629
2420
|
methodDecls := o.methodDeclsForType(ctx, semType.named)
|
|
1630
2421
|
explicitMethods := make(map[string]bool, len(methodDecls))
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
2422
|
+
if len(methodDecls) != 0 {
|
|
2423
|
+
lowered.methods = make([]loweredFunction, 0, len(methodDecls))
|
|
2424
|
+
for _, methodDecl := range methodDecls {
|
|
2425
|
+
if methodDecl != nil {
|
|
2426
|
+
explicitMethods[methodDecl.Name.Name] = true
|
|
2427
|
+
}
|
|
1634
2428
|
}
|
|
1635
2429
|
}
|
|
1636
2430
|
var diagnostics []Diagnostic
|
|
@@ -2434,105 +3228,113 @@ func (o *LoweringOwner) lowerStmtListAfter(
|
|
|
2434
3228
|
) ([]loweredStmt, []Diagnostic) {
|
|
2435
3229
|
lowered := make([]loweredStmt, 0, len(stmts))
|
|
2436
3230
|
var diagnostics []Diagnostic
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
group.
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
3231
|
+
hasGoto := stmtListHasGoto(stmts)
|
|
3232
|
+
var gotoSpans map[string]int
|
|
3233
|
+
var gotoLabels map[string]bool
|
|
3234
|
+
var forwardStarts map[int]forwardGotoLabelSpan
|
|
3235
|
+
if hasGoto {
|
|
3236
|
+
gotoSpans = backwardGotoLabelSpans(stmts)
|
|
3237
|
+
gotoLabels = make(map[string]bool, len(gotoSpans))
|
|
3238
|
+
for label := range gotoSpans {
|
|
3239
|
+
gotoLabels[label] = true
|
|
3240
|
+
}
|
|
3241
|
+
forwardSpans := forwardGotoLabelSpans(stmts, gotoSpans)
|
|
3242
|
+
forwardStarts = make(map[int]forwardGotoLabelSpan, len(forwardSpans))
|
|
3243
|
+
for label, span := range forwardSpans {
|
|
3244
|
+
span.label = label
|
|
3245
|
+
group := forwardStarts[span.start]
|
|
3246
|
+
if group.forwardLabels == nil {
|
|
3247
|
+
group.forwardLabels = make(map[string]bool)
|
|
3248
|
+
}
|
|
3249
|
+
group.forwardLabels[label] = true
|
|
3250
|
+
if group.label == "" || span.labelIdx > group.labelIdx {
|
|
3251
|
+
group.label = span.label
|
|
3252
|
+
group.start = span.start
|
|
3253
|
+
group.labelIdx = span.labelIdx
|
|
3254
|
+
}
|
|
3255
|
+
forwardStarts[span.start] = group
|
|
3256
|
+
}
|
|
2457
3257
|
}
|
|
2458
3258
|
for idx := 0; idx < len(stmts); idx++ {
|
|
2459
3259
|
stmt := stmts[idx]
|
|
2460
3260
|
startLine := sourceLine(ctx, stmt.Pos())
|
|
2461
3261
|
leading := leadingStmtLines(ctx, prevEndLine, startLine)
|
|
2462
|
-
if
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
}
|
|
2469
|
-
idx = cluster.endIdx
|
|
2470
|
-
continue
|
|
2471
|
-
}
|
|
2472
|
-
if span, ok := leadingGotoBackwardLoopSpan(stmts, idx, gotoSpans); ok {
|
|
2473
|
-
loop, loopDiagnostics := o.lowerBackwardGotoLoop(
|
|
2474
|
-
ctx,
|
|
2475
|
-
gotoLabels,
|
|
2476
|
-
span.label,
|
|
2477
|
-
span.labelIdx,
|
|
2478
|
-
span.endIdx,
|
|
2479
|
-
span.forwardLabel,
|
|
2480
|
-
stmts,
|
|
2481
|
-
leading,
|
|
2482
|
-
)
|
|
2483
|
-
diagnostics = append(diagnostics, loopDiagnostics...)
|
|
2484
|
-
lowered = append(lowered, loop...)
|
|
2485
|
-
if endLine := sourceLine(ctx, stmts[span.endIdx].End()); endLine != 0 {
|
|
2486
|
-
prevEndLine = endLine
|
|
2487
|
-
}
|
|
2488
|
-
idx = span.endIdx
|
|
2489
|
-
continue
|
|
2490
|
-
}
|
|
2491
|
-
if span, ok := forwardStarts[idx]; ok {
|
|
2492
|
-
bodyStmts := stmts[idx:span.labelIdx]
|
|
2493
|
-
body, bodyDiagnostics := o.lowerStmtListAfter(
|
|
2494
|
-
ctx.withForwardGotos(span.forwardLabels),
|
|
2495
|
-
bodyStmts,
|
|
2496
|
-
prevEndLine,
|
|
2497
|
-
)
|
|
2498
|
-
diagnostics = append(diagnostics, bodyDiagnostics...)
|
|
2499
|
-
block := loweredStmt{hasBlock: true, text: span.label + ":", children: body}
|
|
2500
|
-
if len(leading) != 0 {
|
|
2501
|
-
block.leading = append(leading, block.leading...)
|
|
2502
|
-
}
|
|
2503
|
-
lowered = append(lowered, block)
|
|
2504
|
-
if labeled, ok := stmts[span.labelIdx].(*ast.LabeledStmt); ok {
|
|
2505
|
-
labelLowered, labelDiagnostics := o.lowerStmt(ctx, labeled.Stmt)
|
|
2506
|
-
diagnostics = append(diagnostics, labelDiagnostics...)
|
|
2507
|
-
lowered = append(lowered, labelLowered...)
|
|
2508
|
-
if endLine := sourceLine(ctx, labeled.End()); endLine != 0 {
|
|
3262
|
+
if hasGoto {
|
|
3263
|
+
if cluster, ok := gotoStateClusterAt(stmts, idx); ok {
|
|
3264
|
+
clusterLowered, clusterDiagnostics := o.lowerGotoStateCluster(ctx, stmts, cluster, leading)
|
|
3265
|
+
diagnostics = append(diagnostics, clusterDiagnostics...)
|
|
3266
|
+
lowered = append(lowered, clusterLowered...)
|
|
3267
|
+
if endLine := sourceLine(ctx, stmts[cluster.endIdx].End()); endLine != 0 {
|
|
2509
3268
|
prevEndLine = endLine
|
|
2510
3269
|
}
|
|
3270
|
+
idx = cluster.endIdx
|
|
3271
|
+
continue
|
|
2511
3272
|
}
|
|
2512
|
-
idx
|
|
2513
|
-
continue
|
|
2514
|
-
}
|
|
2515
|
-
if labeled, ok := stmt.(*ast.LabeledStmt); ok {
|
|
2516
|
-
label := safeIdentifier(labeled.Label.Name)
|
|
2517
|
-
if endIdx, ok := gotoSpans[label]; ok {
|
|
3273
|
+
if span, ok := leadingGotoBackwardLoopSpan(stmts, idx, gotoSpans); ok {
|
|
2518
3274
|
loop, loopDiagnostics := o.lowerBackwardGotoLoop(
|
|
2519
3275
|
ctx,
|
|
2520
3276
|
gotoLabels,
|
|
2521
|
-
label,
|
|
2522
|
-
|
|
2523
|
-
endIdx,
|
|
2524
|
-
|
|
3277
|
+
span.label,
|
|
3278
|
+
span.labelIdx,
|
|
3279
|
+
span.endIdx,
|
|
3280
|
+
span.forwardLabel,
|
|
2525
3281
|
stmts,
|
|
2526
3282
|
leading,
|
|
2527
3283
|
)
|
|
2528
3284
|
diagnostics = append(diagnostics, loopDiagnostics...)
|
|
2529
3285
|
lowered = append(lowered, loop...)
|
|
2530
|
-
if endLine := sourceLine(ctx, stmts[endIdx].End()); endLine != 0 {
|
|
3286
|
+
if endLine := sourceLine(ctx, stmts[span.endIdx].End()); endLine != 0 {
|
|
2531
3287
|
prevEndLine = endLine
|
|
2532
3288
|
}
|
|
2533
|
-
idx = endIdx
|
|
3289
|
+
idx = span.endIdx
|
|
3290
|
+
continue
|
|
3291
|
+
}
|
|
3292
|
+
if span, ok := forwardStarts[idx]; ok {
|
|
3293
|
+
bodyStmts := stmts[idx:span.labelIdx]
|
|
3294
|
+
body, bodyDiagnostics := o.lowerStmtListAfter(
|
|
3295
|
+
ctx.withForwardGotos(span.forwardLabels),
|
|
3296
|
+
bodyStmts,
|
|
3297
|
+
prevEndLine,
|
|
3298
|
+
)
|
|
3299
|
+
diagnostics = append(diagnostics, bodyDiagnostics...)
|
|
3300
|
+
block := loweredStmt{hasBlock: true, text: span.label + ":", children: body}
|
|
3301
|
+
if len(leading) != 0 {
|
|
3302
|
+
block.leading = append(leading, block.leading...)
|
|
3303
|
+
}
|
|
3304
|
+
lowered = append(lowered, block)
|
|
3305
|
+
if labeled, ok := stmts[span.labelIdx].(*ast.LabeledStmt); ok {
|
|
3306
|
+
labelLowered, labelDiagnostics := o.lowerStmt(ctx, labeled.Stmt)
|
|
3307
|
+
diagnostics = append(diagnostics, labelDiagnostics...)
|
|
3308
|
+
lowered = append(lowered, labelLowered...)
|
|
3309
|
+
if endLine := sourceLine(ctx, labeled.End()); endLine != 0 {
|
|
3310
|
+
prevEndLine = endLine
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
idx = span.labelIdx
|
|
2534
3314
|
continue
|
|
2535
3315
|
}
|
|
3316
|
+
if labeled, ok := stmt.(*ast.LabeledStmt); ok {
|
|
3317
|
+
label := safeIdentifier(labeled.Label.Name)
|
|
3318
|
+
if endIdx, ok := gotoSpans[label]; ok {
|
|
3319
|
+
loop, loopDiagnostics := o.lowerBackwardGotoLoop(
|
|
3320
|
+
ctx,
|
|
3321
|
+
gotoLabels,
|
|
3322
|
+
label,
|
|
3323
|
+
idx,
|
|
3324
|
+
endIdx,
|
|
3325
|
+
"",
|
|
3326
|
+
stmts,
|
|
3327
|
+
leading,
|
|
3328
|
+
)
|
|
3329
|
+
diagnostics = append(diagnostics, loopDiagnostics...)
|
|
3330
|
+
lowered = append(lowered, loop...)
|
|
3331
|
+
if endLine := sourceLine(ctx, stmts[endIdx].End()); endLine != 0 {
|
|
3332
|
+
prevEndLine = endLine
|
|
3333
|
+
}
|
|
3334
|
+
idx = endIdx
|
|
3335
|
+
continue
|
|
3336
|
+
}
|
|
3337
|
+
}
|
|
2536
3338
|
}
|
|
2537
3339
|
if stmtCtx, nextCtx, ok := o.lowerDeclStatementContext(ctx, stmt); ok {
|
|
2538
3340
|
stmtLowered, stmtDiagnostics := o.lowerStmt(stmtCtx, stmt)
|
|
@@ -2604,7 +3406,7 @@ func (o *LoweringOwner) lowerDeclStatementContext(
|
|
|
2604
3406
|
if def == nil || aliases[def] != "" {
|
|
2605
3407
|
continue
|
|
2606
3408
|
}
|
|
2607
|
-
if shortDeclDefShadowsOuterName(name.Name, def) {
|
|
3409
|
+
if shortDeclDefShadowsOuterName(ctx, name.Name, def) || valueSpecUsesOuterName(ctx, valueSpec, name.Name, def) {
|
|
2608
3410
|
aliases[def] = ctx.tempName("Shadow")
|
|
2609
3411
|
}
|
|
2610
3412
|
}
|
|
@@ -2852,9 +3654,30 @@ type leadingGotoBackwardLoop struct {
|
|
|
2852
3654
|
}
|
|
2853
3655
|
|
|
2854
3656
|
func stmtListNeedsLoopBranchLabel(stmts []ast.Stmt) bool {
|
|
3657
|
+
if !stmtListHasGoto(stmts) {
|
|
3658
|
+
return false
|
|
3659
|
+
}
|
|
2855
3660
|
return len(backwardGotoLabelSpans(stmts)) != 0
|
|
2856
3661
|
}
|
|
2857
3662
|
|
|
3663
|
+
func stmtListHasGoto(stmts []ast.Stmt) bool {
|
|
3664
|
+
for _, stmt := range stmts {
|
|
3665
|
+
hasGoto := false
|
|
3666
|
+
ast.Inspect(stmt, func(node ast.Node) bool {
|
|
3667
|
+
branch, ok := node.(*ast.BranchStmt)
|
|
3668
|
+
if ok && branch.Tok == token.GOTO && branch.Label != nil {
|
|
3669
|
+
hasGoto = true
|
|
3670
|
+
return false
|
|
3671
|
+
}
|
|
3672
|
+
return !hasGoto
|
|
3673
|
+
})
|
|
3674
|
+
if hasGoto {
|
|
3675
|
+
return true
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
return false
|
|
3679
|
+
}
|
|
3680
|
+
|
|
2858
3681
|
func backwardGotoLabelSpans(stmts []ast.Stmt) map[string]int {
|
|
2859
3682
|
seenLabels := make(map[string]bool)
|
|
2860
3683
|
spans := make(map[string]int)
|
|
@@ -3134,15 +3957,11 @@ func (o *LoweringOwner) lowerAssignStmt(ctx lowerFileContext, stmt *ast.AssignSt
|
|
|
3134
3957
|
if starTarget && stmt.Tok != token.DEFINE {
|
|
3135
3958
|
pointer, pointerDiagnostics := o.lowerPointerStorageExpr(ctx, star.X)
|
|
3136
3959
|
diagnostics = append(diagnostics, pointerDiagnostics...)
|
|
3137
|
-
if stmt.Tok == token.AND_NOT_ASSIGN {
|
|
3138
|
-
stmts = append(stmts, loweredStmt{text: pointer + " = " + pointer + " & ~(" + right + ")"})
|
|
3139
|
-
continue
|
|
3140
|
-
}
|
|
3141
3960
|
if value, ok := integerQuotientAssignExpr(targetType, pointer, right, stmt.Tok); ok {
|
|
3142
3961
|
stmts = append(stmts, loweredStmt{text: value})
|
|
3143
3962
|
continue
|
|
3144
3963
|
}
|
|
3145
|
-
stmts = append(stmts, loweredStmt{text: pointer + " " +
|
|
3964
|
+
stmts = append(stmts, loweredStmt{text: pointer + " = " + lowerCompoundAssignValue(o.runtimeOwner, targetType, pointer, right, stmt.Tok)})
|
|
3146
3965
|
continue
|
|
3147
3966
|
}
|
|
3148
3967
|
if isShortDecl {
|
|
@@ -3152,10 +3971,6 @@ func (o *LoweringOwner) lowerAssignStmt(ctx lowerFileContext, stmt *ast.AssignSt
|
|
|
3152
3971
|
stmts = append(stmts, loweredStmt{text: "let " + left + o.shortDeclTypeAnnotation(ctx, lhs, stmt.Rhs[idx]) + " = " + right})
|
|
3153
3972
|
continue
|
|
3154
3973
|
}
|
|
3155
|
-
if stmt.Tok == token.AND_NOT_ASSIGN {
|
|
3156
|
-
stmts = append(stmts, loweredStmt{text: left + " = " + left + " & ~(" + right + ")"})
|
|
3157
|
-
continue
|
|
3158
|
-
}
|
|
3159
3974
|
if helper, ok := wideIntegerAssignHelper(targetType, stmt.Tok); ok {
|
|
3160
3975
|
stmts = append(stmts, loweredStmt{text: left + " = " + o.runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")"})
|
|
3161
3976
|
continue
|
|
@@ -3168,6 +3983,10 @@ func (o *LoweringOwner) lowerAssignStmt(ctx lowerFileContext, stmt *ast.AssignSt
|
|
|
3168
3983
|
if stmt.Tok == token.DEFINE {
|
|
3169
3984
|
op = "="
|
|
3170
3985
|
}
|
|
3986
|
+
if stmt.Tok != token.ASSIGN && stmt.Tok != token.DEFINE {
|
|
3987
|
+
stmts = append(stmts, loweredStmt{text: left + " = " + lowerCompoundAssignValue(o.runtimeOwner, targetType, left, right, stmt.Tok)})
|
|
3988
|
+
continue
|
|
3989
|
+
}
|
|
3171
3990
|
stmts = append(stmts, loweredStmt{text: left + " " + op + " " + right})
|
|
3172
3991
|
}
|
|
3173
3992
|
return stmts, diagnostics
|
|
@@ -3210,6 +4029,7 @@ func lowerCompoundAssignValue(
|
|
|
3210
4029
|
if value, ok := integerQuotientAssignValueExpr(targetType, left, right, tok); ok {
|
|
3211
4030
|
return value
|
|
3212
4031
|
}
|
|
4032
|
+
right = "(" + right + ")"
|
|
3213
4033
|
switch tok {
|
|
3214
4034
|
case token.ADD_ASSIGN:
|
|
3215
4035
|
return left + " + " + right
|
|
@@ -3230,6 +4050,9 @@ func lowerCompoundAssignValue(
|
|
|
3230
4050
|
case token.SHL_ASSIGN:
|
|
3231
4051
|
return left + " << " + right
|
|
3232
4052
|
case token.SHR_ASSIGN:
|
|
4053
|
+
if bits, ok := unsignedIntegerBits(targetType); ok && bits <= 32 {
|
|
4054
|
+
return "(" + left + " >>> " + right + ") >>> 0"
|
|
4055
|
+
}
|
|
3233
4056
|
return left + " >> " + right
|
|
3234
4057
|
case token.AND_NOT_ASSIGN:
|
|
3235
4058
|
return left + " & ~(" + right + ")"
|
|
@@ -3266,30 +4089,31 @@ func integerQuotientAssignValueExpr(targetType types.Type, left string, right st
|
|
|
3266
4089
|
}
|
|
3267
4090
|
|
|
3268
4091
|
func wideIntegerAssignHelper(targetType types.Type, tok token.Token) (RuntimeHelper, bool) {
|
|
3269
|
-
if !
|
|
4092
|
+
if !isRuntimeWideIntegerType(targetType) {
|
|
3270
4093
|
return "", false
|
|
3271
4094
|
}
|
|
4095
|
+
signed := isFixedSignedWideIntegerType(targetType)
|
|
3272
4096
|
switch tok {
|
|
3273
4097
|
case token.SHL_ASSIGN:
|
|
3274
|
-
return RuntimeHelperUint64Shl, true
|
|
4098
|
+
return wideIntegerHelper(signed, RuntimeHelperUint64Shl, RuntimeHelperInt64Shl), true
|
|
3275
4099
|
case token.SHR_ASSIGN:
|
|
3276
|
-
return RuntimeHelperUint64Shr, true
|
|
4100
|
+
return wideIntegerHelper(signed, RuntimeHelperUint64Shr, RuntimeHelperInt64Shr), true
|
|
3277
4101
|
case token.MUL_ASSIGN:
|
|
3278
|
-
return wideIntegerHelper(
|
|
4102
|
+
return wideIntegerHelper(signed, RuntimeHelperUint64Mul, RuntimeHelperInt64Mul), true
|
|
3279
4103
|
case token.QUO_ASSIGN:
|
|
3280
|
-
return wideIntegerHelper(
|
|
4104
|
+
return wideIntegerHelper(signed, RuntimeHelperUint64Div, RuntimeHelperInt64Div), true
|
|
3281
4105
|
case token.REM_ASSIGN:
|
|
3282
|
-
return wideIntegerHelper(
|
|
4106
|
+
return wideIntegerHelper(signed, RuntimeHelperUint64Mod, RuntimeHelperInt64Mod), true
|
|
3283
4107
|
case token.ADD_ASSIGN:
|
|
3284
|
-
return wideIntegerHelper(
|
|
4108
|
+
return wideIntegerHelper(signed, RuntimeHelperUint64Add, RuntimeHelperInt64Add), true
|
|
3285
4109
|
case token.SUB_ASSIGN:
|
|
3286
|
-
return wideIntegerHelper(
|
|
4110
|
+
return wideIntegerHelper(signed, RuntimeHelperUint64Sub, RuntimeHelperInt64Sub), true
|
|
3287
4111
|
case token.AND_ASSIGN:
|
|
3288
|
-
return wideIntegerHelper(
|
|
4112
|
+
return wideIntegerHelper(signed, RuntimeHelperUint64And, RuntimeHelperInt64And), true
|
|
3289
4113
|
case token.OR_ASSIGN:
|
|
3290
|
-
return wideIntegerHelper(
|
|
4114
|
+
return wideIntegerHelper(signed, RuntimeHelperUint64Or, RuntimeHelperInt64Or), true
|
|
3291
4115
|
case token.XOR_ASSIGN:
|
|
3292
|
-
return wideIntegerHelper(
|
|
4116
|
+
return wideIntegerHelper(signed, RuntimeHelperUint64Xor, RuntimeHelperInt64Xor), true
|
|
3293
4117
|
default:
|
|
3294
4118
|
return "", false
|
|
3295
4119
|
}
|
|
@@ -3366,12 +4190,20 @@ func (o *LoweringOwner) shortDeclTypeAnnotation(ctx lowerFileContext, lhs ast.Ex
|
|
|
3366
4190
|
}
|
|
3367
4191
|
return ": " + typ
|
|
3368
4192
|
}
|
|
4193
|
+
if rhs != nil && isIdentLikeExpr(rhs) && isInterfaceType(obj.Type()) {
|
|
4194
|
+
return ": " + o.tsVariableTypeFor(ctx, obj.Type(), ctx.model.needsVarRef[obj])
|
|
4195
|
+
}
|
|
3369
4196
|
if !shortDeclNeedsTypeAnnotation(obj.Type()) {
|
|
3370
4197
|
return ""
|
|
3371
4198
|
}
|
|
3372
4199
|
return ": " + o.tsVariableTypeFor(ctx, obj.Type(), ctx.model.needsVarRef[obj])
|
|
3373
4200
|
}
|
|
3374
4201
|
|
|
4202
|
+
func isIdentLikeExpr(expr ast.Expr) bool {
|
|
4203
|
+
_, ok := ast.Unparen(expr).(*ast.Ident)
|
|
4204
|
+
return ok
|
|
4205
|
+
}
|
|
4206
|
+
|
|
3375
4207
|
func shortDeclNeedsTypeAnnotation(typ types.Type) bool {
|
|
3376
4208
|
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
3377
4209
|
case *types.Pointer:
|
|
@@ -3401,6 +4233,15 @@ func (o *LoweringOwner) lowerTupleTargetAssignmentStmt(
|
|
|
3401
4233
|
declare bool,
|
|
3402
4234
|
) (loweredStmt, []Diagnostic) {
|
|
3403
4235
|
if !declare {
|
|
4236
|
+
if index, ok := unwrapParenExpr(lhs).(*ast.IndexExpr); ok && isMapType(ctx.semPkg.source.TypesInfo.TypeOf(index.X)) {
|
|
4237
|
+
targetType := assignmentTargetType(ctx, lhs)
|
|
4238
|
+
value = o.lowerValueForTarget(ctx, lhs, targetType, value)
|
|
4239
|
+
stmts, diagnostics := o.lowerMapIndexUpdateStmts(ctx, index, token.ASSIGN, value, targetType)
|
|
4240
|
+
if len(stmts) != 0 {
|
|
4241
|
+
return stmts[0], diagnostics
|
|
4242
|
+
}
|
|
4243
|
+
return loweredStmt{}, diagnostics
|
|
4244
|
+
}
|
|
3404
4245
|
if stmt, diagnostics, ok := o.lowerStarTargetAssignmentStmt(ctx, lhs, value); ok {
|
|
3405
4246
|
return stmt, diagnostics
|
|
3406
4247
|
}
|
|
@@ -3555,7 +4396,7 @@ func (o *LoweringOwner) lowerShortDeclNewShadowAliases(
|
|
|
3555
4396
|
if entry.def == nil || aliases[entry.def] != "" {
|
|
3556
4397
|
continue
|
|
3557
4398
|
}
|
|
3558
|
-
if shortDeclDefShadowsOuterName(entry.name, entry.def) {
|
|
4399
|
+
if shortDeclDefShadowsOuterName(ctx, entry.name, entry.def) {
|
|
3559
4400
|
aliases[entry.def] = ctx.tempName("Shadow")
|
|
3560
4401
|
}
|
|
3561
4402
|
}
|
|
@@ -3584,12 +4425,24 @@ func shortDeclShadowNonValueIdents(ctx lowerFileContext, expr ast.Expr) map[*ast
|
|
|
3584
4425
|
return idents
|
|
3585
4426
|
}
|
|
3586
4427
|
|
|
3587
|
-
func shortDeclDefShadowsOuterName(name string, def types.Object) bool {
|
|
4428
|
+
func shortDeclDefShadowsOuterName(ctx lowerFileContext, name string, def types.Object) bool {
|
|
3588
4429
|
for scope := def.Parent(); scope != nil; scope = scope.Parent() {
|
|
3589
4430
|
if scope == def.Parent() {
|
|
3590
4431
|
continue
|
|
3591
4432
|
}
|
|
3592
4433
|
obj := scope.Lookup(name)
|
|
4434
|
+
if scope.Parent() == types.Universe {
|
|
4435
|
+
if obj == nil {
|
|
4436
|
+
return false
|
|
4437
|
+
}
|
|
4438
|
+
if _, isTypeName := obj.(*types.TypeName); isTypeName {
|
|
4439
|
+
return true
|
|
4440
|
+
}
|
|
4441
|
+
if _, isFunc := obj.(*types.Func); isFunc {
|
|
4442
|
+
return sameSourceFile(ctx, obj.Pos(), def.Pos()) && obj.Pos() < def.Pos()
|
|
4443
|
+
}
|
|
4444
|
+
return false
|
|
4445
|
+
}
|
|
3593
4446
|
if obj != nil && obj.Pos().IsValid() && obj.Pos() < def.Pos() {
|
|
3594
4447
|
return true
|
|
3595
4448
|
}
|
|
@@ -3597,6 +4450,40 @@ func shortDeclDefShadowsOuterName(name string, def types.Object) bool {
|
|
|
3597
4450
|
return false
|
|
3598
4451
|
}
|
|
3599
4452
|
|
|
4453
|
+
func sameSourceFile(ctx lowerFileContext, left token.Pos, right token.Pos) bool {
|
|
4454
|
+
if !left.IsValid() || !right.IsValid() || ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
4455
|
+
return false
|
|
4456
|
+
}
|
|
4457
|
+
leftPos := sourcePos(ctx.semPkg.source, left)
|
|
4458
|
+
rightPos := sourcePos(ctx.semPkg.source, right)
|
|
4459
|
+
return leftPos.file != "" && leftPos.file == rightPos.file
|
|
4460
|
+
}
|
|
4461
|
+
|
|
4462
|
+
func valueSpecUsesOuterName(ctx lowerFileContext, spec *ast.ValueSpec, name string, def types.Object) bool {
|
|
4463
|
+
if spec == nil || name == "" || def == nil {
|
|
4464
|
+
return false
|
|
4465
|
+
}
|
|
4466
|
+
usesOuter := false
|
|
4467
|
+
for _, value := range spec.Values {
|
|
4468
|
+
ast.Inspect(value, func(node ast.Node) bool {
|
|
4469
|
+
ident, ok := node.(*ast.Ident)
|
|
4470
|
+
if !ok || ident.Name != name {
|
|
4471
|
+
return true
|
|
4472
|
+
}
|
|
4473
|
+
obj := ctx.semPkg.source.TypesInfo.Uses[ident]
|
|
4474
|
+
if obj != nil && obj != def {
|
|
4475
|
+
usesOuter = true
|
|
4476
|
+
return false
|
|
4477
|
+
}
|
|
4478
|
+
return true
|
|
4479
|
+
})
|
|
4480
|
+
if usesOuter {
|
|
4481
|
+
return true
|
|
4482
|
+
}
|
|
4483
|
+
}
|
|
4484
|
+
return false
|
|
4485
|
+
}
|
|
4486
|
+
|
|
3600
4487
|
func (o *LoweringOwner) mapIndexDefaultUsesShortDeclName(
|
|
3601
4488
|
ctx lowerFileContext,
|
|
3602
4489
|
rhs ast.Expr,
|
|
@@ -4656,7 +5543,7 @@ func (o *LoweringOwner) lowerRangeFuncStmt(
|
|
|
4656
5543
|
diagnostics = append(diagnostics, assignmentDiagnostics...)
|
|
4657
5544
|
body = append(assignments, body...)
|
|
4658
5545
|
}
|
|
4659
|
-
async := ctx.asyncFunction
|
|
5546
|
+
async := ctx.asyncFunction || stmtsContainAwait(body) || o.rangeFunctionValueNeedsAwait(ctx, stmt.X)
|
|
4660
5547
|
|
|
4661
5548
|
return loweredStmt{rangeFunc: &loweredRangeFunc{
|
|
4662
5549
|
value: rangeValue,
|
|
@@ -5285,6 +6172,19 @@ func (o *LoweringOwner) lowerComplexEqualityExpr(ctx lowerFileContext, expr *ast
|
|
|
5285
6172
|
return value, true
|
|
5286
6173
|
}
|
|
5287
6174
|
|
|
6175
|
+
func (o *LoweringOwner) lowerStructEqualityExpr(ctx lowerFileContext, expr *ast.BinaryExpr, left string, right string) (string, bool) {
|
|
6176
|
+
leftType := ctx.semPkg.source.TypesInfo.TypeOf(expr.X)
|
|
6177
|
+
rightType := ctx.semPkg.source.TypesInfo.TypeOf(expr.Y)
|
|
6178
|
+
if !isStructComparableType(leftType) || !isStructComparableType(rightType) {
|
|
6179
|
+
return "", false
|
|
6180
|
+
}
|
|
6181
|
+
value := o.runtimeOwner.QualifiedHelper(RuntimeHelperComparableEqual) + "(" + left + ", " + right + ")"
|
|
6182
|
+
if expr.Op == token.NEQ {
|
|
6183
|
+
value = "!" + value
|
|
6184
|
+
}
|
|
6185
|
+
return value, true
|
|
6186
|
+
}
|
|
6187
|
+
|
|
5288
6188
|
func (o *LoweringOwner) lowerStringEqualityExpr(ctx lowerFileContext, expr *ast.BinaryExpr, left string, right string) (string, bool) {
|
|
5289
6189
|
leftType := ctx.semPkg.source.TypesInfo.TypeOf(expr.X)
|
|
5290
6190
|
rightType := ctx.semPkg.source.TypesInfo.TypeOf(expr.Y)
|
|
@@ -5413,6 +6313,9 @@ func (o *LoweringOwner) lowerExpr(ctx lowerFileContext, expr ast.Expr) (string,
|
|
|
5413
6313
|
if value, ok := o.lowerComplexEqualityExpr(ctx, typed, left, right); ok {
|
|
5414
6314
|
return value, append(leftDiagnostics, rightDiagnostics...)
|
|
5415
6315
|
}
|
|
6316
|
+
if value, ok := o.lowerStructEqualityExpr(ctx, typed, left, right); ok {
|
|
6317
|
+
return value, append(leftDiagnostics, rightDiagnostics...)
|
|
6318
|
+
}
|
|
5416
6319
|
if value, ok := o.lowerStringEqualityExpr(ctx, typed, left, right); ok {
|
|
5417
6320
|
return value, append(leftDiagnostics, rightDiagnostics...)
|
|
5418
6321
|
}
|
|
@@ -5456,6 +6359,10 @@ func (o *LoweringOwner) lowerExpr(ctx lowerFileContext, expr ast.Expr) (string,
|
|
|
5456
6359
|
return lowerPrefixUnaryExpr(typed.Op, value), diagnostics
|
|
5457
6360
|
}
|
|
5458
6361
|
if typed.Op == token.XOR {
|
|
6362
|
+
if bits, ok := unsignedIntegerBits(ctx.semPkg.source.TypesInfo.TypeOf(typed)); ok && bits <= 32 {
|
|
6363
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint) +
|
|
6364
|
+
"(~" + value + ", " + strconv.Itoa(bits) + ")", diagnostics
|
|
6365
|
+
}
|
|
5459
6366
|
return "~" + value, diagnostics
|
|
5460
6367
|
}
|
|
5461
6368
|
return value, append(diagnostics, loweringUnsupported("expression", ctx.semPkg.pkgPath, "unsupported unary operator"))
|
|
@@ -5538,7 +6445,7 @@ func isLegacyOctalLiteral(value string) bool {
|
|
|
5538
6445
|
func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (string, bool, []Diagnostic) {
|
|
5539
6446
|
signature, _ := ctx.semPkg.source.TypesInfo.TypeOf(lit).(*types.Signature)
|
|
5540
6447
|
deferState := &loweredDeferState{}
|
|
5541
|
-
bodyCtx := ctx.withSignature(signature).withDeferState(deferState).withoutRangeBranch()
|
|
6448
|
+
bodyCtx := ctx.withSignature(signature).withAsyncFunction(false).withDeferState(deferState).withoutRangeBranch()
|
|
5542
6449
|
asyncCompatibleParams := funcLiteralNeedsAsyncFunctionParamCalls(signature)
|
|
5543
6450
|
if asyncCompatibleParams || funcLiteralUsesFunctionIdentifierCall(ctx, lit) {
|
|
5544
6451
|
bodyCtx = bodyCtx.withAsyncFunction(true)
|
|
@@ -5659,7 +6566,7 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
|
|
|
5659
6566
|
}
|
|
5660
6567
|
return alias
|
|
5661
6568
|
}
|
|
5662
|
-
if constObj, ok := obj.(*types.Const); ok &&
|
|
6569
|
+
if constObj, ok := obj.(*types.Const); ok && !raw {
|
|
5663
6570
|
if constValue, ok := lowerConstantValue(constObj.Val()); ok {
|
|
5664
6571
|
return constValue
|
|
5665
6572
|
}
|
|
@@ -5667,6 +6574,9 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
|
|
|
5667
6574
|
if alias := ctx.localAliases[obj]; alias != "" {
|
|
5668
6575
|
if ctx.lazyPackageVars[obj] {
|
|
5669
6576
|
lazyValue := alias + "." + packageVarGetterName(value) + "()"
|
|
6577
|
+
if (ctx.asyncFunction || ctx.topLevel) && o.packageVarHasAsyncLazyInit(ctx, obj) {
|
|
6578
|
+
lazyValue = "(await " + alias + "." + packageVarInitName(value) + "(), " + lazyValue + ")"
|
|
6579
|
+
}
|
|
5670
6580
|
if raw {
|
|
5671
6581
|
return lazyValue
|
|
5672
6582
|
}
|
|
@@ -5682,6 +6592,9 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
|
|
|
5682
6592
|
}
|
|
5683
6593
|
if ctx.lazyPackageVars[obj] {
|
|
5684
6594
|
lazyValue := packageVarGetterName(value) + "()"
|
|
6595
|
+
if (ctx.asyncFunction || ctx.topLevel) && o.packageVarHasAsyncLazyInit(ctx, obj) {
|
|
6596
|
+
lazyValue = "(await " + packageVarInitName(value) + "(), " + lazyValue + ")"
|
|
6597
|
+
}
|
|
5685
6598
|
return o.lowerPackageVarReadValue(ctx, obj, lazyValue)
|
|
5686
6599
|
}
|
|
5687
6600
|
if obj != nil && ctx.model.needsVarRef[obj] {
|
|
@@ -6339,6 +7252,8 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
6339
7252
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperRunesToString) + "(" + value + ")", diagnostics
|
|
6340
7253
|
case isByteSliceType(sourceType):
|
|
6341
7254
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperBytesToString) + "(" + value + ")", diagnostics
|
|
7255
|
+
case overrideNamedStringType(ctx, o, sourceType):
|
|
7256
|
+
return "String(" + value + ")", diagnostics
|
|
6342
7257
|
case isStringType(sourceType):
|
|
6343
7258
|
return value, diagnostics
|
|
6344
7259
|
case isNumericType(sourceType):
|
|
@@ -6397,7 +7312,7 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
6397
7312
|
return renderNamedStructConversion(conversion), diagnostics
|
|
6398
7313
|
}
|
|
6399
7314
|
if isNumericType(targetType) {
|
|
6400
|
-
if constantValue, ok :=
|
|
7315
|
+
if constantValue, ok := o.lowerNumericConstantExprForTarget(ctx, expr.Args[0], targetType); ok {
|
|
6401
7316
|
return constantValue, diagnostics
|
|
6402
7317
|
}
|
|
6403
7318
|
}
|
|
@@ -6429,8 +7344,8 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
6429
7344
|
}
|
|
6430
7345
|
|
|
6431
7346
|
func (o *LoweringOwner) lowerWideIntegerBinaryExpr(ctx lowerFileContext, expr *ast.BinaryExpr, left string, right string) (string, bool) {
|
|
6432
|
-
resultWide :=
|
|
6433
|
-
leftWide :=
|
|
7347
|
+
resultWide := isRuntimeWideIntegerType(ctx.semPkg.source.TypesInfo.TypeOf(expr))
|
|
7348
|
+
leftWide := isRuntimeWideIntegerType(ctx.semPkg.source.TypesInfo.TypeOf(expr.X))
|
|
6434
7349
|
if !resultWide && !leftWide {
|
|
6435
7350
|
return "", false
|
|
6436
7351
|
}
|
|
@@ -6696,6 +7611,22 @@ func (o *LoweringOwner) lowerPointerReceiverMethodCall(
|
|
|
6696
7611
|
return "", nil, false
|
|
6697
7612
|
}
|
|
6698
7613
|
receiverExpr, diagnostics := o.lowerExpr(ctx, selector.X)
|
|
7614
|
+
if o.receiverUsesOverridePackage(signature.Recv().Type()) {
|
|
7615
|
+
receiverExpr = o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
7616
|
+
"<" + o.tsTypeFor(ctx, signature.Recv().Type().(*types.Pointer).Elem()) + ">(" + receiverExpr + ")"
|
|
7617
|
+
}
|
|
7618
|
+
if receiverExpr == o.namedTypeExpr(ctx, receiver) {
|
|
7619
|
+
call := o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
7620
|
+
"<" + o.namedTypeExpr(ctx, receiver) + ">(" + receiverExpr + ")." +
|
|
7621
|
+
methodMemberName(selector.Sel.Name) + "(" + strings.Join(args, ", ") + ")"
|
|
7622
|
+
return call, diagnostics, true
|
|
7623
|
+
}
|
|
7624
|
+
if crossPackageUnexportedNamedType(ctx, receiver) {
|
|
7625
|
+
call := o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
7626
|
+
"<any>(" + receiverExpr + ")." + methodMemberName(selector.Sel.Name) +
|
|
7627
|
+
"(" + strings.Join(args, ", ") + ")"
|
|
7628
|
+
return call, diagnostics, true
|
|
7629
|
+
}
|
|
6699
7630
|
callArgs := append([]string{receiverExpr}, args...)
|
|
6700
7631
|
call := o.namedTypeExpr(ctx, receiver) + ".prototype." + selector.Sel.Name + ".call(" + strings.Join(callArgs, ", ") + ")"
|
|
6701
7632
|
return call, diagnostics, true
|
|
@@ -6813,6 +7744,14 @@ func (o *LoweringOwner) lowerSelectorExpr(ctx lowerFileContext, expr *ast.Select
|
|
|
6813
7744
|
if alias := importAliasForPkgName(ctx, pkgName); alias != "" {
|
|
6814
7745
|
value := alias + "." + expr.Sel.Name
|
|
6815
7746
|
obj, _ := ctx.semPkg.source.TypesInfo.Uses[expr.Sel].(*types.Var)
|
|
7747
|
+
if o.packageVarIsLazy(ctx, obj) ||
|
|
7748
|
+
o.packageVarNameIsLazy(ctx, pkgName.Imported().Path(), expr.Sel.Name) {
|
|
7749
|
+
value = alias + "." + packageVarGetterName(expr.Sel.Name) + "()"
|
|
7750
|
+
if (ctx.asyncFunction || ctx.topLevel) &&
|
|
7751
|
+
o.packageVarNameHasAsyncLazyInit(ctx, pkgName.Imported().Path(), expr.Sel.Name) {
|
|
7752
|
+
value = "(await " + alias + "." + packageVarInitName(expr.Sel.Name) + "(), " + value + ")"
|
|
7753
|
+
}
|
|
7754
|
+
}
|
|
6816
7755
|
if obj != nil && packageVarReadNeedsPointerValue(obj.Type()) {
|
|
6817
7756
|
value = o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
6818
7757
|
"<" + o.tsNonNilTypeFor(ctx, obj.Type()) + ">(" + value + ")"
|
|
@@ -6887,10 +7826,13 @@ func (o *LoweringOwner) packageVarSetterForAssignment(ctx lowerFileContext, expr
|
|
|
6887
7826
|
return "", false
|
|
6888
7827
|
}
|
|
6889
7828
|
alias := ctx.localAliases[obj]
|
|
6890
|
-
if alias
|
|
6891
|
-
return "",
|
|
7829
|
+
if alias != "" {
|
|
7830
|
+
return alias + "." + packageVarSetterName(ident.Name), true
|
|
6892
7831
|
}
|
|
6893
|
-
|
|
7832
|
+
if ctx.lazyPackageVars[obj] {
|
|
7833
|
+
return packageVarSetterName(ident.Name), true
|
|
7834
|
+
}
|
|
7835
|
+
return "", false
|
|
6894
7836
|
}
|
|
6895
7837
|
selector, ok := unwrapParenExpr(expr).(*ast.SelectorExpr)
|
|
6896
7838
|
if !ok {
|
|
@@ -7848,12 +8790,40 @@ func (o *LoweringOwner) lowerStructCompositeLit(
|
|
|
7848
8790
|
func compositeLiteralFieldNeedsPreEval(ctx lowerFileContext, expr ast.Expr) bool {
|
|
7849
8791
|
switch typed := unwrapParenExpr(expr).(type) {
|
|
7850
8792
|
case *ast.CallExpr:
|
|
8793
|
+
for _, arg := range typed.Args {
|
|
8794
|
+
if compositeLiteralFieldNeedsPreEval(ctx, arg) {
|
|
8795
|
+
return true
|
|
8796
|
+
}
|
|
8797
|
+
}
|
|
7851
8798
|
if ident, ok := typed.Fun.(*ast.Ident); ok && isBuiltinCallTarget(ctx, ident) {
|
|
7852
8799
|
return false
|
|
7853
8800
|
}
|
|
7854
8801
|
return typeFromExpr(ctx, typed.Fun) == nil
|
|
7855
8802
|
case *ast.UnaryExpr:
|
|
7856
|
-
return typed.Op == token.ARROW
|
|
8803
|
+
return typed.Op == token.ARROW || compositeLiteralFieldNeedsPreEval(ctx, typed.X)
|
|
8804
|
+
case *ast.BinaryExpr:
|
|
8805
|
+
return compositeLiteralFieldNeedsPreEval(ctx, typed.X) ||
|
|
8806
|
+
compositeLiteralFieldNeedsPreEval(ctx, typed.Y)
|
|
8807
|
+
case *ast.IndexExpr:
|
|
8808
|
+
return compositeLiteralFieldNeedsPreEval(ctx, typed.X) ||
|
|
8809
|
+
compositeLiteralFieldNeedsPreEval(ctx, typed.Index)
|
|
8810
|
+
case *ast.IndexListExpr:
|
|
8811
|
+
if compositeLiteralFieldNeedsPreEval(ctx, typed.X) {
|
|
8812
|
+
return true
|
|
8813
|
+
}
|
|
8814
|
+
for _, index := range typed.Indices {
|
|
8815
|
+
if compositeLiteralFieldNeedsPreEval(ctx, index) {
|
|
8816
|
+
return true
|
|
8817
|
+
}
|
|
8818
|
+
}
|
|
8819
|
+
return false
|
|
8820
|
+
case *ast.SliceExpr:
|
|
8821
|
+
return compositeLiteralFieldNeedsPreEval(ctx, typed.X) ||
|
|
8822
|
+
compositeLiteralFieldNeedsPreEval(ctx, typed.Low) ||
|
|
8823
|
+
compositeLiteralFieldNeedsPreEval(ctx, typed.High) ||
|
|
8824
|
+
compositeLiteralFieldNeedsPreEval(ctx, typed.Max)
|
|
8825
|
+
case *ast.StarExpr:
|
|
8826
|
+
return compositeLiteralFieldNeedsPreEval(ctx, typed.X)
|
|
7857
8827
|
default:
|
|
7858
8828
|
return false
|
|
7859
8829
|
}
|
|
@@ -7918,6 +8888,9 @@ func (o *LoweringOwner) lowerArrayCompositeLit(
|
|
|
7918
8888
|
lit *ast.CompositeLit,
|
|
7919
8889
|
array *types.Array,
|
|
7920
8890
|
) (string, []Diagnostic) {
|
|
8891
|
+
if len(lit.Elts) == 0 && isByteType(array.Elem()) {
|
|
8892
|
+
return "new Uint8Array(" + strconv.FormatInt(array.Len(), 10) + ")", nil
|
|
8893
|
+
}
|
|
7921
8894
|
values := make([]string, int(array.Len()))
|
|
7922
8895
|
for idx := range values {
|
|
7923
8896
|
values[idx] = o.lowerZeroValueExprFor(ctx, array.Elem())
|
|
@@ -8071,7 +9044,7 @@ func (o *LoweringOwner) lowerValueForTarget(
|
|
|
8071
9044
|
}
|
|
8072
9045
|
}
|
|
8073
9046
|
if isNumericType(targetType) {
|
|
8074
|
-
if constantValue, ok :=
|
|
9047
|
+
if constantValue, ok := o.lowerNumericConstantExprForTarget(ctx, expr, targetType); ok {
|
|
8075
9048
|
return constantValue
|
|
8076
9049
|
}
|
|
8077
9050
|
}
|
|
@@ -8100,6 +9073,28 @@ func lowerRealNumericConstantExpr(ctx lowerFileContext, expr ast.Expr) (string,
|
|
|
8100
9073
|
}
|
|
8101
9074
|
}
|
|
8102
9075
|
|
|
9076
|
+
func (o *LoweringOwner) lowerNumericConstantExprForTarget(ctx lowerFileContext, expr ast.Expr, targetType types.Type) (string, bool) {
|
|
9077
|
+
if ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
9078
|
+
return "", false
|
|
9079
|
+
}
|
|
9080
|
+
tv, ok := ctx.semPkg.source.TypesInfo.Types[expr]
|
|
9081
|
+
if ok && tv.Value != nil {
|
|
9082
|
+
if bits, ok := unsignedIntegerBits(targetType); ok && bits >= 64 {
|
|
9083
|
+
if value, ok := lowerWideIntegerConstantValue(tv.Value); ok {
|
|
9084
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint) + "(" +
|
|
9085
|
+
strconv.Quote(value) + ", 64)", true
|
|
9086
|
+
}
|
|
9087
|
+
}
|
|
9088
|
+
if bits, ok := signedIntegerBits(targetType); ok && bits >= 64 {
|
|
9089
|
+
if value, ok := lowerWideIntegerConstantValue(tv.Value); ok {
|
|
9090
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperInt) + "(" +
|
|
9091
|
+
strconv.Quote(value) + ", 64)", true
|
|
9092
|
+
}
|
|
9093
|
+
}
|
|
9094
|
+
}
|
|
9095
|
+
return lowerRealNumericConstantExpr(ctx, expr)
|
|
9096
|
+
}
|
|
9097
|
+
|
|
8103
9098
|
func isRealNumericConstantExpr(ctx lowerFileContext, expr ast.Expr) bool {
|
|
8104
9099
|
if ctx.semPkg != nil && ctx.semPkg.source != nil {
|
|
8105
9100
|
if tv, ok := ctx.semPkg.source.TypesInfo.Types[expr]; ok && tv.Value != nil {
|
|
@@ -8145,6 +9140,9 @@ func (o *LoweringOwner) lowerValueForTargetTypes(
|
|
|
8145
9140
|
return wrapper
|
|
8146
9141
|
}
|
|
8147
9142
|
}
|
|
9143
|
+
if wrapper := o.lowerNumericInterfaceWrapper(ctx, targetType, sourceType, value); wrapper != "" {
|
|
9144
|
+
return wrapper
|
|
9145
|
+
}
|
|
8148
9146
|
if isInterfaceType(targetType) && isStructValueType(sourceType) {
|
|
8149
9147
|
if cloneStructValue {
|
|
8150
9148
|
value = o.lowerStructClone(value)
|
|
@@ -8193,6 +9191,25 @@ func (o *LoweringOwner) lowerValueForTargetTypes(
|
|
|
8193
9191
|
return value
|
|
8194
9192
|
}
|
|
8195
9193
|
|
|
9194
|
+
func (o *LoweringOwner) lowerNumericInterfaceWrapper(
|
|
9195
|
+
ctx lowerFileContext,
|
|
9196
|
+
targetType types.Type,
|
|
9197
|
+
sourceType types.Type,
|
|
9198
|
+
value string,
|
|
9199
|
+
) string {
|
|
9200
|
+
if targetType == nil || sourceType == nil || !isInterfaceType(targetType) || isInterfaceType(sourceType) {
|
|
9201
|
+
return ""
|
|
9202
|
+
}
|
|
9203
|
+
basic, ok := types.Unalias(sourceType).(*types.Basic)
|
|
9204
|
+
if !ok || basic.Info()&types.IsNumeric == 0 || basic.Info()&types.IsUntyped != 0 {
|
|
9205
|
+
return ""
|
|
9206
|
+
}
|
|
9207
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperNamedValueInterfaceValue) +
|
|
9208
|
+
"<" + o.tsTypeFor(ctx, targetType) + ">(" + value + ", " +
|
|
9209
|
+
strconv.Quote(goRuntimeTypeString(sourceType)) + ", {}, " +
|
|
9210
|
+
o.runtimeTypeInfoExpr(sourceType) + ")"
|
|
9211
|
+
}
|
|
9212
|
+
|
|
8196
9213
|
func isBasicFixedWideIntegerType(typ types.Type) bool {
|
|
8197
9214
|
basic, ok := types.Unalias(typ).(*types.Basic)
|
|
8198
9215
|
if !ok {
|
|
@@ -8232,7 +9249,8 @@ func (o *LoweringOwner) lowerNamedValueInterfaceWrapper(
|
|
|
8232
9249
|
}
|
|
8233
9250
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperNamedValueInterfaceValue) +
|
|
8234
9251
|
"<" + o.tsTypeFor(ctx, targetType) + ">(" + value + ", " +
|
|
8235
|
-
strconv.Quote(goRuntimeTypeString(sourceType)) + ", " + methods + "
|
|
9252
|
+
strconv.Quote(goRuntimeTypeString(sourceType)) + ", " + methods + ", " +
|
|
9253
|
+
o.runtimeTypeInfoExpr(sourceType) + ")"
|
|
8236
9254
|
}
|
|
8237
9255
|
|
|
8238
9256
|
func (o *LoweringOwner) lowerPrimitiveErrorWrapper(ctx lowerFileContext, sourceType types.Type, value string) string {
|
|
@@ -8254,7 +9272,8 @@ func (o *LoweringOwner) lowerPrimitiveErrorWrapper(ctx lowerFileContext, sourceT
|
|
|
8254
9272
|
}
|
|
8255
9273
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperNamedValueInterfaceValue) +
|
|
8256
9274
|
"<$.GoError>(" + value + ", " + strconv.Quote(goRuntimeTypeString(sourceType)) +
|
|
8257
|
-
", {\"Error\": " + o.methodFunctionExpr(ctx, named, fn, "Error") + "}
|
|
9275
|
+
", {\"Error\": " + o.methodFunctionExpr(ctx, named, fn, "Error") + "}, " +
|
|
9276
|
+
o.runtimeTypeInfoExpr(sourceType) + ")"
|
|
8258
9277
|
}
|
|
8259
9278
|
|
|
8260
9279
|
func (o *LoweringOwner) lowerStructClone(value string) string {
|
|
@@ -8264,7 +9283,7 @@ func (o *LoweringOwner) lowerStructClone(value string) string {
|
|
|
8264
9283
|
|
|
8265
9284
|
func (o *LoweringOwner) lowerZeroValueExpr(typ types.Type) string {
|
|
8266
9285
|
if named := namedStructType(typ); named != nil && isStructValueType(typ) {
|
|
8267
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMarkAsStructValue) + "(new " + named.Obj().Name() + "())"
|
|
9286
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMarkAsStructValue) + "(new " + safeIdentifier(named.Obj().Name()) + "())"
|
|
8268
9287
|
}
|
|
8269
9288
|
return zeroValueExpr(typ)
|
|
8270
9289
|
}
|
|
@@ -8311,7 +9330,7 @@ func (o *LoweringOwner) lowerZeroValueExprFor(ctx lowerFileContext, typ types.Ty
|
|
|
8311
9330
|
|
|
8312
9331
|
func (o *LoweringOwner) lowerDeclarationZeroValueExpr(ctx lowerFileContext, typ types.Type) string {
|
|
8313
9332
|
if isFunctionType(typ) {
|
|
8314
|
-
return "null as " + o.
|
|
9333
|
+
return "null as unknown as " + o.tsFunctionZeroValueTypeFor(ctx, typ)
|
|
8315
9334
|
}
|
|
8316
9335
|
typeParam, ok := types.Unalias(typ).(*types.TypeParam)
|
|
8317
9336
|
if !ok {
|
|
@@ -8328,6 +9347,13 @@ func (o *LoweringOwner) lowerDeclarationZeroValueExpr(ctx lowerFileContext, typ
|
|
|
8328
9347
|
"(__typeArgs, " + strconv.Quote(typeParam.Obj().Name()) + ", " + zeroValueExpr(typ) + ")"
|
|
8329
9348
|
}
|
|
8330
9349
|
|
|
9350
|
+
func (o *LoweringOwner) tsFunctionZeroValueTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
9351
|
+
if signature := unnamedSignatureForType(typ); signature != nil {
|
|
9352
|
+
return o.tsAsyncCompatibleFunctionTypeFor(ctx, signature)
|
|
9353
|
+
}
|
|
9354
|
+
return o.tsTypeFor(ctx, typ)
|
|
9355
|
+
}
|
|
9356
|
+
|
|
8331
9357
|
func (o *LoweringOwner) runtimeTypeInfoExpr(typ types.Type) string {
|
|
8332
9358
|
return o.runtimeTypeInfoExprWithSeen(typ, make(map[types.Type]bool))
|
|
8333
9359
|
}
|
|
@@ -8789,6 +9815,9 @@ func (o *LoweringOwner) tsNonNilTypeFor(ctx lowerFileContext, typ types.Type) st
|
|
|
8789
9815
|
}
|
|
8790
9816
|
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
8791
9817
|
if _, ok := named.Underlying().(*types.Interface); ok {
|
|
9818
|
+
if !ctx.canReferenceNamedType(named) {
|
|
9819
|
+
return "any"
|
|
9820
|
+
}
|
|
8792
9821
|
return "Exclude<" + o.namedTypeExpr(ctx, named) + ", null>"
|
|
8793
9822
|
}
|
|
8794
9823
|
}
|
|
@@ -8851,7 +9880,7 @@ func zeroValueExpr(typ types.Type) string {
|
|
|
8851
9880
|
return "undefined"
|
|
8852
9881
|
}
|
|
8853
9882
|
if named := namedStructType(typ); named != nil && isStructValueType(typ) {
|
|
8854
|
-
return "new " + named.Obj().Name() + "()"
|
|
9883
|
+
return "new " + safeIdentifier(named.Obj().Name()) + "()"
|
|
8855
9884
|
}
|
|
8856
9885
|
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
8857
9886
|
case *types.Basic:
|
|
@@ -8941,6 +9970,11 @@ func namedFunctionType(typ types.Type) *types.Named {
|
|
|
8941
9970
|
return named
|
|
8942
9971
|
}
|
|
8943
9972
|
|
|
9973
|
+
func overrideNamedStringType(ctx lowerFileContext, owner *LoweringOwner, typ types.Type) bool {
|
|
9974
|
+
named, _ := types.Unalias(typ).(*types.Named)
|
|
9975
|
+
return named != nil && isStringType(named) && owner.typeUsesOverride(named)
|
|
9976
|
+
}
|
|
9977
|
+
|
|
8944
9978
|
func isBuiltinErrorType(typ types.Type) bool {
|
|
8945
9979
|
if typ == nil {
|
|
8946
9980
|
return false
|
|
@@ -9091,6 +10125,16 @@ func isStructValueType(typ types.Type) bool {
|
|
|
9091
10125
|
return namedStructType(typ) != nil
|
|
9092
10126
|
}
|
|
9093
10127
|
|
|
10128
|
+
func isStructComparableType(typ types.Type) bool {
|
|
10129
|
+
if typ == nil {
|
|
10130
|
+
return false
|
|
10131
|
+
}
|
|
10132
|
+
if _, ok := types.Unalias(typ).Underlying().(*types.Struct); !ok {
|
|
10133
|
+
return false
|
|
10134
|
+
}
|
|
10135
|
+
return types.Comparable(typ)
|
|
10136
|
+
}
|
|
10137
|
+
|
|
9094
10138
|
func isPointerToStructType(typ types.Type) bool {
|
|
9095
10139
|
pointer, ok := types.Unalias(typ).Underlying().(*types.Pointer)
|
|
9096
10140
|
if !ok {
|
|
@@ -9270,6 +10314,14 @@ func isFixedSignedWideIntegerType(typ types.Type) bool {
|
|
|
9270
10314
|
return ok && basic.Kind() == types.Int64
|
|
9271
10315
|
}
|
|
9272
10316
|
|
|
10317
|
+
func isRuntimeWideIntegerType(typ types.Type) bool {
|
|
10318
|
+
if isFixedWideIntegerType(typ) {
|
|
10319
|
+
return true
|
|
10320
|
+
}
|
|
10321
|
+
bits, ok := unsignedIntegerBits(typ)
|
|
10322
|
+
return ok && bits > 32
|
|
10323
|
+
}
|
|
10324
|
+
|
|
9273
10325
|
func isRuneSliceType(typ types.Type) bool {
|
|
9274
10326
|
slice, ok := types.Unalias(typ).Underlying().(*types.Slice)
|
|
9275
10327
|
return ok && isRuneType(slice.Elem())
|
|
@@ -9355,8 +10407,7 @@ func (o *LoweringOwner) functionAsync(ctx lowerFileContext, fn *types.Func) bool
|
|
|
9355
10407
|
if fn == nil || ctx.model == nil {
|
|
9356
10408
|
return false
|
|
9357
10409
|
}
|
|
9358
|
-
|
|
9359
|
-
return semFn != nil && semFn.async
|
|
10410
|
+
return ctx.model.functionAsync(fn)
|
|
9360
10411
|
}
|
|
9361
10412
|
|
|
9362
10413
|
func (o *LoweringOwner) callNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool {
|
|
@@ -9505,6 +10556,18 @@ func (o *LoweringOwner) inferGenericTypeArg(
|
|
|
9505
10556
|
}
|
|
9506
10557
|
return
|
|
9507
10558
|
}
|
|
10559
|
+
if paramNamed, ok := types.Unalias(paramType).(*types.Named); ok {
|
|
10560
|
+
if argNamed, ok := types.Unalias(argType).(*types.Named); ok &&
|
|
10561
|
+
namedOriginsEqual(paramNamed, argNamed) {
|
|
10562
|
+
paramArgs := paramNamed.TypeArgs()
|
|
10563
|
+
argArgs := argNamed.TypeArgs()
|
|
10564
|
+
if paramArgs != nil && argArgs != nil {
|
|
10565
|
+
for idx := range min(paramArgs.Len(), argArgs.Len()) {
|
|
10566
|
+
o.inferGenericTypeArg(inferred, paramArgs.At(idx), argArgs.At(idx))
|
|
10567
|
+
}
|
|
10568
|
+
}
|
|
10569
|
+
}
|
|
10570
|
+
}
|
|
9508
10571
|
switch param := types.Unalias(paramType).Underlying().(type) {
|
|
9509
10572
|
case *types.Slice:
|
|
9510
10573
|
if arg, ok := types.Unalias(argType).Underlying().(*types.Slice); ok {
|
|
@@ -9517,6 +10580,24 @@ func (o *LoweringOwner) inferGenericTypeArg(
|
|
|
9517
10580
|
}
|
|
9518
10581
|
}
|
|
9519
10582
|
|
|
10583
|
+
func namedOriginsEqual(a, b *types.Named) bool {
|
|
10584
|
+
if a == nil || b == nil {
|
|
10585
|
+
return false
|
|
10586
|
+
}
|
|
10587
|
+
aOrigin := a.Origin()
|
|
10588
|
+
if aOrigin == nil {
|
|
10589
|
+
aOrigin = a
|
|
10590
|
+
}
|
|
10591
|
+
bOrigin := b.Origin()
|
|
10592
|
+
if bOrigin == nil {
|
|
10593
|
+
bOrigin = b
|
|
10594
|
+
}
|
|
10595
|
+
if aOrigin.Obj() == nil || bOrigin.Obj() == nil {
|
|
10596
|
+
return aOrigin == bOrigin
|
|
10597
|
+
}
|
|
10598
|
+
return aOrigin.Obj() == bOrigin.Obj()
|
|
10599
|
+
}
|
|
10600
|
+
|
|
9520
10601
|
func (o *LoweringOwner) genericTypeDescriptorExpr(ctx lowerFileContext, typ types.Type) string {
|
|
9521
10602
|
if typeParam, ok := types.Unalias(typ).(*types.TypeParam); ok && typeParamInScope(ctx, typeParam) {
|
|
9522
10603
|
return "__typeArgs?.[" + strconv.Quote(typeParam.Obj().Name()) + "] ?? { type: " +
|
|
@@ -9560,7 +10641,12 @@ func (o *LoweringOwner) genericMethodDescriptorsForType(
|
|
|
9560
10641
|
if sig, _ := method.Type().(*types.Signature); sig != nil {
|
|
9561
10642
|
if recv := sig.Recv(); recv != nil {
|
|
9562
10643
|
if _, ok := types.Unalias(recv.Type()).Underlying().(*types.Pointer); !ok {
|
|
9563
|
-
|
|
10644
|
+
if _, ok := types.Unalias(methodSetType).Underlying().(*types.Pointer); ok {
|
|
10645
|
+
receiver = o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) + "(receiver)"
|
|
10646
|
+
} else {
|
|
10647
|
+
receiver = "(" + o.runtimeOwner.QualifiedHelper(RuntimeHelperIsVarRef) +
|
|
10648
|
+
"(receiver) ? receiver.value : receiver)"
|
|
10649
|
+
}
|
|
9564
10650
|
}
|
|
9565
10651
|
}
|
|
9566
10652
|
}
|
|
@@ -9590,9 +10676,9 @@ func namedNonStructMethodSetType(typ types.Type) (*types.Named, types.Type) {
|
|
|
9590
10676
|
|
|
9591
10677
|
func methodFunctionName(receiver *types.Named, method string) string {
|
|
9592
10678
|
if receiver == nil || receiver.Obj() == nil {
|
|
9593
|
-
return method
|
|
10679
|
+
return safeIdentifier(method)
|
|
9594
10680
|
}
|
|
9595
|
-
return receiver.Obj().Name() + "_" + method
|
|
10681
|
+
return safeIdentifier(receiver.Obj().Name()) + "_" + safeIdentifier(method)
|
|
9596
10682
|
}
|
|
9597
10683
|
|
|
9598
10684
|
func methodReceiverNamedType(obj types.Object) *types.Named {
|
|
@@ -9629,7 +10715,7 @@ func (o *LoweringOwner) namedTypeExpr(ctx lowerFileContext, named *types.Named)
|
|
|
9629
10715
|
if named == nil || named.Obj() == nil {
|
|
9630
10716
|
return "unknown"
|
|
9631
10717
|
}
|
|
9632
|
-
baseName := named.Obj().Name()
|
|
10718
|
+
baseName := safeIdentifier(named.Obj().Name())
|
|
9633
10719
|
if alias := ctx.localAliases[named.Obj()]; alias != "" {
|
|
9634
10720
|
baseName = alias + "." + baseName
|
|
9635
10721
|
} else if named.Obj().Pkg() != nil {
|
|
@@ -9692,11 +10778,30 @@ func runtimeNamedTypeName(named *types.Named) string {
|
|
|
9692
10778
|
}
|
|
9693
10779
|
|
|
9694
10780
|
func goRuntimeTypeString(typ types.Type) string {
|
|
9695
|
-
return types.TypeString(typ, func(pkg *types.Package) string {
|
|
10781
|
+
return types.TypeString(runtimeIdentityType(typ), func(pkg *types.Package) string {
|
|
9696
10782
|
return pkg.Name()
|
|
9697
10783
|
})
|
|
9698
10784
|
}
|
|
9699
10785
|
|
|
10786
|
+
func runtimeIdentityType(typ types.Type) types.Type {
|
|
10787
|
+
switch typed := typ.(type) {
|
|
10788
|
+
case *types.Alias:
|
|
10789
|
+
return runtimeIdentityType(types.Unalias(typed))
|
|
10790
|
+
case *types.Pointer:
|
|
10791
|
+
return types.NewPointer(runtimeIdentityType(typed.Elem()))
|
|
10792
|
+
case *types.Slice:
|
|
10793
|
+
return types.NewSlice(runtimeIdentityType(typed.Elem()))
|
|
10794
|
+
case *types.Array:
|
|
10795
|
+
return types.NewArray(runtimeIdentityType(typed.Elem()), typed.Len())
|
|
10796
|
+
case *types.Map:
|
|
10797
|
+
return types.NewMap(runtimeIdentityType(typed.Key()), runtimeIdentityType(typed.Elem()))
|
|
10798
|
+
case *types.Chan:
|
|
10799
|
+
return types.NewChan(typed.Dir(), runtimeIdentityType(typed.Elem()))
|
|
10800
|
+
default:
|
|
10801
|
+
return typ
|
|
10802
|
+
}
|
|
10803
|
+
}
|
|
10804
|
+
|
|
9700
10805
|
func basicRuntimeName(basic *types.Basic) string {
|
|
9701
10806
|
if basic == nil {
|
|
9702
10807
|
return "unknown"
|
|
@@ -9706,6 +10811,32 @@ func basicRuntimeName(basic *types.Basic) string {
|
|
|
9706
10811
|
return "bool"
|
|
9707
10812
|
case types.String:
|
|
9708
10813
|
return "string"
|
|
10814
|
+
case types.Int:
|
|
10815
|
+
return "int"
|
|
10816
|
+
case types.Int8:
|
|
10817
|
+
return "int8"
|
|
10818
|
+
case types.Int16:
|
|
10819
|
+
return "int16"
|
|
10820
|
+
case types.Int32:
|
|
10821
|
+
return "int32"
|
|
10822
|
+
case types.Int64:
|
|
10823
|
+
return "int64"
|
|
10824
|
+
case types.Uint:
|
|
10825
|
+
return "uint"
|
|
10826
|
+
case types.Uint8:
|
|
10827
|
+
return "uint8"
|
|
10828
|
+
case types.Uint16:
|
|
10829
|
+
return "uint16"
|
|
10830
|
+
case types.Uint32:
|
|
10831
|
+
return "uint32"
|
|
10832
|
+
case types.Uint64:
|
|
10833
|
+
return "uint64"
|
|
10834
|
+
case types.Uintptr:
|
|
10835
|
+
return "uintptr"
|
|
10836
|
+
case types.Float32:
|
|
10837
|
+
return "float32"
|
|
10838
|
+
case types.Float64:
|
|
10839
|
+
return "float64"
|
|
9709
10840
|
case types.Complex64:
|
|
9710
10841
|
return "complex64"
|
|
9711
10842
|
case types.Complex128:
|