goscript 0.1.1 → 0.1.3
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-test.go +104 -11
- package/cmd/goscript/cmd-test_test.go +1 -1
- package/cmd/goscript/cmd_compile.go +9 -0
- package/compiler/compile-request.go +31 -0
- package/compiler/compiler.go +1 -1
- package/compiler/compliance_test.go +0 -2
- package/compiler/config.go +2 -0
- package/compiler/gotest/package-result.go +2 -0
- package/compiler/gotest/request.go +85 -20
- package/compiler/gotest/runner.go +733 -96
- package/compiler/gotest/runner_test.go +647 -3
- package/compiler/lowered-program.go +10 -2
- package/compiler/lowering.go +2676 -349
- package/compiler/override-facts.go +77 -27
- package/compiler/override-registry.go +5 -4
- package/compiler/override-registry_test.go +178 -0
- package/compiler/package-graph_test.go +62 -7
- package/compiler/package-test-graph-variant.go +40 -16
- package/compiler/package-test-graph.go +0 -5
- package/compiler/package-test-graph_test.go +61 -3
- package/compiler/runtime-contract.go +40 -0
- package/compiler/semantic-model-types.go +16 -0
- package/compiler/semantic-model.go +336 -91
- package/compiler/semantic-model_test.go +50 -1
- package/compiler/service.go +9 -3
- package/compiler/skeleton_test.go +2371 -296
- package/compiler/tsworkspace/owner-process-unix_test.go +72 -0
- package/compiler/tsworkspace/owner.go +8 -0
- package/compiler/tsworkspace/tool-process-other.go +14 -0
- package/compiler/tsworkspace/tool-process-unix.go +19 -0
- package/compiler/typescript-emitter.go +149 -10
- package/dist/gs/builtin/builtin.d.ts +20 -1
- package/dist/gs/builtin/builtin.js +246 -26
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.d.ts +24 -10
- package/dist/gs/builtin/channel.js +143 -34
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/defer.d.ts +1 -0
- package/dist/gs/builtin/defer.js +12 -2
- package/dist/gs/builtin/defer.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +9 -0
- package/dist/gs/builtin/hostio.js +25 -0
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/map.js +40 -6
- package/dist/gs/builtin/map.js.map +1 -1
- package/dist/gs/builtin/print.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +43 -9
- package/dist/gs/builtin/slice.js +437 -234
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +2 -0
- package/dist/gs/builtin/type.js +55 -10
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +2 -0
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js +28 -28
- package/dist/gs/bytes/buffer.gs.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/bytes/iter.gs.js +13 -13
- package/dist/gs/bytes/iter.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +26 -0
- package/dist/gs/compress/zlib/index.js +168 -0
- package/dist/gs/compress/zlib/index.js.map +1 -0
- package/dist/gs/context/context.d.ts +1 -1
- package/dist/gs/context/context.js +8 -3
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/crypto/ecdh/index.d.ts +52 -0
- package/dist/gs/crypto/ecdh/index.js +226 -0
- package/dist/gs/crypto/ecdh/index.js.map +1 -0
- package/dist/gs/crypto/ed25519/index.d.ts +34 -0
- package/dist/gs/crypto/ed25519/index.js +160 -0
- package/dist/gs/crypto/ed25519/index.js.map +1 -0
- package/dist/gs/crypto/internal/constanttime/index.d.ts +4 -0
- package/dist/gs/crypto/internal/constanttime/index.js +18 -0
- package/dist/gs/crypto/internal/constanttime/index.js.map +1 -0
- package/dist/gs/crypto/rand/index.d.ts +2 -0
- package/dist/gs/crypto/rand/index.js +85 -0
- package/dist/gs/crypto/rand/index.js.map +1 -1
- package/dist/gs/crypto/sha1/index.d.ts +5 -0
- package/dist/gs/crypto/sha1/index.js +106 -0
- package/dist/gs/crypto/sha1/index.js.map +1 -0
- package/dist/gs/crypto/sha256/index.d.ts +8 -0
- package/dist/gs/crypto/sha256/index.js +118 -0
- package/dist/gs/crypto/sha256/index.js.map +1 -0
- package/dist/gs/crypto/sha512/index.d.ts +14 -0
- package/dist/gs/crypto/sha512/index.js +129 -0
- package/dist/gs/crypto/sha512/index.js.map +1 -0
- package/dist/gs/encoding/json/index.d.ts +3 -0
- package/dist/gs/encoding/json/index.js +15 -0
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/errors/errors.js +29 -6
- package/dist/gs/errors/errors.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +1 -1
- package/dist/gs/fmt/fmt.js +64 -3
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +7 -7
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +52 -18
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +56 -20
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +57 -3
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +366 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +20 -0
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js +134 -0
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +1 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.d.ts +3 -0
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js +50 -0
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js.map +1 -0
- package/dist/gs/github.com/klauspost/compress/internal/le/index.js +3 -2
- package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -1
- package/dist/gs/github.com/mr-tron/base58/base58/index.d.ts +27 -0
- package/dist/gs/github.com/mr-tron/base58/base58/index.js +172 -0
- package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.d.ts +21 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js +22 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js.map +1 -0
- package/dist/gs/go/token/index.js +11 -4
- package/dist/gs/go/token/index.js.map +1 -1
- package/dist/gs/hash/fnv/index.d.ts +57 -0
- package/dist/gs/hash/fnv/index.js +299 -0
- package/dist/gs/hash/fnv/index.js.map +1 -0
- package/dist/gs/hash/index.d.ts +17 -0
- package/dist/gs/hash/index.js +94 -0
- package/dist/gs/hash/index.js.map +1 -0
- package/dist/gs/io/fs/readlink.js +2 -6
- package/dist/gs/io/fs/readlink.js.map +1 -1
- package/dist/gs/io/fs/walk.js.map +1 -1
- package/dist/gs/io/io.d.ts +8 -5
- package/dist/gs/io/io.js +20 -2
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/iter/iter.d.ts +3 -2
- package/dist/gs/iter/iter.js.map +1 -1
- package/dist/gs/maps/iter.d.ts +5 -5
- package/dist/gs/maps/iter.js +48 -21
- package/dist/gs/maps/iter.js.map +1 -1
- package/dist/gs/maps/maps.d.ts +6 -6
- package/dist/gs/math/bits/index.js +14 -24
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/mime/index.js +3 -1
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.d.ts +20 -1
- package/dist/gs/net/http/httptest/index.js +85 -3
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +118 -6
- package/dist/gs/net/http/index.js +389 -14
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/net/http/pprof/index.d.ts +8 -0
- package/dist/gs/net/http/pprof/index.js +59 -0
- package/dist/gs/net/http/pprof/index.js.map +1 -0
- package/dist/gs/os/error.gs.js +9 -7
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.js +95 -15
- 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/path/filepath/match.js.map +1 -1
- package/dist/gs/path/filepath/path.d.ts +5 -3
- package/dist/gs/path/filepath/path.js +65 -10
- package/dist/gs/path/filepath/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +3 -2
- package/dist/gs/reflect/index.js +2 -1
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/iter.js +2 -2
- package/dist/gs/reflect/iter.js.map +1 -1
- package/dist/gs/reflect/map.js +26 -0
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +24 -5
- package/dist/gs/reflect/type.js +390 -38
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +1 -0
- package/dist/gs/reflect/types.js +3 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.d.ts +4 -1
- package/dist/gs/reflect/value.js +39 -1
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +1 -1
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/debug/index.d.ts +39 -0
- package/dist/gs/runtime/debug/index.js +58 -0
- package/dist/gs/runtime/debug/index.js.map +1 -1
- package/dist/gs/runtime/pprof/index.d.ts +20 -0
- package/dist/gs/runtime/pprof/index.js +85 -0
- package/dist/gs/runtime/pprof/index.js.map +1 -0
- package/dist/gs/runtime/trace/index.d.ts +19 -0
- package/dist/gs/runtime/trace/index.js +64 -0
- package/dist/gs/runtime/trace/index.js.map +1 -0
- package/dist/gs/slices/slices.d.ts +24 -9
- package/dist/gs/slices/slices.js +229 -24
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/sort/slice.gs.d.ts +5 -3
- package/dist/gs/sort/slice.gs.js +55 -17
- package/dist/gs/sort/slice.gs.js.map +1 -1
- package/dist/gs/strings/builder.js +26 -17
- package/dist/gs/strings/builder.js.map +1 -1
- package/dist/gs/strings/iter.js +140 -75
- package/dist/gs/strings/iter.js.map +1 -1
- package/dist/gs/strings/replace.js +2 -2
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/strings.js +52 -6
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +6 -3
- package/dist/gs/sync/sync.js +39 -11
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/errors.d.ts +116 -112
- package/dist/gs/syscall/errors.js +38 -1
- package/dist/gs/syscall/errors.js.map +1 -1
- package/dist/gs/syscall/fs.d.ts +2 -8
- package/dist/gs/syscall/fs.js.map +1 -1
- package/dist/gs/syscall/js/index.js +20 -12
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/syscall/types.d.ts +4 -1
- package/dist/gs/syscall/types.js.map +1 -1
- package/dist/gs/testing/testing.d.ts +4 -3
- package/dist/gs/testing/testing.js +21 -4
- package/dist/gs/testing/testing.js.map +1 -1
- package/dist/gs/time/time.js +22 -0
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/dist/gs/unique/index.js +7 -2
- package/dist/gs/unique/index.js.map +1 -1
- package/go.mod +8 -8
- package/go.sum +14 -23
- package/gs/builtin/builtin.ts +364 -37
- package/gs/builtin/channel.ts +208 -38
- package/gs/builtin/defer.ts +13 -2
- package/gs/builtin/hostio.test.ts +1 -0
- package/gs/builtin/hostio.ts +38 -0
- package/gs/builtin/map.ts +46 -6
- package/gs/builtin/print.ts +12 -3
- package/gs/builtin/runtime-contract.test.ts +290 -10
- package/gs/builtin/slice.test.ts +70 -0
- package/gs/builtin/slice.ts +566 -255
- package/gs/builtin/type.ts +63 -10
- package/gs/builtin/varRef.ts +2 -0
- package/gs/bytes/buffer.gs.ts +28 -28
- package/gs/bytes/bytes.gs.ts +19 -10
- package/gs/bytes/bytes.test.ts +17 -0
- package/gs/bytes/iter.gs.ts +13 -14
- package/gs/compress/zlib/index.test.ts +28 -0
- package/gs/compress/zlib/index.ts +200 -0
- package/gs/compress/zlib/meta.json +3 -0
- package/gs/context/context.test.ts +36 -2
- package/gs/context/context.ts +9 -4
- package/gs/crypto/ecdh/index.test.ts +43 -0
- package/gs/crypto/ecdh/index.ts +274 -0
- package/gs/crypto/ed25519/index.test.ts +41 -0
- package/gs/crypto/ed25519/index.ts +238 -0
- package/gs/crypto/ed25519/meta.json +13 -0
- package/gs/crypto/internal/constanttime/index.test.ts +25 -0
- package/gs/crypto/internal/constanttime/index.ts +22 -0
- package/gs/crypto/rand/index.test.ts +89 -1
- package/gs/crypto/rand/index.ts +103 -1
- package/gs/crypto/rand/meta.json +4 -1
- package/gs/crypto/sha1/index.test.ts +28 -0
- package/gs/crypto/sha1/index.ts +130 -0
- package/gs/crypto/sha1/meta.json +8 -0
- package/gs/crypto/sha256/index.test.ts +78 -0
- package/gs/crypto/sha256/index.ts +150 -0
- package/gs/crypto/sha256/meta.json +9 -0
- package/gs/crypto/sha512/index.test.ts +31 -0
- package/gs/crypto/sha512/index.ts +161 -0
- package/gs/crypto/sha512/meta.json +11 -0
- package/gs/encoding/json/index.test.ts +25 -3
- package/gs/encoding/json/index.ts +21 -3
- package/gs/errors/errors.test.ts +4 -1
- package/gs/errors/errors.ts +32 -8
- package/gs/fmt/fmt.test.ts +23 -1
- package/gs/fmt/fmt.ts +76 -10
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +62 -7
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +78 -36
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +32 -11
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +122 -43
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +31 -0
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +518 -4
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +6 -0
- package/gs/github.com/aperturerobotics/util/conc/index.test.ts +30 -0
- package/gs/github.com/aperturerobotics/util/conc/index.ts +172 -0
- package/gs/github.com/aperturerobotics/util/conc/meta.json +9 -0
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.ts +1 -4
- package/gs/github.com/hack-pad/safejs/internal/catch/index.test.ts +35 -0
- package/gs/github.com/hack-pad/safejs/internal/catch/index.ts +65 -0
- package/gs/github.com/hack-pad/safejs/internal/catch/meta.json +9 -0
- package/gs/github.com/klauspost/compress/internal/le/index.test.ts +2 -1
- package/gs/github.com/klauspost/compress/internal/le/index.ts +6 -5
- package/gs/github.com/mr-tron/base58/base58/index.test.ts +70 -0
- package/gs/github.com/mr-tron/base58/base58/index.ts +231 -0
- package/gs/github.com/mr-tron/base58/base58/meta.json +3 -0
- package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +46 -0
- package/gs/github.com/zeebo/blake3/internal/consts/index.ts +26 -0
- package/gs/go/token/index.ts +17 -4
- package/gs/hash/fnv/index.test.ts +67 -0
- package/gs/hash/fnv/index.ts +351 -0
- package/gs/hash/fnv/meta.json +3 -0
- package/gs/hash/index.test.ts +37 -0
- package/gs/hash/index.ts +118 -0
- package/gs/hash/meta.json +5 -0
- package/gs/internal/byteorder/index.test.ts +6 -6
- package/gs/io/fs/readlink.ts +40 -48
- package/gs/io/fs/walk.ts +10 -2
- package/gs/io/io.test.ts +64 -0
- package/gs/io/io.ts +34 -13
- package/gs/iter/iter.ts +8 -2
- package/gs/maps/iter.ts +69 -26
- package/gs/maps/maps.test.ts +23 -0
- package/gs/maps/maps.ts +6 -6
- package/gs/math/bits/index.test.ts +20 -0
- package/gs/math/bits/index.ts +15 -28
- package/gs/mime/index.ts +8 -2
- package/gs/net/http/httptest/index.test.ts +85 -0
- package/gs/net/http/httptest/index.ts +113 -3
- package/gs/net/http/index.test.ts +159 -1
- package/gs/net/http/index.ts +515 -15
- package/gs/net/http/meta.json +6 -0
- package/gs/net/http/pprof/index.test.ts +47 -0
- package/gs/net/http/pprof/index.ts +65 -0
- package/gs/os/error.gs.ts +9 -10
- package/gs/os/error.test.ts +41 -0
- package/gs/os/file_unix_js.test.ts +55 -0
- package/gs/os/tempfile.gs.test.ts +37 -10
- package/gs/os/types_js.gs.ts +94 -15
- package/gs/os/zero_copy_posix.gs.ts +1 -2
- package/gs/path/filepath/match.ts +4 -1
- package/gs/path/filepath/meta.json +6 -0
- package/gs/path/filepath/path.test.ts +57 -2
- package/gs/path/filepath/path.ts +91 -12
- package/gs/reflect/field.test.ts +63 -0
- package/gs/reflect/index.ts +4 -1
- package/gs/reflect/iter.ts +2 -2
- package/gs/reflect/map.test.ts +24 -2
- package/gs/reflect/map.ts +35 -0
- package/gs/reflect/type.ts +543 -60
- package/gs/reflect/typefor.test.ts +100 -0
- package/gs/reflect/types.ts +3 -1
- package/gs/reflect/value.ts +50 -1
- package/gs/reflect/visiblefields.ts +1 -1
- package/gs/runtime/debug/index.test.ts +22 -1
- package/gs/runtime/debug/index.ts +88 -0
- package/gs/runtime/pprof/index.test.ts +36 -0
- package/gs/runtime/pprof/index.ts +104 -0
- package/gs/runtime/pprof/meta.json +6 -0
- package/gs/runtime/trace/index.test.ts +45 -0
- package/gs/runtime/trace/index.ts +97 -0
- package/gs/runtime/trace/meta.json +7 -0
- package/gs/slices/meta.json +2 -1
- package/gs/slices/slices.test.ts +86 -0
- package/gs/slices/slices.ts +284 -37
- package/gs/sort/slice.gs.ts +73 -23
- package/gs/sort/slice.test.ts +40 -0
- package/gs/strings/builder.test.ts +8 -0
- package/gs/strings/builder.ts +29 -17
- package/gs/strings/iter.test.ts +5 -7
- package/gs/strings/iter.ts +146 -71
- package/gs/strings/replace.test.ts +1 -4
- package/gs/strings/replace.ts +6 -6
- package/gs/strings/strings.test.ts +4 -0
- package/gs/strings/strings.ts +54 -6
- package/gs/sync/meta.json +1 -0
- package/gs/sync/sync.test.ts +57 -1
- package/gs/sync/sync.ts +45 -13
- package/gs/syscall/errors.ts +158 -115
- package/gs/syscall/fs.ts +8 -8
- package/gs/syscall/js/index.ts +49 -22
- package/gs/syscall/net.test.ts +26 -0
- package/gs/syscall/types.ts +7 -2
- package/gs/testing/testing.test.ts +56 -0
- package/gs/testing/testing.ts +27 -10
- package/gs/time/meta.json +2 -2
- package/gs/time/time.test.ts +4 -0
- package/gs/time/time.ts +33 -2
- package/gs/unicode/unicode.test.ts +14 -3
- package/gs/unicode/unicode.ts +1 -5
- package/gs/unique/index.ts +9 -2
- package/package.json +3 -3
package/compiler/lowering.go
CHANGED
|
@@ -15,6 +15,7 @@ import (
|
|
|
15
15
|
"slices"
|
|
16
16
|
"strconv"
|
|
17
17
|
"strings"
|
|
18
|
+
"unicode/utf8"
|
|
18
19
|
)
|
|
19
20
|
|
|
20
21
|
// LoweringOwner owns conversion from the semantic model to compiler IR.
|
|
@@ -86,10 +87,13 @@ func (o *LoweringOwner) lowerPackage(model *SemanticModel, semPkg *semanticPacka
|
|
|
86
87
|
pkgPath: semPkg.pkgPath,
|
|
87
88
|
name: semPkg.name,
|
|
88
89
|
}
|
|
90
|
+
declFiles := packageDeclFiles(semPkg)
|
|
91
|
+
outputNames := packageOutputNames(semPkg)
|
|
92
|
+
lazyPackageVars := o.lazyPackageVars(semPkg, declFiles)
|
|
89
93
|
var diagnostics []Diagnostic
|
|
90
94
|
for idx, file := range semPkg.source.Syntax {
|
|
91
95
|
sourcePath := sourceFilePath(semPkg, idx, file)
|
|
92
|
-
loweredFile, fileDiagnostics := o.lowerFile(model, semPkg, file, sourcePath)
|
|
96
|
+
loweredFile, fileDiagnostics := o.lowerFile(model, semPkg, file, sourcePath, declFiles, outputNames, lazyPackageVars)
|
|
93
97
|
diagnostics = append(diagnostics, fileDiagnostics...)
|
|
94
98
|
if loweredFile != nil {
|
|
95
99
|
loweredPkg.files = append(loweredPkg.files, loweredFile)
|
|
@@ -118,6 +122,9 @@ func (o *LoweringOwner) lowerFile(
|
|
|
118
122
|
semPkg *semanticPackage,
|
|
119
123
|
file *ast.File,
|
|
120
124
|
sourcePath string,
|
|
125
|
+
declFiles map[types.Object]string,
|
|
126
|
+
outputNames map[string]string,
|
|
127
|
+
lazyPackageVars map[types.Object]bool,
|
|
121
128
|
) (*loweredFile, []Diagnostic) {
|
|
122
129
|
associatedMethods := o.methodDeclsForFileTypes(semPkg, file)
|
|
123
130
|
relevantImportFiles := map[string]bool{sourcePath: true}
|
|
@@ -138,7 +145,9 @@ func (o *LoweringOwner) lowerFile(
|
|
|
138
145
|
importAliases := make(map[string]string)
|
|
139
146
|
importPaths := make(map[string]string)
|
|
140
147
|
importNames := make(map[string]string)
|
|
141
|
-
|
|
148
|
+
importObjects := make(map[*types.PkgName]string)
|
|
149
|
+
localRefs := o.analyzeLocalFileReferences(semPkg, file, sourcePath, associatedMethods, declFiles, outputNames)
|
|
150
|
+
reservedImportAliases := localRefs.reservedNames
|
|
142
151
|
seenImport := make(map[string]bool)
|
|
143
152
|
for idx, importFile := range semPkg.source.Syntax {
|
|
144
153
|
importSourcePath := sourceFilePath(semPkg, idx, importFile)
|
|
@@ -170,36 +179,51 @@ func (o *LoweringOwner) lowerFile(
|
|
|
170
179
|
importAliases[alias] = pkgName.Imported().Path()
|
|
171
180
|
importPaths[pkgName.Imported().Path()] = alias
|
|
172
181
|
importNames[name] = alias
|
|
182
|
+
importObjects[pkgName] = alias
|
|
173
183
|
loweredFile.imports = append(loweredFile.imports, loweredImport{
|
|
174
|
-
alias:
|
|
175
|
-
source:
|
|
184
|
+
alias: alias,
|
|
185
|
+
source: source,
|
|
186
|
+
sideEffect: true,
|
|
176
187
|
})
|
|
177
188
|
}
|
|
178
189
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
localAliases, localAliasSources, implicitImports := o.localFileAliases(semPkg, file, sourcePath, associatedMethods)
|
|
183
|
-
lazyPackageVars := o.lazyPackageVars(semPkg)
|
|
184
|
-
implicitImportPaths := make([]string, 0, len(implicitImports))
|
|
185
|
-
for pkgPath := range implicitImports {
|
|
190
|
+
implicitImportPaths := make([]string, 0, len(localRefs.implicitImports))
|
|
191
|
+
for pkgPath := range localRefs.implicitImports {
|
|
186
192
|
if pkgPath != "" && pkgPath != semPkg.pkgPath {
|
|
187
193
|
implicitImportPaths = append(implicitImportPaths, pkgPath)
|
|
188
194
|
}
|
|
189
195
|
}
|
|
190
196
|
slices.Sort(implicitImportPaths)
|
|
191
197
|
for _, pkgPath := range implicitImportPaths {
|
|
192
|
-
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)
|
|
193
211
|
}
|
|
194
|
-
localImports := make([]loweredImport, 0, len(
|
|
212
|
+
localImports := make([]loweredImport, 0, len(localRefs.aliases))
|
|
195
213
|
seenLocalImport := make(map[string]bool)
|
|
196
|
-
for _, alias := range
|
|
214
|
+
for _, alias := range localRefs.aliases {
|
|
197
215
|
if seenLocalImport[alias] {
|
|
198
216
|
continue
|
|
199
217
|
}
|
|
200
218
|
seenLocalImport[alias] = true
|
|
201
|
-
source :=
|
|
202
|
-
|
|
219
|
+
source := localRefs.aliasSources[alias]
|
|
220
|
+
typeOnly := !localRefs.runtimeAliases[alias]
|
|
221
|
+
localImports = append(localImports, loweredImport{
|
|
222
|
+
alias: alias,
|
|
223
|
+
source: source,
|
|
224
|
+
sideEffect: !typeOnly,
|
|
225
|
+
typeOnly: typeOnly,
|
|
226
|
+
})
|
|
203
227
|
}
|
|
204
228
|
slices.SortFunc(localImports, func(a, b loweredImport) int {
|
|
205
229
|
return cmp.Compare(a.alias, b.alias)
|
|
@@ -213,15 +237,21 @@ func (o *LoweringOwner) lowerFile(
|
|
|
213
237
|
importAliases: importAliases,
|
|
214
238
|
importPaths: importPaths,
|
|
215
239
|
importNames: importNames,
|
|
240
|
+
importObjects: importObjects,
|
|
216
241
|
sourcePath: sourcePath,
|
|
217
|
-
localAliases:
|
|
242
|
+
localAliases: localRefs.aliases,
|
|
218
243
|
lazyPackageVars: lazyPackageVars,
|
|
219
244
|
tempNames: newTempNameOwner(),
|
|
220
245
|
topLevel: true,
|
|
221
246
|
}
|
|
222
247
|
var diagnostics []Diagnostic
|
|
248
|
+
var packageInitCalls []string
|
|
223
249
|
appendDecls := func(decls []loweredDecl) {
|
|
224
250
|
for _, decl := range decls {
|
|
251
|
+
if decl.packageInitCall != "" {
|
|
252
|
+
packageInitCalls = append(packageInitCalls, decl.packageInitCall)
|
|
253
|
+
continue
|
|
254
|
+
}
|
|
225
255
|
loweredFile.decls = append(loweredFile.decls, decl)
|
|
226
256
|
if decl.indexExport != "" {
|
|
227
257
|
loweredFile.exports = append(loweredFile.exports, decl.indexExport)
|
|
@@ -229,6 +259,9 @@ func (o *LoweringOwner) lowerFile(
|
|
|
229
259
|
if decl.typeIndexExport != "" {
|
|
230
260
|
loweredFile.typeExports = append(loweredFile.typeExports, decl.typeIndexExport)
|
|
231
261
|
}
|
|
262
|
+
if decl.sideEffect {
|
|
263
|
+
loweredFile.sideEffect = true
|
|
264
|
+
}
|
|
232
265
|
if decl.function != nil && decl.function.indexExported && decl.function.name != "main" {
|
|
233
266
|
loweredFile.exports = append(loweredFile.exports, decl.function.name)
|
|
234
267
|
}
|
|
@@ -252,6 +285,9 @@ func (o *LoweringOwner) lowerFile(
|
|
|
252
285
|
lowerDecl(decl)
|
|
253
286
|
}
|
|
254
287
|
}
|
|
288
|
+
for _, call := range packageInitCalls {
|
|
289
|
+
loweredFile.decls = append(loweredFile.decls, loweredDecl{code: "await " + call})
|
|
290
|
+
}
|
|
255
291
|
for _, decl := range loweredFile.decls {
|
|
256
292
|
if decl.function == nil || !decl.function.init {
|
|
257
293
|
continue
|
|
@@ -287,7 +323,7 @@ func (o *LoweringOwner) addGeneratedTypeImports(
|
|
|
287
323
|
}
|
|
288
324
|
slices.Sort(pkgPaths)
|
|
289
325
|
for _, pkgPath := range pkgPaths {
|
|
290
|
-
o.addGeneratedImportPath(model, pkgPath, loweredFile, importAliases, importPaths, reservedImportAliases, seenImport)
|
|
326
|
+
o.addGeneratedImportPath(model, pkgPath, loweredFile, importAliases, importPaths, reservedImportAliases, seenImport, true)
|
|
291
327
|
}
|
|
292
328
|
}
|
|
293
329
|
|
|
@@ -299,6 +335,7 @@ func (o *LoweringOwner) addGeneratedImportPath(
|
|
|
299
335
|
importPaths map[string]string,
|
|
300
336
|
reservedImportAliases map[string]bool,
|
|
301
337
|
seenImport map[string]bool,
|
|
338
|
+
typeOnly bool,
|
|
302
339
|
) {
|
|
303
340
|
if !o.hasGeneratedImportPackage(model, pkgPath) {
|
|
304
341
|
return
|
|
@@ -317,8 +354,10 @@ func (o *LoweringOwner) addGeneratedImportPath(
|
|
|
317
354
|
importAliases[alias] = pkgPath
|
|
318
355
|
importPaths[pkgPath] = alias
|
|
319
356
|
loweredFile.imports = append(loweredFile.imports, loweredImport{
|
|
320
|
-
alias:
|
|
321
|
-
source:
|
|
357
|
+
alias: alias,
|
|
358
|
+
source: source,
|
|
359
|
+
sideEffect: !typeOnly,
|
|
360
|
+
typeOnly: typeOnly,
|
|
322
361
|
})
|
|
323
362
|
}
|
|
324
363
|
|
|
@@ -351,36 +390,6 @@ func uniqueImportAlias(alias string, pkgPath string, importAliases map[string]st
|
|
|
351
390
|
}
|
|
352
391
|
}
|
|
353
392
|
|
|
354
|
-
func localDeclarationNames(semPkg *semanticPackage, file *ast.File, associatedMethods []*ast.FuncDecl) map[string]bool {
|
|
355
|
-
if semPkg == nil || semPkg.source == nil {
|
|
356
|
-
return nil
|
|
357
|
-
}
|
|
358
|
-
names := make(map[string]bool)
|
|
359
|
-
inspect := func(node ast.Node) bool {
|
|
360
|
-
ident, ok := node.(*ast.Ident)
|
|
361
|
-
if !ok {
|
|
362
|
-
return true
|
|
363
|
-
}
|
|
364
|
-
obj := semPkg.source.TypesInfo.Defs[ident]
|
|
365
|
-
if obj == nil {
|
|
366
|
-
return true
|
|
367
|
-
}
|
|
368
|
-
if _, ok := obj.(*types.PkgName); ok {
|
|
369
|
-
return true
|
|
370
|
-
}
|
|
371
|
-
name := safeIdentifier(obj.Name())
|
|
372
|
-
if name != "_" {
|
|
373
|
-
names[name] = true
|
|
374
|
-
}
|
|
375
|
-
return true
|
|
376
|
-
}
|
|
377
|
-
ast.Inspect(file, inspect)
|
|
378
|
-
for _, methodDecl := range associatedMethods {
|
|
379
|
-
ast.Inspect(methodDecl, inspect)
|
|
380
|
-
}
|
|
381
|
-
return names
|
|
382
|
-
}
|
|
383
|
-
|
|
384
393
|
func (o *LoweringOwner) methodDeclsForFileTypes(semPkg *semanticPackage, file *ast.File) []*ast.FuncDecl {
|
|
385
394
|
if semPkg == nil || semPkg.source == nil || file == nil {
|
|
386
395
|
return nil
|
|
@@ -433,54 +442,89 @@ func (o *LoweringOwner) methodDeclsForFileTypes(semPkg *semanticPackage, file *a
|
|
|
433
442
|
return methods
|
|
434
443
|
}
|
|
435
444
|
|
|
436
|
-
|
|
445
|
+
type localFileReferenceAnalysis struct {
|
|
446
|
+
reservedNames map[string]bool
|
|
447
|
+
aliases map[types.Object]string
|
|
448
|
+
aliasSources map[string]string
|
|
449
|
+
runtimeAliases map[string]bool
|
|
450
|
+
implicitImports map[string]bool
|
|
451
|
+
implicitRuntime map[string]bool
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
func (o *LoweringOwner) analyzeLocalFileReferences(
|
|
437
455
|
semPkg *semanticPackage,
|
|
438
456
|
file *ast.File,
|
|
439
457
|
sourcePath string,
|
|
440
458
|
associatedMethods []*ast.FuncDecl,
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
outputSourcePath := sourceFilePath(semPkg, idx, syntax)
|
|
452
|
-
outputNames[outputSourcePath] = sourceOutputName(outputSourcePath)
|
|
459
|
+
declFiles map[types.Object]string,
|
|
460
|
+
outputNames map[string]string,
|
|
461
|
+
) localFileReferenceAnalysis {
|
|
462
|
+
analysis := localFileReferenceAnalysis{
|
|
463
|
+
reservedNames: make(map[string]bool),
|
|
464
|
+
aliases: make(map[types.Object]string),
|
|
465
|
+
aliasSources: make(map[string]string),
|
|
466
|
+
runtimeAliases: make(map[string]bool),
|
|
467
|
+
implicitImports: make(map[string]bool),
|
|
468
|
+
implicitRuntime: make(map[string]bool),
|
|
453
469
|
}
|
|
454
|
-
aliases := make(map[types.Object]string)
|
|
455
|
-
aliasSources := make(map[string]string)
|
|
456
|
-
implicitImports := make(map[string]bool)
|
|
457
470
|
seenObjects := make(map[types.Object]bool)
|
|
458
471
|
seenTypes := make(map[types.Type]bool)
|
|
459
472
|
var addTypeDeps func(typ types.Type)
|
|
460
|
-
var
|
|
461
|
-
|
|
462
|
-
|
|
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 {
|
|
463
478
|
return
|
|
464
479
|
}
|
|
465
|
-
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
|
+
}
|
|
466
485
|
return
|
|
467
486
|
}
|
|
468
|
-
seenObjects[obj] = true
|
|
469
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
|
+
}
|
|
470
495
|
if declFile != "" && declFile != sourcePath {
|
|
471
496
|
outputName := outputNames[declFile]
|
|
472
497
|
if outputName != "" {
|
|
473
498
|
alias := "__goscript_" + safeIdentifier(strings.TrimSuffix(outputName, ".gs.ts"))
|
|
474
|
-
aliases[obj] = alias
|
|
475
|
-
aliasSources[alias] = "./" + outputName
|
|
499
|
+
analysis.aliases[obj] = alias
|
|
500
|
+
analysis.aliasSources[alias] = "./" + outputName
|
|
501
|
+
if runtime {
|
|
502
|
+
analysis.runtimeAliases[alias] = true
|
|
503
|
+
}
|
|
476
504
|
}
|
|
477
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
|
|
478
515
|
switch typed := obj.(type) {
|
|
479
516
|
case *types.TypeName:
|
|
480
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
|
+
}
|
|
481
525
|
if named, ok := types.Unalias(typed.Type()).(*types.Named); ok {
|
|
482
526
|
for method := range named.Methods() {
|
|
483
|
-
addObject(method)
|
|
527
|
+
addObject(method, false)
|
|
484
528
|
}
|
|
485
529
|
}
|
|
486
530
|
case *types.Var:
|
|
@@ -514,7 +558,7 @@ func (o *LoweringOwner) localFileAliases(
|
|
|
514
558
|
seenTypes[typ] = true
|
|
515
559
|
if alias, ok := typ.(*types.Alias); ok {
|
|
516
560
|
if obj := alias.Obj(); obj != nil && obj.Pkg() != nil && obj.Pkg().Path() != semPkg.pkgPath {
|
|
517
|
-
implicitImports[obj.Pkg().Path()] = true
|
|
561
|
+
analysis.implicitImports[obj.Pkg().Path()] = true
|
|
518
562
|
if args := alias.TypeArgs(); args != nil {
|
|
519
563
|
for t := range args.Types() {
|
|
520
564
|
addTypeDeps(t)
|
|
@@ -523,7 +567,7 @@ func (o *LoweringOwner) localFileAliases(
|
|
|
523
567
|
addTypeDeps(alias.Rhs())
|
|
524
568
|
return
|
|
525
569
|
}
|
|
526
|
-
addObject(alias.Obj())
|
|
570
|
+
addObject(alias.Obj(), false)
|
|
527
571
|
if args := alias.TypeArgs(); args != nil {
|
|
528
572
|
for t := range args.Types() {
|
|
529
573
|
addTypeDeps(t)
|
|
@@ -534,7 +578,7 @@ func (o *LoweringOwner) localFileAliases(
|
|
|
534
578
|
}
|
|
535
579
|
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
536
580
|
if obj := named.Obj(); obj != nil && obj.Pkg() != nil && obj.Pkg().Path() != semPkg.pkgPath {
|
|
537
|
-
implicitImports[obj.Pkg().Path()] = true
|
|
581
|
+
analysis.implicitImports[obj.Pkg().Path()] = true
|
|
538
582
|
if args := named.TypeArgs(); args != nil {
|
|
539
583
|
for t := range args.Types() {
|
|
540
584
|
addTypeDeps(t)
|
|
@@ -542,7 +586,7 @@ func (o *LoweringOwner) localFileAliases(
|
|
|
542
586
|
}
|
|
543
587
|
return
|
|
544
588
|
}
|
|
545
|
-
addObject(named.Obj())
|
|
589
|
+
addObject(named.Obj(), false)
|
|
546
590
|
if args := named.TypeArgs(); args != nil {
|
|
547
591
|
for t := range args.Types() {
|
|
548
592
|
addTypeDeps(t)
|
|
@@ -588,20 +632,142 @@ func (o *LoweringOwner) localFileAliases(
|
|
|
588
632
|
}
|
|
589
633
|
}
|
|
590
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
|
+
}
|
|
591
716
|
inspect := func(node ast.Node) bool {
|
|
592
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
|
+
}
|
|
593
722
|
case *ast.Ident:
|
|
594
|
-
|
|
723
|
+
if obj := semPkg.source.TypesInfo.Defs[typed]; obj != nil {
|
|
724
|
+
if _, ok := obj.(*types.PkgName); !ok {
|
|
725
|
+
name := safeIdentifier(obj.Name())
|
|
726
|
+
if name != "_" {
|
|
727
|
+
analysis.reservedNames[name] = true
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
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
|
+
}
|
|
746
|
+
addTypeDeps(selection.Obj().Type())
|
|
599
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
|
+
}
|
|
600
751
|
addTypeDeps(obj.Type())
|
|
601
752
|
}
|
|
602
753
|
if pointer, ok := types.Unalias(semPkg.source.TypesInfo.TypeOf(typed.X)).Underlying().(*types.Pointer); ok {
|
|
603
754
|
addTypeDeps(pointer.Elem())
|
|
604
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))
|
|
605
771
|
}
|
|
606
772
|
return true
|
|
607
773
|
}
|
|
@@ -609,7 +775,163 @@ func (o *LoweringOwner) localFileAliases(
|
|
|
609
775
|
for _, methodDecl := range associatedMethods {
|
|
610
776
|
ast.Inspect(methodDecl, inspect)
|
|
611
777
|
}
|
|
612
|
-
return
|
|
778
|
+
return analysis
|
|
779
|
+
}
|
|
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
|
|
613
935
|
}
|
|
614
936
|
|
|
615
937
|
func safeIdentifier(value string) string {
|
|
@@ -668,12 +990,16 @@ type lowerFileContext struct {
|
|
|
668
990
|
importAliases map[string]string
|
|
669
991
|
importPaths map[string]string
|
|
670
992
|
importNames map[string]string
|
|
993
|
+
importObjects map[*types.PkgName]string
|
|
671
994
|
sourcePath string
|
|
672
995
|
localAliases map[types.Object]string
|
|
673
996
|
lazyPackageVars map[types.Object]bool
|
|
674
997
|
identAliases map[types.Object]string
|
|
998
|
+
identAliasRefs map[types.Object]bool
|
|
675
999
|
tempNames *tempNameOwner
|
|
676
1000
|
signature *types.Signature
|
|
1001
|
+
typeParams map[string]bool
|
|
1002
|
+
staticTypeParams map[string]bool
|
|
677
1003
|
asyncFunction bool
|
|
678
1004
|
functionTypeDepth int
|
|
679
1005
|
deferState *loweredDeferState
|
|
@@ -694,6 +1020,30 @@ type tempNameOwner struct {
|
|
|
694
1020
|
counters map[string]int
|
|
695
1021
|
}
|
|
696
1022
|
|
|
1023
|
+
func (ctx lowerFileContext) canReferenceNamedType(named *types.Named) bool {
|
|
1024
|
+
if named == nil || named.Obj() == nil {
|
|
1025
|
+
return true
|
|
1026
|
+
}
|
|
1027
|
+
return ctx.canReferenceObjectPackage(named.Obj())
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
func (ctx lowerFileContext) canReferenceObjectPackage(obj types.Object) bool {
|
|
1031
|
+
if obj == nil || obj.Pkg() == nil || ctx.semPkg == nil {
|
|
1032
|
+
return true
|
|
1033
|
+
}
|
|
1034
|
+
pkgPath := obj.Pkg().Path()
|
|
1035
|
+
if pkgPath == "" || pkgPath == ctx.semPkg.pkgPath {
|
|
1036
|
+
return true
|
|
1037
|
+
}
|
|
1038
|
+
if ctx.importPaths[pkgPath] != "" {
|
|
1039
|
+
return true
|
|
1040
|
+
}
|
|
1041
|
+
if ctx.localAliases[obj] != "" {
|
|
1042
|
+
return true
|
|
1043
|
+
}
|
|
1044
|
+
return false
|
|
1045
|
+
}
|
|
1046
|
+
|
|
697
1047
|
func newTempNameOwner() *tempNameOwner {
|
|
698
1048
|
return &tempNameOwner{counters: make(map[string]int)}
|
|
699
1049
|
}
|
|
@@ -720,6 +1070,20 @@ func (ctx lowerFileContext) withIdentAliases(aliases map[types.Object]string) lo
|
|
|
720
1070
|
return ctx
|
|
721
1071
|
}
|
|
722
1072
|
|
|
1073
|
+
func (ctx lowerFileContext) withIdentRefAliases(aliases map[types.Object]string) lowerFileContext {
|
|
1074
|
+
if len(aliases) == 0 {
|
|
1075
|
+
return ctx
|
|
1076
|
+
}
|
|
1077
|
+
ctx = ctx.withIdentAliases(aliases)
|
|
1078
|
+
refs := make(map[types.Object]bool, len(ctx.identAliasRefs)+len(aliases))
|
|
1079
|
+
maps.Copy(refs, ctx.identAliasRefs)
|
|
1080
|
+
for obj := range aliases {
|
|
1081
|
+
refs[obj] = true
|
|
1082
|
+
}
|
|
1083
|
+
ctx.identAliasRefs = refs
|
|
1084
|
+
return ctx
|
|
1085
|
+
}
|
|
1086
|
+
|
|
723
1087
|
func (o *tempNameOwner) next(prefix string) string {
|
|
724
1088
|
idx := o.counters[prefix]
|
|
725
1089
|
o.counters[prefix] = idx + 1
|
|
@@ -825,8 +1189,8 @@ func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([
|
|
|
825
1189
|
lazy := ctx.topLevel && ctx.lazyPackageVars[obj]
|
|
826
1190
|
code := keyword + " " + declName + ": " + variableType + " = " + value
|
|
827
1191
|
if lazy {
|
|
828
|
-
keyword = "
|
|
829
|
-
code = "
|
|
1192
|
+
keyword = "var"
|
|
1193
|
+
code = "var " + declName + ": " + variableType + " = undefined as unknown as " + variableType
|
|
830
1194
|
}
|
|
831
1195
|
indexExport := ""
|
|
832
1196
|
if ctx.topLevel && name.Name != "_" {
|
|
@@ -838,9 +1202,29 @@ func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([
|
|
|
838
1202
|
decls = append(decls, loweredDecl{code: code, indexExport: indexExport})
|
|
839
1203
|
if lazy {
|
|
840
1204
|
getterName := packageVarGetterName(name.Name)
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
1205
|
+
initName := packageVarInitName(name.Name)
|
|
1206
|
+
initIndexExport := ""
|
|
1207
|
+
if ast.IsExported(name.Name) {
|
|
1208
|
+
initIndexExport = initName
|
|
1209
|
+
}
|
|
1210
|
+
getterCode := "export function " + getterName + "(): " + variableType + " {\n\t"
|
|
1211
|
+
if strings.Contains(value, "await ") {
|
|
1212
|
+
initCode := "export async function " + initName + "(): globalThis.Promise<void> {\n\t" +
|
|
1213
|
+
"if (((" + declName + ") as any) === undefined) {\n\t\t" +
|
|
1214
|
+
declName + " = " + value + "\n\t}\n}"
|
|
1215
|
+
decls = append(decls, loweredDecl{code: initCode, indexExport: initIndexExport})
|
|
1216
|
+
decls = append(decls, loweredDecl{packageInitCall: initName + "()"})
|
|
1217
|
+
getterCode += "if (((" + declName + ") as any) === undefined) {\n\t\t" +
|
|
1218
|
+
"throw new Error(" + strconv.Quote("goscript package variable "+name.Name+" read before initialization") + ")\n\t}\n"
|
|
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})
|
|
1224
|
+
getterCode += "if (((" + declName + ") as any) === undefined) {\n\t\t" +
|
|
1225
|
+
initName + "()\n\t}\n"
|
|
1226
|
+
}
|
|
1227
|
+
getterCode += "\treturn " + declName + "\n}"
|
|
844
1228
|
getterIndexExport := ""
|
|
845
1229
|
if ast.IsExported(name.Name) {
|
|
846
1230
|
getterIndexExport = getterName
|
|
@@ -852,10 +1236,15 @@ func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([
|
|
|
852
1236
|
setterType := o.tsPackageVarSetterValueTypeFor(ctx, obj.Type())
|
|
853
1237
|
setterTarget := declName
|
|
854
1238
|
if ctx.model.needsVarRef[obj] {
|
|
855
|
-
|
|
1239
|
+
if lazy {
|
|
1240
|
+
setterTarget = packageVarGetterName(name.Name) + "().value"
|
|
1241
|
+
} else {
|
|
1242
|
+
setterTarget += ".value"
|
|
1243
|
+
}
|
|
856
1244
|
}
|
|
857
|
-
|
|
858
|
-
|
|
1245
|
+
setterValue := "__goscriptValue"
|
|
1246
|
+
setterCode := "export function " + setterName + "(" + setterValue + ": " + setterType + "): void {\n\t" +
|
|
1247
|
+
setterTarget + " = " + setterValue + "\n}"
|
|
859
1248
|
setterIndexExport := ""
|
|
860
1249
|
if ast.IsExported(name.Name) {
|
|
861
1250
|
setterIndexExport = setterName
|
|
@@ -909,6 +1298,9 @@ func initializerMayHaveRuntimeEffects(ctx lowerFileContext, expr ast.Expr) bool
|
|
|
909
1298
|
}
|
|
910
1299
|
switch typed := node.(type) {
|
|
911
1300
|
case *ast.CallExpr:
|
|
1301
|
+
if isEffectFreePackageInitializerCall(ctx, typed) {
|
|
1302
|
+
return true
|
|
1303
|
+
}
|
|
912
1304
|
if callTargetSignature(ctx, typed.Fun) != nil {
|
|
913
1305
|
hasEffects = true
|
|
914
1306
|
return false
|
|
@@ -924,23 +1316,322 @@ func initializerMayHaveRuntimeEffects(ctx lowerFileContext, expr ast.Expr) bool
|
|
|
924
1316
|
return hasEffects
|
|
925
1317
|
}
|
|
926
1318
|
|
|
927
|
-
func (
|
|
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
|
+
|
|
1401
|
+
func packageDeclFiles(semPkg *semanticPackage) map[types.Object]string {
|
|
1402
|
+
if semPkg == nil || semPkg.source == nil {
|
|
1403
|
+
return nil
|
|
1404
|
+
}
|
|
1405
|
+
declFiles := make(map[types.Object]string)
|
|
1406
|
+
for _, decl := range semPkg.declarations {
|
|
1407
|
+
if decl.object != nil && decl.position.file != "" {
|
|
1408
|
+
declFiles[decl.object] = decl.position.file
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
return declFiles
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
func packageOutputNames(semPkg *semanticPackage) map[string]string {
|
|
1415
|
+
if semPkg == nil || semPkg.source == nil {
|
|
1416
|
+
return nil
|
|
1417
|
+
}
|
|
1418
|
+
outputNames := make(map[string]string, len(semPkg.source.Syntax))
|
|
1419
|
+
for idx, syntax := range semPkg.source.Syntax {
|
|
1420
|
+
outputSourcePath := sourceFilePath(semPkg, idx, syntax)
|
|
1421
|
+
outputNames[outputSourcePath] = sourceOutputName(outputSourcePath)
|
|
1422
|
+
}
|
|
1423
|
+
return outputNames
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
func (o *LoweringOwner) lazyPackageVars(semPkg *semanticPackage, declFiles map[types.Object]string) map[types.Object]bool {
|
|
928
1427
|
if semPkg == nil || semPkg.source == nil {
|
|
929
1428
|
return nil
|
|
930
1429
|
}
|
|
931
|
-
|
|
932
|
-
for
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
1430
|
+
varOrder := make(map[types.Object]int)
|
|
1431
|
+
for idx, obj := range semPkg.initOrder {
|
|
1432
|
+
varOrder[obj] = idx
|
|
1433
|
+
}
|
|
1434
|
+
funcRefs := packageVarsReferencedFromOtherFileTopLevelCalls(semPkg, declFiles)
|
|
1435
|
+
lazy := make(map[types.Object]bool)
|
|
1436
|
+
for idx, file := range semPkg.source.Syntax {
|
|
1437
|
+
sourcePath := sourceFilePath(semPkg, idx, file)
|
|
1438
|
+
for _, decl := range file.Decls {
|
|
1439
|
+
genDecl, ok := decl.(*ast.GenDecl)
|
|
1440
|
+
if !ok || genDecl.Tok != token.VAR {
|
|
1441
|
+
continue
|
|
1442
|
+
}
|
|
1443
|
+
for _, spec := range genDecl.Specs {
|
|
1444
|
+
valueSpec, ok := spec.(*ast.ValueSpec)
|
|
1445
|
+
if !ok {
|
|
1446
|
+
continue
|
|
1447
|
+
}
|
|
1448
|
+
for valueIdx, name := range valueSpec.Names {
|
|
1449
|
+
obj, _ := semPkg.source.TypesInfo.Defs[name].(*types.Var)
|
|
1450
|
+
if obj == nil {
|
|
1451
|
+
continue
|
|
1452
|
+
}
|
|
1453
|
+
if valueIdx < len(valueSpec.Values) &&
|
|
1454
|
+
initializerReferencesLaterPackageVar(semPkg, varOrder, obj, valueSpec.Values[valueIdx]) {
|
|
1455
|
+
lazy[obj] = true
|
|
1456
|
+
continue
|
|
1457
|
+
}
|
|
1458
|
+
if valueIdx < len(valueSpec.Values) &&
|
|
1459
|
+
initializerReferencesOtherFileObject(semPkg, declFiles, sourcePath, valueSpec.Values[valueIdx]) {
|
|
1460
|
+
lazy[obj] = true
|
|
1461
|
+
continue
|
|
1462
|
+
}
|
|
1463
|
+
if valueIdx < len(valueSpec.Values) &&
|
|
1464
|
+
initializerCallsFunctionReferencingLaterPackageVar(semPkg, varOrder, obj, valueSpec.Values[valueIdx]) {
|
|
1465
|
+
lazy[obj] = true
|
|
1466
|
+
continue
|
|
1467
|
+
}
|
|
1468
|
+
if valueIdx >= len(valueSpec.Values) &&
|
|
1469
|
+
zeroValueReferencesOtherFileObject(semPkg, declFiles, sourcePath, obj.Type()) {
|
|
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
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
return lazy
|
|
1483
|
+
}
|
|
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
|
|
936
1628
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1629
|
+
semPkg := ctx.model.packages[pkgPath]
|
|
1630
|
+
if semPkg == nil || semPkg.source == nil {
|
|
1631
|
+
return false
|
|
940
1632
|
}
|
|
941
|
-
|
|
942
|
-
for
|
|
943
|
-
sourcePath := sourceFilePath(semPkg, idx, file)
|
|
1633
|
+
initCtx := lowerFileContext{model: ctx.model, semPkg: semPkg, topLevel: true}
|
|
1634
|
+
for _, file := range semPkg.source.Syntax {
|
|
944
1635
|
for _, decl := range file.Decls {
|
|
945
1636
|
genDecl, ok := decl.(*ast.GenDecl)
|
|
946
1637
|
if !ok || genDecl.Tok != token.VAR {
|
|
@@ -951,30 +1642,51 @@ func (o *LoweringOwner) lazyPackageVars(semPkg *semanticPackage) map[types.Objec
|
|
|
951
1642
|
if !ok {
|
|
952
1643
|
continue
|
|
953
1644
|
}
|
|
954
|
-
for
|
|
955
|
-
|
|
956
|
-
if obj == nil {
|
|
957
|
-
continue
|
|
958
|
-
}
|
|
959
|
-
if valueIdx < len(valueSpec.Values) &&
|
|
960
|
-
initializerReferencesOtherFileObject(semPkg, declFiles, sourcePath, valueSpec.Values[valueIdx]) {
|
|
961
|
-
lazy[obj] = true
|
|
962
|
-
continue
|
|
963
|
-
}
|
|
964
|
-
if valueIdx < len(valueSpec.Values) &&
|
|
965
|
-
initializerCallsFunctionReferencingLaterPackageVar(semPkg, varOrder, obj, valueSpec.Values[valueIdx]) {
|
|
966
|
-
lazy[obj] = true
|
|
1645
|
+
for idx, ident := range valueSpec.Names {
|
|
1646
|
+
if ident.Name != name || idx >= len(valueSpec.Values) {
|
|
967
1647
|
continue
|
|
968
1648
|
}
|
|
969
|
-
|
|
970
|
-
zeroValueReferencesOtherFileObject(semPkg, declFiles, sourcePath, obj.Type()) {
|
|
971
|
-
lazy[obj] = true
|
|
972
|
-
}
|
|
1649
|
+
return o.topLevelInitializerNeedsAwait(initCtx, valueSpec.Values[idx])
|
|
973
1650
|
}
|
|
974
1651
|
}
|
|
975
1652
|
}
|
|
976
1653
|
}
|
|
977
|
-
return
|
|
1654
|
+
return false
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
func initializerReferencesLaterPackageVar(
|
|
1658
|
+
semPkg *semanticPackage,
|
|
1659
|
+
varOrder map[types.Object]int,
|
|
1660
|
+
current types.Object,
|
|
1661
|
+
expr ast.Expr,
|
|
1662
|
+
) bool {
|
|
1663
|
+
currentIdx, ok := varOrder[current]
|
|
1664
|
+
if !ok {
|
|
1665
|
+
return false
|
|
1666
|
+
}
|
|
1667
|
+
references := false
|
|
1668
|
+
ast.Inspect(expr, func(node ast.Node) bool {
|
|
1669
|
+
if references {
|
|
1670
|
+
return false
|
|
1671
|
+
}
|
|
1672
|
+
if _, ok := node.(*ast.FuncLit); ok {
|
|
1673
|
+
return false
|
|
1674
|
+
}
|
|
1675
|
+
ident, ok := node.(*ast.Ident)
|
|
1676
|
+
if !ok {
|
|
1677
|
+
return true
|
|
1678
|
+
}
|
|
1679
|
+
obj, ok := semPkg.source.TypesInfo.Uses[ident].(*types.Var)
|
|
1680
|
+
if !ok || obj.Pkg() == nil || obj.Pkg().Path() != semPkg.pkgPath {
|
|
1681
|
+
return true
|
|
1682
|
+
}
|
|
1683
|
+
if idx, ok := varOrder[obj]; ok && idx > currentIdx {
|
|
1684
|
+
references = true
|
|
1685
|
+
return false
|
|
1686
|
+
}
|
|
1687
|
+
return true
|
|
1688
|
+
})
|
|
1689
|
+
return references
|
|
978
1690
|
}
|
|
979
1691
|
|
|
980
1692
|
func initializerCallsFunctionReferencingLaterPackageVar(
|
|
@@ -1164,7 +1876,7 @@ func (o *LoweringOwner) lowerTupleValueSpec(
|
|
|
1164
1876
|
tupleExpr := tempName
|
|
1165
1877
|
if lazyTuple {
|
|
1166
1878
|
tupleGetterName := packageVarGetterName(tempName)
|
|
1167
|
-
decls = append(decls, loweredDecl{code: "
|
|
1879
|
+
decls = append(decls, loweredDecl{code: "var " + tempName + ": any = undefined as any"})
|
|
1168
1880
|
decls = append(decls, loweredDecl{code: "function " + tupleGetterName + "(): any {\n\t" +
|
|
1169
1881
|
"if (((" + tempName + ") as any) === undefined) {\n\t\t" +
|
|
1170
1882
|
tempName + " = " + right + "\n\t}\n\treturn " + tempName + "\n}"})
|
|
@@ -1189,8 +1901,8 @@ func (o *LoweringOwner) lowerTupleValueSpec(
|
|
|
1189
1901
|
code := keyword + " " + o.lowerIdent(ctx, name, true) + ": " + variableType + " = " + value
|
|
1190
1902
|
lazy := lazyTuple || ctx.topLevel && ctx.lazyPackageVars[obj]
|
|
1191
1903
|
if lazy {
|
|
1192
|
-
keyword = "
|
|
1193
|
-
code = "
|
|
1904
|
+
keyword = "var"
|
|
1905
|
+
code = "var " + o.lowerIdent(ctx, name, true) + ": " + variableType + " = undefined as unknown as " + variableType
|
|
1194
1906
|
}
|
|
1195
1907
|
indexExport := ""
|
|
1196
1908
|
if ctx.topLevel {
|
|
@@ -1223,7 +1935,7 @@ func lowerConstantValue(value constant.Value) (string, bool) {
|
|
|
1223
1935
|
case constant.Bool:
|
|
1224
1936
|
return strconv.FormatBool(constant.BoolVal(value)), true
|
|
1225
1937
|
case constant.String:
|
|
1226
|
-
return
|
|
1938
|
+
return lowerGoStringLiteral(constant.StringVal(value)), true
|
|
1227
1939
|
case constant.Int:
|
|
1228
1940
|
if intValue, ok := constant.Int64Val(value); ok {
|
|
1229
1941
|
return strconv.FormatInt(intValue, 10), true
|
|
@@ -1237,7 +1949,7 @@ func lowerConstantValue(value constant.Value) (string, bool) {
|
|
|
1237
1949
|
case constant.Complex:
|
|
1238
1950
|
real := constant.Real(value).ExactString()
|
|
1239
1951
|
imag := constant.Imag(value).ExactString()
|
|
1240
|
-
return "(
|
|
1952
|
+
return "$.complex(" + real + ", " + imag + ")", true
|
|
1241
1953
|
default:
|
|
1242
1954
|
return "", false
|
|
1243
1955
|
}
|
|
@@ -1333,6 +2045,13 @@ func byteSliceLiteral(data []byte) string {
|
|
|
1333
2045
|
return "new Uint8Array([" + strings.Join(values, ", ") + "])"
|
|
1334
2046
|
}
|
|
1335
2047
|
|
|
2048
|
+
func lowerGoStringLiteral(value string) string {
|
|
2049
|
+
if utf8.ValidString(value) {
|
|
2050
|
+
return strconv.Quote(value)
|
|
2051
|
+
}
|
|
2052
|
+
return "$.bytesToString(" + byteSliceLiteral([]byte(value)) + ")"
|
|
2053
|
+
}
|
|
2054
|
+
|
|
1336
2055
|
func (o *LoweringOwner) lowerTypeSpec(ctx lowerFileContext, spec *ast.TypeSpec) (loweredDecl, []Diagnostic) {
|
|
1337
2056
|
obj, _ := ctx.semPkg.source.TypesInfo.Defs[spec.Name].(*types.TypeName)
|
|
1338
2057
|
if obj == nil {
|
|
@@ -1372,12 +2091,13 @@ func (o *LoweringOwner) lowerTypeSpec(ctx lowerFileContext, spec *ast.TypeSpec)
|
|
|
1372
2091
|
if signature, ok := named.Underlying().(*types.Signature); ok {
|
|
1373
2092
|
loweredType = o.tsAsyncCompatibleFunctionTypeFor(ctx, signature)
|
|
1374
2093
|
}
|
|
1375
|
-
|
|
2094
|
+
typeName := safeIdentifier(semType.name)
|
|
2095
|
+
code := "type " + typeName + " = " + loweredType
|
|
1376
2096
|
typeIndexExport := ""
|
|
1377
2097
|
if ctx.topLevel {
|
|
1378
2098
|
code = "export " + code
|
|
1379
2099
|
if ast.IsExported(semType.name) {
|
|
1380
|
-
typeIndexExport =
|
|
2100
|
+
typeIndexExport = typeName
|
|
1381
2101
|
}
|
|
1382
2102
|
}
|
|
1383
2103
|
return loweredDecl{code: code, typeIndexExport: typeIndexExport}, nil
|
|
@@ -1385,18 +2105,19 @@ func (o *LoweringOwner) lowerTypeSpec(ctx lowerFileContext, spec *ast.TypeSpec)
|
|
|
1385
2105
|
|
|
1386
2106
|
func (o *LoweringOwner) lowerInterfaceType(ctx lowerFileContext, semType *semanticType, iface *types.Interface) loweredDecl {
|
|
1387
2107
|
iface.Complete()
|
|
1388
|
-
|
|
2108
|
+
typeName := safeIdentifier(semType.name)
|
|
2109
|
+
code := "type " + typeName + " = " + o.tsInterfaceType(ctx, iface)
|
|
1389
2110
|
typeIndexExport := ""
|
|
1390
2111
|
if ctx.topLevel {
|
|
1391
2112
|
code = "export " + code
|
|
1392
2113
|
if ast.IsExported(semType.name) {
|
|
1393
|
-
typeIndexExport =
|
|
2114
|
+
typeIndexExport = typeName
|
|
1394
2115
|
}
|
|
1395
2116
|
}
|
|
1396
2117
|
code = code + "\n\n" + o.runtimeOwner.QualifiedHelper(RuntimeHelperRegisterInterfaceType) +
|
|
1397
2118
|
"(\n\t" + strconv.Quote(runtimeNamedTypeName(semType.named)) +
|
|
1398
2119
|
",\n\tnull,\n\t" + o.runtimeMethodSignatures(iface) + "\n)"
|
|
1399
|
-
return loweredDecl{code: code, typeIndexExport: typeIndexExport}
|
|
2120
|
+
return loweredDecl{code: code, typeIndexExport: typeIndexExport, sideEffect: true}
|
|
1400
2121
|
}
|
|
1401
2122
|
|
|
1402
2123
|
func (o *LoweringOwner) tsInterfaceType(ctx lowerFileContext, iface *types.Interface) string {
|
|
@@ -1407,7 +2128,7 @@ func (o *LoweringOwner) tsInterfaceType(ctx lowerFileContext, iface *types.Inter
|
|
|
1407
2128
|
for method := range iface.Methods() {
|
|
1408
2129
|
methods = append(methods, o.tsMethodSignature(ctx, method))
|
|
1409
2130
|
}
|
|
1410
|
-
return "
|
|
2131
|
+
return "{\n\t" + strings.Join(methods, "\n\t") + "\n}"
|
|
1411
2132
|
}
|
|
1412
2133
|
|
|
1413
2134
|
func (o *LoweringOwner) tsMethodSignature(ctx lowerFileContext, method *types.Func) string {
|
|
@@ -1417,7 +2138,7 @@ func (o *LoweringOwner) tsMethodSignature(ctx lowerFileContext, method *types.Fu
|
|
|
1417
2138
|
}
|
|
1418
2139
|
async := o.functionAsync(ctx, method)
|
|
1419
2140
|
return method.Name() + "(" + o.tsSignatureParamsFor(ctx, signature, async) + "): " +
|
|
1420
|
-
|
|
2141
|
+
asyncCompatibleMethodResultType(o.tsSignatureResultFor(ctx, signature), async)
|
|
1421
2142
|
}
|
|
1422
2143
|
|
|
1423
2144
|
func (o *LoweringOwner) runtimeMethodSignatures(iface *types.Interface) string {
|
|
@@ -1478,11 +2199,15 @@ func (o *LoweringOwner) lowerStructType(ctx lowerFileContext, semType *semanticT
|
|
|
1478
2199
|
lowered := &loweredStruct{
|
|
1479
2200
|
exported: ctx.topLevel,
|
|
1480
2201
|
indexExported: ctx.topLevel && ast.IsExported(semType.name),
|
|
1481
|
-
name: semType.name,
|
|
2202
|
+
name: safeIdentifier(semType.name),
|
|
1482
2203
|
typeName: runtimeNamedTypeName(semType.named),
|
|
1483
2204
|
cloneMethod: "clone",
|
|
1484
2205
|
}
|
|
1485
2206
|
for idx, field := range semType.fields {
|
|
2207
|
+
structValue := isStructValueType(field.typ)
|
|
2208
|
+
if named := namedStructType(field.typ); named != nil && crossPackageUnexportedNamedType(ctx, named) {
|
|
2209
|
+
structValue = false
|
|
2210
|
+
}
|
|
1486
2211
|
fieldName := tsStructFieldName(field.name, idx)
|
|
1487
2212
|
runtimeName := ""
|
|
1488
2213
|
if fieldName != field.name {
|
|
@@ -1496,11 +2221,18 @@ func (o *LoweringOwner) lowerStructType(ctx lowerFileContext, semType *semanticT
|
|
|
1496
2221
|
runtimeType: o.runtimeTypeInfoExpr(field.typ),
|
|
1497
2222
|
doc: field.doc,
|
|
1498
2223
|
tag: field.tag,
|
|
1499
|
-
structValue:
|
|
2224
|
+
structValue: structValue,
|
|
2225
|
+
arrayValue: isArrayType(field.typ),
|
|
1500
2226
|
})
|
|
1501
2227
|
}
|
|
1502
2228
|
|
|
1503
2229
|
methodDecls := o.methodDeclsForType(ctx, semType.named)
|
|
2230
|
+
explicitMethods := make(map[string]bool, len(methodDecls))
|
|
2231
|
+
for _, methodDecl := range methodDecls {
|
|
2232
|
+
if methodDecl != nil {
|
|
2233
|
+
explicitMethods[methodDecl.Name.Name] = true
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
1504
2236
|
var diagnostics []Diagnostic
|
|
1505
2237
|
for _, methodDecl := range methodDecls {
|
|
1506
2238
|
method, methodDiagnostics := o.lowerFuncDecl(ctx, methodDecl)
|
|
@@ -1512,9 +2244,121 @@ func (o *LoweringOwner) lowerStructType(ctx lowerFileContext, semType *semanticT
|
|
|
1512
2244
|
lowered.methods = append(lowered.methods, *method)
|
|
1513
2245
|
}
|
|
1514
2246
|
}
|
|
2247
|
+
for _, field := range semType.fields {
|
|
2248
|
+
methods := o.lowerEmbeddedMethodForwarders(ctx, field, explicitMethods)
|
|
2249
|
+
lowered.methods = append(lowered.methods, methods...)
|
|
2250
|
+
}
|
|
1515
2251
|
return lowered, diagnostics
|
|
1516
2252
|
}
|
|
1517
2253
|
|
|
2254
|
+
func (o *LoweringOwner) lowerEmbeddedMethodForwarders(
|
|
2255
|
+
ctx lowerFileContext,
|
|
2256
|
+
field semanticField,
|
|
2257
|
+
explicitMethods map[string]bool,
|
|
2258
|
+
) []loweredFunction {
|
|
2259
|
+
if !field.embedded {
|
|
2260
|
+
return nil
|
|
2261
|
+
}
|
|
2262
|
+
methodSetType := field.typ
|
|
2263
|
+
if named := namedStructType(field.typ); named != nil {
|
|
2264
|
+
methodSetType = types.NewPointer(field.typ)
|
|
2265
|
+
} else if pointerToNamedStructType(field.typ) != nil {
|
|
2266
|
+
methodSetType = field.typ
|
|
2267
|
+
} else if _, ok := types.Unalias(field.typ).Underlying().(*types.Interface); !ok {
|
|
2268
|
+
return nil
|
|
2269
|
+
}
|
|
2270
|
+
methodSet := types.NewMethodSet(methodSetType)
|
|
2271
|
+
if methodSet.Len() == 0 {
|
|
2272
|
+
return nil
|
|
2273
|
+
}
|
|
2274
|
+
var methods []loweredFunction
|
|
2275
|
+
for selection := range methodSet.Methods() {
|
|
2276
|
+
method, _ := selection.Obj().(*types.Func)
|
|
2277
|
+
if method == nil || explicitMethods[method.Name()] {
|
|
2278
|
+
continue
|
|
2279
|
+
}
|
|
2280
|
+
if !ast.IsExported(method.Name()) && method.Pkg() != nil && method.Pkg().Path() != ctx.semPkg.pkgPath {
|
|
2281
|
+
continue
|
|
2282
|
+
}
|
|
2283
|
+
signature, _ := method.Type().(*types.Signature)
|
|
2284
|
+
if signature == nil {
|
|
2285
|
+
continue
|
|
2286
|
+
}
|
|
2287
|
+
async := o.functionAsync(ctx, method)
|
|
2288
|
+
targetType := o.tsEmbeddedForwarderTargetType(ctx, field.typ)
|
|
2289
|
+
lowered := loweredFunction{
|
|
2290
|
+
async: async,
|
|
2291
|
+
name: methodMemberName(method.Name()),
|
|
2292
|
+
runtimeName: method.Name(),
|
|
2293
|
+
result: asyncResultType("any", async),
|
|
2294
|
+
deferState: &loweredDeferState{},
|
|
2295
|
+
}
|
|
2296
|
+
args := make([]string, 0, signature.Params().Len())
|
|
2297
|
+
for idx := range signature.Params().Len() {
|
|
2298
|
+
param := signature.Params().At(idx)
|
|
2299
|
+
name := safeParamName(param, idx)
|
|
2300
|
+
args = append(args, name)
|
|
2301
|
+
lowered.params = append(lowered.params, loweredParam{name: name, typ: "any"})
|
|
2302
|
+
}
|
|
2303
|
+
target := o.embeddedForwarderTargetExpr(ctx, field, selection, targetType)
|
|
2304
|
+
call := target + "." + method.Name() + "(" + strings.Join(args, ", ") + ")"
|
|
2305
|
+
if async {
|
|
2306
|
+
call = "await " + call
|
|
2307
|
+
}
|
|
2308
|
+
lowered.body = []loweredStmt{{text: "return " + call}}
|
|
2309
|
+
methods = append(methods, lowered)
|
|
2310
|
+
explicitMethods[method.Name()] = true
|
|
2311
|
+
}
|
|
2312
|
+
return methods
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
func (o *LoweringOwner) embeddedForwarderTargetExpr(
|
|
2316
|
+
ctx lowerFileContext,
|
|
2317
|
+
field semanticField,
|
|
2318
|
+
selection *types.Selection,
|
|
2319
|
+
targetType string,
|
|
2320
|
+
) string {
|
|
2321
|
+
pointerValue := o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue)
|
|
2322
|
+
expr := pointerValue + "<" + targetType + ">(this." + tsStructFieldName(field.name, 0) + ")"
|
|
2323
|
+
if selection == nil || len(selection.Index()) <= 1 {
|
|
2324
|
+
return expr
|
|
2325
|
+
}
|
|
2326
|
+
|
|
2327
|
+
typ := field.typ
|
|
2328
|
+
for _, index := range selection.Index()[:len(selection.Index())-1] {
|
|
2329
|
+
structType, ok := types.Unalias(derefPointerType(typ)).Underlying().(*types.Struct)
|
|
2330
|
+
if !ok || index < 0 || index >= structType.NumFields() {
|
|
2331
|
+
return expr
|
|
2332
|
+
}
|
|
2333
|
+
field := structType.Field(index)
|
|
2334
|
+
expr += "." + tsStructFieldName(field.Name(), index)
|
|
2335
|
+
typ = field.Type()
|
|
2336
|
+
expr = o.embeddedForwarderSelectableExpr(ctx, typ, expr)
|
|
2337
|
+
}
|
|
2338
|
+
return expr
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
func (o *LoweringOwner) embeddedForwarderSelectableExpr(ctx lowerFileContext, typ types.Type, expr string) string {
|
|
2342
|
+
pointerValue := o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue)
|
|
2343
|
+
if named := pointerToNamedStructType(typ); named != nil {
|
|
2344
|
+
return pointerValue + "<any>(" + expr + ")"
|
|
2345
|
+
}
|
|
2346
|
+
if _, ok := types.Unalias(typ).Underlying().(*types.Interface); ok {
|
|
2347
|
+
return pointerValue + "<any>(" + expr + ")"
|
|
2348
|
+
}
|
|
2349
|
+
return expr
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2352
|
+
func (o *LoweringOwner) tsEmbeddedForwarderTargetType(ctx lowerFileContext, typ types.Type) string {
|
|
2353
|
+
if named := pointerToNamedStructType(typ); named != nil {
|
|
2354
|
+
return o.namedTypeExpr(ctx, named)
|
|
2355
|
+
}
|
|
2356
|
+
if named := namedStructType(typ); named != nil {
|
|
2357
|
+
return o.namedTypeExpr(ctx, named)
|
|
2358
|
+
}
|
|
2359
|
+
return "Exclude<" + o.tsStructFieldTypeFor(ctx, typ) + ", null>"
|
|
2360
|
+
}
|
|
2361
|
+
|
|
1518
2362
|
func (o *LoweringOwner) methodDeclsForType(ctx lowerFileContext, named *types.Named) []*ast.FuncDecl {
|
|
1519
2363
|
if named == nil {
|
|
1520
2364
|
return nil
|
|
@@ -1574,7 +2418,8 @@ func (o *LoweringOwner) lowerNamedReceiverMethodDecl(
|
|
|
1574
2418
|
return nil, nil
|
|
1575
2419
|
}
|
|
1576
2420
|
async := o.functionAsync(ctx, fnObj)
|
|
1577
|
-
|
|
2421
|
+
functionCtx := ctx.withSignature(signature)
|
|
2422
|
+
resultCtx := functionCtx.withAsyncFunction(async)
|
|
1578
2423
|
result := o.tsSignatureResultFor(resultCtx, signature)
|
|
1579
2424
|
receiverName := "recv"
|
|
1580
2425
|
if len(decl.Recv.List) != 0 && len(decl.Recv.List[0].Names) != 0 {
|
|
@@ -1634,7 +2479,11 @@ func (o *LoweringOwner) lowerFuncDecl(ctx lowerFileContext, decl *ast.FuncDecl)
|
|
|
1634
2479
|
return nil, nil
|
|
1635
2480
|
}
|
|
1636
2481
|
async := o.functionAsync(ctx, fnObj)
|
|
1637
|
-
|
|
2482
|
+
if decl.Name.Name == "main" {
|
|
2483
|
+
async = true
|
|
2484
|
+
}
|
|
2485
|
+
functionCtx := ctx.withSignature(signature)
|
|
2486
|
+
resultCtx := functionCtx.withAsyncFunction(async)
|
|
1638
2487
|
result := o.tsSignatureResultFor(resultCtx, signature)
|
|
1639
2488
|
deferState := &loweredDeferState{}
|
|
1640
2489
|
name := safeIdentifier(decl.Name.Name)
|
|
@@ -1659,9 +2508,10 @@ func (o *LoweringOwner) lowerFuncDecl(ctx lowerFileContext, decl *ast.FuncDecl)
|
|
|
1659
2508
|
runtimeName: runtimeName,
|
|
1660
2509
|
result: asyncResultType(result, async),
|
|
1661
2510
|
deferState: deferState,
|
|
1662
|
-
namedResults: o.lowerNamedResults(
|
|
2511
|
+
namedResults: o.lowerNamedResults(functionCtx, signature),
|
|
1663
2512
|
}
|
|
1664
2513
|
if signature.TypeParams() != nil && signature.TypeParams().Len() != 0 {
|
|
2514
|
+
lowered.typeParams = signatureTypeParamNames(signature)
|
|
1665
2515
|
lowered.params = append(lowered.params, loweredParam{
|
|
1666
2516
|
name: "__typeArgs",
|
|
1667
2517
|
typ: "$.GenericTypeArgs | undefined",
|
|
@@ -1684,24 +2534,20 @@ func (o *LoweringOwner) lowerFuncDecl(ctx lowerFileContext, decl *ast.FuncDecl)
|
|
|
1684
2534
|
lowered.receiverValue = o.runtimeOwner.QualifiedHelper(RuntimeHelperVarRef) + "(this)"
|
|
1685
2535
|
}
|
|
1686
2536
|
}
|
|
1687
|
-
if decl.Name.Name == "main" {
|
|
1688
|
-
lowered.async = true
|
|
1689
|
-
lowered.result = asyncResultType(o.tsSignatureResultFor(ctx.withAsyncFunction(true), signature), true)
|
|
1690
|
-
}
|
|
1691
2537
|
for idx := range signature.Params().Len() {
|
|
1692
2538
|
param := signature.Params().At(idx)
|
|
1693
|
-
lowered.params, lowered.paramBindings = o.appendLoweredParam(
|
|
2539
|
+
lowered.params, lowered.paramBindings = o.appendLoweredParam(functionCtx, lowered.params, lowered.paramBindings, param, idx, decl.Body == nil || async)
|
|
1694
2540
|
}
|
|
1695
2541
|
if decl.Body != nil {
|
|
1696
|
-
body, diagnostics := o.lowerBlock(
|
|
2542
|
+
body, diagnostics := o.lowerBlock(functionCtx.withAsyncFunction(async).withDeferState(deferState), decl.Body)
|
|
1697
2543
|
lowered.body = body
|
|
1698
2544
|
if deferState.async && !lowered.async {
|
|
1699
2545
|
lowered.async = true
|
|
1700
|
-
lowered.result = asyncResultType(o.tsSignatureResultFor(
|
|
2546
|
+
lowered.result = asyncResultType(o.tsSignatureResultFor(functionCtx.withAsyncFunction(true), signature), true)
|
|
1701
2547
|
}
|
|
1702
2548
|
return lowered, diagnostics
|
|
1703
2549
|
}
|
|
1704
|
-
if zeroReturn, ok := o.lowerBodylessReturnStmt(
|
|
2550
|
+
if zeroReturn, ok := o.lowerBodylessReturnStmt(functionCtx, signature); ok {
|
|
1705
2551
|
lowered.body = []loweredStmt{{text: zeroReturn}}
|
|
1706
2552
|
}
|
|
1707
2553
|
return lowered, nil
|
|
@@ -1754,6 +2600,54 @@ func rangeBindingAssignedInBody(ctx lowerFileContext, expr ast.Expr, body *ast.B
|
|
|
1754
2600
|
return objectAssignedInBlock(ctx, obj, body)
|
|
1755
2601
|
}
|
|
1756
2602
|
|
|
2603
|
+
func (o *LoweringOwner) lowerMapRangeBinding(
|
|
2604
|
+
ctx lowerFileContext,
|
|
2605
|
+
expr ast.Expr,
|
|
2606
|
+
name string,
|
|
2607
|
+
fallback string,
|
|
2608
|
+
tempPrefix string,
|
|
2609
|
+
declare bool,
|
|
2610
|
+
) (string, []loweredStmt, []Diagnostic) {
|
|
2611
|
+
if expr == nil {
|
|
2612
|
+
return fallback, nil, nil
|
|
2613
|
+
}
|
|
2614
|
+
if ident, ok := expr.(*ast.Ident); ok && ident.Name == "_" {
|
|
2615
|
+
return fallback, nil, nil
|
|
2616
|
+
}
|
|
2617
|
+
if declare {
|
|
2618
|
+
obj := rangeBindingObject(ctx, expr)
|
|
2619
|
+
if name == "" || obj == nil || !ctx.model.needsVarRef[obj] {
|
|
2620
|
+
if name != "" {
|
|
2621
|
+
return name, nil, nil
|
|
2622
|
+
}
|
|
2623
|
+
return fallback, nil, nil
|
|
2624
|
+
}
|
|
2625
|
+
rawName := ctx.tempName(tempPrefix)
|
|
2626
|
+
value := rawName
|
|
2627
|
+
if isStructValueType(obj.Type()) {
|
|
2628
|
+
value = o.lowerStructClone(value)
|
|
2629
|
+
}
|
|
2630
|
+
return rawName, []loweredStmt{{
|
|
2631
|
+
text: "let " + name + ": " + o.tsVariableTypeFor(ctx, obj.Type(), true) + " = " +
|
|
2632
|
+
o.runtimeOwner.QualifiedHelper(RuntimeHelperVarRef) + "(" + value + ")",
|
|
2633
|
+
}}, nil
|
|
2634
|
+
}
|
|
2635
|
+
rawName := ctx.tempName(tempPrefix)
|
|
2636
|
+
left, diagnostics := o.lowerAssignmentTarget(ctx, expr, false)
|
|
2637
|
+
return rawName, []loweredStmt{{text: left + " = " + rawName}}, diagnostics
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
func rangeBindingObject(ctx lowerFileContext, expr ast.Expr) types.Object {
|
|
2641
|
+
ident, ok := expr.(*ast.Ident)
|
|
2642
|
+
if !ok || ident.Name == "_" || ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
2643
|
+
return nil
|
|
2644
|
+
}
|
|
2645
|
+
if obj := ctx.semPkg.source.TypesInfo.Defs[ident]; obj != nil {
|
|
2646
|
+
return obj
|
|
2647
|
+
}
|
|
2648
|
+
return ctx.semPkg.source.TypesInfo.Uses[ident]
|
|
2649
|
+
}
|
|
2650
|
+
|
|
1757
2651
|
func expressionUsesObject(ctx lowerFileContext, expr ast.Expr, obj types.Object) bool {
|
|
1758
2652
|
if expr == nil || obj == nil || ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
1759
2653
|
return false
|
|
@@ -1803,6 +2697,20 @@ func (o *LoweringOwner) appendLoweredParam(
|
|
|
1803
2697
|
|
|
1804
2698
|
func (ctx lowerFileContext) withSignature(signature *types.Signature) lowerFileContext {
|
|
1805
2699
|
ctx.signature = signature
|
|
2700
|
+
if signature != nil && signature.TypeParams() != nil && signature.TypeParams().Len() != 0 {
|
|
2701
|
+
next := make(map[string]bool, len(ctx.typeParams)+signature.TypeParams().Len())
|
|
2702
|
+
maps.Copy(next, ctx.typeParams)
|
|
2703
|
+
nextStatic := make(map[string]bool, len(ctx.staticTypeParams)+signature.TypeParams().Len())
|
|
2704
|
+
maps.Copy(nextStatic, ctx.staticTypeParams)
|
|
2705
|
+
for typeParam := range signature.TypeParams().TypeParams() {
|
|
2706
|
+
next[typeParam.Obj().Name()] = true
|
|
2707
|
+
if signatureUsesTypeParamAsSliceElem(signature, typeParam) {
|
|
2708
|
+
nextStatic[typeParam.Obj().Name()] = true
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
ctx.typeParams = next
|
|
2712
|
+
ctx.staticTypeParams = nextStatic
|
|
2713
|
+
}
|
|
1806
2714
|
return ctx
|
|
1807
2715
|
}
|
|
1808
2716
|
|
|
@@ -1852,7 +2760,18 @@ func (ctx lowerFileContext) withoutRangeBreak() lowerFileContext {
|
|
|
1852
2760
|
}
|
|
1853
2761
|
|
|
1854
2762
|
func (ctx lowerFileContext) withGotoLabels(labels map[string]bool) lowerFileContext {
|
|
1855
|
-
ctx.gotoLabels
|
|
2763
|
+
if len(ctx.gotoLabels) == 0 {
|
|
2764
|
+
ctx.gotoLabels = labels
|
|
2765
|
+
return ctx
|
|
2766
|
+
}
|
|
2767
|
+
merged := make(map[string]bool, len(ctx.gotoLabels)+len(labels))
|
|
2768
|
+
for label := range ctx.gotoLabels {
|
|
2769
|
+
merged[label] = true
|
|
2770
|
+
}
|
|
2771
|
+
for label := range labels {
|
|
2772
|
+
merged[label] = true
|
|
2773
|
+
}
|
|
2774
|
+
ctx.gotoLabels = merged
|
|
1856
2775
|
return ctx
|
|
1857
2776
|
}
|
|
1858
2777
|
|
|
@@ -1884,6 +2803,11 @@ func (ctx lowerFileContext) withLoopLabel(label string) lowerFileContext {
|
|
|
1884
2803
|
return ctx
|
|
1885
2804
|
}
|
|
1886
2805
|
|
|
2806
|
+
func (ctx lowerFileContext) withoutLoopLabel() lowerFileContext {
|
|
2807
|
+
ctx.loopLabel = ""
|
|
2808
|
+
return ctx
|
|
2809
|
+
}
|
|
2810
|
+
|
|
1887
2811
|
func (ctx lowerFileContext) withSwitchBreak() lowerFileContext {
|
|
1888
2812
|
ctx.switchBreak = true
|
|
1889
2813
|
return ctx
|
|
@@ -1999,6 +2923,22 @@ func (o *LoweringOwner) lowerStmt(ctx lowerFileContext, stmt ast.Stmt) ([]lowere
|
|
|
1999
2923
|
expr, diagnostics := o.lowerPointerStorageExpr(ctx, star.X)
|
|
2000
2924
|
return []loweredStmt{{text: expr + typed.Tok.String()}}, diagnostics
|
|
2001
2925
|
}
|
|
2926
|
+
if index, ok := unwrapParenExpr(typed.X).(*ast.IndexExpr); ok && isMapType(ctx.semPkg.source.TypesInfo.TypeOf(index.X)) {
|
|
2927
|
+
right := "1"
|
|
2928
|
+
tok := token.ADD_ASSIGN
|
|
2929
|
+
if typed.Tok == token.DEC {
|
|
2930
|
+
tok = token.SUB_ASSIGN
|
|
2931
|
+
}
|
|
2932
|
+
return o.lowerMapIndexUpdateStmts(ctx, index, tok, right, ctx.semPkg.source.TypesInfo.TypeOf(typed.X))
|
|
2933
|
+
}
|
|
2934
|
+
if setter, ok := o.packageVarSetterForAssignment(ctx, typed.X); ok {
|
|
2935
|
+
expr, diagnostics := o.lowerExpr(ctx, typed.X)
|
|
2936
|
+
op := "+"
|
|
2937
|
+
if typed.Tok == token.DEC {
|
|
2938
|
+
op = "-"
|
|
2939
|
+
}
|
|
2940
|
+
return []loweredStmt{{text: setter + "(" + expr + " " + op + " 1)"}}, diagnostics
|
|
2941
|
+
}
|
|
2002
2942
|
expr, diagnostics := o.lowerExpr(ctx, typed.X)
|
|
2003
2943
|
return []loweredStmt{{text: expr + typed.Tok.String()}}, diagnostics
|
|
2004
2944
|
case *ast.BranchStmt:
|
|
@@ -2068,6 +3008,10 @@ func packageVarGetterName(name string) string {
|
|
|
2068
3008
|
return "__goscript_get_" + safeIdentifier(name)
|
|
2069
3009
|
}
|
|
2070
3010
|
|
|
3011
|
+
func packageVarInitName(name string) string {
|
|
3012
|
+
return "__goscript_init_" + safeIdentifier(name)
|
|
3013
|
+
}
|
|
3014
|
+
|
|
2071
3015
|
func (o *LoweringOwner) lowerElse(ctx lowerFileContext, stmt ast.Stmt) ([]loweredStmt, []Diagnostic) {
|
|
2072
3016
|
switch typed := stmt.(type) {
|
|
2073
3017
|
case *ast.BlockStmt:
|
|
@@ -2190,6 +3134,19 @@ func (o *LoweringOwner) lowerStmtListAfter(
|
|
|
2190
3134
|
continue
|
|
2191
3135
|
}
|
|
2192
3136
|
}
|
|
3137
|
+
if stmtCtx, nextCtx, ok := o.lowerDeclStatementContext(ctx, stmt); ok {
|
|
3138
|
+
stmtLowered, stmtDiagnostics := o.lowerStmt(stmtCtx, stmt)
|
|
3139
|
+
diagnostics = append(diagnostics, stmtDiagnostics...)
|
|
3140
|
+
if len(stmtLowered) != 0 && len(leading) != 0 {
|
|
3141
|
+
stmtLowered[0].leading = append(leading, stmtLowered[0].leading...)
|
|
3142
|
+
}
|
|
3143
|
+
lowered = append(lowered, stmtLowered...)
|
|
3144
|
+
ctx = nextCtx
|
|
3145
|
+
if endLine := sourceLine(ctx, stmt.End()); endLine != 0 {
|
|
3146
|
+
prevEndLine = endLine
|
|
3147
|
+
}
|
|
3148
|
+
continue
|
|
3149
|
+
}
|
|
2193
3150
|
if stmtCtx, nextCtx, prelude, ok := o.lowerShortDeclStatementContext(ctx, stmt); ok {
|
|
2194
3151
|
stmtLowered, stmtDiagnostics := o.lowerStmt(stmtCtx, stmt)
|
|
2195
3152
|
diagnostics = append(diagnostics, stmtDiagnostics...)
|
|
@@ -2221,6 +3178,44 @@ func (o *LoweringOwner) lowerStmtListAfter(
|
|
|
2221
3178
|
return lowered, diagnostics
|
|
2222
3179
|
}
|
|
2223
3180
|
|
|
3181
|
+
func (o *LoweringOwner) lowerDeclStatementContext(
|
|
3182
|
+
ctx lowerFileContext,
|
|
3183
|
+
stmt ast.Stmt,
|
|
3184
|
+
) (lowerFileContext, lowerFileContext, bool) {
|
|
3185
|
+
declStmt, ok := stmt.(*ast.DeclStmt)
|
|
3186
|
+
if !ok {
|
|
3187
|
+
return ctx, ctx, false
|
|
3188
|
+
}
|
|
3189
|
+
genDecl, ok := declStmt.Decl.(*ast.GenDecl)
|
|
3190
|
+
if !ok || genDecl.Tok != token.VAR {
|
|
3191
|
+
return ctx, ctx, false
|
|
3192
|
+
}
|
|
3193
|
+
aliases := make(map[types.Object]string)
|
|
3194
|
+
for _, spec := range genDecl.Specs {
|
|
3195
|
+
valueSpec, ok := spec.(*ast.ValueSpec)
|
|
3196
|
+
if !ok {
|
|
3197
|
+
continue
|
|
3198
|
+
}
|
|
3199
|
+
for _, name := range valueSpec.Names {
|
|
3200
|
+
if name.Name == "_" {
|
|
3201
|
+
continue
|
|
3202
|
+
}
|
|
3203
|
+
def := ctx.semPkg.source.TypesInfo.Defs[name]
|
|
3204
|
+
if def == nil || aliases[def] != "" {
|
|
3205
|
+
continue
|
|
3206
|
+
}
|
|
3207
|
+
if shortDeclDefShadowsOuterName(name.Name, def) {
|
|
3208
|
+
aliases[def] = ctx.tempName("Shadow")
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
if len(aliases) == 0 {
|
|
3213
|
+
return ctx, ctx, false
|
|
3214
|
+
}
|
|
3215
|
+
nextCtx := ctx.withIdentRefAliases(aliases)
|
|
3216
|
+
return nextCtx, nextCtx, true
|
|
3217
|
+
}
|
|
3218
|
+
|
|
2224
3219
|
type gotoStateCluster struct {
|
|
2225
3220
|
startIdx int
|
|
2226
3221
|
firstLabelIdx int
|
|
@@ -2387,10 +3382,8 @@ func (o *LoweringOwner) lowerShortDeclStatementContext(
|
|
|
2387
3382
|
if len(oldAliases) == 0 && len(newAliases) == 0 {
|
|
2388
3383
|
return ctx, ctx, nil, false
|
|
2389
3384
|
}
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
maps.Copy(stmtAliases, newAliases)
|
|
2393
|
-
return ctx.withIdentAliases(stmtAliases), ctx.withIdentAliases(newAliases), prelude, true
|
|
3385
|
+
stmtCtx := ctx.withIdentAliases(oldAliases).withIdentRefAliases(newAliases)
|
|
3386
|
+
return stmtCtx, ctx.withIdentRefAliases(newAliases), prelude, true
|
|
2394
3387
|
}
|
|
2395
3388
|
|
|
2396
3389
|
func (o *LoweringOwner) lowerBackwardGotoLoop(
|
|
@@ -2605,6 +3598,9 @@ func (o *LoweringOwner) lowerSendStmt(ctx lowerFileContext, stmt *ast.SendStmt)
|
|
|
2605
3598
|
channel, channelDiagnostics := o.lowerExpr(ctx, stmt.Chan)
|
|
2606
3599
|
value, valueDiagnostics := o.lowerExpr(ctx, stmt.Value)
|
|
2607
3600
|
diagnostics := append(channelDiagnostics, valueDiagnostics...)
|
|
3601
|
+
if channelType, _ := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(stmt.Chan)).Underlying().(*types.Chan); channelType != nil {
|
|
3602
|
+
value = o.lowerValueForTarget(ctx, stmt.Value, channelType.Elem(), value)
|
|
3603
|
+
}
|
|
2608
3604
|
return "await " + o.runtimeOwner.QualifiedHelper(RuntimeHelperChanSend) + "(" + channel + ", " + value + ")", diagnostics
|
|
2609
3605
|
}
|
|
2610
3606
|
|
|
@@ -2616,6 +3612,25 @@ func (o *LoweringOwner) lowerGoStmt(ctx lowerFileContext, stmt *ast.GoStmt) (str
|
|
|
2616
3612
|
}
|
|
2617
3613
|
|
|
2618
3614
|
func (o *LoweringOwner) lowerDeferStmt(ctx lowerFileContext, stmt *ast.DeferStmt) (string, []Diagnostic) {
|
|
3615
|
+
if nestedCall, ok := stmt.Call.Fun.(*ast.CallExpr); ok {
|
|
3616
|
+
callee, diagnostics := o.lowerCallExpr(ctx, nestedCall)
|
|
3617
|
+
args, argDiagnostics := o.lowerCallArgs(ctx, stmt.Call, callTargetSignature(ctx, stmt.Call.Fun))
|
|
3618
|
+
diagnostics = append(diagnostics, argDiagnostics...)
|
|
3619
|
+
calleeTemp := ctx.tempName("DeferCallee")
|
|
3620
|
+
call := o.lowerCallableExpr(ctx, stmt.Call.Fun, calleeTemp) + "(" + strings.Join(args, ", ") + ")"
|
|
3621
|
+
call = o.awaitCallIfNeeded(ctx, stmt.Call.Fun, call)
|
|
3622
|
+
async := strings.Contains(callee, "await ") || strings.Contains(call, "await ")
|
|
3623
|
+
if ctx.deferState != nil {
|
|
3624
|
+
ctx.deferState.used = true
|
|
3625
|
+
if async {
|
|
3626
|
+
ctx.deferState.async = true
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
if async {
|
|
3630
|
+
return "const " + calleeTemp + " = " + callee + "\n__defer.defer(async () => { " + call + " })", diagnostics
|
|
3631
|
+
}
|
|
3632
|
+
return "const " + calleeTemp + " = " + callee + "\n__defer.defer(() => { " + call + " })", diagnostics
|
|
3633
|
+
}
|
|
2619
3634
|
call, diagnostics := o.lowerCallExpr(ctx, stmt.Call)
|
|
2620
3635
|
async := strings.Contains(call, "await ")
|
|
2621
3636
|
if ctx.deferState != nil {
|
|
@@ -2682,41 +3697,51 @@ func (o *LoweringOwner) lowerAssignStmt(ctx lowerFileContext, stmt *ast.AssignSt
|
|
|
2682
3697
|
isShortDecl := stmt.Tok == token.DEFINE && isShortAssignTargetNew(ctx, lhs)
|
|
2683
3698
|
right, rightDiagnostics := o.lowerExpr(ctx, stmt.Rhs[idx])
|
|
2684
3699
|
diagnostics = append(diagnostics, rightDiagnostics...)
|
|
2685
|
-
targetType := ctx
|
|
3700
|
+
targetType := assignmentTargetType(ctx, lhs)
|
|
2686
3701
|
right = o.lowerValueForTarget(ctx, stmt.Rhs[idx], targetType, right)
|
|
2687
|
-
if
|
|
2688
|
-
|
|
3702
|
+
if targetType != nil && genericCallResultUsesTypeParam(ctx, stmt.Rhs[idx]) {
|
|
3703
|
+
right = "(" + right + " as " + o.tsTypeFor(ctx, targetType) + ")"
|
|
3704
|
+
}
|
|
3705
|
+
if setter, ok := o.packageVarSetterForAssignment(ctx, lhs); ok {
|
|
3706
|
+
value, ok := o.packageVarAssignmentValue(ctx, lhs, targetType, right, stmt.Tok)
|
|
3707
|
+
if !ok {
|
|
3708
|
+
value = right
|
|
3709
|
+
}
|
|
3710
|
+
stmts = append(stmts, loweredStmt{text: setter + "(" + value + ")"})
|
|
2689
3711
|
continue
|
|
2690
3712
|
}
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
keyExpr, keyDiagnostics := o.lowerExpr(ctx, index.Index)
|
|
2696
|
-
diagnostics = append(diagnostics, mapDiagnostics...)
|
|
2697
|
-
diagnostics = append(diagnostics, keyDiagnostics...)
|
|
2698
|
-
stmts = append(stmts, loweredStmt{text: o.runtimeOwner.QualifiedHelper(RuntimeHelperMapSet) + "(" + mapExpr + ", " + keyExpr + ", " + right + ")"})
|
|
3713
|
+
if index, ok := lhs.(*ast.IndexExpr); ok && isMapType(ctx.semPkg.source.TypesInfo.TypeOf(index.X)) && stmt.Tok != token.DEFINE {
|
|
3714
|
+
update, updateDiagnostics := o.lowerMapIndexUpdateStmts(ctx, index, stmt.Tok, right, targetType)
|
|
3715
|
+
diagnostics = append(diagnostics, updateDiagnostics...)
|
|
3716
|
+
stmts = append(stmts, update...)
|
|
2699
3717
|
continue
|
|
2700
3718
|
}
|
|
2701
|
-
|
|
3719
|
+
left, leftDiagnostics := o.lowerAssignmentTarget(ctx, lhs, isShortDecl)
|
|
3720
|
+
diagnostics = append(diagnostics, leftDiagnostics...)
|
|
3721
|
+
star, starTarget := unwrapParenExpr(lhs).(*ast.StarExpr)
|
|
3722
|
+
if starTarget && stmt.Tok == token.ASSIGN && isStructValueType(targetType) {
|
|
2702
3723
|
pointer, pointerDiagnostics := o.lowerPointerValueExpr(ctx, star.X)
|
|
2703
3724
|
diagnostics = append(diagnostics, pointerDiagnostics...)
|
|
2704
3725
|
stmts = append(stmts, loweredStmt{text: o.runtimeOwner.QualifiedHelper(RuntimeHelperAssignStruct) + "(" + pointer + ", " + right + ")"})
|
|
2705
3726
|
continue
|
|
2706
3727
|
}
|
|
2707
|
-
if
|
|
3728
|
+
if starTarget && stmt.Tok == token.ASSIGN {
|
|
2708
3729
|
pointer, pointerDiagnostics := o.lowerPointerStorageExpr(ctx, star.X)
|
|
2709
3730
|
diagnostics = append(diagnostics, pointerDiagnostics...)
|
|
2710
3731
|
stmts = append(stmts, loweredStmt{text: pointer + " = " + right})
|
|
2711
3732
|
continue
|
|
2712
3733
|
}
|
|
2713
|
-
if
|
|
3734
|
+
if starTarget && stmt.Tok != token.DEFINE {
|
|
2714
3735
|
pointer, pointerDiagnostics := o.lowerPointerStorageExpr(ctx, star.X)
|
|
2715
3736
|
diagnostics = append(diagnostics, pointerDiagnostics...)
|
|
2716
3737
|
if stmt.Tok == token.AND_NOT_ASSIGN {
|
|
2717
3738
|
stmts = append(stmts, loweredStmt{text: pointer + " = " + pointer + " & ~(" + right + ")"})
|
|
2718
3739
|
continue
|
|
2719
3740
|
}
|
|
3741
|
+
if value, ok := integerQuotientAssignExpr(targetType, pointer, right, stmt.Tok); ok {
|
|
3742
|
+
stmts = append(stmts, loweredStmt{text: value})
|
|
3743
|
+
continue
|
|
3744
|
+
}
|
|
2720
3745
|
stmts = append(stmts, loweredStmt{text: pointer + " " + stmt.Tok.String() + " " + right})
|
|
2721
3746
|
continue
|
|
2722
3747
|
}
|
|
@@ -2735,13 +3760,109 @@ func (o *LoweringOwner) lowerAssignStmt(ctx lowerFileContext, stmt *ast.AssignSt
|
|
|
2735
3760
|
stmts = append(stmts, loweredStmt{text: left + " = " + o.runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")"})
|
|
2736
3761
|
continue
|
|
2737
3762
|
}
|
|
3763
|
+
if value, ok := integerQuotientAssignExpr(targetType, left, right, stmt.Tok); ok {
|
|
3764
|
+
stmts = append(stmts, loweredStmt{text: value})
|
|
3765
|
+
continue
|
|
3766
|
+
}
|
|
2738
3767
|
op := stmt.Tok.String()
|
|
2739
3768
|
if stmt.Tok == token.DEFINE {
|
|
2740
3769
|
op = "="
|
|
2741
3770
|
}
|
|
2742
|
-
stmts = append(stmts, loweredStmt{text: left + " " + op + " " + right})
|
|
3771
|
+
stmts = append(stmts, loweredStmt{text: left + " " + op + " " + right})
|
|
3772
|
+
}
|
|
3773
|
+
return stmts, diagnostics
|
|
3774
|
+
}
|
|
3775
|
+
|
|
3776
|
+
func (o *LoweringOwner) lowerMapIndexUpdateStmts(
|
|
3777
|
+
ctx lowerFileContext,
|
|
3778
|
+
index *ast.IndexExpr,
|
|
3779
|
+
tok token.Token,
|
|
3780
|
+
right string,
|
|
3781
|
+
targetType types.Type,
|
|
3782
|
+
) ([]loweredStmt, []Diagnostic) {
|
|
3783
|
+
mapExpr, mapDiagnostics := o.lowerExpr(ctx, index.X)
|
|
3784
|
+
keyExpr, keyDiagnostics := o.lowerExpr(ctx, index.Index)
|
|
3785
|
+
diagnostics := append(mapDiagnostics, keyDiagnostics...)
|
|
3786
|
+
if tok == token.ASSIGN {
|
|
3787
|
+
return []loweredStmt{{text: o.runtimeOwner.QualifiedHelper(RuntimeHelperMapSet) + "(" + mapExpr + ", " + keyExpr + ", " + right + ")"}}, diagnostics
|
|
3788
|
+
}
|
|
3789
|
+
mapTemp := ctx.tempName("Map")
|
|
3790
|
+
keyTemp := ctx.tempName("MapKey")
|
|
3791
|
+
current := o.lowerMapGetValue(ctx, index, mapTemp, keyTemp)
|
|
3792
|
+
value := lowerCompoundAssignValue(o.runtimeOwner, targetType, current, right, tok)
|
|
3793
|
+
return []loweredStmt{
|
|
3794
|
+
{text: "const " + mapTemp + " = " + mapExpr},
|
|
3795
|
+
{text: "const " + keyTemp + " = " + keyExpr},
|
|
3796
|
+
{text: o.runtimeOwner.QualifiedHelper(RuntimeHelperMapSet) + "(" + mapTemp + ", " + keyTemp + ", " + value + ")"},
|
|
3797
|
+
}, diagnostics
|
|
3798
|
+
}
|
|
3799
|
+
|
|
3800
|
+
func lowerCompoundAssignValue(
|
|
3801
|
+
runtimeOwner *RuntimeContractOwner,
|
|
3802
|
+
targetType types.Type,
|
|
3803
|
+
left string,
|
|
3804
|
+
right string,
|
|
3805
|
+
tok token.Token,
|
|
3806
|
+
) string {
|
|
3807
|
+
if helper, ok := wideIntegerAssignHelper(targetType, tok); ok {
|
|
3808
|
+
return runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")"
|
|
3809
|
+
}
|
|
3810
|
+
if value, ok := integerQuotientAssignValueExpr(targetType, left, right, tok); ok {
|
|
3811
|
+
return value
|
|
3812
|
+
}
|
|
3813
|
+
switch tok {
|
|
3814
|
+
case token.ADD_ASSIGN:
|
|
3815
|
+
return left + " + " + right
|
|
3816
|
+
case token.SUB_ASSIGN:
|
|
3817
|
+
return left + " - " + right
|
|
3818
|
+
case token.MUL_ASSIGN:
|
|
3819
|
+
return left + " * " + right
|
|
3820
|
+
case token.QUO_ASSIGN:
|
|
3821
|
+
return left + " / " + right
|
|
3822
|
+
case token.REM_ASSIGN:
|
|
3823
|
+
return left + " % " + right
|
|
3824
|
+
case token.AND_ASSIGN:
|
|
3825
|
+
return left + " & " + right
|
|
3826
|
+
case token.OR_ASSIGN:
|
|
3827
|
+
return left + " | " + right
|
|
3828
|
+
case token.XOR_ASSIGN:
|
|
3829
|
+
return left + " ^ " + right
|
|
3830
|
+
case token.SHL_ASSIGN:
|
|
3831
|
+
return left + " << " + right
|
|
3832
|
+
case token.SHR_ASSIGN:
|
|
3833
|
+
return left + " >> " + right
|
|
3834
|
+
case token.AND_NOT_ASSIGN:
|
|
3835
|
+
return left + " & ~(" + right + ")"
|
|
3836
|
+
default:
|
|
3837
|
+
return right
|
|
3838
|
+
}
|
|
3839
|
+
}
|
|
3840
|
+
|
|
3841
|
+
func integerQuotientAssignExpr(targetType types.Type, left string, right string, tok token.Token) (string, bool) {
|
|
3842
|
+
value, ok := integerQuotientAssignValueExpr(targetType, left, right, tok)
|
|
3843
|
+
if !ok {
|
|
3844
|
+
return "", false
|
|
3845
|
+
}
|
|
3846
|
+
return left + " = " + value, true
|
|
3847
|
+
}
|
|
3848
|
+
|
|
3849
|
+
func assignmentTargetType(ctx lowerFileContext, lhs ast.Expr) types.Type {
|
|
3850
|
+
if ident, ok := lhs.(*ast.Ident); ok {
|
|
3851
|
+
if obj := ctx.semPkg.source.TypesInfo.Defs[ident]; obj != nil {
|
|
3852
|
+
return obj.Type()
|
|
3853
|
+
}
|
|
2743
3854
|
}
|
|
2744
|
-
return
|
|
3855
|
+
return ctx.semPkg.source.TypesInfo.TypeOf(lhs)
|
|
3856
|
+
}
|
|
3857
|
+
|
|
3858
|
+
func integerQuotientAssignValueExpr(targetType types.Type, left string, right string, tok token.Token) (string, bool) {
|
|
3859
|
+
if tok != token.QUO_ASSIGN || !isIntegerType(targetType) {
|
|
3860
|
+
return "", false
|
|
3861
|
+
}
|
|
3862
|
+
if bits, ok := unsignedIntegerBits(targetType); ok && bits <= 32 {
|
|
3863
|
+
return "(" + left + " / " + right + ") >>> 0", true
|
|
3864
|
+
}
|
|
3865
|
+
return "Math.trunc(" + left + " / " + right + ")", true
|
|
2745
3866
|
}
|
|
2746
3867
|
|
|
2747
3868
|
func wideIntegerAssignHelper(targetType types.Type, tok token.Token) (RuntimeHelper, bool) {
|
|
@@ -2754,17 +3875,21 @@ func wideIntegerAssignHelper(targetType types.Type, tok token.Token) (RuntimeHel
|
|
|
2754
3875
|
case token.SHR_ASSIGN:
|
|
2755
3876
|
return RuntimeHelperUint64Shr, true
|
|
2756
3877
|
case token.MUL_ASSIGN:
|
|
2757
|
-
return RuntimeHelperUint64Mul, true
|
|
3878
|
+
return wideIntegerHelper(isFixedSignedWideIntegerType(targetType), RuntimeHelperUint64Mul, RuntimeHelperInt64Mul), true
|
|
3879
|
+
case token.QUO_ASSIGN:
|
|
3880
|
+
return wideIntegerHelper(isFixedSignedWideIntegerType(targetType), RuntimeHelperUint64Div, RuntimeHelperInt64Div), true
|
|
3881
|
+
case token.REM_ASSIGN:
|
|
3882
|
+
return wideIntegerHelper(isFixedSignedWideIntegerType(targetType), RuntimeHelperUint64Mod, RuntimeHelperInt64Mod), true
|
|
2758
3883
|
case token.ADD_ASSIGN:
|
|
2759
|
-
return RuntimeHelperUint64Add, true
|
|
3884
|
+
return wideIntegerHelper(isFixedSignedWideIntegerType(targetType), RuntimeHelperUint64Add, RuntimeHelperInt64Add), true
|
|
2760
3885
|
case token.SUB_ASSIGN:
|
|
2761
|
-
return RuntimeHelperUint64Sub, true
|
|
3886
|
+
return wideIntegerHelper(isFixedSignedWideIntegerType(targetType), RuntimeHelperUint64Sub, RuntimeHelperInt64Sub), true
|
|
2762
3887
|
case token.AND_ASSIGN:
|
|
2763
|
-
return RuntimeHelperUint64And, true
|
|
3888
|
+
return wideIntegerHelper(isFixedSignedWideIntegerType(targetType), RuntimeHelperUint64And, RuntimeHelperInt64And), true
|
|
2764
3889
|
case token.OR_ASSIGN:
|
|
2765
|
-
return RuntimeHelperUint64Or, true
|
|
3890
|
+
return wideIntegerHelper(isFixedSignedWideIntegerType(targetType), RuntimeHelperUint64Or, RuntimeHelperInt64Or), true
|
|
2766
3891
|
case token.XOR_ASSIGN:
|
|
2767
|
-
return RuntimeHelperUint64Xor, true
|
|
3892
|
+
return wideIntegerHelper(isFixedSignedWideIntegerType(targetType), RuntimeHelperUint64Xor, RuntimeHelperInt64Xor), true
|
|
2768
3893
|
default:
|
|
2769
3894
|
return "", false
|
|
2770
3895
|
}
|
|
@@ -2834,14 +3959,15 @@ func (o *LoweringOwner) shortDeclTypeAnnotation(ctx lowerFileContext, lhs ast.Ex
|
|
|
2834
3959
|
if obj == nil {
|
|
2835
3960
|
return ""
|
|
2836
3961
|
}
|
|
2837
|
-
if signature := unnamedSignatureForType(obj.Type()); signature != nil && rhsIsMethodValue(ctx, rhs) {
|
|
2838
|
-
return ": " + o.tsAsyncCompatibleFunctionTypeFor(ctx, signature)
|
|
2839
|
-
}
|
|
2840
3962
|
if signature := unnamedSignatureForType(obj.Type()); signature != nil {
|
|
2841
|
-
|
|
2842
|
-
if
|
|
2843
|
-
|
|
3963
|
+
typ := o.tsAsyncCompatibleFunctionTypeFor(ctx, signature)
|
|
3964
|
+
if ctx.model.needsVarRef[obj] {
|
|
3965
|
+
typ = "$.VarRef<" + typ + ">"
|
|
2844
3966
|
}
|
|
3967
|
+
return ": " + typ
|
|
3968
|
+
}
|
|
3969
|
+
if rhs != nil && isIdentLikeExpr(rhs) && isInterfaceType(obj.Type()) {
|
|
3970
|
+
return ": " + o.tsVariableTypeFor(ctx, obj.Type(), ctx.model.needsVarRef[obj])
|
|
2845
3971
|
}
|
|
2846
3972
|
if !shortDeclNeedsTypeAnnotation(obj.Type()) {
|
|
2847
3973
|
return ""
|
|
@@ -2849,12 +3975,19 @@ func (o *LoweringOwner) shortDeclTypeAnnotation(ctx lowerFileContext, lhs ast.Ex
|
|
|
2849
3975
|
return ": " + o.tsVariableTypeFor(ctx, obj.Type(), ctx.model.needsVarRef[obj])
|
|
2850
3976
|
}
|
|
2851
3977
|
|
|
3978
|
+
func isIdentLikeExpr(expr ast.Expr) bool {
|
|
3979
|
+
_, ok := ast.Unparen(expr).(*ast.Ident)
|
|
3980
|
+
return ok
|
|
3981
|
+
}
|
|
3982
|
+
|
|
2852
3983
|
func shortDeclNeedsTypeAnnotation(typ types.Type) bool {
|
|
2853
3984
|
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
2854
3985
|
case *types.Pointer:
|
|
2855
|
-
return namedStructType(typed.Elem()) != nil
|
|
3986
|
+
return namedStructType(typed.Elem()) != nil || namedNonStructType(typed.Elem()) != nil
|
|
2856
3987
|
case *types.Map:
|
|
2857
3988
|
return true
|
|
3989
|
+
case *types.Slice:
|
|
3990
|
+
return true
|
|
2858
3991
|
default:
|
|
2859
3992
|
return false
|
|
2860
3993
|
}
|
|
@@ -2876,6 +4009,15 @@ func (o *LoweringOwner) lowerTupleTargetAssignmentStmt(
|
|
|
2876
4009
|
declare bool,
|
|
2877
4010
|
) (loweredStmt, []Diagnostic) {
|
|
2878
4011
|
if !declare {
|
|
4012
|
+
if index, ok := unwrapParenExpr(lhs).(*ast.IndexExpr); ok && isMapType(ctx.semPkg.source.TypesInfo.TypeOf(index.X)) {
|
|
4013
|
+
targetType := assignmentTargetType(ctx, lhs)
|
|
4014
|
+
value = o.lowerValueForTarget(ctx, lhs, targetType, value)
|
|
4015
|
+
stmts, diagnostics := o.lowerMapIndexUpdateStmts(ctx, index, token.ASSIGN, value, targetType)
|
|
4016
|
+
if len(stmts) != 0 {
|
|
4017
|
+
return stmts[0], diagnostics
|
|
4018
|
+
}
|
|
4019
|
+
return loweredStmt{}, diagnostics
|
|
4020
|
+
}
|
|
2879
4021
|
if stmt, diagnostics, ok := o.lowerStarTargetAssignmentStmt(ctx, lhs, value); ok {
|
|
2880
4022
|
return stmt, diagnostics
|
|
2881
4023
|
}
|
|
@@ -2895,7 +4037,7 @@ func (o *LoweringOwner) lowerStarTargetAssignmentStmt(
|
|
|
2895
4037
|
lhs ast.Expr,
|
|
2896
4038
|
right string,
|
|
2897
4039
|
) (loweredStmt, []Diagnostic, bool) {
|
|
2898
|
-
star, ok := lhs.(*ast.StarExpr)
|
|
4040
|
+
star, ok := unwrapParenExpr(lhs).(*ast.StarExpr)
|
|
2899
4041
|
if !ok {
|
|
2900
4042
|
return loweredStmt{}, nil, false
|
|
2901
4043
|
}
|
|
@@ -2915,7 +4057,7 @@ func (o *LoweringOwner) lowerTupleReassignmentStmt(
|
|
|
2915
4057
|
diagnostics []Diagnostic,
|
|
2916
4058
|
) ([]loweredStmt, []Diagnostic) {
|
|
2917
4059
|
tempName := ctx.tempName("Tuple")
|
|
2918
|
-
stmts := []loweredStmt{{text: "let " + tempName + " = " + right}}
|
|
4060
|
+
stmts := []loweredStmt{{text: "let " + tempName + ": any = " + right}}
|
|
2919
4061
|
for idx, lhs := range stmt.Lhs {
|
|
2920
4062
|
if ident, ok := lhs.(*ast.Ident); ok && ident.Name == "_" {
|
|
2921
4063
|
continue
|
|
@@ -3064,8 +4206,8 @@ func shortDeclDefShadowsOuterName(name string, def types.Object) bool {
|
|
|
3064
4206
|
if scope == def.Parent() {
|
|
3065
4207
|
continue
|
|
3066
4208
|
}
|
|
3067
|
-
obj
|
|
3068
|
-
if
|
|
4209
|
+
obj := scope.Lookup(name)
|
|
4210
|
+
if obj != nil && obj.Pos().IsValid() && obj.Pos() < def.Pos() {
|
|
3069
4211
|
return true
|
|
3070
4212
|
}
|
|
3071
4213
|
}
|
|
@@ -3281,6 +4423,9 @@ func (o *LoweringOwner) lowerReturnStmt(ctx lowerFileContext, stmt *ast.ReturnSt
|
|
|
3281
4423
|
if ctx.rangeBranch != nil {
|
|
3282
4424
|
return o.lowerRangeFuncReturnStmt(ctx, stmt)
|
|
3283
4425
|
}
|
|
4426
|
+
if o.returnNeedsNamedResultDefer(ctx) {
|
|
4427
|
+
return o.lowerNamedResultDeferReturnStmt(ctx, stmt)
|
|
4428
|
+
}
|
|
3284
4429
|
if len(stmt.Results) == 0 {
|
|
3285
4430
|
if result, ok := o.lowerNamedResultReturn(ctx); ok {
|
|
3286
4431
|
return "return " + result, nil
|
|
@@ -3313,6 +4458,125 @@ func (o *LoweringOwner) lowerReturnStmt(ctx lowerFileContext, stmt *ast.ReturnSt
|
|
|
3313
4458
|
return "return [" + strings.Join(parts, ", ") + "]", diagnostics
|
|
3314
4459
|
}
|
|
3315
4460
|
|
|
4461
|
+
func (o *LoweringOwner) returnNeedsNamedResultDefer(ctx lowerFileContext) bool {
|
|
4462
|
+
if ctx.deferState == nil || !ctx.deferState.used || ctx.signature == nil || ctx.signature.Results() == nil {
|
|
4463
|
+
return false
|
|
4464
|
+
}
|
|
4465
|
+
for result := range ctx.signature.Results().Variables() {
|
|
4466
|
+
if result.Name() != "" {
|
|
4467
|
+
return true
|
|
4468
|
+
}
|
|
4469
|
+
}
|
|
4470
|
+
return false
|
|
4471
|
+
}
|
|
4472
|
+
|
|
4473
|
+
func (o *LoweringOwner) lowerNamedResultDeferReturnStmt(ctx lowerFileContext, stmt *ast.ReturnStmt) (string, []Diagnostic) {
|
|
4474
|
+
var diagnostics []Diagnostic
|
|
4475
|
+
var lines []string
|
|
4476
|
+
explicitTemp := ""
|
|
4477
|
+
if len(stmt.Results) != 0 {
|
|
4478
|
+
var value string
|
|
4479
|
+
var values []string
|
|
4480
|
+
if len(stmt.Results) == 1 && ctx.signature.Results().Len() > 1 {
|
|
4481
|
+
expr, exprDiagnostics := o.lowerExpr(ctx, stmt.Results[0])
|
|
4482
|
+
diagnostics = append(diagnostics, exprDiagnostics...)
|
|
4483
|
+
if prefix, tuple, ok := o.lowerTupleReturnValue(ctx, stmt.Results[0], expr); ok {
|
|
4484
|
+
lines = append(lines, prefix)
|
|
4485
|
+
value = tuple
|
|
4486
|
+
} else {
|
|
4487
|
+
value = expr
|
|
4488
|
+
}
|
|
4489
|
+
} else {
|
|
4490
|
+
values = make([]string, 0, len(stmt.Results))
|
|
4491
|
+
for idx, result := range stmt.Results {
|
|
4492
|
+
expr, exprDiagnostics := o.lowerExpr(ctx, result)
|
|
4493
|
+
diagnostics = append(diagnostics, exprDiagnostics...)
|
|
4494
|
+
if idx < ctx.signature.Results().Len() {
|
|
4495
|
+
expr = o.lowerValueForTarget(ctx, result, ctx.signature.Results().At(idx).Type(), expr)
|
|
4496
|
+
}
|
|
4497
|
+
values = append(values, expr)
|
|
4498
|
+
}
|
|
4499
|
+
}
|
|
4500
|
+
temp := ctx.tempName("Return")
|
|
4501
|
+
explicitTemp = temp
|
|
4502
|
+
tempType := o.tsSignatureResultFor(ctx, ctx.signature)
|
|
4503
|
+
if value != "" {
|
|
4504
|
+
lines = append(lines, "const "+temp+": "+tempType+" = "+value)
|
|
4505
|
+
} else if len(values) == 1 {
|
|
4506
|
+
lines = append(lines, "const "+temp+": "+tempType+" = "+values[0])
|
|
4507
|
+
} else {
|
|
4508
|
+
lines = append(lines, "const "+temp+": "+tempType+" = ["+strings.Join(values, ", ")+"]")
|
|
4509
|
+
}
|
|
4510
|
+
for idx := range ctx.signature.Results().Len() {
|
|
4511
|
+
result := ctx.signature.Results().At(idx)
|
|
4512
|
+
name := result.Name()
|
|
4513
|
+
if name == "" || name == "_" {
|
|
4514
|
+
continue
|
|
4515
|
+
}
|
|
4516
|
+
target := safeIdentifier(name)
|
|
4517
|
+
if ctx.model.needsVarRef[result] {
|
|
4518
|
+
target += ".value"
|
|
4519
|
+
}
|
|
4520
|
+
source := temp
|
|
4521
|
+
if ctx.signature.Results().Len() > 1 {
|
|
4522
|
+
source += "[" + strconv.Itoa(idx) + "]"
|
|
4523
|
+
}
|
|
4524
|
+
lines = append(lines, target+" = "+source)
|
|
4525
|
+
}
|
|
4526
|
+
}
|
|
4527
|
+
lines = append(lines, o.lowerDeferDisposeStmt(ctx))
|
|
4528
|
+
if result, ok := o.lowerNamedResultReturnWithExplicitTemp(ctx, explicitTemp); ok {
|
|
4529
|
+
lines = append(lines, "return "+result)
|
|
4530
|
+
} else {
|
|
4531
|
+
lines = append(lines, "return")
|
|
4532
|
+
}
|
|
4533
|
+
return strings.Join(lines, "\n"), diagnostics
|
|
4534
|
+
}
|
|
4535
|
+
|
|
4536
|
+
func (o *LoweringOwner) lowerNamedResultReturnWithExplicitTemp(ctx lowerFileContext, explicitTemp string) (string, bool) {
|
|
4537
|
+
if explicitTemp == "" {
|
|
4538
|
+
return o.lowerNamedResultReturn(ctx)
|
|
4539
|
+
}
|
|
4540
|
+
parts := make([]string, 0, ctx.signature.Results().Len())
|
|
4541
|
+
hasNamedResult := false
|
|
4542
|
+
multi := ctx.signature.Results().Len() > 1
|
|
4543
|
+
for idx := range ctx.signature.Results().Len() {
|
|
4544
|
+
result := ctx.signature.Results().At(idx)
|
|
4545
|
+
name := result.Name()
|
|
4546
|
+
if name == "" || name == "_" {
|
|
4547
|
+
source := explicitTemp
|
|
4548
|
+
if multi {
|
|
4549
|
+
source += "[" + strconv.Itoa(idx) + "]"
|
|
4550
|
+
}
|
|
4551
|
+
parts = append(parts, source)
|
|
4552
|
+
if name != "" {
|
|
4553
|
+
hasNamedResult = true
|
|
4554
|
+
}
|
|
4555
|
+
continue
|
|
4556
|
+
}
|
|
4557
|
+
hasNamedResult = true
|
|
4558
|
+
returnExpr := safeIdentifier(name)
|
|
4559
|
+
if ctx.model.needsVarRef[result] {
|
|
4560
|
+
returnExpr += ".value"
|
|
4561
|
+
}
|
|
4562
|
+
parts = append(parts, returnExpr)
|
|
4563
|
+
}
|
|
4564
|
+
if !hasNamedResult {
|
|
4565
|
+
return "", false
|
|
4566
|
+
}
|
|
4567
|
+
if len(parts) == 1 {
|
|
4568
|
+
return parts[0], true
|
|
4569
|
+
}
|
|
4570
|
+
return "[" + strings.Join(parts, ", ") + "]", true
|
|
4571
|
+
}
|
|
4572
|
+
|
|
4573
|
+
func (o *LoweringOwner) lowerDeferDisposeStmt(ctx lowerFileContext) string {
|
|
4574
|
+
if ctx.deferState != nil && ctx.deferState.async {
|
|
4575
|
+
return "await __defer[Symbol.asyncDispose]()"
|
|
4576
|
+
}
|
|
4577
|
+
return "__defer[Symbol.dispose]()"
|
|
4578
|
+
}
|
|
4579
|
+
|
|
3316
4580
|
func (o *LoweringOwner) lowerBodylessReturnStmt(ctx lowerFileContext, signature *types.Signature) (string, bool) {
|
|
3317
4581
|
if signature.Results().Len() == 0 {
|
|
3318
4582
|
return "", false
|
|
@@ -3434,6 +4698,9 @@ func genericCallResultUsesTypeParam(ctx lowerFileContext, expr ast.Expr) bool {
|
|
|
3434
4698
|
return false
|
|
3435
4699
|
}
|
|
3436
4700
|
signature := genericFunctionSignatureForCall(ctx, call.Fun)
|
|
4701
|
+
if signature == nil {
|
|
4702
|
+
signature = sourceFunctionSignatureForCall(ctx, call.Fun)
|
|
4703
|
+
}
|
|
3437
4704
|
if signature == nil || signature.Results() == nil || signature.Results().Len() != 1 {
|
|
3438
4705
|
return false
|
|
3439
4706
|
}
|
|
@@ -3446,6 +4713,9 @@ func genericCallTupleResultTypeParamIndexes(ctx lowerFileContext, expr ast.Expr)
|
|
|
3446
4713
|
return nil
|
|
3447
4714
|
}
|
|
3448
4715
|
signature := genericFunctionSignatureForCall(ctx, call.Fun)
|
|
4716
|
+
if signature == nil {
|
|
4717
|
+
signature = sourceFunctionSignatureForCall(ctx, call.Fun)
|
|
4718
|
+
}
|
|
3449
4719
|
if signature == nil || signature.Results() == nil || signature.Results().Len() < 2 {
|
|
3450
4720
|
return nil
|
|
3451
4721
|
}
|
|
@@ -3471,6 +4741,30 @@ func genericFunctionSignatureForCall(ctx lowerFileContext, fun ast.Expr) *types.
|
|
|
3471
4741
|
}
|
|
3472
4742
|
}
|
|
3473
4743
|
|
|
4744
|
+
func sourceFunctionSignatureForCall(ctx lowerFileContext, fun ast.Expr) *types.Signature {
|
|
4745
|
+
for {
|
|
4746
|
+
switch typed := ast.Unparen(fun).(type) {
|
|
4747
|
+
case *ast.IndexExpr:
|
|
4748
|
+
fun = typed.X
|
|
4749
|
+
case *ast.IndexListExpr:
|
|
4750
|
+
fun = typed.X
|
|
4751
|
+
default:
|
|
4752
|
+
if ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
4753
|
+
return nil
|
|
4754
|
+
}
|
|
4755
|
+
fn := calledFunction(ctx.semPkg.source, fun)
|
|
4756
|
+
if fn == nil {
|
|
4757
|
+
return nil
|
|
4758
|
+
}
|
|
4759
|
+
if origin := fn.Origin(); origin != nil {
|
|
4760
|
+
fn = origin
|
|
4761
|
+
}
|
|
4762
|
+
signature, _ := fn.Type().(*types.Signature)
|
|
4763
|
+
return signature
|
|
4764
|
+
}
|
|
4765
|
+
}
|
|
4766
|
+
}
|
|
4767
|
+
|
|
3474
4768
|
func typeContainsTypeParam(typ types.Type) bool {
|
|
3475
4769
|
return typeContainsTypeParamSeen(typ, make(map[types.Type]bool))
|
|
3476
4770
|
}
|
|
@@ -3569,27 +4863,57 @@ func (o *LoweringOwner) lowerNamedResults(ctx lowerFileContext, signature *types
|
|
|
3569
4863
|
}
|
|
3570
4864
|
|
|
3571
4865
|
func (o *LoweringOwner) lowerNamedResultReturn(ctx lowerFileContext) (string, bool) {
|
|
3572
|
-
|
|
3573
|
-
if len(results) == 0 {
|
|
4866
|
+
if ctx.signature == nil || ctx.signature.Results() == nil || ctx.signature.Results().Len() == 0 {
|
|
3574
4867
|
return "", false
|
|
3575
4868
|
}
|
|
3576
|
-
|
|
3577
|
-
|
|
4869
|
+
parts := make([]string, 0, ctx.signature.Results().Len())
|
|
4870
|
+
hasNamedResult := false
|
|
4871
|
+
for result := range ctx.signature.Results().Variables() {
|
|
4872
|
+
name := result.Name()
|
|
4873
|
+
if name == "" {
|
|
4874
|
+
parts = append(parts, o.lowerDeclarationZeroValueExpr(ctx, result.Type()))
|
|
4875
|
+
continue
|
|
4876
|
+
}
|
|
4877
|
+
hasNamedResult = true
|
|
4878
|
+
if name == "_" {
|
|
4879
|
+
parts = append(parts, o.lowerDeclarationZeroValueExpr(ctx, result.Type()))
|
|
4880
|
+
continue
|
|
4881
|
+
}
|
|
4882
|
+
returnExpr := safeIdentifier(name)
|
|
4883
|
+
if ctx.model.needsVarRef[result] {
|
|
4884
|
+
returnExpr += ".value"
|
|
4885
|
+
}
|
|
4886
|
+
parts = append(parts, returnExpr)
|
|
4887
|
+
}
|
|
4888
|
+
if !hasNamedResult {
|
|
4889
|
+
return "", false
|
|
3578
4890
|
}
|
|
3579
|
-
parts
|
|
3580
|
-
|
|
3581
|
-
parts = append(parts, result.returnExpr)
|
|
4891
|
+
if len(parts) == 1 {
|
|
4892
|
+
return parts[0], true
|
|
3582
4893
|
}
|
|
3583
4894
|
return "[" + strings.Join(parts, ", ") + "]", true
|
|
3584
4895
|
}
|
|
3585
4896
|
|
|
3586
4897
|
func (o *LoweringOwner) lowerForStmt(ctx lowerFileContext, stmt *ast.ForStmt) (loweredStmt, []Diagnostic) {
|
|
3587
|
-
bodyCtx := ctx.withoutRangeLoopBranches()
|
|
4898
|
+
bodyCtx := ctx.withoutRangeLoopBranches().withoutLoopLabel()
|
|
3588
4899
|
loopLabel := ""
|
|
3589
4900
|
if stmtListNeedsLoopBranchLabel(stmt.Body.List) {
|
|
3590
4901
|
loopLabel = ctx.tempName("Loop")
|
|
3591
4902
|
bodyCtx = bodyCtx.withLoopLabel(loopLabel)
|
|
3592
4903
|
}
|
|
4904
|
+
initCtx := ctx
|
|
4905
|
+
loopCtx := ctx
|
|
4906
|
+
var initPrelude []loweredStmt
|
|
4907
|
+
if assign, ok := stmt.Init.(*ast.AssignStmt); ok && assign.Tok == token.DEFINE {
|
|
4908
|
+
oldAliases, prelude := o.lowerShortDeclShadowAliases(ctx, assign)
|
|
4909
|
+
newAliases := o.lowerShortDeclNewShadowAliases(ctx, assign)
|
|
4910
|
+
if len(oldAliases) != 0 || len(newAliases) != 0 {
|
|
4911
|
+
initCtx = ctx.withIdentAliases(oldAliases).withIdentRefAliases(newAliases)
|
|
4912
|
+
loopCtx = ctx.withIdentRefAliases(newAliases)
|
|
4913
|
+
bodyCtx = bodyCtx.withIdentRefAliases(newAliases)
|
|
4914
|
+
initPrelude = prelude
|
|
4915
|
+
}
|
|
4916
|
+
}
|
|
3593
4917
|
if stmt.Init == nil && stmt.Post == nil {
|
|
3594
4918
|
cond := "true"
|
|
3595
4919
|
var diagnostics []Diagnostic
|
|
@@ -3614,19 +4938,19 @@ func (o *LoweringOwner) lowerForStmt(ctx lowerFileContext, stmt *ast.ForStmt) (l
|
|
|
3614
4938
|
init := ""
|
|
3615
4939
|
var diagnostics []Diagnostic
|
|
3616
4940
|
if stmt.Init != nil {
|
|
3617
|
-
lowered, initDiagnostics := o.lowerForInitStmt(
|
|
4941
|
+
lowered, initDiagnostics := o.lowerForInitStmt(initCtx, stmt.Init)
|
|
3618
4942
|
diagnostics = append(diagnostics, initDiagnostics...)
|
|
3619
4943
|
init = lowered
|
|
3620
4944
|
}
|
|
3621
4945
|
cond := ""
|
|
3622
4946
|
if stmt.Cond != nil {
|
|
3623
4947
|
var condDiagnostics []Diagnostic
|
|
3624
|
-
cond, condDiagnostics = o.lowerExpr(
|
|
4948
|
+
cond, condDiagnostics = o.lowerExpr(loopCtx, stmt.Cond)
|
|
3625
4949
|
diagnostics = append(diagnostics, condDiagnostics...)
|
|
3626
4950
|
}
|
|
3627
4951
|
post := ""
|
|
3628
4952
|
if stmt.Post != nil {
|
|
3629
|
-
lowered, postDiagnostics := o.lowerForPostStmt(
|
|
4953
|
+
lowered, postDiagnostics := o.lowerForPostStmt(loopCtx, stmt.Post)
|
|
3630
4954
|
diagnostics = append(diagnostics, postDiagnostics...)
|
|
3631
4955
|
post = lowered
|
|
3632
4956
|
}
|
|
@@ -3636,11 +4960,15 @@ func (o *LoweringOwner) lowerForStmt(ctx lowerFileContext, stmt *ast.ForStmt) (l
|
|
|
3636
4960
|
if loopLabel != "" {
|
|
3637
4961
|
text = loopLabel + ": " + text
|
|
3638
4962
|
}
|
|
3639
|
-
|
|
4963
|
+
forStmt := loweredStmt{
|
|
3640
4964
|
hasBlock: true,
|
|
3641
4965
|
text: text,
|
|
3642
4966
|
children: body,
|
|
3643
|
-
}
|
|
4967
|
+
}
|
|
4968
|
+
if len(initPrelude) != 0 {
|
|
4969
|
+
return loweredStmt{children: append(initPrelude, forStmt)}, diagnostics
|
|
4970
|
+
}
|
|
4971
|
+
return forStmt, diagnostics
|
|
3644
4972
|
}
|
|
3645
4973
|
|
|
3646
4974
|
func (o *LoweringOwner) lowerForInitStmt(ctx lowerFileContext, stmt ast.Stmt) (string, []Diagnostic) {
|
|
@@ -3729,9 +5057,13 @@ func (o *LoweringOwner) lowerForPostStmt(ctx lowerFileContext, stmt ast.Stmt) (s
|
|
|
3729
5057
|
diagnostics = append(diagnostics, leftDiagnostics...)
|
|
3730
5058
|
lefts = append(lefts, left)
|
|
3731
5059
|
}
|
|
3732
|
-
for
|
|
5060
|
+
for idx, rhs := range assign.Rhs {
|
|
3733
5061
|
right, rightDiagnostics := o.lowerExpr(ctx, rhs)
|
|
3734
5062
|
diagnostics = append(diagnostics, rightDiagnostics...)
|
|
5063
|
+
if idx < len(assign.Lhs) {
|
|
5064
|
+
targetType := ctx.semPkg.source.TypesInfo.TypeOf(assign.Lhs[idx])
|
|
5065
|
+
right = o.lowerValueForTarget(ctx, rhs, targetType, right)
|
|
5066
|
+
}
|
|
3735
5067
|
rights = append(rights, right)
|
|
3736
5068
|
}
|
|
3737
5069
|
return "[" + strings.Join(lefts, ", ") + "] = [" + strings.Join(rights, ", ") + "]", diagnostics
|
|
@@ -3746,7 +5078,7 @@ func (o *LoweringOwner) lowerForPostStmt(ctx lowerFileContext, stmt ast.Stmt) (s
|
|
|
3746
5078
|
func (o *LoweringOwner) lowerRangeStmt(ctx lowerFileContext, stmt *ast.RangeStmt) (loweredStmt, []Diagnostic) {
|
|
3747
5079
|
rangeValue, diagnostics := o.lowerExpr(ctx, stmt.X)
|
|
3748
5080
|
aliases := o.lowerRangeDeclShadowAliases(ctx, stmt)
|
|
3749
|
-
bodyCtx := ctx
|
|
5081
|
+
bodyCtx := ctx.withoutLoopLabel()
|
|
3750
5082
|
if len(aliases) != 0 {
|
|
3751
5083
|
bodyCtx = bodyCtx.withIdentAliases(aliases)
|
|
3752
5084
|
}
|
|
@@ -3795,23 +5127,21 @@ func (o *LoweringOwner) lowerRangeStmt(ctx lowerFileContext, stmt *ast.RangeStmt
|
|
|
3795
5127
|
if strings.HasPrefix(rangeTarget, "await ") {
|
|
3796
5128
|
rangeTarget = "(" + rangeTarget + ")"
|
|
3797
5129
|
}
|
|
3798
|
-
key := keyName
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
value := valueName
|
|
3803
|
-
if value == "" {
|
|
3804
|
-
value = "__rangeValue"
|
|
3805
|
-
}
|
|
5130
|
+
key, keyBindings, keyDiagnostics := o.lowerMapRangeBinding(ctx, stmt.Key, keyName, "__rangeKey", "RangeKey", stmt.Tok == token.DEFINE)
|
|
5131
|
+
value, valueBindings, valueDiagnostics := o.lowerMapRangeBinding(ctx, stmt.Value, valueName, "__rangeValue", "RangeValue", stmt.Tok == token.DEFINE)
|
|
5132
|
+
diagnostics = append(diagnostics, keyDiagnostics...)
|
|
5133
|
+
diagnostics = append(diagnostics, valueDiagnostics...)
|
|
3806
5134
|
binding := "const"
|
|
3807
5135
|
if rangeBindingAssignedInBody(ctx, stmt.Key, stmt.Body) ||
|
|
3808
5136
|
rangeBindingAssignedInBody(ctx, stmt.Value, stmt.Body) {
|
|
3809
5137
|
binding = "let"
|
|
3810
5138
|
}
|
|
5139
|
+
children := append(keyBindings, valueBindings...)
|
|
5140
|
+
children = append(children, body...)
|
|
3811
5141
|
return loweredStmt{
|
|
3812
5142
|
hasBlock: true,
|
|
3813
5143
|
text: "for (" + binding + " [" + key + ", " + value + "] of " + rangeTarget + "?.entries() ?? [])",
|
|
3814
|
-
children:
|
|
5144
|
+
children: children,
|
|
3815
5145
|
}, diagnostics
|
|
3816
5146
|
}
|
|
3817
5147
|
if isStringType(rangeType) {
|
|
@@ -3848,8 +5178,12 @@ func (o *LoweringOwner) lowerRangeStmt(ctx lowerFileContext, stmt *ast.RangeStmt
|
|
|
3848
5178
|
|
|
3849
5179
|
body, bodyDiagnostics := o.lowerBlock(bodyCtx.withoutRangeLoopBranches(), stmt.Body)
|
|
3850
5180
|
diagnostics = append(diagnostics, bodyDiagnostics...)
|
|
3851
|
-
rangeTarget :=
|
|
3852
|
-
|
|
5181
|
+
rangeTarget := ctx.tempName("RangeTarget")
|
|
5182
|
+
rangeTargetValue := o.lowerArrayPointerTarget(ctx, rangeValue, rangeType)
|
|
5183
|
+
indexTarget := rangeTarget
|
|
5184
|
+
if isNilableType(rangeType) {
|
|
5185
|
+
indexTarget += "!"
|
|
5186
|
+
}
|
|
3853
5187
|
indexName := keyName
|
|
3854
5188
|
if indexName == "" {
|
|
3855
5189
|
indexName = "__rangeIndex"
|
|
@@ -3864,7 +5198,7 @@ func (o *LoweringOwner) lowerRangeStmt(ctx lowerFileContext, stmt *ast.RangeStmt
|
|
|
3864
5198
|
}
|
|
3865
5199
|
return loweredStmt{
|
|
3866
5200
|
hasBlock: true,
|
|
3867
|
-
text: "for (let " + indexName + " = 0; " + indexName + " < " + o.runtimeOwner.QualifiedHelper(RuntimeHelperLen) + "(" + rangeTarget + "); " + indexName + "++)",
|
|
5201
|
+
text: "for (let " + rangeTarget + " = " + rangeTargetValue + ", " + indexName + " = 0; " + indexName + " < " + o.runtimeOwner.QualifiedHelper(RuntimeHelperLen) + "(" + rangeTarget + "); " + indexName + "++)",
|
|
3868
5202
|
children: children,
|
|
3869
5203
|
}, diagnostics
|
|
3870
5204
|
}
|
|
@@ -3933,18 +5267,19 @@ func (o *LoweringOwner) lowerRangeFuncStmt(
|
|
|
3933
5267
|
rangeBranch.value = ctx.tempName("RangeReturnValue")
|
|
3934
5268
|
rangeBranch.resultType = o.tsSignatureResultFor(ctx, ctx.signature)
|
|
3935
5269
|
}
|
|
3936
|
-
body, diagnostics := o.lowerBlock(ctx.withRangeBranch(rangeBranch), stmt.Body)
|
|
5270
|
+
body, diagnostics := o.lowerBlock(ctx.withoutLoopLabel().withRangeBranch(rangeBranch), stmt.Body)
|
|
3937
5271
|
if stmt.Tok != token.DEFINE {
|
|
3938
5272
|
assignments, assignmentDiagnostics := o.lowerRangeFuncAssignments(ctx, stmt, paramNames)
|
|
3939
5273
|
diagnostics = append(diagnostics, assignmentDiagnostics...)
|
|
3940
5274
|
body = append(assignments, body...)
|
|
3941
5275
|
}
|
|
5276
|
+
async := ctx.asyncFunction
|
|
3942
5277
|
|
|
3943
5278
|
return loweredStmt{rangeFunc: &loweredRangeFunc{
|
|
3944
5279
|
value: rangeValue,
|
|
3945
5280
|
params: paramNames,
|
|
3946
5281
|
body: body,
|
|
3947
|
-
async:
|
|
5282
|
+
async: async,
|
|
3948
5283
|
returnBranch: rangeBranch,
|
|
3949
5284
|
parentBranch: parentBranch,
|
|
3950
5285
|
}}, diagnostics
|
|
@@ -3989,6 +5324,7 @@ func (o *LoweringOwner) lowerSelectStmt(ctx lowerFileContext, stmt *ast.SelectSt
|
|
|
3989
5324
|
lowered := &loweredSelect{
|
|
3990
5325
|
hasReturn: selectName + "HasReturn",
|
|
3991
5326
|
value: selectName + "Value",
|
|
5327
|
+
result: selectName + "Result",
|
|
3992
5328
|
resultType: resultType,
|
|
3993
5329
|
}
|
|
3994
5330
|
var diagnostics []Diagnostic
|
|
@@ -4025,7 +5361,7 @@ func (o *LoweringOwner) lowerSelectStmt(ctx lowerFileContext, stmt *ast.SelectSt
|
|
|
4025
5361
|
})
|
|
4026
5362
|
caseID++
|
|
4027
5363
|
case *ast.ExprStmt:
|
|
4028
|
-
channel, prelude, receiveDiagnostics := o.lowerSelectReceiveComm(ctx, nil, comm.X)
|
|
5364
|
+
channel, prelude, receiveDiagnostics := o.lowerSelectReceiveComm(ctx, nil, comm.X, lowered.result)
|
|
4029
5365
|
body, bodyDiagnostics := o.lowerStmtList(ctx.withLocalScope().withoutRangeBreak(), clause.Body)
|
|
4030
5366
|
diagnostics = append(diagnostics, receiveDiagnostics...)
|
|
4031
5367
|
diagnostics = append(diagnostics, bodyDiagnostics...)
|
|
@@ -4037,7 +5373,7 @@ func (o *LoweringOwner) lowerSelectStmt(ctx lowerFileContext, stmt *ast.SelectSt
|
|
|
4037
5373
|
})
|
|
4038
5374
|
caseID++
|
|
4039
5375
|
case *ast.AssignStmt:
|
|
4040
|
-
channel, prelude, receiveDiagnostics := o.lowerSelectReceiveComm(ctx, comm, nil)
|
|
5376
|
+
channel, prelude, receiveDiagnostics := o.lowerSelectReceiveComm(ctx, comm, nil, lowered.result)
|
|
4041
5377
|
body, bodyDiagnostics := o.lowerStmtList(ctx.withLocalScope().withoutRangeBreak(), clause.Body)
|
|
4042
5378
|
diagnostics = append(diagnostics, receiveDiagnostics...)
|
|
4043
5379
|
diagnostics = append(diagnostics, bodyDiagnostics...)
|
|
@@ -4083,11 +5419,22 @@ func stmtsEndInReturn(stmts []loweredStmt) bool {
|
|
|
4083
5419
|
return false
|
|
4084
5420
|
}
|
|
4085
5421
|
last := stmts[len(stmts)-1]
|
|
4086
|
-
|
|
5422
|
+
return stmtEndsInReturn(last)
|
|
5423
|
+
}
|
|
5424
|
+
|
|
5425
|
+
func stmtEndsInReturn(stmt loweredStmt) bool {
|
|
5426
|
+
trimmed := strings.TrimSpace(stmt.text)
|
|
5427
|
+
if strings.HasPrefix(trimmed, "return") {
|
|
4087
5428
|
return true
|
|
4088
5429
|
}
|
|
4089
|
-
if
|
|
4090
|
-
return
|
|
5430
|
+
if stmt.selectStmt != nil {
|
|
5431
|
+
return stmt.selectStmt.returns
|
|
5432
|
+
}
|
|
5433
|
+
if trimmed == "" && (stmt.hasBlock || len(stmt.children) != 0) {
|
|
5434
|
+
return stmtsEndInReturn(stmt.children)
|
|
5435
|
+
}
|
|
5436
|
+
if strings.HasPrefix(trimmed, "if ") && len(stmt.elseBody) != 0 {
|
|
5437
|
+
return stmtsEndInReturn(stmt.children) && stmtsEndInReturn(stmt.elseBody)
|
|
4091
5438
|
}
|
|
4092
5439
|
return false
|
|
4093
5440
|
}
|
|
@@ -4134,6 +5481,7 @@ func (o *LoweringOwner) lowerSelectReceiveComm(
|
|
|
4134
5481
|
ctx lowerFileContext,
|
|
4135
5482
|
assign *ast.AssignStmt,
|
|
4136
5483
|
expr ast.Expr,
|
|
5484
|
+
resultName string,
|
|
4137
5485
|
) (string, []loweredStmt, []Diagnostic) {
|
|
4138
5486
|
receiveExpr := expr
|
|
4139
5487
|
if assign != nil && len(assign.Rhs) == 1 {
|
|
@@ -4162,7 +5510,7 @@ func (o *LoweringOwner) lowerSelectReceiveComm(
|
|
|
4162
5510
|
if assign.Tok == token.DEFINE && isShortAssignTargetNew(ctx, lhs) {
|
|
4163
5511
|
prefix = "let "
|
|
4164
5512
|
}
|
|
4165
|
-
prelude = append(prelude, loweredStmt{text: prefix + left + " =
|
|
5513
|
+
prelude = append(prelude, loweredStmt{text: prefix + left + " = " + resultName + fields[idx]})
|
|
4166
5514
|
}
|
|
4167
5515
|
return channel, prelude, diagnostics
|
|
4168
5516
|
}
|
|
@@ -4177,15 +5525,24 @@ func (o *LoweringOwner) lowerSwitchStmt(ctx lowerFileContext, stmt *ast.SwitchSt
|
|
|
4177
5525
|
}
|
|
4178
5526
|
|
|
4179
5527
|
value := "true"
|
|
5528
|
+
var tagType types.Type
|
|
4180
5529
|
if stmt.Tag != nil {
|
|
4181
5530
|
var valueDiagnostics []Diagnostic
|
|
4182
5531
|
value, valueDiagnostics = o.lowerExpr(ctx, stmt.Tag)
|
|
4183
5532
|
diagnostics = append(diagnostics, valueDiagnostics...)
|
|
4184
5533
|
value = lowerConstantComparableValue(ctx, stmt.Tag, value)
|
|
5534
|
+
tagType = ctx.semPkg.source.TypesInfo.TypeOf(stmt.Tag)
|
|
4185
5535
|
} else if switchHasConstantCaseExpr(ctx, stmt) {
|
|
4186
5536
|
value = "(true as boolean)"
|
|
4187
5537
|
}
|
|
4188
5538
|
|
|
5539
|
+
compareCases := tagType != nil && isInterfaceType(tagType)
|
|
5540
|
+
compareValue := value
|
|
5541
|
+
if compareCases {
|
|
5542
|
+
compareValue = ctx.tempName("Switch")
|
|
5543
|
+
init = append(init, loweredStmt{text: "let " + compareValue + " = " + value})
|
|
5544
|
+
value = "true"
|
|
5545
|
+
}
|
|
4189
5546
|
switchIR := &loweredSwitch{value: value}
|
|
4190
5547
|
for _, raw := range stmt.Body.List {
|
|
4191
5548
|
clause, ok := raw.(*ast.CaseClause)
|
|
@@ -4207,6 +5564,11 @@ func (o *LoweringOwner) lowerSwitchStmt(ctx lowerFileContext, stmt *ast.SwitchSt
|
|
|
4207
5564
|
for _, expr := range clause.List {
|
|
4208
5565
|
lowered, exprDiagnostics := o.lowerExpr(ctx, expr)
|
|
4209
5566
|
diagnostics = append(diagnostics, exprDiagnostics...)
|
|
5567
|
+
if compareCases {
|
|
5568
|
+
sourceType := ctx.semPkg.source.TypesInfo.TypeOf(expr)
|
|
5569
|
+
lowered = o.lowerValueForTargetTypes(ctx, tagType, sourceType, lowered, shouldCloneStructValue(expr))
|
|
5570
|
+
lowered = o.runtimeOwner.QualifiedHelper(RuntimeHelperComparableEqual) + "(" + compareValue + ", " + lowered + ")"
|
|
5571
|
+
}
|
|
4210
5572
|
values = append(values, lowered)
|
|
4211
5573
|
}
|
|
4212
5574
|
switchIR.cases = append(switchIR.cases, loweredSwitchCase{
|
|
@@ -4309,7 +5671,7 @@ func (o *LoweringOwner) lowerTypeSwitchStmt(ctx lowerFileContext, stmt *ast.Type
|
|
|
4309
5671
|
if typ == nil {
|
|
4310
5672
|
tsTypes = append(tsTypes, "any")
|
|
4311
5673
|
} else {
|
|
4312
|
-
tsTypes = append(tsTypes, o.
|
|
5674
|
+
tsTypes = append(tsTypes, o.tsTypeSwitchCaseTypeFor(ctx, typ))
|
|
4313
5675
|
}
|
|
4314
5676
|
}
|
|
4315
5677
|
switchIR.cases = append(switchIR.cases, loweredTypeSwitchCase{
|
|
@@ -4323,6 +5685,15 @@ func (o *LoweringOwner) lowerTypeSwitchStmt(ctx lowerFileContext, stmt *ast.Type
|
|
|
4323
5685
|
return lowered, diagnostics
|
|
4324
5686
|
}
|
|
4325
5687
|
|
|
5688
|
+
func (o *LoweringOwner) tsTypeSwitchCaseTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
5689
|
+
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
5690
|
+
if _, ok := named.Underlying().(*types.Interface); ok {
|
|
5691
|
+
return o.tsNonNilTypeFor(ctx, named)
|
|
5692
|
+
}
|
|
5693
|
+
}
|
|
5694
|
+
return o.tsTypeFor(ctx, typ)
|
|
5695
|
+
}
|
|
5696
|
+
|
|
4326
5697
|
func loweredStmtsUseVarRefName(stmts []loweredStmt, name string) bool {
|
|
4327
5698
|
if name == "" {
|
|
4328
5699
|
return false
|
|
@@ -4518,7 +5889,108 @@ func (o *LoweringOwner) lowerArrayEqualityExpr(ctx lowerFileContext, expr *ast.B
|
|
|
4518
5889
|
return value, true
|
|
4519
5890
|
}
|
|
4520
5891
|
|
|
5892
|
+
func (o *LoweringOwner) lowerComplexEqualityExpr(ctx lowerFileContext, expr *ast.BinaryExpr, left string, right string) (string, bool) {
|
|
5893
|
+
leftType := ctx.semPkg.source.TypesInfo.TypeOf(expr.X)
|
|
5894
|
+
rightType := ctx.semPkg.source.TypesInfo.TypeOf(expr.Y)
|
|
5895
|
+
if !isComplexType(leftType) || !isComplexType(rightType) {
|
|
5896
|
+
return "", false
|
|
5897
|
+
}
|
|
5898
|
+
value := o.runtimeOwner.QualifiedHelper(RuntimeHelperArrayEqual) + "(" + left + ", " + right + ")"
|
|
5899
|
+
if expr.Op == token.NEQ {
|
|
5900
|
+
value = "!" + value
|
|
5901
|
+
}
|
|
5902
|
+
return value, true
|
|
5903
|
+
}
|
|
5904
|
+
|
|
5905
|
+
func (o *LoweringOwner) lowerStringEqualityExpr(ctx lowerFileContext, expr *ast.BinaryExpr, left string, right string) (string, bool) {
|
|
5906
|
+
leftType := ctx.semPkg.source.TypesInfo.TypeOf(expr.X)
|
|
5907
|
+
rightType := ctx.semPkg.source.TypesInfo.TypeOf(expr.Y)
|
|
5908
|
+
if !isStringType(leftType) || !isStringType(rightType) {
|
|
5909
|
+
return "", false
|
|
5910
|
+
}
|
|
5911
|
+
value := o.runtimeOwner.QualifiedHelper(RuntimeHelperStringEqual) + "(" + left + ", " + right + ")"
|
|
5912
|
+
if expr.Op == token.NEQ {
|
|
5913
|
+
value = "!" + value
|
|
5914
|
+
}
|
|
5915
|
+
return value, true
|
|
5916
|
+
}
|
|
5917
|
+
|
|
5918
|
+
func (o *LoweringOwner) lowerInterfaceEqualityExpr(ctx lowerFileContext, expr *ast.BinaryExpr, left string, right string) (string, bool) {
|
|
5919
|
+
if isNilExpr(expr.X) || isNilExpr(expr.Y) {
|
|
5920
|
+
return "", false
|
|
5921
|
+
}
|
|
5922
|
+
leftType := ctx.semPkg.source.TypesInfo.TypeOf(expr.X)
|
|
5923
|
+
rightType := ctx.semPkg.source.TypesInfo.TypeOf(expr.Y)
|
|
5924
|
+
if !isInterfaceType(leftType) && !isInterfaceType(rightType) {
|
|
5925
|
+
return "", false
|
|
5926
|
+
}
|
|
5927
|
+
value := o.runtimeOwner.QualifiedHelper(RuntimeHelperComparableEqual) + "(" + left + ", " + right + ")"
|
|
5928
|
+
if expr.Op == token.NEQ {
|
|
5929
|
+
value = "!" + value
|
|
5930
|
+
}
|
|
5931
|
+
return value, true
|
|
5932
|
+
}
|
|
5933
|
+
|
|
5934
|
+
func (o *LoweringOwner) lowerStringOrderExpr(
|
|
5935
|
+
ctx lowerFileContext,
|
|
5936
|
+
expr *ast.BinaryExpr,
|
|
5937
|
+
left string,
|
|
5938
|
+
right string,
|
|
5939
|
+
leftDiagnostics []Diagnostic,
|
|
5940
|
+
rightDiagnostics []Diagnostic,
|
|
5941
|
+
) (string, []Diagnostic, bool) {
|
|
5942
|
+
leftType := ctx.semPkg.source.TypesInfo.TypeOf(expr.X)
|
|
5943
|
+
rightType := ctx.semPkg.source.TypesInfo.TypeOf(expr.Y)
|
|
5944
|
+
if !isStringType(leftType) || !isStringType(rightType) {
|
|
5945
|
+
return "", nil, false
|
|
5946
|
+
}
|
|
5947
|
+
left, leftDiagnostics = o.lowerStringOrderOperand(ctx, expr.X, left, leftDiagnostics)
|
|
5948
|
+
right, rightDiagnostics = o.lowerStringOrderOperand(ctx, expr.Y, right, rightDiagnostics)
|
|
5949
|
+
compare := o.runtimeOwner.QualifiedHelper(RuntimeHelperStringCompare) + "(" + left + ", " + right + ")"
|
|
5950
|
+
switch expr.Op {
|
|
5951
|
+
case token.LSS:
|
|
5952
|
+
return compare + " < 0", append(leftDiagnostics, rightDiagnostics...), true
|
|
5953
|
+
case token.LEQ:
|
|
5954
|
+
return compare + " <= 0", append(leftDiagnostics, rightDiagnostics...), true
|
|
5955
|
+
case token.GTR:
|
|
5956
|
+
return compare + " > 0", append(leftDiagnostics, rightDiagnostics...), true
|
|
5957
|
+
case token.GEQ:
|
|
5958
|
+
return compare + " >= 0", append(leftDiagnostics, rightDiagnostics...), true
|
|
5959
|
+
default:
|
|
5960
|
+
return "", nil, false
|
|
5961
|
+
}
|
|
5962
|
+
}
|
|
5963
|
+
|
|
5964
|
+
func (o *LoweringOwner) lowerStringOrderOperand(
|
|
5965
|
+
ctx lowerFileContext,
|
|
5966
|
+
expr ast.Expr,
|
|
5967
|
+
fallback string,
|
|
5968
|
+
fallbackDiagnostics []Diagnostic,
|
|
5969
|
+
) (string, []Diagnostic) {
|
|
5970
|
+
call, ok := unwrapParenExpr(expr).(*ast.CallExpr)
|
|
5971
|
+
if !ok || len(call.Args) != 1 {
|
|
5972
|
+
return fallback, fallbackDiagnostics
|
|
5973
|
+
}
|
|
5974
|
+
targetType := typeFromExpr(ctx, call.Fun)
|
|
5975
|
+
sourceType := ctx.semPkg.source.TypesInfo.TypeOf(call.Args[0])
|
|
5976
|
+
if targetType == nil || sourceType == nil || !isStringType(targetType) || !isByteSliceType(sourceType) {
|
|
5977
|
+
return fallback, fallbackDiagnostics
|
|
5978
|
+
}
|
|
5979
|
+
return o.lowerExpr(ctx, call.Args[0])
|
|
5980
|
+
}
|
|
5981
|
+
|
|
5982
|
+
func binaryOperandUsesTypeParam(ctx lowerFileContext, expr ast.Expr) bool {
|
|
5983
|
+
typ := ctx.semPkg.source.TypesInfo.TypeOf(expr)
|
|
5984
|
+
_, ok := types.Unalias(typ).(*types.TypeParam)
|
|
5985
|
+
return ok
|
|
5986
|
+
}
|
|
5987
|
+
|
|
4521
5988
|
func (o *LoweringOwner) lowerExpr(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
5989
|
+
if value := ctx.semPkg.source.TypesInfo.Types[unwrapParenExpr(expr)].Value; value != nil && value.Kind() == constant.Complex {
|
|
5990
|
+
if constantValue, ok := lowerConstantValue(value); ok {
|
|
5991
|
+
return constantValue, nil
|
|
5992
|
+
}
|
|
5993
|
+
}
|
|
4522
5994
|
switch typed := expr.(type) {
|
|
4523
5995
|
case *ast.BasicLit:
|
|
4524
5996
|
return lowerBasicLit(typed), nil
|
|
@@ -4526,6 +5998,11 @@ func (o *LoweringOwner) lowerExpr(ctx lowerFileContext, expr ast.Expr) (string,
|
|
|
4526
5998
|
return o.lowerIdent(ctx, typed, false), nil
|
|
4527
5999
|
case *ast.BinaryExpr:
|
|
4528
6000
|
if value := ctx.semPkg.source.TypesInfo.Types[typed].Value; value != nil {
|
|
6001
|
+
if (typed.Op == token.SHL || typed.Op == token.SHR) && (value.Kind() == constant.Int || value.Kind() == constant.Float) {
|
|
6002
|
+
if constantValue, ok := lowerConstantValue(value); ok {
|
|
6003
|
+
return constantValue, nil
|
|
6004
|
+
}
|
|
6005
|
+
}
|
|
4529
6006
|
if constantValue, ok := lowerLargeIntegerConstantValue(value); ok {
|
|
4530
6007
|
return constantValue, nil
|
|
4531
6008
|
}
|
|
@@ -4550,8 +6027,20 @@ func (o *LoweringOwner) lowerExpr(ctx lowerFileContext, expr ast.Expr) (string,
|
|
|
4550
6027
|
if value, ok := o.lowerArrayEqualityExpr(ctx, typed, left, right); ok {
|
|
4551
6028
|
return value, append(leftDiagnostics, rightDiagnostics...)
|
|
4552
6029
|
}
|
|
6030
|
+
if value, ok := o.lowerComplexEqualityExpr(ctx, typed, left, right); ok {
|
|
6031
|
+
return value, append(leftDiagnostics, rightDiagnostics...)
|
|
6032
|
+
}
|
|
6033
|
+
if value, ok := o.lowerStringEqualityExpr(ctx, typed, left, right); ok {
|
|
6034
|
+
return value, append(leftDiagnostics, rightDiagnostics...)
|
|
6035
|
+
}
|
|
6036
|
+
if value, ok := o.lowerInterfaceEqualityExpr(ctx, typed, left, right); ok {
|
|
6037
|
+
return value, append(leftDiagnostics, rightDiagnostics...)
|
|
6038
|
+
}
|
|
4553
6039
|
left, right = o.lowerEqualityOperands(ctx, typed, left, right)
|
|
4554
6040
|
}
|
|
6041
|
+
if value, ok := o.lowerWideIntegerBinaryExpr(ctx, typed, left, right); ok {
|
|
6042
|
+
return value, append(leftDiagnostics, rightDiagnostics...)
|
|
6043
|
+
}
|
|
4555
6044
|
if typed.Op == token.QUO && isIntegerType(ctx.semPkg.source.TypesInfo.TypeOf(typed)) {
|
|
4556
6045
|
return "Math.trunc(" + left + " / " + right + ")", append(leftDiagnostics, rightDiagnostics...)
|
|
4557
6046
|
}
|
|
@@ -4561,8 +6050,14 @@ func (o *LoweringOwner) lowerExpr(ctx lowerFileContext, expr ast.Expr) (string,
|
|
|
4561
6050
|
"(" + left + ", " + right + ", " + strconv.Itoa(bits) + ")", append(leftDiagnostics, rightDiagnostics...)
|
|
4562
6051
|
}
|
|
4563
6052
|
}
|
|
4564
|
-
if value, ok := o.
|
|
4565
|
-
return value,
|
|
6053
|
+
if value, diagnostics, ok := o.lowerStringOrderExpr(ctx, typed, left, right, leftDiagnostics, rightDiagnostics); ok {
|
|
6054
|
+
return value, diagnostics
|
|
6055
|
+
}
|
|
6056
|
+
if binaryOperandUsesTypeParam(ctx, typed.X) {
|
|
6057
|
+
left = "(" + left + " as any)"
|
|
6058
|
+
}
|
|
6059
|
+
if binaryOperandUsesTypeParam(ctx, typed.Y) {
|
|
6060
|
+
right = "(" + right + " as any)"
|
|
4566
6061
|
}
|
|
4567
6062
|
return left + " " + typed.Op.String() + " " + right, append(leftDiagnostics, rightDiagnostics...)
|
|
4568
6063
|
case *ast.UnaryExpr:
|
|
@@ -4575,7 +6070,7 @@ func (o *LoweringOwner) lowerExpr(ctx lowerFileContext, expr ast.Expr) (string,
|
|
|
4575
6070
|
}
|
|
4576
6071
|
value, diagnostics := o.lowerExpr(ctx, typed.X)
|
|
4577
6072
|
if typed.Op == token.NOT || typed.Op == token.SUB || typed.Op == token.ADD {
|
|
4578
|
-
return typed.Op
|
|
6073
|
+
return lowerPrefixUnaryExpr(typed.Op, value), diagnostics
|
|
4579
6074
|
}
|
|
4580
6075
|
if typed.Op == token.XOR {
|
|
4581
6076
|
return "~" + value, diagnostics
|
|
@@ -4621,7 +6116,7 @@ func lowerBasicLit(lit *ast.BasicLit) string {
|
|
|
4621
6116
|
if err != nil {
|
|
4622
6117
|
return strconv.Quote(lit.Value)
|
|
4623
6118
|
}
|
|
4624
|
-
return
|
|
6119
|
+
return lowerGoStringLiteral(value)
|
|
4625
6120
|
}
|
|
4626
6121
|
if lit.Kind == token.INT && isLegacyOctalLiteral(lit.Value) {
|
|
4627
6122
|
digits := strings.TrimLeft(strings.ReplaceAll(lit.Value, "_", ""), "0")
|
|
@@ -4665,8 +6160,17 @@ func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (st
|
|
|
4665
6160
|
if asyncCompatibleParams || funcLiteralUsesFunctionIdentifierCall(ctx, lit) {
|
|
4666
6161
|
bodyCtx = bodyCtx.withAsyncFunction(true)
|
|
4667
6162
|
}
|
|
6163
|
+
var params []loweredParam
|
|
6164
|
+
var paramBindings []loweredStmt
|
|
6165
|
+
if signature != nil && signature.Params() != nil {
|
|
6166
|
+
for idx := range signature.Params().Len() {
|
|
6167
|
+
param := signature.Params().At(idx)
|
|
6168
|
+
params, paramBindings = o.appendLoweredParam(ctx, params, paramBindings, param, idx, asyncCompatibleParams)
|
|
6169
|
+
}
|
|
6170
|
+
}
|
|
4668
6171
|
body, diagnostics := o.lowerBlock(bodyCtx, lit.Body)
|
|
4669
6172
|
var rendered strings.Builder
|
|
6173
|
+
renderStmts(&rendered, paramBindings, 1)
|
|
4670
6174
|
renderNamedResults(&rendered, o.lowerNamedResults(ctx, signature), 1)
|
|
4671
6175
|
renderDeferStack(&rendered, deferState, 1)
|
|
4672
6176
|
renderStmts(&rendered, body, 1)
|
|
@@ -4675,21 +6179,28 @@ func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (st
|
|
|
4675
6179
|
if async {
|
|
4676
6180
|
prefix = "async "
|
|
4677
6181
|
}
|
|
4678
|
-
function := prefix + "(" +
|
|
6182
|
+
function := prefix + "(" + renderLoweredParams(params) + "): " +
|
|
4679
6183
|
asyncResultType(o.tsSignatureResultFor(ctx, signature), async) + " => {\n" +
|
|
4680
6184
|
rendered.String() + "}"
|
|
4681
6185
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperFunctionValue) +
|
|
4682
6186
|
"(" + function + ", " + o.runtimeFunctionTypeInfo(signature, "") + ")", async, diagnostics
|
|
4683
6187
|
}
|
|
4684
6188
|
|
|
6189
|
+
func renderLoweredParams(params []loweredParam) string {
|
|
6190
|
+
if len(params) == 0 {
|
|
6191
|
+
return ""
|
|
6192
|
+
}
|
|
6193
|
+
rendered := make([]string, 0, len(params))
|
|
6194
|
+
for _, param := range params {
|
|
6195
|
+
rendered = append(rendered, param.name+": "+param.typ)
|
|
6196
|
+
}
|
|
6197
|
+
return strings.Join(rendered, ", ")
|
|
6198
|
+
}
|
|
6199
|
+
|
|
4685
6200
|
func funcLiteralUsesFunctionIdentifierCall(ctx lowerFileContext, lit *ast.FuncLit) bool {
|
|
4686
6201
|
if lit == nil || lit.Body == nil || ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
4687
6202
|
return false
|
|
4688
6203
|
}
|
|
4689
|
-
signature, _ := ctx.semPkg.source.TypesInfo.TypeOf(lit).(*types.Signature)
|
|
4690
|
-
if signature == nil || signature.Results() == nil || signature.Results().Len() == 0 {
|
|
4691
|
-
return false
|
|
4692
|
-
}
|
|
4693
6204
|
uses := false
|
|
4694
6205
|
ast.Inspect(lit.Body, func(node ast.Node) bool {
|
|
4695
6206
|
if uses {
|
|
@@ -4760,6 +6271,9 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
|
|
|
4760
6271
|
}
|
|
4761
6272
|
obj := objectForIdent(ctx, ident)
|
|
4762
6273
|
if alias := ctx.identAliases[obj]; alias != "" {
|
|
6274
|
+
if !raw && obj != nil && ctx.identAliasRefs[obj] && ctx.model.needsVarRef[obj] {
|
|
6275
|
+
return alias + ".value"
|
|
6276
|
+
}
|
|
4763
6277
|
return alias
|
|
4764
6278
|
}
|
|
4765
6279
|
if constObj, ok := obj.(*types.Const); ok && ctx.localAliases[obj] != "" {
|
|
@@ -4770,22 +6284,28 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
|
|
|
4770
6284
|
if alias := ctx.localAliases[obj]; alias != "" {
|
|
4771
6285
|
if ctx.lazyPackageVars[obj] {
|
|
4772
6286
|
lazyValue := alias + "." + packageVarGetterName(value) + "()"
|
|
4773
|
-
if
|
|
4774
|
-
|
|
6287
|
+
if (ctx.asyncFunction || ctx.topLevel) && o.packageVarHasAsyncLazyInit(ctx, obj) {
|
|
6288
|
+
lazyValue = "(await " + alias + "." + packageVarInitName(value) + "(), " + lazyValue + ")"
|
|
6289
|
+
}
|
|
6290
|
+
if raw {
|
|
6291
|
+
return lazyValue
|
|
4775
6292
|
}
|
|
4776
|
-
return lazyValue
|
|
6293
|
+
return o.lowerPackageVarReadValue(ctx, obj, lazyValue)
|
|
4777
6294
|
}
|
|
4778
|
-
|
|
6295
|
+
if raw {
|
|
6296
|
+
return alias + "." + value
|
|
6297
|
+
}
|
|
6298
|
+
return o.lowerPackageVarReadValue(ctx, obj, alias+"."+value)
|
|
4779
6299
|
}
|
|
4780
6300
|
if raw {
|
|
4781
6301
|
return value
|
|
4782
6302
|
}
|
|
4783
6303
|
if ctx.lazyPackageVars[obj] {
|
|
4784
6304
|
lazyValue := packageVarGetterName(value) + "()"
|
|
4785
|
-
if
|
|
4786
|
-
|
|
6305
|
+
if (ctx.asyncFunction || ctx.topLevel) && o.packageVarHasAsyncLazyInit(ctx, obj) {
|
|
6306
|
+
lazyValue = "(await " + packageVarInitName(value) + "(), " + lazyValue + ")"
|
|
4787
6307
|
}
|
|
4788
|
-
return lazyValue
|
|
6308
|
+
return o.lowerPackageVarReadValue(ctx, obj, lazyValue)
|
|
4789
6309
|
}
|
|
4790
6310
|
if obj != nil && ctx.model.needsVarRef[obj] {
|
|
4791
6311
|
return value + ".value"
|
|
@@ -4793,6 +6313,17 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
|
|
|
4793
6313
|
return value
|
|
4794
6314
|
}
|
|
4795
6315
|
|
|
6316
|
+
func (o *LoweringOwner) lowerPackageVarReadValue(ctx lowerFileContext, obj types.Object, value string) string {
|
|
6317
|
+
if obj == nil || ctx.model == nil || !ctx.model.needsVarRef[obj] {
|
|
6318
|
+
return value
|
|
6319
|
+
}
|
|
6320
|
+
if varObj, ok := obj.(*types.Var); ok && packageVarReadNeedsPointerValue(varObj.Type()) {
|
|
6321
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
6322
|
+
"<" + o.tsNonNilTypeFor(ctx, varObj.Type()) + ">(" + value + ")"
|
|
6323
|
+
}
|
|
6324
|
+
return value + ".value"
|
|
6325
|
+
}
|
|
6326
|
+
|
|
4796
6327
|
func objectForIdent(ctx lowerFileContext, ident *ast.Ident) types.Object {
|
|
4797
6328
|
if ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
4798
6329
|
return nil
|
|
@@ -4820,6 +6351,28 @@ func objectForValueExpr(ctx lowerFileContext, expr ast.Expr) types.Object {
|
|
|
4820
6351
|
}
|
|
4821
6352
|
}
|
|
4822
6353
|
|
|
6354
|
+
func objectNeedsVarRef(ctx lowerFileContext, obj types.Object) bool {
|
|
6355
|
+
if obj == nil || ctx.model == nil {
|
|
6356
|
+
return false
|
|
6357
|
+
}
|
|
6358
|
+
if ctx.model.needsVarRef[obj] {
|
|
6359
|
+
return true
|
|
6360
|
+
}
|
|
6361
|
+
if obj.Pkg() == nil {
|
|
6362
|
+
return false
|
|
6363
|
+
}
|
|
6364
|
+
semPkg := ctx.model.packages[obj.Pkg().Path()]
|
|
6365
|
+
if semPkg == nil {
|
|
6366
|
+
return false
|
|
6367
|
+
}
|
|
6368
|
+
for _, value := range semPkg.values {
|
|
6369
|
+
if value.name == obj.Name() && ctx.model.needsVarRef[value.object] {
|
|
6370
|
+
return true
|
|
6371
|
+
}
|
|
6372
|
+
}
|
|
6373
|
+
return false
|
|
6374
|
+
}
|
|
6375
|
+
|
|
4823
6376
|
func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr) (string, []Diagnostic) {
|
|
4824
6377
|
if ident, ok := expr.Fun.(*ast.Ident); ok && isBuiltinCallTarget(ctx, ident) {
|
|
4825
6378
|
switch ident.Name {
|
|
@@ -4846,6 +6399,22 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
4846
6399
|
}
|
|
4847
6400
|
return o.runtimeOwner.QualifiedHelper(helper) + "(" + strings.Join(args, ", ") + ")", diagnostics
|
|
4848
6401
|
case "append":
|
|
6402
|
+
if len(expr.Args) > 0 {
|
|
6403
|
+
if slice, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(expr.Args[0])).Underlying().(*types.Slice); ok {
|
|
6404
|
+
for idx := 1; idx < len(args); idx++ {
|
|
6405
|
+
if expr.Ellipsis != token.NoPos && idx == len(args)-1 {
|
|
6406
|
+
continue
|
|
6407
|
+
}
|
|
6408
|
+
args[idx] = o.lowerValueForTargetTypes(
|
|
6409
|
+
ctx,
|
|
6410
|
+
slice.Elem(),
|
|
6411
|
+
ctx.semPkg.source.TypesInfo.TypeOf(expr.Args[idx]),
|
|
6412
|
+
args[idx],
|
|
6413
|
+
false,
|
|
6414
|
+
)
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
}
|
|
4849
6418
|
if expr.Ellipsis != token.NoPos && len(args) > 1 {
|
|
4850
6419
|
last := len(args) - 1
|
|
4851
6420
|
spread := args[last]
|
|
@@ -4854,7 +6423,13 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
4854
6423
|
}
|
|
4855
6424
|
args[last] = "...(" + spread + " ?? [])"
|
|
4856
6425
|
}
|
|
4857
|
-
|
|
6426
|
+
appendHelper := o.runtimeOwner.QualifiedHelper(RuntimeHelperAppend)
|
|
6427
|
+
if len(args) > 0 && args[0] == "null" {
|
|
6428
|
+
if slice, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(expr)).Underlying().(*types.Slice); ok {
|
|
6429
|
+
appendHelper += "<" + o.tsTypeFor(ctx, slice.Elem()) + ">"
|
|
6430
|
+
}
|
|
6431
|
+
}
|
|
6432
|
+
return appendHelper + "(" + strings.Join(args, ", ") + ")", diagnostics
|
|
4858
6433
|
case "cap":
|
|
4859
6434
|
if len(expr.Args) == 1 {
|
|
4860
6435
|
args[0] = o.lowerArrayPointerTarget(ctx, args[0], ctx.semPkg.source.TypesInfo.TypeOf(expr.Args[0]))
|
|
@@ -4906,7 +6481,7 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
4906
6481
|
if typeParam := receiverTypeParam(selection.Recv()); typeParam != nil {
|
|
4907
6482
|
receiverExpr, receiverDiagnostics := o.lowerExpr(ctx, fun.X)
|
|
4908
6483
|
diagnostics = append(diagnostics, receiverDiagnostics...)
|
|
4909
|
-
if !
|
|
6484
|
+
if !typeParamInScope(ctx, typeParam) {
|
|
4910
6485
|
call := receiverExpr + "." + fun.Sel.Name + "(" + strings.Join(args, ", ") + ")"
|
|
4911
6486
|
return o.awaitCallIfNeeded(ctx, fun, call), diagnostics
|
|
4912
6487
|
}
|
|
@@ -4914,11 +6489,14 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
4914
6489
|
call := o.runtimeOwner.QualifiedHelper(RuntimeHelperCallGenericMethod) + "(" + strings.Join(methodArgs, ", ") + ")"
|
|
4915
6490
|
return o.awaitCallIfNeeded(ctx, fun, call), diagnostics
|
|
4916
6491
|
}
|
|
4917
|
-
receiver :=
|
|
6492
|
+
receiver := methodReceiverNamedType(selection.Obj())
|
|
6493
|
+
if receiver == nil {
|
|
6494
|
+
receiver = receiverNamedType(selection.Recv())
|
|
6495
|
+
}
|
|
4918
6496
|
if namedNonInterfaceNonStructType(receiver) {
|
|
4919
6497
|
return o.lowerNamedReceiverMethodCall(ctx, fun, args, diagnostics)
|
|
4920
6498
|
}
|
|
4921
|
-
if call, callDiagnostics, ok := o.
|
|
6499
|
+
if call, callDiagnostics, ok := o.lowerPointerReceiverMethodCall(ctx, fun, selection, args); ok {
|
|
4922
6500
|
return o.awaitCallIfNeeded(ctx, fun, call), append(diagnostics, callDiagnostics...)
|
|
4923
6501
|
}
|
|
4924
6502
|
receiverExpr, receiverDiagnostics := o.lowerMethodReceiverExpr(ctx, fun.X, selection)
|
|
@@ -5024,6 +6602,7 @@ func (o *LoweringOwner) lowerCallArgs(
|
|
|
5024
6602
|
lowered = o.lowerCallArgForTarget(ctx, arg, params.At(idx).Type(), lowered, overrideCall)
|
|
5025
6603
|
} else if expr.Ellipsis != token.NoPos && idx == len(expr.Args)-1 {
|
|
5026
6604
|
lowered = o.lowerCallArgForTarget(ctx, arg, params.At(fixedCount).Type(), lowered, overrideCall)
|
|
6605
|
+
lowered = "...(" + lowered + " ?? [])"
|
|
5027
6606
|
} else {
|
|
5028
6607
|
lowered = o.lowerCallArgForTarget(ctx, arg, targetType, lowered, overrideCall)
|
|
5029
6608
|
}
|
|
@@ -5107,19 +6686,41 @@ func (o *LoweringOwner) lowerTupleCallArgs(
|
|
|
5107
6686
|
parts = append(parts, converted)
|
|
5108
6687
|
}
|
|
5109
6688
|
if !changed {
|
|
5110
|
-
return []string{"...(" + value + ")"}, diagnostics, true
|
|
6689
|
+
return []string{"...(" + o.parenthesizedTupleCast(ctx, value, params) + ")"}, diagnostics, true
|
|
5111
6690
|
}
|
|
5112
6691
|
temp := ctx.tempName("TupleArg")
|
|
5113
6692
|
for idx, part := range parts {
|
|
5114
6693
|
parts[idx] = strings.ReplaceAll(part, "__goscriptTupleArg", temp)
|
|
5115
6694
|
}
|
|
5116
|
-
body := "const " + temp + " = " + value + "; return
|
|
6695
|
+
body := "const " + temp + " = " + value + "; return " + o.tupleLiteralCast(ctx, params, parts)
|
|
5117
6696
|
if strings.Contains(value, "await ") {
|
|
5118
6697
|
return []string{"...(await (async () => { " + body + " })())"}, diagnostics, true
|
|
5119
6698
|
}
|
|
5120
6699
|
return []string{"...(() => { " + body + " })()"}, diagnostics, true
|
|
5121
6700
|
}
|
|
5122
6701
|
|
|
6702
|
+
func (o *LoweringOwner) parenthesizedTupleCast(ctx lowerFileContext, value string, params *types.Tuple) string {
|
|
6703
|
+
if strings.HasPrefix(value, "await ") {
|
|
6704
|
+
return "(" + value + ") as " + o.tupleTypeForParams(ctx, params)
|
|
6705
|
+
}
|
|
6706
|
+
return value + " as " + o.tupleTypeForParams(ctx, params)
|
|
6707
|
+
}
|
|
6708
|
+
|
|
6709
|
+
func (o *LoweringOwner) tupleLiteralCast(ctx lowerFileContext, params *types.Tuple, parts []string) string {
|
|
6710
|
+
return "[" + strings.Join(parts, ", ") + "] as " + o.tupleTypeForParams(ctx, params)
|
|
6711
|
+
}
|
|
6712
|
+
|
|
6713
|
+
func (o *LoweringOwner) tupleTypeForParams(ctx lowerFileContext, params *types.Tuple) string {
|
|
6714
|
+
if params == nil || params.Len() == 0 {
|
|
6715
|
+
return "[]"
|
|
6716
|
+
}
|
|
6717
|
+
parts := make([]string, 0, params.Len())
|
|
6718
|
+
for v := range params.Variables() {
|
|
6719
|
+
parts = append(parts, o.tsTypeFor(ctx, v.Type()))
|
|
6720
|
+
}
|
|
6721
|
+
return "[" + strings.Join(parts, ", ") + "]"
|
|
6722
|
+
}
|
|
6723
|
+
|
|
5123
6724
|
func (o *LoweringOwner) lowerFixedCallArgs(
|
|
5124
6725
|
ctx lowerFileContext,
|
|
5125
6726
|
exprs []ast.Expr,
|
|
@@ -5153,7 +6754,7 @@ func (o *LoweringOwner) lowerCallArgForTarget(
|
|
|
5153
6754
|
value = o.lowerValueForTarget(ctx, expr, targetType, value)
|
|
5154
6755
|
sourceType := ctx.semPkg.source.TypesInfo.TypeOf(expr)
|
|
5155
6756
|
if overrideCall && isNonEmptyInterfaceType(targetType) && (isInterfaceType(sourceType) || isNilableType(sourceType)) {
|
|
5156
|
-
return o.runtimeOwner.QualifiedHelper(
|
|
6757
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValueOrNil) + "(" + value + ")!"
|
|
5157
6758
|
}
|
|
5158
6759
|
return value
|
|
5159
6760
|
}
|
|
@@ -5293,7 +6894,7 @@ func (o *LoweringOwner) lowerMakeExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
5293
6894
|
args = append(args, "() => "+o.lowerZeroValueExprFor(ctx, typed.Elem()))
|
|
5294
6895
|
}
|
|
5295
6896
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMakeSlice) +
|
|
5296
|
-
"<" + o.
|
|
6897
|
+
"<" + o.tsSliceElemTypeFor(ctx, typed.Elem()) + ">(" + strings.Join(args, ", ") + ")", diagnostics
|
|
5297
6898
|
case *types.Map:
|
|
5298
6899
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMakeMap) +
|
|
5299
6900
|
"<" + o.tsTypeFor(ctx, typed.Key()) + ", " + o.tsTypeFor(ctx, typed.Elem()) + ">()", nil
|
|
@@ -5321,7 +6922,8 @@ func (o *LoweringOwner) lowerNewExpr(ctx lowerFileContext, expr *ast.CallExpr) (
|
|
|
5321
6922
|
if named := namedStructType(typ); named != nil {
|
|
5322
6923
|
return "new " + o.namedTypeExpr(ctx, named) + "()", nil
|
|
5323
6924
|
}
|
|
5324
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperVarRef) +
|
|
6925
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperVarRef) +
|
|
6926
|
+
"<" + o.tsTypeFor(ctx, typ) + ">(" + o.lowerDeclarationZeroValueExpr(ctx, typ) + ")", nil
|
|
5325
6927
|
}
|
|
5326
6928
|
|
|
5327
6929
|
func (o *LoweringOwner) lowerConversionExpr(
|
|
@@ -5339,12 +6941,17 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
5339
6941
|
return value, append(diagnostics, addressDiagnostics...)
|
|
5340
6942
|
}
|
|
5341
6943
|
}
|
|
6944
|
+
if helper, addressDiagnostics, ok := o.lowerReflectHeaderPointerConversion(ctx, targetType, expr.Args[0]); ok {
|
|
6945
|
+
return helper, append(diagnostics, addressDiagnostics...)
|
|
6946
|
+
}
|
|
6947
|
+
if helper, addressDiagnostics, ok := o.lowerUnsafeArrayPointerConversion(ctx, targetType, expr.Args[0]); ok {
|
|
6948
|
+
return helper, append(diagnostics, addressDiagnostics...)
|
|
6949
|
+
}
|
|
5342
6950
|
if isUnsafePointerType(targetType) {
|
|
5343
6951
|
return "(" + value + " as any)", diagnostics
|
|
5344
6952
|
}
|
|
5345
6953
|
if isNilExpr(expr.Args[0]) && isPointerType(targetType) {
|
|
5346
|
-
return
|
|
5347
|
-
"(" + strconv.Quote(goRuntimeTypeString(targetType)) + ")", diagnostics
|
|
6954
|
+
return "null", diagnostics
|
|
5348
6955
|
}
|
|
5349
6956
|
if isInterfaceType(targetType) {
|
|
5350
6957
|
return o.lowerValueForTarget(ctx, expr.Args[0], targetType, value), diagnostics
|
|
@@ -5402,6 +7009,13 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
5402
7009
|
return result, diagnostics
|
|
5403
7010
|
}
|
|
5404
7011
|
}
|
|
7012
|
+
if target := pointerToNamedStructType(targetType); target != nil {
|
|
7013
|
+
source := pointerToNamedStructType(sourceType)
|
|
7014
|
+
if source != nil && !types.Identical(target, source) &&
|
|
7015
|
+
types.IdenticalIgnoreTags(target.Underlying(), source.Underlying()) {
|
|
7016
|
+
return "(" + value + " as unknown as " + o.tsTypeFor(ctx, targetType) + ")", diagnostics
|
|
7017
|
+
}
|
|
7018
|
+
}
|
|
5405
7019
|
if conversion, ok := o.lowerNamedStructConversion(ctx, expr.Args[0], targetType, sourceType, value); ok {
|
|
5406
7020
|
return renderNamedStructConversion(conversion), diagnostics
|
|
5407
7021
|
}
|
|
@@ -5421,6 +7035,9 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
5421
7035
|
return value, diagnostics
|
|
5422
7036
|
}
|
|
5423
7037
|
if isNumericType(targetType) {
|
|
7038
|
+
if isFloatType(targetType) {
|
|
7039
|
+
return value, diagnostics
|
|
7040
|
+
}
|
|
5424
7041
|
if bits, ok := unsignedIntegerBits(targetType); ok {
|
|
5425
7042
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint) +
|
|
5426
7043
|
"(" + value + ", " + strconv.Itoa(bits) + ")", diagnostics
|
|
@@ -5440,45 +7057,64 @@ func (o *LoweringOwner) lowerWideIntegerBinaryExpr(ctx lowerFileContext, expr *a
|
|
|
5440
7057
|
if !resultWide && !leftWide {
|
|
5441
7058
|
return "", false
|
|
5442
7059
|
}
|
|
7060
|
+
signed := isFixedSignedWideIntegerType(ctx.semPkg.source.TypesInfo.TypeOf(expr)) ||
|
|
7061
|
+
isFixedSignedWideIntegerType(ctx.semPkg.source.TypesInfo.TypeOf(expr.X))
|
|
5443
7062
|
switch expr.Op {
|
|
5444
7063
|
case token.SHL, token.SHR:
|
|
5445
7064
|
helper := RuntimeHelperUint64Shr
|
|
5446
7065
|
if expr.Op == token.SHL {
|
|
5447
7066
|
helper = RuntimeHelperUint64Shl
|
|
5448
7067
|
}
|
|
7068
|
+
if signed {
|
|
7069
|
+
helper = RuntimeHelperInt64Shr
|
|
7070
|
+
if expr.Op == token.SHL {
|
|
7071
|
+
helper = RuntimeHelperInt64Shl
|
|
7072
|
+
}
|
|
7073
|
+
}
|
|
5449
7074
|
if _, ok := constantShiftAmount(ctx, expr.Y); !ok {
|
|
5450
7075
|
return o.runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")", true
|
|
5451
7076
|
}
|
|
5452
7077
|
amount, ok := constantShiftAmount(ctx, expr.Y)
|
|
5453
|
-
if ok && amount >= 32 && expr.Op == token.SHL {
|
|
7078
|
+
if ok && amount >= 32 && expr.Op == token.SHL && !signed {
|
|
5454
7079
|
base := o.lowerWideShiftLeftOperand(ctx, expr.X, left)
|
|
5455
7080
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Mul) +
|
|
5456
7081
|
"(" + base + ", " + shiftMultiplier(amount) + ")", true
|
|
5457
7082
|
}
|
|
5458
7083
|
return o.runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")", true
|
|
5459
7084
|
case token.MUL:
|
|
5460
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Mul) + "(" + left + ", " + right + ")", true
|
|
7085
|
+
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Mul, RuntimeHelperInt64Mul)) + "(" + left + ", " + right + ")", true
|
|
7086
|
+
case token.QUO:
|
|
7087
|
+
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Div, RuntimeHelperInt64Div)) + "(" + left + ", " + right + ")", true
|
|
7088
|
+
case token.REM:
|
|
7089
|
+
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Mod, RuntimeHelperInt64Mod)) + "(" + left + ", " + right + ")", true
|
|
5461
7090
|
case token.ADD:
|
|
5462
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Add) + "(" + left + ", " + right + ")", true
|
|
7091
|
+
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Add, RuntimeHelperInt64Add)) + "(" + left + ", " + right + ")", true
|
|
5463
7092
|
case token.SUB:
|
|
5464
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Sub) + "(" + left + ", " + right + ")", true
|
|
7093
|
+
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Sub, RuntimeHelperInt64Sub)) + "(" + left + ", " + right + ")", true
|
|
5465
7094
|
case token.AND:
|
|
5466
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64And) + "(" + left + ", " + right + ")", true
|
|
7095
|
+
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64And, RuntimeHelperInt64And)) + "(" + left + ", " + right + ")", true
|
|
5467
7096
|
case token.XOR:
|
|
5468
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Xor) + "(" + left + ", " + right + ")", true
|
|
7097
|
+
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Xor, RuntimeHelperInt64Xor)) + "(" + left + ", " + right + ")", true
|
|
5469
7098
|
case token.OR:
|
|
5470
7099
|
shift, ok := wideLeftShiftExpr(ctx, expr.X)
|
|
5471
|
-
if ok {
|
|
7100
|
+
if ok && !signed {
|
|
5472
7101
|
if bits, ok := lowIntegerBits(ctx, expr.Y); ok && bits <= shift {
|
|
5473
7102
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Add) + "(" + left + ", " + right + ")", true
|
|
5474
7103
|
}
|
|
5475
7104
|
}
|
|
5476
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Or) + "(" + left + ", " + right + ")", true
|
|
7105
|
+
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Or, RuntimeHelperInt64Or)) + "(" + left + ", " + right + ")", true
|
|
5477
7106
|
default:
|
|
5478
7107
|
return "", false
|
|
5479
7108
|
}
|
|
5480
7109
|
}
|
|
5481
7110
|
|
|
7111
|
+
func wideIntegerHelper(signed bool, unsigned RuntimeHelper, signedHelper RuntimeHelper) RuntimeHelper {
|
|
7112
|
+
if signed {
|
|
7113
|
+
return signedHelper
|
|
7114
|
+
}
|
|
7115
|
+
return unsigned
|
|
7116
|
+
}
|
|
7117
|
+
|
|
5482
7118
|
func (o *LoweringOwner) lowerWideShiftLeftOperand(ctx lowerFileContext, expr ast.Expr, fallback string) string {
|
|
5483
7119
|
call, ok := unwrapParenExpr(expr).(*ast.CallExpr)
|
|
5484
7120
|
if !ok || len(call.Args) != 1 {
|
|
@@ -5647,7 +7283,10 @@ func (o *LoweringOwner) lowerNamedReceiverMethodCall(
|
|
|
5647
7283
|
diagnostics []Diagnostic,
|
|
5648
7284
|
) (string, []Diagnostic) {
|
|
5649
7285
|
selection := ctx.semPkg.source.TypesInfo.Selections[selector]
|
|
5650
|
-
receiver :=
|
|
7286
|
+
receiver := methodReceiverNamedType(selection.Obj())
|
|
7287
|
+
if receiver == nil {
|
|
7288
|
+
receiver = selectedReceiverNamedType(ctx.semPkg.source, selector, selection)
|
|
7289
|
+
}
|
|
5651
7290
|
receiverExpr, receiverDiagnostics := o.lowerNamedReceiverForMethod(ctx, selector.X, selection)
|
|
5652
7291
|
diagnostics = append(diagnostics, receiverDiagnostics...)
|
|
5653
7292
|
allArgs := append([]string{receiverExpr}, args...)
|
|
@@ -5655,7 +7294,7 @@ func (o *LoweringOwner) lowerNamedReceiverMethodCall(
|
|
|
5655
7294
|
return o.awaitCallIfNeeded(ctx, selector, call), diagnostics
|
|
5656
7295
|
}
|
|
5657
7296
|
|
|
5658
|
-
func (o *LoweringOwner)
|
|
7297
|
+
func (o *LoweringOwner) lowerPointerReceiverMethodCall(
|
|
5659
7298
|
ctx lowerFileContext,
|
|
5660
7299
|
selector *ast.SelectorExpr,
|
|
5661
7300
|
selection *types.Selection,
|
|
@@ -5668,9 +7307,6 @@ func (o *LoweringOwner) lowerNilablePointerReceiverMethodCall(
|
|
|
5668
7307
|
if method == nil {
|
|
5669
7308
|
return "", nil, false
|
|
5670
7309
|
}
|
|
5671
|
-
if !methodAllowsNilReceiver(ctx, method) {
|
|
5672
|
-
return "", nil, false
|
|
5673
|
-
}
|
|
5674
7310
|
signature, _ := method.Type().(*types.Signature)
|
|
5675
7311
|
if signature == nil || signature.Recv() == nil {
|
|
5676
7312
|
return "", nil, false
|
|
@@ -5683,6 +7319,16 @@ func (o *LoweringOwner) lowerNilablePointerReceiverMethodCall(
|
|
|
5683
7319
|
return "", nil, false
|
|
5684
7320
|
}
|
|
5685
7321
|
receiverExpr, diagnostics := o.lowerExpr(ctx, selector.X)
|
|
7322
|
+
if o.receiverUsesOverridePackage(signature.Recv().Type()) {
|
|
7323
|
+
receiverExpr = o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
7324
|
+
"<" + o.tsTypeFor(ctx, signature.Recv().Type().(*types.Pointer).Elem()) + ">(" + receiverExpr + ")"
|
|
7325
|
+
}
|
|
7326
|
+
if receiverExpr == o.namedTypeExpr(ctx, receiver) {
|
|
7327
|
+
call := o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
7328
|
+
"<" + o.namedTypeExpr(ctx, receiver) + ">(" + receiverExpr + ")." +
|
|
7329
|
+
methodMemberName(selector.Sel.Name) + "(" + strings.Join(args, ", ") + ")"
|
|
7330
|
+
return call, diagnostics, true
|
|
7331
|
+
}
|
|
5686
7332
|
callArgs := append([]string{receiverExpr}, args...)
|
|
5687
7333
|
call := o.namedTypeExpr(ctx, receiver) + ".prototype." + selector.Sel.Name + ".call(" + strings.Join(callArgs, ", ") + ")"
|
|
5688
7334
|
return call, diagnostics, true
|
|
@@ -5783,8 +7429,12 @@ func (o *LoweringOwner) lowerNamedReceiverForMethod(
|
|
|
5783
7429
|
}
|
|
5784
7430
|
return o.lowerAddressExpr(ctx, expr)
|
|
5785
7431
|
}
|
|
5786
|
-
receiver, diagnostics := o.
|
|
5787
|
-
|
|
7432
|
+
receiver, diagnostics := o.lowerMethodReceiverExpr(ctx, expr, selection)
|
|
7433
|
+
selectedType := ctx.semPkg.source.TypesInfo.TypeOf(expr)
|
|
7434
|
+
if index := selection.Index(); len(index) > 1 && !o.receiverUsesOverridePackage(selectedType) {
|
|
7435
|
+
selectedType = promotedMethodReceiverType(selectedType, index[:len(index)-1])
|
|
7436
|
+
}
|
|
7437
|
+
if receiverType != nil && isPointerType(selectedType) {
|
|
5788
7438
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) + "<" + o.tsTypeFor(ctx, receiverType) + ">(" + receiver + ")", diagnostics
|
|
5789
7439
|
}
|
|
5790
7440
|
return receiver, diagnostics
|
|
@@ -5793,17 +7443,35 @@ func (o *LoweringOwner) lowerNamedReceiverForMethod(
|
|
|
5793
7443
|
func (o *LoweringOwner) lowerSelectorExpr(ctx lowerFileContext, expr *ast.SelectorExpr) (string, []Diagnostic) {
|
|
5794
7444
|
if ident, ok := expr.X.(*ast.Ident); ok {
|
|
5795
7445
|
if pkgName, _ := objectForIdent(ctx, ident).(*types.PkgName); pkgName != nil {
|
|
5796
|
-
if alias := ctx
|
|
5797
|
-
|
|
7446
|
+
if alias := importAliasForPkgName(ctx, pkgName); alias != "" {
|
|
7447
|
+
value := alias + "." + expr.Sel.Name
|
|
7448
|
+
obj, _ := ctx.semPkg.source.TypesInfo.Uses[expr.Sel].(*types.Var)
|
|
7449
|
+
if o.packageVarIsLazy(ctx, obj) ||
|
|
7450
|
+
o.packageVarNameIsLazy(ctx, pkgName.Imported().Path(), expr.Sel.Name) {
|
|
7451
|
+
value = alias + "." + packageVarGetterName(expr.Sel.Name) + "()"
|
|
7452
|
+
if (ctx.asyncFunction || ctx.topLevel) &&
|
|
7453
|
+
o.packageVarNameHasAsyncLazyInit(ctx, pkgName.Imported().Path(), expr.Sel.Name) {
|
|
7454
|
+
value = "(await " + alias + "." + packageVarInitName(expr.Sel.Name) + "(), " + value + ")"
|
|
7455
|
+
}
|
|
7456
|
+
}
|
|
7457
|
+
if obj != nil && packageVarReadNeedsPointerValue(obj.Type()) {
|
|
7458
|
+
value = o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
7459
|
+
"<" + o.tsNonNilTypeFor(ctx, obj.Type()) + ">(" + value + ")"
|
|
7460
|
+
}
|
|
7461
|
+
return value, nil
|
|
5798
7462
|
}
|
|
5799
7463
|
}
|
|
5800
7464
|
}
|
|
5801
7465
|
if selection := ctx.semPkg.source.TypesInfo.Selections[expr]; selection != nil {
|
|
5802
7466
|
switch selection.Kind() {
|
|
5803
7467
|
case types.MethodVal:
|
|
5804
|
-
|
|
7468
|
+
namedReceiver := methodReceiverNamedType(selection.Obj())
|
|
7469
|
+
if namedReceiver == nil {
|
|
7470
|
+
namedReceiver = selectedReceiverNamedType(ctx.semPkg.source, expr, selection)
|
|
7471
|
+
}
|
|
7472
|
+
if namedNonInterfaceNonStructType(namedReceiver) {
|
|
5805
7473
|
receiverExpr, diagnostics := o.lowerNamedReceiverForMethod(ctx, expr.X, selection)
|
|
5806
|
-
methodExpr := o.methodFunctionExpr(ctx,
|
|
7474
|
+
methodExpr := o.methodFunctionExpr(ctx, namedReceiver, selection.Obj(), expr.Sel.Name)
|
|
5807
7475
|
return o.lowerMethodValueClosure(ctx, selection, receiverExpr, methodExpr, true), diagnostics
|
|
5808
7476
|
}
|
|
5809
7477
|
receiver, diagnostics := o.lowerMethodReceiverExpr(ctx, expr.X, selection)
|
|
@@ -5818,9 +7486,41 @@ func (o *LoweringOwner) lowerSelectorExpr(ctx lowerFileContext, expr *ast.Select
|
|
|
5818
7486
|
}
|
|
5819
7487
|
}
|
|
5820
7488
|
left, diagnostics := o.lowerExpr(ctx, expr.X)
|
|
7489
|
+
left = parenthesizeAwaitedExpr(left)
|
|
5821
7490
|
return left + "." + expr.Sel.Name, diagnostics
|
|
5822
7491
|
}
|
|
5823
7492
|
|
|
7493
|
+
func packageVarSelectorNeedsPointerValue(ctx lowerFileContext, expr ast.Expr) bool {
|
|
7494
|
+
selector, ok := ast.Unparen(expr).(*ast.SelectorExpr)
|
|
7495
|
+
if !ok || ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
7496
|
+
return false
|
|
7497
|
+
}
|
|
7498
|
+
if selection := ctx.semPkg.source.TypesInfo.Selections[selector]; selection != nil {
|
|
7499
|
+
return false
|
|
7500
|
+
}
|
|
7501
|
+
ident, ok := ast.Unparen(selector.X).(*ast.Ident)
|
|
7502
|
+
if !ok {
|
|
7503
|
+
return false
|
|
7504
|
+
}
|
|
7505
|
+
pkgName, _ := objectForIdent(ctx, ident).(*types.PkgName)
|
|
7506
|
+
if importAliasForPkgName(ctx, pkgName) == "" {
|
|
7507
|
+
return false
|
|
7508
|
+
}
|
|
7509
|
+
obj, _ := ctx.semPkg.source.TypesInfo.Uses[selector.Sel].(*types.Var)
|
|
7510
|
+
return obj != nil && packageVarReadNeedsPointerValue(obj.Type())
|
|
7511
|
+
}
|
|
7512
|
+
|
|
7513
|
+
func packageVarReadNeedsPointerValue(typ types.Type) bool {
|
|
7514
|
+
if typ == nil || isPointerType(typ) {
|
|
7515
|
+
return false
|
|
7516
|
+
}
|
|
7517
|
+
if isStructValueType(typ) {
|
|
7518
|
+
return true
|
|
7519
|
+
}
|
|
7520
|
+
_, ok := types.Unalias(typ).Underlying().(*types.Array)
|
|
7521
|
+
return ok
|
|
7522
|
+
}
|
|
7523
|
+
|
|
5824
7524
|
func (o *LoweringOwner) packageVarSetterForAssignment(ctx lowerFileContext, expr ast.Expr) (string, bool) {
|
|
5825
7525
|
if ident, ok := unwrapParenExpr(expr).(*ast.Ident); ok {
|
|
5826
7526
|
obj, _ := objectForIdent(ctx, ident).(*types.Var)
|
|
@@ -5828,10 +7528,13 @@ func (o *LoweringOwner) packageVarSetterForAssignment(ctx lowerFileContext, expr
|
|
|
5828
7528
|
return "", false
|
|
5829
7529
|
}
|
|
5830
7530
|
alias := ctx.localAliases[obj]
|
|
5831
|
-
if alias
|
|
5832
|
-
return "",
|
|
7531
|
+
if alias != "" {
|
|
7532
|
+
return alias + "." + packageVarSetterName(ident.Name), true
|
|
7533
|
+
}
|
|
7534
|
+
if ctx.lazyPackageVars[obj] {
|
|
7535
|
+
return packageVarSetterName(ident.Name), true
|
|
5833
7536
|
}
|
|
5834
|
-
return
|
|
7537
|
+
return "", false
|
|
5835
7538
|
}
|
|
5836
7539
|
selector, ok := unwrapParenExpr(expr).(*ast.SelectorExpr)
|
|
5837
7540
|
if !ok {
|
|
@@ -5845,7 +7548,7 @@ func (o *LoweringOwner) packageVarSetterForAssignment(ctx lowerFileContext, expr
|
|
|
5845
7548
|
if pkgName == nil {
|
|
5846
7549
|
return "", false
|
|
5847
7550
|
}
|
|
5848
|
-
alias := ctx
|
|
7551
|
+
alias := importAliasForPkgName(ctx, pkgName)
|
|
5849
7552
|
if alias == "" {
|
|
5850
7553
|
return "", false
|
|
5851
7554
|
}
|
|
@@ -5856,6 +7559,36 @@ func (o *LoweringOwner) packageVarSetterForAssignment(ctx lowerFileContext, expr
|
|
|
5856
7559
|
return alias + "." + packageVarSetterName(selector.Sel.Name), true
|
|
5857
7560
|
}
|
|
5858
7561
|
|
|
7562
|
+
func (o *LoweringOwner) packageVarAssignmentValue(
|
|
7563
|
+
ctx lowerFileContext,
|
|
7564
|
+
lhs ast.Expr,
|
|
7565
|
+
targetType types.Type,
|
|
7566
|
+
right string,
|
|
7567
|
+
tok token.Token,
|
|
7568
|
+
) (string, bool) {
|
|
7569
|
+
if tok == token.ASSIGN {
|
|
7570
|
+
return right, true
|
|
7571
|
+
}
|
|
7572
|
+
left, diagnostics := o.lowerExpr(ctx, lhs)
|
|
7573
|
+
if len(diagnostics) != 0 {
|
|
7574
|
+
return "", false
|
|
7575
|
+
}
|
|
7576
|
+
if tok == token.AND_NOT_ASSIGN {
|
|
7577
|
+
return left + " & ~(" + right + ")", true
|
|
7578
|
+
}
|
|
7579
|
+
if helper, ok := wideIntegerAssignHelper(targetType, tok); ok {
|
|
7580
|
+
return o.runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")", true
|
|
7581
|
+
}
|
|
7582
|
+
if value, ok := integerQuotientAssignValueExpr(targetType, left, right, tok); ok {
|
|
7583
|
+
return value, true
|
|
7584
|
+
}
|
|
7585
|
+
op := tok.String()
|
|
7586
|
+
if before, ok := strings.CutSuffix(op, "="); ok {
|
|
7587
|
+
op = before
|
|
7588
|
+
}
|
|
7589
|
+
return left + " " + op + " " + right, true
|
|
7590
|
+
}
|
|
7591
|
+
|
|
5859
7592
|
func (o *LoweringOwner) tsPackageVarSetterValueTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
5860
7593
|
if signature := unnamedSignatureForType(typ); signature != nil {
|
|
5861
7594
|
return o.tsAsyncCompatibleFunctionTypeFor(ctx, signature)
|
|
@@ -5870,25 +7603,28 @@ func (o *LoweringOwner) lowerFieldSelectionExpr(
|
|
|
5870
7603
|
address bool,
|
|
5871
7604
|
) (string, []Diagnostic) {
|
|
5872
7605
|
receiver, diagnostics := o.lowerFieldReceiverExpr(ctx, expr.X)
|
|
7606
|
+
receiver = parenthesizeAwaitedExpr(receiver)
|
|
5873
7607
|
index := selection.Index()
|
|
5874
7608
|
if len(index) == 0 {
|
|
7609
|
+
fieldName := tsStructFieldName(expr.Sel.Name, 0)
|
|
5875
7610
|
if address {
|
|
5876
|
-
return o.lowerFieldAddressExpr(ctx, receiver, ctx.semPkg.source.TypesInfo.TypeOf(expr.X),
|
|
7611
|
+
return o.lowerFieldAddressExpr(ctx, receiver, ctx.semPkg.source.TypesInfo.TypeOf(expr.X), fieldName), diagnostics
|
|
5877
7612
|
}
|
|
5878
|
-
return receiver + "." +
|
|
7613
|
+
return receiver + "." + fieldName, diagnostics
|
|
5879
7614
|
}
|
|
5880
7615
|
|
|
5881
7616
|
typ := derefPointerType(ctx.semPkg.source.TypesInfo.TypeOf(expr.X))
|
|
5882
7617
|
for idx, fieldIndex := range index {
|
|
5883
7618
|
structType := structUnderlyingType(typ)
|
|
5884
7619
|
if structType == nil || fieldIndex < 0 || fieldIndex >= structType.NumFields() {
|
|
7620
|
+
fieldName := tsStructFieldName(expr.Sel.Name, 0)
|
|
5885
7621
|
if address {
|
|
5886
|
-
return receiver + "._fields." +
|
|
7622
|
+
return receiver + "._fields." + fieldName, diagnostics
|
|
5887
7623
|
}
|
|
5888
|
-
return receiver + "." +
|
|
7624
|
+
return receiver + "." + fieldName, diagnostics
|
|
5889
7625
|
}
|
|
5890
7626
|
field := structType.Field(fieldIndex)
|
|
5891
|
-
name := field.Name()
|
|
7627
|
+
name := tsStructFieldName(field.Name(), fieldIndex)
|
|
5892
7628
|
if idx == len(index)-1 {
|
|
5893
7629
|
if address {
|
|
5894
7630
|
return o.lowerFieldAddressExpr(ctx, receiver, typ, name), diagnostics
|
|
@@ -5906,9 +7642,9 @@ func (o *LoweringOwner) lowerFieldSelectionExpr(
|
|
|
5906
7642
|
}
|
|
5907
7643
|
|
|
5908
7644
|
if address {
|
|
5909
|
-
return o.lowerFieldAddressExpr(ctx, receiver, typ, expr.Sel.Name), diagnostics
|
|
7645
|
+
return o.lowerFieldAddressExpr(ctx, receiver, typ, tsStructFieldName(expr.Sel.Name, 0)), diagnostics
|
|
5910
7646
|
}
|
|
5911
|
-
return receiver + "." + expr.Sel.Name, diagnostics
|
|
7647
|
+
return receiver + "." + tsStructFieldName(expr.Sel.Name, 0), diagnostics
|
|
5912
7648
|
}
|
|
5913
7649
|
|
|
5914
7650
|
func (o *LoweringOwner) lowerFieldAddressExpr(ctx lowerFileContext, receiver string, typ types.Type, fieldName string) string {
|
|
@@ -5980,9 +7716,11 @@ func (o *LoweringOwner) lowerFieldReceiverExpr(ctx lowerFileContext, expr ast.Ex
|
|
|
5980
7716
|
return o.lowerPointerValueExpr(ctx, expr)
|
|
5981
7717
|
}
|
|
5982
7718
|
value, diagnostics := o.lowerExpr(ctx, expr)
|
|
7719
|
+
value = parenthesizeAwaitedExpr(value)
|
|
5983
7720
|
if obj := objectForValueExpr(ctx, expr); obj != nil &&
|
|
5984
|
-
ctx
|
|
7721
|
+
objectNeedsVarRef(ctx, obj) &&
|
|
5985
7722
|
isStructValueType(obj.Type()) &&
|
|
7723
|
+
!packageVarSelectorNeedsPointerValue(ctx, expr) &&
|
|
5986
7724
|
fieldReceiverNeedsVarRefValue(ctx, expr, obj) {
|
|
5987
7725
|
return value + ".value", diagnostics
|
|
5988
7726
|
}
|
|
@@ -5993,7 +7731,16 @@ func fieldReceiverNeedsVarRefValue(ctx lowerFileContext, expr ast.Expr, obj type
|
|
|
5993
7731
|
if _, ok := expr.(*ast.Ident); !ok {
|
|
5994
7732
|
return true
|
|
5995
7733
|
}
|
|
5996
|
-
|
|
7734
|
+
if ctx.identAliases[obj] != "" {
|
|
7735
|
+
return !ctx.identAliasRefs[obj]
|
|
7736
|
+
}
|
|
7737
|
+
if ctx.localAliases[obj] != "" {
|
|
7738
|
+
if varObj, ok := obj.(*types.Var); ok && packageVarReadNeedsPointerValue(varObj.Type()) {
|
|
7739
|
+
return false
|
|
7740
|
+
}
|
|
7741
|
+
return !ctx.lazyPackageVars[obj]
|
|
7742
|
+
}
|
|
7743
|
+
return false
|
|
5997
7744
|
}
|
|
5998
7745
|
|
|
5999
7746
|
func (o *LoweringOwner) lowerMethodReceiverExpr(
|
|
@@ -6016,14 +7763,24 @@ func (o *LoweringOwner) lowerMethodReceiverExpr(
|
|
|
6016
7763
|
receiver, diagnostics = o.lowerPointerValueExpr(ctx, expr)
|
|
6017
7764
|
} else {
|
|
6018
7765
|
receiver, diagnostics = o.lowerExpr(ctx, expr)
|
|
7766
|
+
receiver = parenthesizeAwaitedExpr(receiver)
|
|
6019
7767
|
}
|
|
6020
7768
|
receiverType := ctx.semPkg.source.TypesInfo.TypeOf(expr)
|
|
7769
|
+
if !receiverPointer {
|
|
7770
|
+
if obj := objectForValueExpr(ctx, expr); obj != nil &&
|
|
7771
|
+
objectNeedsVarRef(ctx, obj) &&
|
|
7772
|
+
isStructValueType(obj.Type()) &&
|
|
7773
|
+
!packageVarSelectorNeedsPointerValue(ctx, expr) &&
|
|
7774
|
+
fieldReceiverNeedsVarRefValue(ctx, expr, obj) {
|
|
7775
|
+
receiver += ".value"
|
|
7776
|
+
}
|
|
7777
|
+
}
|
|
6021
7778
|
if index := selection.Index(); len(index) > 1 && !o.receiverUsesOverridePackage(receiverType) {
|
|
6022
7779
|
receiver, receiverType = o.lowerPromotedMethodReceiver(ctx, receiver, receiverType, index[:len(index)-1])
|
|
6023
7780
|
}
|
|
6024
7781
|
if receiverPointer {
|
|
6025
7782
|
if obj := objectForValueExpr(ctx, expr); obj != nil &&
|
|
6026
|
-
ctx
|
|
7783
|
+
objectNeedsVarRef(ctx, obj) &&
|
|
6027
7784
|
isStructValueType(obj.Type()) &&
|
|
6028
7785
|
fieldReceiverNeedsVarRefValue(ctx, expr, obj) {
|
|
6029
7786
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
@@ -6074,16 +7831,38 @@ func (o *LoweringOwner) lowerPromotedMethodReceiver(
|
|
|
6074
7831
|
return receiver, typ
|
|
6075
7832
|
}
|
|
6076
7833
|
|
|
7834
|
+
func promotedMethodReceiverType(typ types.Type, index []int) types.Type {
|
|
7835
|
+
typ = derefPointerType(typ)
|
|
7836
|
+
for _, fieldIndex := range index {
|
|
7837
|
+
structType := structUnderlyingType(typ)
|
|
7838
|
+
if structType == nil || fieldIndex < 0 || fieldIndex >= structType.NumFields() {
|
|
7839
|
+
return typ
|
|
7840
|
+
}
|
|
7841
|
+
typ = structType.Field(fieldIndex).Type()
|
|
7842
|
+
if pointer, ok := types.Unalias(typ).Underlying().(*types.Pointer); ok {
|
|
7843
|
+
typ = pointer.Elem()
|
|
7844
|
+
}
|
|
7845
|
+
}
|
|
7846
|
+
return typ
|
|
7847
|
+
}
|
|
7848
|
+
|
|
6077
7849
|
func (o *LoweringOwner) lowerAssignmentTarget(
|
|
6078
7850
|
ctx lowerFileContext,
|
|
6079
7851
|
expr ast.Expr,
|
|
6080
7852
|
declare bool,
|
|
6081
7853
|
) (string, []Diagnostic) {
|
|
6082
|
-
switch typed := expr.(type) {
|
|
7854
|
+
switch typed := unwrapParenExpr(expr).(type) {
|
|
6083
7855
|
case *ast.Ident:
|
|
6084
7856
|
if declare {
|
|
6085
7857
|
return o.lowerIdent(ctx, typed, true), nil
|
|
6086
7858
|
}
|
|
7859
|
+
if obj := objectForIdent(ctx, typed); obj != nil && ctx.lazyPackageVars[obj] {
|
|
7860
|
+
target := o.lowerIdent(ctx, typed, true)
|
|
7861
|
+
if ctx.model.needsVarRef[obj] {
|
|
7862
|
+
target += ".value"
|
|
7863
|
+
}
|
|
7864
|
+
return target, nil
|
|
7865
|
+
}
|
|
6087
7866
|
return o.lowerIdent(ctx, typed, false), nil
|
|
6088
7867
|
case *ast.StarExpr:
|
|
6089
7868
|
return o.lowerPointerValueExpr(ctx, typed.X)
|
|
@@ -6093,7 +7872,10 @@ func (o *LoweringOwner) lowerAssignmentTarget(
|
|
|
6093
7872
|
}
|
|
6094
7873
|
|
|
6095
7874
|
func (o *LoweringOwner) lowerAddressExpr(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
6096
|
-
|
|
7875
|
+
if value, ok := o.lowerPackageVarAddressExpr(ctx, expr); ok {
|
|
7876
|
+
return value, nil
|
|
7877
|
+
}
|
|
7878
|
+
switch typed := unwrapParenExpr(expr).(type) {
|
|
6097
7879
|
case *ast.Ident:
|
|
6098
7880
|
return o.lowerIdent(ctx, typed, true), nil
|
|
6099
7881
|
case *ast.CompositeLit:
|
|
@@ -6115,6 +7897,55 @@ func (o *LoweringOwner) lowerAddressExpr(ctx lowerFileContext, expr ast.Expr) (s
|
|
|
6115
7897
|
}
|
|
6116
7898
|
}
|
|
6117
7899
|
|
|
7900
|
+
func (o *LoweringOwner) lowerPackageVarAddressExpr(ctx lowerFileContext, expr ast.Expr) (string, bool) {
|
|
7901
|
+
switch typed := unwrapParenExpr(expr).(type) {
|
|
7902
|
+
case *ast.Ident:
|
|
7903
|
+
obj, _ := objectForIdent(ctx, typed).(*types.Var)
|
|
7904
|
+
if obj == nil || !objectNeedsVarRef(ctx, obj) {
|
|
7905
|
+
return "", false
|
|
7906
|
+
}
|
|
7907
|
+
return o.lowerIdent(ctx, typed, true), true
|
|
7908
|
+
case *ast.SelectorExpr:
|
|
7909
|
+
if selection := ctx.semPkg.source.TypesInfo.Selections[typed]; selection != nil {
|
|
7910
|
+
return "", false
|
|
7911
|
+
}
|
|
7912
|
+
ident, ok := unwrapParenExpr(typed.X).(*ast.Ident)
|
|
7913
|
+
if !ok {
|
|
7914
|
+
return "", false
|
|
7915
|
+
}
|
|
7916
|
+
pkgName, _ := objectForIdent(ctx, ident).(*types.PkgName)
|
|
7917
|
+
if pkgName == nil {
|
|
7918
|
+
return "", false
|
|
7919
|
+
}
|
|
7920
|
+
alias := importAliasForPkgName(ctx, pkgName)
|
|
7921
|
+
if alias == "" {
|
|
7922
|
+
return "", false
|
|
7923
|
+
}
|
|
7924
|
+
obj, _ := ctx.semPkg.source.TypesInfo.Uses[typed.Sel].(*types.Var)
|
|
7925
|
+
if obj == nil || !objectNeedsVarRef(ctx, obj) {
|
|
7926
|
+
return "", false
|
|
7927
|
+
}
|
|
7928
|
+
return alias + "." + typed.Sel.Name, true
|
|
7929
|
+
default:
|
|
7930
|
+
return "", false
|
|
7931
|
+
}
|
|
7932
|
+
}
|
|
7933
|
+
|
|
7934
|
+
func importAliasForPkgName(ctx lowerFileContext, pkgName *types.PkgName) string {
|
|
7935
|
+
if pkgName == nil {
|
|
7936
|
+
return ""
|
|
7937
|
+
}
|
|
7938
|
+
if alias := ctx.importObjects[pkgName]; alias != "" {
|
|
7939
|
+
return alias
|
|
7940
|
+
}
|
|
7941
|
+
if imported := pkgName.Imported(); imported != nil {
|
|
7942
|
+
if alias := ctx.importPaths[imported.Path()]; alias != "" {
|
|
7943
|
+
return alias
|
|
7944
|
+
}
|
|
7945
|
+
}
|
|
7946
|
+
return ctx.importNames[pkgName.Name()]
|
|
7947
|
+
}
|
|
7948
|
+
|
|
6118
7949
|
func (o *LoweringOwner) lowerIndexAddressExpr(ctx lowerFileContext, expr *ast.IndexExpr) (string, []Diagnostic) {
|
|
6119
7950
|
target, targetDiagnostics := o.lowerExpr(ctx, expr.X)
|
|
6120
7951
|
index, indexDiagnostics := o.lowerExpr(ctx, expr.Index)
|
|
@@ -6171,46 +8002,240 @@ func (o *LoweringOwner) lowerIndexAddressIntegerExpr(
|
|
|
6171
8002
|
if isStringType(targetType) || isMapType(targetType) {
|
|
6172
8003
|
return "", diagnostics, false
|
|
6173
8004
|
}
|
|
6174
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexAddress) +
|
|
6175
|
-
"(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + index + ")", diagnostics, true
|
|
8005
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexAddress) +
|
|
8006
|
+
"(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + index + ")", diagnostics, true
|
|
8007
|
+
}
|
|
8008
|
+
|
|
8009
|
+
func (o *LoweringOwner) lowerPointerValueExpr(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
8010
|
+
if value, diagnostics, ok := o.lowerUnsafeStringPointerValue(ctx, expr); ok {
|
|
8011
|
+
return value, diagnostics
|
|
8012
|
+
}
|
|
8013
|
+
if value, diagnostics, ok := o.lowerUnsafeStringByteSlicePointerValue(ctx, expr); ok {
|
|
8014
|
+
return value, diagnostics
|
|
8015
|
+
}
|
|
8016
|
+
base, diagnostics := o.lowerExpr(ctx, expr)
|
|
8017
|
+
typeArg := ""
|
|
8018
|
+
if pointer, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(expr)).Underlying().(*types.Pointer); ok {
|
|
8019
|
+
typeArg = "<" + o.tsTypeFor(ctx, pointer.Elem()) + ">"
|
|
8020
|
+
}
|
|
8021
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) + typeArg + "(" + base + ")", diagnostics
|
|
8022
|
+
}
|
|
8023
|
+
|
|
8024
|
+
func (o *LoweringOwner) lowerUnsafeStringPointerValue(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic, bool) {
|
|
8025
|
+
call, ok := unwrapParenExpr(expr).(*ast.CallExpr)
|
|
8026
|
+
if !ok || len(call.Args) != 1 {
|
|
8027
|
+
return "", nil, false
|
|
8028
|
+
}
|
|
8029
|
+
targetType := typeFromExpr(ctx, call.Fun)
|
|
8030
|
+
if targetType == nil {
|
|
8031
|
+
return "", nil, false
|
|
8032
|
+
}
|
|
8033
|
+
targetPointer, _ := types.Unalias(targetType).Underlying().(*types.Pointer)
|
|
8034
|
+
if targetPointer == nil || !isStringType(targetPointer.Elem()) {
|
|
8035
|
+
return "", nil, false
|
|
8036
|
+
}
|
|
8037
|
+
unsafeCall, ok := unwrapParenExpr(call.Args[0]).(*ast.CallExpr)
|
|
8038
|
+
unsafeTargetType := typeFromExpr(ctx, unsafeCall.Fun)
|
|
8039
|
+
if !ok || len(unsafeCall.Args) != 1 || unsafeTargetType == nil || !isUnsafePointerType(unsafeTargetType) {
|
|
8040
|
+
return "", nil, false
|
|
8041
|
+
}
|
|
8042
|
+
address, ok := unwrapParenExpr(unsafeCall.Args[0]).(*ast.UnaryExpr)
|
|
8043
|
+
if !ok || address.Op != token.AND || !isByteSliceType(ctx.semPkg.source.TypesInfo.TypeOf(address.X)) {
|
|
8044
|
+
return "", nil, false
|
|
8045
|
+
}
|
|
8046
|
+
value, diagnostics := o.lowerExpr(ctx, address.X)
|
|
8047
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperBytesToString) + "(" + value + ")", diagnostics, true
|
|
8048
|
+
}
|
|
8049
|
+
|
|
8050
|
+
func (o *LoweringOwner) lowerUnsafeStringByteSlicePointerValue(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic, bool) {
|
|
8051
|
+
call, ok := unwrapParenExpr(expr).(*ast.CallExpr)
|
|
8052
|
+
if !ok || len(call.Args) != 1 {
|
|
8053
|
+
return "", nil, false
|
|
8054
|
+
}
|
|
8055
|
+
targetType := typeFromExpr(ctx, call.Fun)
|
|
8056
|
+
if targetType == nil {
|
|
8057
|
+
return "", nil, false
|
|
8058
|
+
}
|
|
8059
|
+
targetPointer, _ := types.Unalias(targetType).Underlying().(*types.Pointer)
|
|
8060
|
+
if targetPointer == nil || !isByteSliceType(targetPointer.Elem()) {
|
|
8061
|
+
return "", nil, false
|
|
8062
|
+
}
|
|
8063
|
+
unsafeCall, ok := unwrapParenExpr(call.Args[0]).(*ast.CallExpr)
|
|
8064
|
+
unsafeTargetType := typeFromExpr(ctx, unsafeCall.Fun)
|
|
8065
|
+
if !ok || len(unsafeCall.Args) != 1 || unsafeTargetType == nil || !isUnsafePointerType(unsafeTargetType) {
|
|
8066
|
+
return "", nil, false
|
|
8067
|
+
}
|
|
8068
|
+
address, ok := unwrapParenExpr(unsafeCall.Args[0]).(*ast.UnaryExpr)
|
|
8069
|
+
if !ok || address.Op != token.AND {
|
|
8070
|
+
return "", nil, false
|
|
8071
|
+
}
|
|
8072
|
+
source, ok := localStringSliceHeaderSource(ctx, address.X)
|
|
8073
|
+
if !ok {
|
|
8074
|
+
return "", nil, false
|
|
8075
|
+
}
|
|
8076
|
+
value, diagnostics := o.lowerExpr(ctx, source)
|
|
8077
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperStringToBytes) + "(" + value + ")", diagnostics, true
|
|
8078
|
+
}
|
|
8079
|
+
|
|
8080
|
+
func (o *LoweringOwner) lowerReflectHeaderPointerConversion(
|
|
8081
|
+
ctx lowerFileContext,
|
|
8082
|
+
targetType types.Type,
|
|
8083
|
+
expr ast.Expr,
|
|
8084
|
+
) (string, []Diagnostic, bool) {
|
|
8085
|
+
targetPointer, _ := types.Unalias(targetType).Underlying().(*types.Pointer)
|
|
8086
|
+
if targetPointer == nil {
|
|
8087
|
+
return "", nil, false
|
|
8088
|
+
}
|
|
8089
|
+
header, _ := types.Unalias(targetPointer.Elem()).(*types.Named)
|
|
8090
|
+
if header == nil || header.Obj() == nil || header.Obj().Pkg() == nil || header.Obj().Pkg().Path() != "reflect" {
|
|
8091
|
+
return "", nil, false
|
|
8092
|
+
}
|
|
8093
|
+
unsafeCall, ok := unwrapParenExpr(expr).(*ast.CallExpr)
|
|
8094
|
+
if !ok || len(unsafeCall.Args) != 1 || !isUnsafePointerType(typeFromExpr(ctx, unsafeCall.Fun)) {
|
|
8095
|
+
return "", nil, false
|
|
8096
|
+
}
|
|
8097
|
+
address, ok := unwrapParenExpr(unsafeCall.Args[0]).(*ast.UnaryExpr)
|
|
8098
|
+
if !ok || address.Op != token.AND {
|
|
8099
|
+
return "", nil, false
|
|
8100
|
+
}
|
|
8101
|
+
switch header.Obj().Name() {
|
|
8102
|
+
case "StringHeader":
|
|
8103
|
+
if !isStringType(ctx.semPkg.source.TypesInfo.TypeOf(address.X)) {
|
|
8104
|
+
return "", nil, false
|
|
8105
|
+
}
|
|
8106
|
+
value, diagnostics := o.lowerAddressedValueRef(ctx, address.X)
|
|
8107
|
+
helper := o.runtimeOwner.QualifiedHelper(RuntimeHelperStringHeaderRef) + "(" + value + ")"
|
|
8108
|
+
return "(" + helper + " as unknown as " + o.tsTypeFor(ctx, targetType) + ")", diagnostics, true
|
|
8109
|
+
case "SliceHeader":
|
|
8110
|
+
if !isByteSliceType(ctx.semPkg.source.TypesInfo.TypeOf(address.X)) {
|
|
8111
|
+
return "", nil, false
|
|
8112
|
+
}
|
|
8113
|
+
value, diagnostics := o.lowerAddressedValueRef(ctx, address.X)
|
|
8114
|
+
helper := o.runtimeOwner.QualifiedHelper(RuntimeHelperSliceHeaderRef) + "(" + value + ")"
|
|
8115
|
+
return "(" + helper + " as unknown as " + o.tsTypeFor(ctx, targetType) + ")", diagnostics, true
|
|
8116
|
+
default:
|
|
8117
|
+
return "", nil, false
|
|
8118
|
+
}
|
|
8119
|
+
}
|
|
8120
|
+
|
|
8121
|
+
func (o *LoweringOwner) lowerUnsafeArrayPointerConversion(
|
|
8122
|
+
ctx lowerFileContext,
|
|
8123
|
+
targetType types.Type,
|
|
8124
|
+
expr ast.Expr,
|
|
8125
|
+
) (string, []Diagnostic, bool) {
|
|
8126
|
+
targetPointer, _ := types.Unalias(targetType).Underlying().(*types.Pointer)
|
|
8127
|
+
if targetPointer == nil {
|
|
8128
|
+
return "", nil, false
|
|
8129
|
+
}
|
|
8130
|
+
array, _ := types.Unalias(targetPointer.Elem()).Underlying().(*types.Array)
|
|
8131
|
+
if array == nil {
|
|
8132
|
+
return "", nil, false
|
|
8133
|
+
}
|
|
8134
|
+
unsafeCall, ok := unwrapParenExpr(expr).(*ast.CallExpr)
|
|
8135
|
+
if !ok || len(unsafeCall.Args) != 1 || !isUnsafePointerType(typeFromExpr(ctx, unsafeCall.Fun)) {
|
|
8136
|
+
return "", nil, false
|
|
8137
|
+
}
|
|
8138
|
+
address, ok := unwrapParenExpr(unsafeCall.Args[0]).(*ast.UnaryExpr)
|
|
8139
|
+
if !ok || address.Op != token.AND {
|
|
8140
|
+
return "", nil, false
|
|
8141
|
+
}
|
|
8142
|
+
index, ok := unwrapParenExpr(address.X).(*ast.IndexExpr)
|
|
8143
|
+
if !ok {
|
|
8144
|
+
return "", nil, false
|
|
8145
|
+
}
|
|
8146
|
+
ref, diagnostics := o.lowerAddressExpr(ctx, index)
|
|
8147
|
+
helper := o.runtimeOwner.QualifiedHelper(RuntimeHelperArrayPointerFromIndexRef) +
|
|
8148
|
+
"<" + o.tsTypeFor(ctx, array.Elem()) + ">(" + ref + ", " + strconv.FormatInt(array.Len(), 10) + ")"
|
|
8149
|
+
return "(" + helper + " as unknown as " + o.tsTypeFor(ctx, targetType) + ")", diagnostics, true
|
|
8150
|
+
}
|
|
8151
|
+
|
|
8152
|
+
func (o *LoweringOwner) lowerAddressedValueRef(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
8153
|
+
if ident, ok := unwrapParenExpr(expr).(*ast.Ident); ok {
|
|
8154
|
+
if obj := objectForIdent(ctx, ident); obj != nil && ctx.model.needsVarRef[obj] {
|
|
8155
|
+
return o.lowerIdent(ctx, ident, true), nil
|
|
8156
|
+
}
|
|
8157
|
+
}
|
|
8158
|
+
value, diagnostics := o.lowerExpr(ctx, expr)
|
|
8159
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperVarRef) + "(" + value + ")", diagnostics
|
|
6176
8160
|
}
|
|
6177
8161
|
|
|
6178
|
-
func (
|
|
6179
|
-
|
|
6180
|
-
|
|
8162
|
+
func localStringSliceHeaderSource(ctx lowerFileContext, expr ast.Expr) (ast.Expr, bool) {
|
|
8163
|
+
lit, ok := unwrapParenExpr(expr).(*ast.CompositeLit)
|
|
8164
|
+
if !ok {
|
|
8165
|
+
return nil, false
|
|
6181
8166
|
}
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
typeArg = "<" + o.tsTypeFor(ctx, pointer.Elem()) + ">"
|
|
8167
|
+
structType, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(lit)).Underlying().(*types.Struct)
|
|
8168
|
+
if !ok || structType.NumFields() != 2 {
|
|
8169
|
+
return nil, false
|
|
6186
8170
|
}
|
|
6187
|
-
|
|
8171
|
+
if !isStringType(structType.Field(0).Type()) || !isIntegerType(structType.Field(1).Type()) {
|
|
8172
|
+
return nil, false
|
|
8173
|
+
}
|
|
8174
|
+
var source ast.Expr
|
|
8175
|
+
var capacity ast.Expr
|
|
8176
|
+
for idx, elt := range lit.Elts {
|
|
8177
|
+
fieldIndex := idx
|
|
8178
|
+
valueExpr := elt
|
|
8179
|
+
if keyed, ok := elt.(*ast.KeyValueExpr); ok {
|
|
8180
|
+
valueExpr = keyed.Value
|
|
8181
|
+
ident, ok := keyed.Key.(*ast.Ident)
|
|
8182
|
+
if !ok {
|
|
8183
|
+
return nil, false
|
|
8184
|
+
}
|
|
8185
|
+
fieldIndex = -1
|
|
8186
|
+
for index := range structType.NumFields() {
|
|
8187
|
+
if structType.Field(index).Name() == ident.Name {
|
|
8188
|
+
fieldIndex = index
|
|
8189
|
+
break
|
|
8190
|
+
}
|
|
8191
|
+
}
|
|
8192
|
+
if fieldIndex < 0 {
|
|
8193
|
+
return nil, false
|
|
8194
|
+
}
|
|
8195
|
+
}
|
|
8196
|
+
switch fieldIndex {
|
|
8197
|
+
case 0:
|
|
8198
|
+
source = valueExpr
|
|
8199
|
+
case 1:
|
|
8200
|
+
capacity = valueExpr
|
|
8201
|
+
}
|
|
8202
|
+
}
|
|
8203
|
+
if source == nil || capacity == nil {
|
|
8204
|
+
return nil, false
|
|
8205
|
+
}
|
|
8206
|
+
if !isStringType(ctx.semPkg.source.TypesInfo.TypeOf(source)) ||
|
|
8207
|
+
!isIntegerType(ctx.semPkg.source.TypesInfo.TypeOf(capacity)) {
|
|
8208
|
+
return nil, false
|
|
8209
|
+
}
|
|
8210
|
+
if !isLenCallOfExpr(ctx, capacity, source) {
|
|
8211
|
+
return nil, false
|
|
8212
|
+
}
|
|
8213
|
+
return source, true
|
|
6188
8214
|
}
|
|
6189
8215
|
|
|
6190
|
-
func (
|
|
8216
|
+
func isLenCallOfExpr(ctx lowerFileContext, expr ast.Expr, target ast.Expr) bool {
|
|
6191
8217
|
call, ok := unwrapParenExpr(expr).(*ast.CallExpr)
|
|
6192
8218
|
if !ok || len(call.Args) != 1 {
|
|
6193
|
-
return
|
|
6194
|
-
}
|
|
6195
|
-
targetType := typeFromExpr(ctx, call.Fun)
|
|
6196
|
-
if targetType == nil {
|
|
6197
|
-
return "", nil, false
|
|
8219
|
+
return false
|
|
6198
8220
|
}
|
|
6199
|
-
|
|
6200
|
-
if
|
|
6201
|
-
return
|
|
8221
|
+
ident, ok := unwrapParenExpr(call.Fun).(*ast.Ident)
|
|
8222
|
+
if !ok || ident.Name != "len" {
|
|
8223
|
+
return false
|
|
6202
8224
|
}
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
if !ok || len(unsafeCall.Args) != 1 || unsafeTargetType == nil || !isUnsafePointerType(unsafeTargetType) {
|
|
6206
|
-
return "", nil, false
|
|
8225
|
+
if objectForIdent(ctx, ident) != types.Universe.Lookup("len") {
|
|
8226
|
+
return false
|
|
6207
8227
|
}
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
8228
|
+
return sameLoweredSourceExpr(ctx, call.Args[0], target)
|
|
8229
|
+
}
|
|
8230
|
+
|
|
8231
|
+
func sameLoweredSourceExpr(ctx lowerFileContext, left ast.Expr, right ast.Expr) bool {
|
|
8232
|
+
left = unwrapParenExpr(left)
|
|
8233
|
+
right = unwrapParenExpr(right)
|
|
8234
|
+
if leftIdent, ok := left.(*ast.Ident); ok {
|
|
8235
|
+
rightIdent, ok := right.(*ast.Ident)
|
|
8236
|
+
return ok && objectForIdent(ctx, leftIdent) == objectForIdent(ctx, rightIdent)
|
|
6211
8237
|
}
|
|
6212
|
-
|
|
6213
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperBytesToString) + "(" + value + ")", diagnostics, true
|
|
8238
|
+
return false
|
|
6214
8239
|
}
|
|
6215
8240
|
|
|
6216
8241
|
func (o *LoweringOwner) lowerPointerStorageExpr(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
@@ -6362,6 +8387,13 @@ func (o *LoweringOwner) lowerCompositeLit(
|
|
|
6362
8387
|
lit *ast.CompositeLit,
|
|
6363
8388
|
markStruct bool,
|
|
6364
8389
|
) (string, []Diagnostic) {
|
|
8390
|
+
if len(lit.Elts) == 0 {
|
|
8391
|
+
if typeParam, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(lit)).(*types.TypeParam); ok {
|
|
8392
|
+
if typeParamInScope(ctx, typeParam) {
|
|
8393
|
+
return o.lowerDeclarationZeroValueExpr(ctx, typeParam), nil
|
|
8394
|
+
}
|
|
8395
|
+
}
|
|
8396
|
+
}
|
|
6365
8397
|
named := namedStructType(ctx.semPkg.source.TypesInfo.TypeOf(lit))
|
|
6366
8398
|
if named != nil {
|
|
6367
8399
|
return o.lowerStructCompositeLit(ctx, lit, named, markStruct)
|
|
@@ -6402,6 +8434,7 @@ func (o *LoweringOwner) lowerStructCompositeLit(
|
|
|
6402
8434
|
) (string, []Diagnostic) {
|
|
6403
8435
|
structType, _ := named.Underlying().(*types.Struct)
|
|
6404
8436
|
fields := make([]string, 0, len(lit.Elts))
|
|
8437
|
+
var prelude []string
|
|
6405
8438
|
var diagnostics []Diagnostic
|
|
6406
8439
|
for idx, elt := range lit.Elts {
|
|
6407
8440
|
fieldName := ""
|
|
@@ -6410,9 +8443,13 @@ func (o *LoweringOwner) lowerStructCompositeLit(
|
|
|
6410
8443
|
if keyed, ok := elt.(*ast.KeyValueExpr); ok {
|
|
6411
8444
|
valueExpr = keyed.Value
|
|
6412
8445
|
if ident, ok := keyed.Key.(*ast.Ident); ok {
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
8446
|
+
for index := range structType.NumFields() {
|
|
8447
|
+
field := structType.Field(index)
|
|
8448
|
+
if field.Name() == ident.Name {
|
|
8449
|
+
fieldName = tsStructFieldName(field.Name(), index)
|
|
8450
|
+
fieldType = field.Type()
|
|
8451
|
+
break
|
|
8452
|
+
}
|
|
6416
8453
|
}
|
|
6417
8454
|
}
|
|
6418
8455
|
} else if idx < structType.NumFields() {
|
|
@@ -6427,6 +8464,11 @@ func (o *LoweringOwner) lowerStructCompositeLit(
|
|
|
6427
8464
|
value, valueDiagnostics := o.lowerExpr(ctx, valueExpr)
|
|
6428
8465
|
diagnostics = append(diagnostics, valueDiagnostics...)
|
|
6429
8466
|
value = o.lowerValueForTarget(ctx, valueExpr, fieldType, value)
|
|
8467
|
+
if compositeLiteralFieldNeedsPreEval(ctx, valueExpr) {
|
|
8468
|
+
temp := ctx.tempName("LiteralField")
|
|
8469
|
+
prelude = append(prelude, "const "+temp+" = "+value)
|
|
8470
|
+
value = temp
|
|
8471
|
+
}
|
|
6430
8472
|
fields = append(fields, fieldName+": "+value)
|
|
6431
8473
|
}
|
|
6432
8474
|
|
|
@@ -6437,9 +8479,30 @@ func (o *LoweringOwner) lowerStructCompositeLit(
|
|
|
6437
8479
|
if markStruct {
|
|
6438
8480
|
expr = o.runtimeOwner.QualifiedHelper(RuntimeHelperMarkAsStructValue) + "(" + expr + ")"
|
|
6439
8481
|
}
|
|
8482
|
+
if len(prelude) != 0 {
|
|
8483
|
+
body := strings.Join(prelude, "; ") + "; return " + expr
|
|
8484
|
+
if strings.Contains(body, "await ") {
|
|
8485
|
+
return "(await (async () => { " + body + " })())", diagnostics
|
|
8486
|
+
}
|
|
8487
|
+
return "(() => { " + body + " })()", diagnostics
|
|
8488
|
+
}
|
|
6440
8489
|
return expr, diagnostics
|
|
6441
8490
|
}
|
|
6442
8491
|
|
|
8492
|
+
func compositeLiteralFieldNeedsPreEval(ctx lowerFileContext, expr ast.Expr) bool {
|
|
8493
|
+
switch typed := unwrapParenExpr(expr).(type) {
|
|
8494
|
+
case *ast.CallExpr:
|
|
8495
|
+
if ident, ok := typed.Fun.(*ast.Ident); ok && isBuiltinCallTarget(ctx, ident) {
|
|
8496
|
+
return false
|
|
8497
|
+
}
|
|
8498
|
+
return typeFromExpr(ctx, typed.Fun) == nil
|
|
8499
|
+
case *ast.UnaryExpr:
|
|
8500
|
+
return typed.Op == token.ARROW
|
|
8501
|
+
default:
|
|
8502
|
+
return false
|
|
8503
|
+
}
|
|
8504
|
+
}
|
|
8505
|
+
|
|
6443
8506
|
func (o *LoweringOwner) lowerAnonymousStructCompositeLit(
|
|
6444
8507
|
ctx lowerFileContext,
|
|
6445
8508
|
lit *ast.CompositeLit,
|
|
@@ -6460,10 +8523,10 @@ func (o *LoweringOwner) lowerAnonymousStructCompositeLit(
|
|
|
6460
8523
|
if keyed, ok := elt.(*ast.KeyValueExpr); ok {
|
|
6461
8524
|
valueExpr = keyed.Value
|
|
6462
8525
|
if ident, ok := keyed.Key.(*ast.Ident); ok {
|
|
6463
|
-
fieldName = ident.Name
|
|
6464
8526
|
for index := range structType.NumFields() {
|
|
6465
8527
|
field := structType.Field(index)
|
|
6466
|
-
if field.Name() ==
|
|
8528
|
+
if field.Name() == ident.Name {
|
|
8529
|
+
fieldName = tsStructFieldName(field.Name(), index)
|
|
6467
8530
|
fieldIndex = index
|
|
6468
8531
|
fieldType = field.Type()
|
|
6469
8532
|
break
|
|
@@ -6571,7 +8634,7 @@ func (o *LoweringOwner) lowerSliceCompositeLit(
|
|
|
6571
8634
|
nextIndex = index + 1
|
|
6572
8635
|
}
|
|
6573
8636
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperArrayToSlice) +
|
|
6574
|
-
"<" + o.
|
|
8637
|
+
"<" + o.tsSliceElemTypeFor(ctx, slice.Elem()) + ">([" + strings.Join(values, ", ") + "])", diagnostics
|
|
6575
8638
|
}
|
|
6576
8639
|
|
|
6577
8640
|
func (o *LoweringOwner) lowerMapCompositeLit(
|
|
@@ -6602,7 +8665,7 @@ func (o *LoweringOwner) lowerTypeAssertExpr(ctx lowerFileContext, expr *ast.Type
|
|
|
6602
8665
|
targetType := ctx.semPkg.source.TypesInfo.TypeOf(expr.Type)
|
|
6603
8666
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMustTypeAssert) +
|
|
6604
8667
|
"<" + o.tsTypeAssertionTypeFor(ctx, targetType) + ">(" +
|
|
6605
|
-
value + ", " + o.
|
|
8668
|
+
value + ", " + o.runtimeTypeAssertInfoExpr(ctx, targetType) + ")", diagnostics
|
|
6606
8669
|
}
|
|
6607
8670
|
|
|
6608
8671
|
func (o *LoweringOwner) lowerTupleExpr(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
@@ -6612,7 +8675,7 @@ func (o *LoweringOwner) lowerTupleExpr(ctx lowerFileContext, expr ast.Expr) (str
|
|
|
6612
8675
|
targetType := ctx.semPkg.source.TypesInfo.TypeOf(typed.Type)
|
|
6613
8676
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperTypeAssertTuple) +
|
|
6614
8677
|
"<" + o.tsTypeAssertionTypeFor(ctx, targetType) + ">(" +
|
|
6615
|
-
value + ", " + o.
|
|
8678
|
+
value + ", " + o.runtimeTypeAssertInfoExpr(ctx, targetType) + ")", diagnostics
|
|
6616
8679
|
case *ast.IndexExpr:
|
|
6617
8680
|
if isMapType(ctx.semPkg.source.TypesInfo.TypeOf(typed.X)) {
|
|
6618
8681
|
target, targetDiagnostics := o.lowerExpr(ctx, typed.X)
|
|
@@ -6644,6 +8707,9 @@ func (o *LoweringOwner) lowerValueForTarget(
|
|
|
6644
8707
|
) string {
|
|
6645
8708
|
sourceType := ctx.semPkg.source.TypesInfo.TypeOf(expr)
|
|
6646
8709
|
if isComplexType(targetType) {
|
|
8710
|
+
if isComplexType(sourceType) {
|
|
8711
|
+
return value
|
|
8712
|
+
}
|
|
6647
8713
|
if isRealNumericConstantExpr(ctx, expr) {
|
|
6648
8714
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperComplex) + "(" + value + ", 0)"
|
|
6649
8715
|
}
|
|
@@ -6697,6 +8763,14 @@ func isRealNumericConstantExpr(ctx lowerFileContext, expr ast.Expr) bool {
|
|
|
6697
8763
|
}
|
|
6698
8764
|
}
|
|
6699
8765
|
|
|
8766
|
+
func lowerPrefixUnaryExpr(op token.Token, value string) string {
|
|
8767
|
+
prefix := op.String()
|
|
8768
|
+
if (op == token.SUB && strings.HasPrefix(value, "-")) || (op == token.ADD && strings.HasPrefix(value, "+")) {
|
|
8769
|
+
return prefix + "(" + value + ")"
|
|
8770
|
+
}
|
|
8771
|
+
return prefix + value
|
|
8772
|
+
}
|
|
8773
|
+
|
|
6700
8774
|
func (o *LoweringOwner) lowerValueForTargetTypes(
|
|
6701
8775
|
ctx lowerFileContext,
|
|
6702
8776
|
targetType types.Type,
|
|
@@ -6704,6 +8778,9 @@ func (o *LoweringOwner) lowerValueForTargetTypes(
|
|
|
6704
8778
|
value string,
|
|
6705
8779
|
cloneStructValue bool,
|
|
6706
8780
|
) string {
|
|
8781
|
+
if targetType == nil || sourceType == nil {
|
|
8782
|
+
return value
|
|
8783
|
+
}
|
|
6707
8784
|
if isFunctionType(targetType) && isUntypedNilType(sourceType) {
|
|
6708
8785
|
return "(" + value + " as " + o.tsTypeFor(ctx, targetType) + ")"
|
|
6709
8786
|
}
|
|
@@ -6734,6 +8811,15 @@ func (o *LoweringOwner) lowerValueForTargetTypes(
|
|
|
6734
8811
|
return o.lowerStructClone(value)
|
|
6735
8812
|
}
|
|
6736
8813
|
if isIntegerType(targetType) && isIntegerType(sourceType) {
|
|
8814
|
+
if isBasicFixedWideIntegerType(targetType) {
|
|
8815
|
+
if bits, ok := unsignedIntegerBits(targetType); ok {
|
|
8816
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint) +
|
|
8817
|
+
"(" + value + ", " + strconv.Itoa(bits) + ")"
|
|
8818
|
+
}
|
|
8819
|
+
if _, ok := signedIntegerBits(targetType); ok {
|
|
8820
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperInt) + "(" + value + ")"
|
|
8821
|
+
}
|
|
8822
|
+
}
|
|
6737
8823
|
if bits, ok := unsignedIntegerBits(targetType); ok && bits < 64 {
|
|
6738
8824
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint) +
|
|
6739
8825
|
"(" + value + ", " + strconv.Itoa(bits) + ")"
|
|
@@ -6751,12 +8837,28 @@ func (o *LoweringOwner) lowerValueForTargetTypes(
|
|
|
6751
8837
|
return value
|
|
6752
8838
|
}
|
|
6753
8839
|
|
|
8840
|
+
func isBasicFixedWideIntegerType(typ types.Type) bool {
|
|
8841
|
+
basic, ok := types.Unalias(typ).(*types.Basic)
|
|
8842
|
+
if !ok {
|
|
8843
|
+
return false
|
|
8844
|
+
}
|
|
8845
|
+
switch basic.Kind() {
|
|
8846
|
+
case types.Int64, types.Uint64, types.Uintptr:
|
|
8847
|
+
return true
|
|
8848
|
+
default:
|
|
8849
|
+
return false
|
|
8850
|
+
}
|
|
8851
|
+
}
|
|
8852
|
+
|
|
6754
8853
|
func (o *LoweringOwner) lowerNamedValueInterfaceWrapper(
|
|
6755
8854
|
ctx lowerFileContext,
|
|
6756
8855
|
targetType types.Type,
|
|
6757
8856
|
sourceType types.Type,
|
|
6758
8857
|
value string,
|
|
6759
8858
|
) string {
|
|
8859
|
+
if targetType == nil || sourceType == nil {
|
|
8860
|
+
return ""
|
|
8861
|
+
}
|
|
6760
8862
|
if !isInterfaceType(targetType) || isInterfaceType(sourceType) {
|
|
6761
8863
|
return ""
|
|
6762
8864
|
}
|
|
@@ -6794,8 +8896,9 @@ func (o *LoweringOwner) lowerPrimitiveErrorWrapper(ctx lowerFileContext, sourceT
|
|
|
6794
8896
|
if fn == nil {
|
|
6795
8897
|
return ""
|
|
6796
8898
|
}
|
|
6797
|
-
return o.runtimeOwner.QualifiedHelper(
|
|
6798
|
-
"(" + value + ", " +
|
|
8899
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperNamedValueInterfaceValue) +
|
|
8900
|
+
"<$.GoError>(" + value + ", " + strconv.Quote(goRuntimeTypeString(sourceType)) +
|
|
8901
|
+
", {\"Error\": " + o.methodFunctionExpr(ctx, named, fn, "Error") + "})"
|
|
6799
8902
|
}
|
|
6800
8903
|
|
|
6801
8904
|
func (o *LoweringOwner) lowerStructClone(value string) string {
|
|
@@ -6805,13 +8908,16 @@ func (o *LoweringOwner) lowerStructClone(value string) string {
|
|
|
6805
8908
|
|
|
6806
8909
|
func (o *LoweringOwner) lowerZeroValueExpr(typ types.Type) string {
|
|
6807
8910
|
if named := namedStructType(typ); named != nil && isStructValueType(typ) {
|
|
6808
|
-
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMarkAsStructValue) + "(new " + named.Obj().Name() + "())"
|
|
8911
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMarkAsStructValue) + "(new " + safeIdentifier(named.Obj().Name()) + "())"
|
|
6809
8912
|
}
|
|
6810
8913
|
return zeroValueExpr(typ)
|
|
6811
8914
|
}
|
|
6812
8915
|
|
|
6813
8916
|
func (o *LoweringOwner) lowerZeroValueExprFor(ctx lowerFileContext, typ types.Type) string {
|
|
6814
8917
|
if named := namedStructType(typ); named != nil && isStructValueType(typ) {
|
|
8918
|
+
if crossPackageUnexportedNamedType(ctx, named) {
|
|
8919
|
+
return "undefined as any"
|
|
8920
|
+
}
|
|
6815
8921
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMarkAsStructValue) + "(new " + o.namedTypeExpr(ctx, named) + "())"
|
|
6816
8922
|
}
|
|
6817
8923
|
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
@@ -6859,7 +8965,7 @@ func (o *LoweringOwner) lowerDeclarationZeroValueExpr(ctx lowerFileContext, typ
|
|
|
6859
8965
|
}
|
|
6860
8966
|
return value
|
|
6861
8967
|
}
|
|
6862
|
-
if !
|
|
8968
|
+
if !typeParamInScope(ctx, typeParam) {
|
|
6863
8969
|
return zeroValueExpr(typ)
|
|
6864
8970
|
}
|
|
6865
8971
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperGenericZero) +
|
|
@@ -6870,6 +8976,15 @@ func (o *LoweringOwner) runtimeTypeInfoExpr(typ types.Type) string {
|
|
|
6870
8976
|
return o.runtimeTypeInfoExprWithSeen(typ, make(map[types.Type]bool))
|
|
6871
8977
|
}
|
|
6872
8978
|
|
|
8979
|
+
func (o *LoweringOwner) runtimeTypeAssertInfoExpr(ctx lowerFileContext, typ types.Type) string {
|
|
8980
|
+
typeParam, ok := types.Unalias(typ).(*types.TypeParam)
|
|
8981
|
+
if !ok || !typeParamInScope(ctx, typeParam) {
|
|
8982
|
+
return o.runtimeTypeInfoExpr(typ)
|
|
8983
|
+
}
|
|
8984
|
+
return "__typeArgs?.[" + strconv.Quote(typeParam.Obj().Name()) + "]?.type ?? " +
|
|
8985
|
+
o.runtimeTypeInfoExpr(typ)
|
|
8986
|
+
}
|
|
8987
|
+
|
|
6873
8988
|
func (o *LoweringOwner) runtimeTypeInfoExprWithSeen(typ types.Type, seen map[types.Type]bool) string {
|
|
6874
8989
|
typeKind := o.runtimeOwner.QualifiedHelper(RuntimeHelperTypeKind)
|
|
6875
8990
|
if typ == nil {
|
|
@@ -6890,20 +9005,14 @@ func (o *LoweringOwner) runtimeTypeInfoExprWithSeen(typ types.Type, seen map[typ
|
|
|
6890
9005
|
return o.runtimeFunctionTypeInfoWithSeen(named.Underlying().(*types.Signature), runtimeNamedTypeName(named), seen)
|
|
6891
9006
|
}
|
|
6892
9007
|
if named := namedNonStructType(typ); named != nil {
|
|
9008
|
+
if basic, ok := types.Unalias(named.Underlying()).(*types.Basic); ok {
|
|
9009
|
+
return runtimeBasicTypeInfoExpr(typeKind, basic, runtimeNamedTypeName(named))
|
|
9010
|
+
}
|
|
6893
9011
|
return strconv.Quote(runtimeNamedTypeName(named))
|
|
6894
9012
|
}
|
|
6895
9013
|
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
6896
9014
|
case *types.Basic:
|
|
6897
|
-
|
|
6898
|
-
case typed.Info()&types.IsBoolean != 0:
|
|
6899
|
-
return "{ kind: " + typeKind + ".Basic, name: \"bool\" }"
|
|
6900
|
-
case typed.Info()&types.IsString != 0:
|
|
6901
|
-
return "{ kind: " + typeKind + ".Basic, name: \"string\" }"
|
|
6902
|
-
case typed.Info()&types.IsNumeric != 0:
|
|
6903
|
-
return "{ kind: " + typeKind + ".Basic, name: \"" + basicRuntimeName(typed) + "\" }"
|
|
6904
|
-
default:
|
|
6905
|
-
return "{ kind: " + typeKind + ".Basic, name: \"unknown\" }"
|
|
6906
|
-
}
|
|
9015
|
+
return runtimeBasicTypeInfoExpr(typeKind, typed, "")
|
|
6907
9016
|
case *types.Pointer:
|
|
6908
9017
|
return "{ kind: " + typeKind + ".Pointer, elemType: " + o.runtimeTypeInfoExprWithSeen(typed.Elem(), seen) + " }"
|
|
6909
9018
|
case *types.Struct:
|
|
@@ -6926,6 +9035,23 @@ func (o *LoweringOwner) runtimeTypeInfoExprWithSeen(typ types.Type, seen map[typ
|
|
|
6926
9035
|
}
|
|
6927
9036
|
}
|
|
6928
9037
|
|
|
9038
|
+
func runtimeBasicTypeInfoExpr(typeKind string, basic *types.Basic, typeName string) string {
|
|
9039
|
+
name := "unknown"
|
|
9040
|
+
switch {
|
|
9041
|
+
case basic.Info()&types.IsBoolean != 0:
|
|
9042
|
+
name = "bool"
|
|
9043
|
+
case basic.Info()&types.IsString != 0:
|
|
9044
|
+
name = "string"
|
|
9045
|
+
case basic.Info()&types.IsNumeric != 0:
|
|
9046
|
+
name = basicRuntimeName(basic)
|
|
9047
|
+
}
|
|
9048
|
+
parts := []string{"kind: " + typeKind + ".Basic", "name: " + strconv.Quote(name)}
|
|
9049
|
+
if typeName != "" {
|
|
9050
|
+
parts = append(parts, "typeName: "+strconv.Quote(typeName))
|
|
9051
|
+
}
|
|
9052
|
+
return "{ " + strings.Join(parts, ", ") + " }"
|
|
9053
|
+
}
|
|
9054
|
+
|
|
6929
9055
|
func (o *LoweringOwner) shallowRuntimeTypeInfoExpr(typ types.Type) string {
|
|
6930
9056
|
typeKind := o.runtimeOwner.QualifiedHelper(RuntimeHelperTypeKind)
|
|
6931
9057
|
switch types.Unalias(typ).Underlying().(type) {
|
|
@@ -6998,7 +9124,8 @@ func (o *LoweringOwner) runtimeFunctionTypeInfoWithSeen(signature *types.Signatu
|
|
|
6998
9124
|
if signature.Variadic() {
|
|
6999
9125
|
parts = append(parts, "isVariadic: true")
|
|
7000
9126
|
}
|
|
7001
|
-
|
|
9127
|
+
runtimePackage := strings.TrimSuffix(typeKind, ".TypeKind")
|
|
9128
|
+
return "({ " + strings.Join(parts, ", ") + " } as " + runtimePackage + ".FunctionTypeInfo)"
|
|
7002
9129
|
}
|
|
7003
9130
|
|
|
7004
9131
|
func (o *LoweringOwner) runtimeSignatureTypes(tuple *types.Tuple, seen map[types.Type]bool) string {
|
|
@@ -7012,20 +9139,11 @@ func (o *LoweringOwner) runtimeSignatureTypes(tuple *types.Tuple, seen map[types
|
|
|
7012
9139
|
return "[" + strings.Join(types, ", ") + "]"
|
|
7013
9140
|
}
|
|
7014
9141
|
|
|
7015
|
-
func fieldByName(structType *types.Struct, name string) *types.Var {
|
|
7016
|
-
for field := range structType.Fields() {
|
|
7017
|
-
if field.Name() == name {
|
|
7018
|
-
return field
|
|
7019
|
-
}
|
|
7020
|
-
}
|
|
7021
|
-
return nil
|
|
7022
|
-
}
|
|
7023
|
-
|
|
7024
9142
|
func tsStructFieldName(name string, idx int) string {
|
|
7025
9143
|
if name == "_" {
|
|
7026
9144
|
return "_blank" + strconv.Itoa(idx)
|
|
7027
9145
|
}
|
|
7028
|
-
return name
|
|
9146
|
+
return safeIdentifier(name)
|
|
7029
9147
|
}
|
|
7030
9148
|
|
|
7031
9149
|
func shouldCloneStructValue(expr ast.Expr) bool {
|
|
@@ -7076,6 +9194,11 @@ func (o *LoweringOwner) tsSignatureResultFor(ctx lowerFileContext, signature *ty
|
|
|
7076
9194
|
}
|
|
7077
9195
|
|
|
7078
9196
|
func (o *LoweringOwner) tsSignatureResultTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
9197
|
+
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
9198
|
+
if _, ok := types.Unalias(named.Underlying()).(*types.Signature); ok {
|
|
9199
|
+
return o.tsTypeFor(ctx, typ)
|
|
9200
|
+
}
|
|
9201
|
+
}
|
|
7079
9202
|
if signature := signatureForType(typ); ctx.functionTypeDepth == 0 && signature != nil {
|
|
7080
9203
|
return o.tsAsyncCompatibleFunctionResultTypeFor(ctx, signature)
|
|
7081
9204
|
}
|
|
@@ -7139,6 +9262,13 @@ func asyncCompatibleResultType(result string) string {
|
|
|
7139
9262
|
return result + " | " + tsPromiseType(result)
|
|
7140
9263
|
}
|
|
7141
9264
|
|
|
9265
|
+
func asyncCompatibleMethodResultType(result string, async bool) string {
|
|
9266
|
+
if !async {
|
|
9267
|
+
return result
|
|
9268
|
+
}
|
|
9269
|
+
return asyncCompatibleResultType(result)
|
|
9270
|
+
}
|
|
9271
|
+
|
|
7142
9272
|
func tsPromiseType(result string) string {
|
|
7143
9273
|
return "globalThis.Promise<" + result + ">"
|
|
7144
9274
|
}
|
|
@@ -7203,10 +9333,16 @@ func (o *LoweringOwner) tsTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
|
7203
9333
|
if crossPackageUnexportedNamedType(ctx, named) {
|
|
7204
9334
|
return "any"
|
|
7205
9335
|
}
|
|
9336
|
+
if !ctx.canReferenceNamedType(named) {
|
|
9337
|
+
return "any"
|
|
9338
|
+
}
|
|
7206
9339
|
name := o.namedTypeExpr(ctx, named)
|
|
7207
9340
|
if _, ok := named.Underlying().(*types.Interface); ok {
|
|
7208
9341
|
return name + " | null"
|
|
7209
9342
|
}
|
|
9343
|
+
if _, ok := types.Unalias(named.Underlying()).(*types.Signature); ok {
|
|
9344
|
+
return name + " | null"
|
|
9345
|
+
}
|
|
7210
9346
|
return name
|
|
7211
9347
|
}
|
|
7212
9348
|
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
@@ -7233,7 +9369,7 @@ func (o *LoweringOwner) tsTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
|
7233
9369
|
}
|
|
7234
9370
|
return tsArrayType(o.tsTypeFor(ctx, typed.Elem()))
|
|
7235
9371
|
case *types.Slice:
|
|
7236
|
-
return "$.Slice<" + o.
|
|
9372
|
+
return "$.Slice<" + o.tsSliceElemTypeFor(ctx, typed.Elem()) + ">"
|
|
7237
9373
|
case *types.Map:
|
|
7238
9374
|
return "Map<" + o.tsTypeFor(ctx, typed.Key()) + ", " + o.tsTypeFor(ctx, typed.Elem()) + "> | null"
|
|
7239
9375
|
case *types.Chan:
|
|
@@ -7251,12 +9387,18 @@ func (o *LoweringOwner) tsTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
|
7251
9387
|
if crossPackageUnexportedNamedType(ctx, named) {
|
|
7252
9388
|
return "any"
|
|
7253
9389
|
}
|
|
9390
|
+
if !ctx.canReferenceNamedType(named) {
|
|
9391
|
+
return "any"
|
|
9392
|
+
}
|
|
7254
9393
|
return "$.VarRef<" + o.namedTypeExpr(ctx, named) + "> | null"
|
|
7255
9394
|
}
|
|
7256
9395
|
if named := namedStructType(typed.Elem()); named != nil {
|
|
7257
9396
|
if crossPackageUnexportedNamedType(ctx, named) {
|
|
7258
9397
|
return "any"
|
|
7259
9398
|
}
|
|
9399
|
+
if !ctx.canReferenceNamedType(named) {
|
|
9400
|
+
return "any"
|
|
9401
|
+
}
|
|
7260
9402
|
name := o.namedTypeExpr(ctx, named)
|
|
7261
9403
|
return name + " | $.VarRef<" + name + "> | null"
|
|
7262
9404
|
}
|
|
@@ -7272,12 +9414,28 @@ func (o *LoweringOwner) tsTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
|
7272
9414
|
}
|
|
7273
9415
|
}
|
|
7274
9416
|
|
|
9417
|
+
func (o *LoweringOwner) tsSliceElemTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
9418
|
+
if typeParam, ok := types.Unalias(typ).(*types.TypeParam); ok && staticTypeParamInScope(ctx, typeParam) {
|
|
9419
|
+
return safeIdentifier(typeParam.Obj().Name())
|
|
9420
|
+
}
|
|
9421
|
+
if pointer, ok := types.Unalias(typ).(*types.Pointer); ok {
|
|
9422
|
+
if typeParam, ok := types.Unalias(pointer.Elem()).(*types.TypeParam); ok && staticTypeParamInScope(ctx, typeParam) {
|
|
9423
|
+
name := safeIdentifier(typeParam.Obj().Name())
|
|
9424
|
+
return name + " | $.VarRef<" + name + "> | null"
|
|
9425
|
+
}
|
|
9426
|
+
}
|
|
9427
|
+
return o.tsTypeFor(ctx, typ)
|
|
9428
|
+
}
|
|
9429
|
+
|
|
7275
9430
|
func (o *LoweringOwner) tsNonNilTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
7276
9431
|
if isBuiltinErrorType(typ) {
|
|
7277
9432
|
return "Exclude<$.GoError, null>"
|
|
7278
9433
|
}
|
|
7279
9434
|
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
7280
9435
|
if _, ok := named.Underlying().(*types.Interface); ok {
|
|
9436
|
+
if !ctx.canReferenceNamedType(named) {
|
|
9437
|
+
return "any"
|
|
9438
|
+
}
|
|
7281
9439
|
return "Exclude<" + o.namedTypeExpr(ctx, named) + ", null>"
|
|
7282
9440
|
}
|
|
7283
9441
|
}
|
|
@@ -7288,6 +9446,9 @@ func (o *LoweringOwner) aliasTypeExpr(ctx lowerFileContext, alias *types.Alias)
|
|
|
7288
9446
|
if alias == nil || alias.Obj() == nil {
|
|
7289
9447
|
return "unknown"
|
|
7290
9448
|
}
|
|
9449
|
+
if !ctx.canReferenceObjectPackage(alias.Obj()) {
|
|
9450
|
+
return "any"
|
|
9451
|
+
}
|
|
7291
9452
|
if alias.Obj().Pkg() == nil {
|
|
7292
9453
|
return o.tsTypeFor(ctx, alias.Rhs())
|
|
7293
9454
|
}
|
|
@@ -7337,7 +9498,7 @@ func zeroValueExpr(typ types.Type) string {
|
|
|
7337
9498
|
return "undefined"
|
|
7338
9499
|
}
|
|
7339
9500
|
if named := namedStructType(typ); named != nil && isStructValueType(typ) {
|
|
7340
|
-
return "new " + named.Obj().Name() + "()"
|
|
9501
|
+
return "new " + safeIdentifier(named.Obj().Name()) + "()"
|
|
7341
9502
|
}
|
|
7342
9503
|
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
7343
9504
|
case *types.Basic:
|
|
@@ -7397,6 +9558,14 @@ func namedStructType(typ types.Type) *types.Named {
|
|
|
7397
9558
|
return named
|
|
7398
9559
|
}
|
|
7399
9560
|
|
|
9561
|
+
func pointerToNamedStructType(typ types.Type) *types.Named {
|
|
9562
|
+
pointer, ok := types.Unalias(typ).Underlying().(*types.Pointer)
|
|
9563
|
+
if !ok {
|
|
9564
|
+
return nil
|
|
9565
|
+
}
|
|
9566
|
+
return namedStructType(pointer.Elem())
|
|
9567
|
+
}
|
|
9568
|
+
|
|
7400
9569
|
func namedNonStructType(typ types.Type) *types.Named {
|
|
7401
9570
|
named, _ := types.Unalias(typ).(*types.Named)
|
|
7402
9571
|
if named == nil {
|
|
@@ -7458,6 +9627,94 @@ func signatureHasTypeParam(signature *types.Signature, target *types.TypeParam)
|
|
|
7458
9627
|
return false
|
|
7459
9628
|
}
|
|
7460
9629
|
|
|
9630
|
+
func typeParamInScope(ctx lowerFileContext, target *types.TypeParam) bool {
|
|
9631
|
+
if target == nil {
|
|
9632
|
+
return false
|
|
9633
|
+
}
|
|
9634
|
+
if signatureHasTypeParam(ctx.signature, target) {
|
|
9635
|
+
return true
|
|
9636
|
+
}
|
|
9637
|
+
return ctx.typeParams[target.Obj().Name()]
|
|
9638
|
+
}
|
|
9639
|
+
|
|
9640
|
+
func staticTypeParamInScope(ctx lowerFileContext, target *types.TypeParam) bool {
|
|
9641
|
+
if target == nil || !typeParamInScope(ctx, target) {
|
|
9642
|
+
return false
|
|
9643
|
+
}
|
|
9644
|
+
return ctx.staticTypeParams[target.Obj().Name()]
|
|
9645
|
+
}
|
|
9646
|
+
|
|
9647
|
+
func typeParamConstraintIsAny(typeParam *types.TypeParam) bool {
|
|
9648
|
+
if typeParam == nil {
|
|
9649
|
+
return false
|
|
9650
|
+
}
|
|
9651
|
+
iface, ok := typeParam.Constraint().Underlying().(*types.Interface)
|
|
9652
|
+
if !ok {
|
|
9653
|
+
return false
|
|
9654
|
+
}
|
|
9655
|
+
return iface.NumMethods() == 0 && iface.NumEmbeddeds() == 0
|
|
9656
|
+
}
|
|
9657
|
+
|
|
9658
|
+
func signatureTypeParamNames(signature *types.Signature) []string {
|
|
9659
|
+
if signature == nil || signature.TypeParams() == nil {
|
|
9660
|
+
return nil
|
|
9661
|
+
}
|
|
9662
|
+
typeParams := signature.TypeParams()
|
|
9663
|
+
names := make([]string, 0, typeParams.Len())
|
|
9664
|
+
for typeParam := range typeParams.TypeParams() {
|
|
9665
|
+
if !signatureUsesTypeParamAsSliceElem(signature, typeParam) {
|
|
9666
|
+
continue
|
|
9667
|
+
}
|
|
9668
|
+
names = append(names, safeIdentifier(typeParam.Obj().Name()))
|
|
9669
|
+
}
|
|
9670
|
+
return names
|
|
9671
|
+
}
|
|
9672
|
+
|
|
9673
|
+
func signatureUsesTypeParamAsSliceElem(signature *types.Signature, target *types.TypeParam) bool {
|
|
9674
|
+
if signature == nil || target == nil {
|
|
9675
|
+
return false
|
|
9676
|
+
}
|
|
9677
|
+
return tupleUsesTypeParamAsSliceElem(signature.Params(), target) ||
|
|
9678
|
+
tupleUsesTypeParamAsSliceElem(signature.Results(), target)
|
|
9679
|
+
}
|
|
9680
|
+
|
|
9681
|
+
func tupleUsesTypeParamAsSliceElem(tuple *types.Tuple, target *types.TypeParam) bool {
|
|
9682
|
+
if tuple == nil {
|
|
9683
|
+
return false
|
|
9684
|
+
}
|
|
9685
|
+
for variable := range tuple.Variables() {
|
|
9686
|
+
if typeUsesTypeParamAsSliceElem(variable.Type(), target) {
|
|
9687
|
+
return true
|
|
9688
|
+
}
|
|
9689
|
+
}
|
|
9690
|
+
return false
|
|
9691
|
+
}
|
|
9692
|
+
|
|
9693
|
+
func typeUsesTypeParamAsSliceElem(typ types.Type, target *types.TypeParam) bool {
|
|
9694
|
+
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
9695
|
+
case *types.Slice:
|
|
9696
|
+
if typeParam, ok := types.Unalias(typed.Elem()).(*types.TypeParam); ok &&
|
|
9697
|
+
(typeParam == target || typeParam.Obj() == target.Obj()) {
|
|
9698
|
+
return true
|
|
9699
|
+
}
|
|
9700
|
+
return typeUsesTypeParamAsSliceElem(typed.Elem(), target)
|
|
9701
|
+
case *types.Array:
|
|
9702
|
+
return typeUsesTypeParamAsSliceElem(typed.Elem(), target)
|
|
9703
|
+
case *types.Pointer:
|
|
9704
|
+
return typeUsesTypeParamAsSliceElem(typed.Elem(), target)
|
|
9705
|
+
case *types.Map:
|
|
9706
|
+
return typeUsesTypeParamAsSliceElem(typed.Key(), target) ||
|
|
9707
|
+
typeUsesTypeParamAsSliceElem(typed.Elem(), target)
|
|
9708
|
+
case *types.Chan:
|
|
9709
|
+
return typeUsesTypeParamAsSliceElem(typed.Elem(), target)
|
|
9710
|
+
case *types.Signature:
|
|
9711
|
+
return tupleUsesTypeParamAsSliceElem(typed.Params(), target) ||
|
|
9712
|
+
tupleUsesTypeParamAsSliceElem(typed.Results(), target)
|
|
9713
|
+
default:
|
|
9714
|
+
return false
|
|
9715
|
+
}
|
|
9716
|
+
}
|
|
9717
|
+
|
|
7461
9718
|
func sameNamedTypeOrigin(a *types.Named, b *types.Named) bool {
|
|
7462
9719
|
if a == nil || b == nil {
|
|
7463
9720
|
return false
|
|
@@ -7585,6 +9842,11 @@ func isIntegerType(typ types.Type) bool {
|
|
|
7585
9842
|
return ok && basic.Info()&types.IsInteger != 0
|
|
7586
9843
|
}
|
|
7587
9844
|
|
|
9845
|
+
func isFloatType(typ types.Type) bool {
|
|
9846
|
+
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
9847
|
+
return ok && basic.Info()&types.IsFloat != 0
|
|
9848
|
+
}
|
|
9849
|
+
|
|
7588
9850
|
func unsignedIntegerBits(typ types.Type) (int, bool) {
|
|
7589
9851
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
7590
9852
|
if !ok || basic.Info()&types.IsUnsigned == 0 {
|
|
@@ -7632,6 +9894,9 @@ func isWideIntegerType(typ types.Type) bool {
|
|
|
7632
9894
|
}
|
|
7633
9895
|
|
|
7634
9896
|
func isFixedWideIntegerType(typ types.Type) bool {
|
|
9897
|
+
if typ == nil {
|
|
9898
|
+
return false
|
|
9899
|
+
}
|
|
7635
9900
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
7636
9901
|
if !ok {
|
|
7637
9902
|
return false
|
|
@@ -7644,6 +9909,14 @@ func isFixedWideIntegerType(typ types.Type) bool {
|
|
|
7644
9909
|
}
|
|
7645
9910
|
}
|
|
7646
9911
|
|
|
9912
|
+
func isFixedSignedWideIntegerType(typ types.Type) bool {
|
|
9913
|
+
if typ == nil {
|
|
9914
|
+
return false
|
|
9915
|
+
}
|
|
9916
|
+
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
9917
|
+
return ok && basic.Kind() == types.Int64
|
|
9918
|
+
}
|
|
9919
|
+
|
|
7647
9920
|
func isRuneSliceType(typ types.Type) bool {
|
|
7648
9921
|
slice, ok := types.Unalias(typ).Underlying().(*types.Slice)
|
|
7649
9922
|
return ok && isRuneType(slice.Elem())
|
|
@@ -7672,6 +9945,8 @@ func sliceTypeHint(typ types.Type) string {
|
|
|
7672
9945
|
return "string"
|
|
7673
9946
|
case isNumericType(typ):
|
|
7674
9947
|
return "number"
|
|
9948
|
+
case isBoolType(typ):
|
|
9949
|
+
return "boolean"
|
|
7675
9950
|
default:
|
|
7676
9951
|
return ""
|
|
7677
9952
|
}
|
|
@@ -7800,6 +10075,13 @@ func (o *LoweringOwner) awaitCallIfNeeded(ctx lowerFileContext, fun ast.Expr, ca
|
|
|
7800
10075
|
return call
|
|
7801
10076
|
}
|
|
7802
10077
|
|
|
10078
|
+
func parenthesizeAwaitedExpr(expr string) string {
|
|
10079
|
+
if strings.HasPrefix(expr, "await ") {
|
|
10080
|
+
return "(" + expr + ")"
|
|
10081
|
+
}
|
|
10082
|
+
return expr
|
|
10083
|
+
}
|
|
10084
|
+
|
|
7803
10085
|
func (o *LoweringOwner) genericTypeArgsExpr(ctx lowerFileContext, callee ast.Expr, typeArgExprs []ast.Expr) string {
|
|
7804
10086
|
signature := genericFunctionSignature(ctx, callee)
|
|
7805
10087
|
if signature == nil {
|
|
@@ -7883,7 +10165,7 @@ func (o *LoweringOwner) inferGenericTypeArg(
|
|
|
7883
10165
|
}
|
|
7884
10166
|
|
|
7885
10167
|
func (o *LoweringOwner) genericTypeDescriptorExpr(ctx lowerFileContext, typ types.Type) string {
|
|
7886
|
-
if typeParam, ok := types.Unalias(typ).(*types.TypeParam); ok &&
|
|
10168
|
+
if typeParam, ok := types.Unalias(typ).(*types.TypeParam); ok && typeParamInScope(ctx, typeParam) {
|
|
7887
10169
|
return "__typeArgs?.[" + strconv.Quote(typeParam.Obj().Name()) + "] ?? { type: " +
|
|
7888
10170
|
o.runtimeTypeInfoExpr(typ) + ", zero: () => " + o.lowerZeroValueExprFor(ctx, typ) + " }"
|
|
7889
10171
|
}
|
|
@@ -7921,7 +10203,21 @@ func (o *LoweringOwner) genericMethodDescriptorsForType(
|
|
|
7921
10203
|
methods = append(methods, method.Name()+": (receiver: any, ...args: any[]) => receiver."+method.Name()+"(...args)")
|
|
7922
10204
|
continue
|
|
7923
10205
|
}
|
|
7924
|
-
|
|
10206
|
+
receiver := "receiver"
|
|
10207
|
+
if sig, _ := method.Type().(*types.Signature); sig != nil {
|
|
10208
|
+
if recv := sig.Recv(); recv != nil {
|
|
10209
|
+
if _, ok := types.Unalias(recv.Type()).Underlying().(*types.Pointer); !ok {
|
|
10210
|
+
if _, ok := types.Unalias(methodSetType).Underlying().(*types.Pointer); ok {
|
|
10211
|
+
receiver = o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) + "(receiver)"
|
|
10212
|
+
} else {
|
|
10213
|
+
receiver = "(" + o.runtimeOwner.QualifiedHelper(RuntimeHelperIsVarRef) +
|
|
10214
|
+
"(receiver) ? receiver.value : receiver)"
|
|
10215
|
+
}
|
|
10216
|
+
}
|
|
10217
|
+
}
|
|
10218
|
+
}
|
|
10219
|
+
methods = append(methods, method.Name()+": (receiver: any, ...args: any[]) => "+
|
|
10220
|
+
"("+o.methodFunctionExpr(ctx, named.Origin(), method, method.Name())+" as any)("+receiver+", ...args)")
|
|
7925
10221
|
}
|
|
7926
10222
|
if len(methods) == 0 {
|
|
7927
10223
|
return ""
|
|
@@ -7946,9 +10242,21 @@ func namedNonStructMethodSetType(typ types.Type) (*types.Named, types.Type) {
|
|
|
7946
10242
|
|
|
7947
10243
|
func methodFunctionName(receiver *types.Named, method string) string {
|
|
7948
10244
|
if receiver == nil || receiver.Obj() == nil {
|
|
7949
|
-
return method
|
|
10245
|
+
return safeIdentifier(method)
|
|
10246
|
+
}
|
|
10247
|
+
return safeIdentifier(receiver.Obj().Name()) + "_" + safeIdentifier(method)
|
|
10248
|
+
}
|
|
10249
|
+
|
|
10250
|
+
func methodReceiverNamedType(obj types.Object) *types.Named {
|
|
10251
|
+
fn, _ := obj.(*types.Func)
|
|
10252
|
+
if fn == nil {
|
|
10253
|
+
return nil
|
|
10254
|
+
}
|
|
10255
|
+
signature, _ := fn.Type().(*types.Signature)
|
|
10256
|
+
if signature == nil || signature.Recv() == nil {
|
|
10257
|
+
return nil
|
|
7950
10258
|
}
|
|
7951
|
-
return
|
|
10259
|
+
return receiverNamedType(signature.Recv().Type())
|
|
7952
10260
|
}
|
|
7953
10261
|
|
|
7954
10262
|
func (o *LoweringOwner) methodFunctionExpr(
|
|
@@ -7973,7 +10281,7 @@ func (o *LoweringOwner) namedTypeExpr(ctx lowerFileContext, named *types.Named)
|
|
|
7973
10281
|
if named == nil || named.Obj() == nil {
|
|
7974
10282
|
return "unknown"
|
|
7975
10283
|
}
|
|
7976
|
-
baseName := named.Obj().Name()
|
|
10284
|
+
baseName := safeIdentifier(named.Obj().Name())
|
|
7977
10285
|
if alias := ctx.localAliases[named.Obj()]; alias != "" {
|
|
7978
10286
|
baseName = alias + "." + baseName
|
|
7979
10287
|
} else if named.Obj().Pkg() != nil {
|
|
@@ -8036,11 +10344,30 @@ func runtimeNamedTypeName(named *types.Named) string {
|
|
|
8036
10344
|
}
|
|
8037
10345
|
|
|
8038
10346
|
func goRuntimeTypeString(typ types.Type) string {
|
|
8039
|
-
return types.TypeString(typ, func(pkg *types.Package) string {
|
|
10347
|
+
return types.TypeString(runtimeIdentityType(typ), func(pkg *types.Package) string {
|
|
8040
10348
|
return pkg.Name()
|
|
8041
10349
|
})
|
|
8042
10350
|
}
|
|
8043
10351
|
|
|
10352
|
+
func runtimeIdentityType(typ types.Type) types.Type {
|
|
10353
|
+
switch typed := typ.(type) {
|
|
10354
|
+
case *types.Alias:
|
|
10355
|
+
return runtimeIdentityType(types.Unalias(typed))
|
|
10356
|
+
case *types.Pointer:
|
|
10357
|
+
return types.NewPointer(runtimeIdentityType(typed.Elem()))
|
|
10358
|
+
case *types.Slice:
|
|
10359
|
+
return types.NewSlice(runtimeIdentityType(typed.Elem()))
|
|
10360
|
+
case *types.Array:
|
|
10361
|
+
return types.NewArray(runtimeIdentityType(typed.Elem()), typed.Len())
|
|
10362
|
+
case *types.Map:
|
|
10363
|
+
return types.NewMap(runtimeIdentityType(typed.Key()), runtimeIdentityType(typed.Elem()))
|
|
10364
|
+
case *types.Chan:
|
|
10365
|
+
return types.NewChan(typed.Dir(), runtimeIdentityType(typed.Elem()))
|
|
10366
|
+
default:
|
|
10367
|
+
return typ
|
|
10368
|
+
}
|
|
10369
|
+
}
|
|
10370
|
+
|
|
8044
10371
|
func basicRuntimeName(basic *types.Basic) string {
|
|
8045
10372
|
if basic == nil {
|
|
8046
10373
|
return "unknown"
|