goscript 0.1.3 → 0.2.0
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/README.md +5 -2
- package/cmd/go_js_wasm_exec/main.go +201 -0
- package/cmd/go_js_wasm_exec/main_test.go +83 -0
- package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +35 -8
- package/cmd/goscript/cmd-test.go +14 -0
- package/cmd/goscript/cmd-test_test.go +1 -1
- package/cmd/goscript/cmd_compile_test.go +105 -6
- package/compiler/build-flags.go +9 -10
- package/compiler/compile-request.go +12 -9
- package/compiler/compliance_test.go +0 -1
- package/compiler/config.go +2 -0
- package/compiler/gotest/request.go +28 -0
- package/compiler/gotest/runner.go +353 -27
- package/compiler/gotest/runner_test.go +400 -1
- package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
- package/compiler/gotest/testdata/browserapi/go.mod +3 -0
- package/compiler/lowered-program.go +24 -17
- package/compiler/lowering.go +988 -263
- package/compiler/lowering_bench_test.go +364 -0
- package/compiler/override-facts.go +15 -0
- package/compiler/override-parity-verifier.go +450 -0
- package/compiler/override-parity.go +122 -0
- package/compiler/override-registry_test.go +559 -0
- package/compiler/package-graph.go +61 -4
- package/compiler/package-graph_test.go +30 -0
- package/compiler/protobuf-ts-binding.go +514 -0
- package/compiler/protobuf-ts-binding_test.go +172 -0
- package/compiler/semantic-model-types.go +17 -4
- package/compiler/semantic-model.go +709 -72
- package/compiler/semantic-model_test.go +219 -0
- package/compiler/service.go +20 -1
- package/compiler/skeleton_test.go +1008 -20
- package/compiler/typescript-emitter.go +147 -15
- package/dist/gs/builtin/builtin.d.ts +2 -2
- package/dist/gs/builtin/builtin.js +20 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +2 -1
- package/dist/gs/builtin/slice.js +34 -4
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +14 -6
- package/dist/gs/builtin/type.js +224 -64
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +11 -0
- package/dist/gs/builtin/varRef.js +57 -2
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js +1 -1
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.js +1 -1
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +13 -6
- package/dist/gs/compress/zlib/index.js +131 -35
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/crypto/sha1/index.js +2 -5
- package/dist/gs/crypto/sha1/index.js.map +1 -1
- package/dist/gs/crypto/sha256/index.js +2 -5
- package/dist/gs/crypto/sha256/index.js.map +1 -1
- package/dist/gs/crypto/sha512/index.js +2 -5
- package/dist/gs/crypto/sha512/index.js.map +1 -1
- package/dist/gs/embed/index.d.ts +6 -0
- package/dist/gs/embed/index.js +210 -5
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/encoding/json/index.d.ts +114 -0
- package/dist/gs/encoding/json/index.js +544 -36
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +3 -3
- package/dist/gs/fmt/fmt.js +29 -16
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +100 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +564 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.d.ts +45 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js +229 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/errors.js +54 -30
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/go/scanner/index.d.ts +2 -0
- package/dist/gs/go/scanner/index.js +29 -5
- package/dist/gs/go/scanner/index.js.map +1 -1
- package/dist/gs/go/token/index.js +22 -6
- package/dist/gs/go/token/index.js.map +1 -1
- package/dist/gs/hash/index.d.ts +6 -0
- package/dist/gs/hash/index.js +20 -0
- package/dist/gs/hash/index.js.map +1 -1
- package/dist/gs/internal/goarch/index.d.ts +43 -3
- package/dist/gs/internal/goarch/index.js +42 -10
- package/dist/gs/internal/goarch/index.js.map +1 -1
- package/dist/gs/io/fs/fs.js +26 -14
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/fs/readdir.js +8 -4
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/sub.js +8 -1
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/io.d.ts +12 -6
- package/dist/gs/io/io.js +87 -42
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +31 -5
- package/dist/gs/math/bits/index.js +29 -28
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/mime/index.d.ts +16 -0
- package/dist/gs/mime/index.js +315 -6
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.d.ts +12 -0
- package/dist/gs/net/http/httptest/index.js +85 -6
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +303 -6
- package/dist/gs/net/http/index.js +1615 -58
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/dir_unix.gs.js +1 -1
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/error.gs.js +1 -1
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.d.ts +1 -0
- package/dist/gs/os/exec.gs.js +4 -8
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.js +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/index.d.ts +1 -1
- package/dist/gs/os/index.js +1 -1
- package/dist/gs/os/index.js.map +1 -1
- package/dist/gs/os/proc.gs.d.ts +4 -0
- package/dist/gs/os/proc.gs.js +12 -6
- package/dist/gs/os/proc.gs.js.map +1 -1
- package/dist/gs/os/root_js.gs.js +1 -1
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/types.gs.js +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +6 -2
- package/dist/gs/os/types_js.gs.js +170 -9
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/path/path.js +11 -7
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +5 -4
- package/dist/gs/reflect/index.js +4 -3
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js +15 -0
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +26 -6
- package/dist/gs/reflect/type.js +1498 -279
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +14 -6
- package/dist/gs/reflect/types.js +35 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.d.ts +1 -0
- package/dist/gs/reflect/value.js +83 -41
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +4 -140
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/pprof/index.d.ts +8 -2
- package/dist/gs/runtime/pprof/index.js +50 -30
- package/dist/gs/runtime/pprof/index.js.map +1 -1
- package/dist/gs/runtime/runtime.js +5 -4
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/runtime/trace/index.js +5 -19
- package/dist/gs/runtime/trace/index.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.js +1 -1
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/complex.gs.d.ts +3 -0
- package/dist/gs/strconv/complex.gs.js +148 -0
- package/dist/gs/strconv/complex.gs.js.map +1 -0
- package/dist/gs/strconv/index.d.ts +1 -0
- package/dist/gs/strconv/index.js +1 -0
- package/dist/gs/strconv/index.js.map +1 -1
- package/dist/gs/strings/builder.js +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +11 -7
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.js +15 -7
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/strings.d.ts +5 -0
- package/dist/gs/strings/strings.js +57 -5
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.js +9 -9
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/atomic/value.gs.js +2 -2
- package/dist/gs/sync/atomic/value.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +2 -1
- package/dist/gs/sync/sync.js +37 -16
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/env.js +22 -14
- package/dist/gs/syscall/env.js.map +1 -1
- package/dist/gs/syscall/js/index.js +9 -0
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/testing/testing.js +59 -15
- package/dist/gs/testing/testing.js.map +1 -1
- package/dist/gs/time/time.d.ts +24 -1
- package/dist/gs/time/time.js +43 -3
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unique/index.js +7 -1
- package/dist/gs/unique/index.js.map +1 -1
- package/go.mod +3 -3
- package/go.sum +16 -0
- package/gs/builtin/builtin.ts +25 -2
- package/gs/builtin/runtime-contract.test.ts +260 -18
- package/gs/builtin/slice.ts +51 -4
- package/gs/builtin/type.ts +310 -63
- package/gs/builtin/varRef.ts +85 -2
- package/gs/bytes/buffer.gs.ts +1 -1
- package/gs/bytes/reader.gs.ts +1 -1
- package/gs/compress/zlib/index.test.ts +159 -1
- package/gs/compress/zlib/index.ts +164 -37
- package/gs/compress/zlib/meta.json +4 -1
- package/gs/compress/zlib/parity.json +51 -0
- package/gs/crypto/sha1/index.test.ts +19 -2
- package/gs/crypto/sha1/index.ts +3 -6
- package/gs/crypto/sha256/index.test.ts +14 -2
- package/gs/crypto/sha256/index.ts +3 -6
- package/gs/crypto/sha512/index.test.ts +17 -2
- package/gs/crypto/sha512/index.ts +3 -6
- package/gs/embed/index.test.ts +87 -0
- package/gs/embed/index.ts +229 -5
- package/gs/encoding/json/index.test.ts +360 -6
- package/gs/encoding/json/index.ts +679 -38
- package/gs/encoding/json/parity.json +81 -0
- package/gs/fmt/fmt.test.ts +41 -3
- package/gs/fmt/fmt.ts +40 -17
- package/gs/fmt/meta.json +6 -1
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +211 -3
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +857 -1
- package/gs/github.com/go-git/go-billy/v6/osfs/index.test.ts +110 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/index.ts +280 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/meta.json +8 -0
- package/gs/github.com/pkg/errors/errors.ts +54 -30
- package/gs/go/scanner/index.test.ts +39 -56
- package/gs/go/scanner/index.ts +33 -5
- package/gs/go/scanner/parity.json +27 -0
- package/gs/go/token/index.ts +22 -6
- package/gs/hash/index.test.ts +20 -33
- package/gs/hash/index.ts +28 -0
- package/gs/hash/parity.json +21 -0
- package/gs/internal/goarch/index.test.ts +32 -0
- package/gs/internal/goarch/index.ts +45 -13
- package/gs/internal/goarch/parity.json +144 -0
- package/gs/io/fs/fs.ts +26 -14
- package/gs/io/fs/readdir.test.ts +38 -0
- package/gs/io/fs/readdir.ts +8 -4
- package/gs/io/fs/sub.ts +8 -1
- package/gs/io/io.test.ts +77 -6
- package/gs/io/io.ts +115 -52
- package/gs/io/meta.json +7 -1
- package/gs/io/parity.json +162 -0
- package/gs/math/bits/index.test.ts +14 -1
- package/gs/math/bits/index.ts +75 -32
- package/gs/math/bits/parity.json +156 -0
- package/gs/mime/index.test.ts +90 -0
- package/gs/mime/index.ts +369 -6
- package/gs/mime/parity.json +36 -0
- package/gs/net/http/httptest/index.test.ts +98 -2
- package/gs/net/http/httptest/index.ts +101 -6
- package/gs/net/http/httptest/parity.json +15 -0
- package/gs/net/http/index.test.ts +797 -12
- package/gs/net/http/index.ts +1874 -136
- package/gs/net/http/meta.json +16 -1
- package/gs/net/http/parity.json +193 -0
- package/gs/os/dir_unix.gs.ts +1 -1
- package/gs/os/error.gs.ts +1 -1
- package/gs/os/exec.gs.ts +4 -8
- package/gs/os/exec_posix.gs.ts +1 -1
- package/gs/os/file_unix_js.test.ts +52 -0
- package/gs/os/index.test.ts +9 -0
- package/gs/os/index.ts +1 -0
- package/gs/os/meta.json +4 -0
- package/gs/os/parity.json +9 -0
- package/gs/os/proc.gs.ts +18 -5
- package/gs/os/proc.test.ts +26 -0
- package/gs/os/readdir.test.ts +56 -0
- package/gs/os/root_js.gs.ts +1 -1
- package/gs/os/types.gs.ts +1 -1
- package/gs/os/types_js.gs.ts +170 -9
- package/gs/os/types_unix.gs.ts +1 -1
- package/gs/path/path.ts +11 -7
- package/gs/reflect/deepequal.test.ts +10 -1
- package/gs/reflect/field.test.ts +37 -15
- package/gs/reflect/function-types.test.ts +518 -22
- package/gs/reflect/index.ts +8 -6
- package/gs/reflect/map.ts +20 -0
- package/gs/reflect/meta.json +6 -4
- package/gs/reflect/parity.json +234 -0
- package/gs/reflect/sliceat.test.ts +156 -0
- package/gs/reflect/structof.test.ts +401 -0
- package/gs/reflect/type.ts +1980 -365
- package/gs/reflect/typefor.test.ts +540 -10
- package/gs/reflect/types.ts +43 -18
- package/gs/reflect/value.ts +105 -45
- package/gs/reflect/visiblefields.ts +5 -168
- package/gs/runtime/parity.json +24 -0
- package/gs/runtime/pprof/index.test.ts +29 -7
- package/gs/runtime/pprof/index.ts +56 -30
- package/gs/runtime/pprof/parity.json +27 -0
- package/gs/runtime/runtime.test.ts +3 -1
- package/gs/runtime/runtime.ts +4 -3
- package/gs/runtime/trace/index.test.ts +5 -3
- package/gs/runtime/trace/index.ts +8 -20
- package/gs/runtime/trace/parity.json +36 -0
- package/gs/strconv/atoi.gs.ts +1 -1
- package/gs/strconv/complex.gs.ts +174 -0
- package/gs/strconv/complex.test.ts +65 -0
- package/gs/strconv/index.ts +1 -0
- package/gs/strconv/parity.json +120 -0
- package/gs/strings/builder.ts +1 -1
- package/gs/strings/meta.json +5 -2
- package/gs/strings/parity.json +186 -0
- package/gs/strings/reader.test.ts +2 -2
- package/gs/strings/reader.ts +11 -7
- package/gs/strings/replace.ts +15 -7
- package/gs/strings/strings.test.ts +22 -2
- package/gs/strings/strings.ts +64 -6
- package/gs/sync/atomic/type.gs.ts +9 -9
- package/gs/sync/atomic/value.gs.ts +2 -2
- package/gs/sync/meta.json +1 -0
- package/gs/sync/sync.test.ts +41 -1
- package/gs/sync/sync.ts +41 -16
- package/gs/syscall/env.ts +29 -14
- package/gs/syscall/js/index.test.ts +18 -0
- package/gs/syscall/js/index.ts +12 -0
- package/gs/testing/testing.test.ts +99 -3
- package/gs/testing/testing.ts +95 -24
- package/gs/time/parity.json +225 -0
- package/gs/time/time.test.ts +20 -2
- package/gs/time/time.ts +49 -7
- package/gs/unique/index.ts +7 -1
- package/package.json +4 -2
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -814
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -31
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1233
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
- /package/compiler/{wasm_api.go → wasm-api.go} +0 -0
package/gs/reflect/type.ts
CHANGED
|
@@ -9,10 +9,9 @@ export { StructField }
|
|
|
9
9
|
import { MapIter } from './map.js'
|
|
10
10
|
import {
|
|
11
11
|
getTypeByName as builtinGetTypeByName,
|
|
12
|
-
TypeKind,
|
|
13
12
|
isStructTypeInfo,
|
|
14
13
|
isInterfaceTypeInfo,
|
|
15
|
-
|
|
14
|
+
structFieldRuntimeKey,
|
|
16
15
|
} from '../builtin/type.js'
|
|
17
16
|
import { Zero } from './value.js'
|
|
18
17
|
import { DeepEqual } from './deepequal.js'
|
|
@@ -181,8 +180,13 @@ export const UnsafePointer: Kind = 26
|
|
|
181
180
|
|
|
182
181
|
const pointerAddressStride = 0x100000000
|
|
183
182
|
const pointerAddresses = new WeakMap<object, number>()
|
|
183
|
+
const fieldPointerAddresses = new WeakMap<
|
|
184
|
+
object,
|
|
185
|
+
globalThis.Map<string, number>
|
|
186
|
+
>()
|
|
184
187
|
let nextPointerAddress = 1
|
|
185
188
|
const canonicalTypes = new globalThis.Map<string, Type>()
|
|
189
|
+
const constructingRegisteredTypes = new globalThis.Map<string, Type>()
|
|
186
190
|
|
|
187
191
|
function pointerAddress(value: object): number {
|
|
188
192
|
let address = pointerAddresses.get(value)
|
|
@@ -194,16 +198,139 @@ function pointerAddress(value: object): number {
|
|
|
194
198
|
return address
|
|
195
199
|
}
|
|
196
200
|
|
|
201
|
+
function fieldPointerAddress(target: object, key: string): number {
|
|
202
|
+
let addresses = fieldPointerAddresses.get(target)
|
|
203
|
+
if (addresses === undefined) {
|
|
204
|
+
addresses = new globalThis.Map<string, number>()
|
|
205
|
+
fieldPointerAddresses.set(target, addresses)
|
|
206
|
+
}
|
|
207
|
+
let address = addresses.get(key)
|
|
208
|
+
if (address === undefined) {
|
|
209
|
+
address = nextPointerAddress * pointerAddressStride
|
|
210
|
+
nextPointerAddress++
|
|
211
|
+
addresses.set(key, address)
|
|
212
|
+
}
|
|
213
|
+
return address
|
|
214
|
+
}
|
|
215
|
+
|
|
197
216
|
function internType(t: Type): Type {
|
|
198
|
-
const key =
|
|
217
|
+
const key = typeIdentityKey(t)
|
|
199
218
|
const existing = canonicalTypes.get(key)
|
|
200
219
|
if (existing) {
|
|
220
|
+
mergeTypeMetadata(existing, t)
|
|
201
221
|
return existing
|
|
202
222
|
}
|
|
203
223
|
canonicalTypes.set(key, t)
|
|
204
224
|
return t
|
|
205
225
|
}
|
|
206
226
|
|
|
227
|
+
function mergeTypeMetadata(target: Type, source: Type): void {
|
|
228
|
+
if (target instanceof BasicType && source instanceof BasicType) {
|
|
229
|
+
target.mergeMethodSignatures(source.methodSignatures())
|
|
230
|
+
return
|
|
231
|
+
}
|
|
232
|
+
if (target instanceof PointerType && source instanceof PointerType) {
|
|
233
|
+
target.mergeMethodSignatures(source.methodSignatures())
|
|
234
|
+
return
|
|
235
|
+
}
|
|
236
|
+
if (target instanceof FunctionType && source instanceof FunctionType) {
|
|
237
|
+
target.mergeSignature(source)
|
|
238
|
+
target.mergeMethodSignatures(source.methodSignatures())
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function typeIdentityKey(t: Type, seen = new Set<Type>()): string {
|
|
243
|
+
if (seen.has(t)) {
|
|
244
|
+
return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`
|
|
245
|
+
}
|
|
246
|
+
seen.add(t)
|
|
247
|
+
if (t instanceof StructType) {
|
|
248
|
+
return t.identityKey(seen)
|
|
249
|
+
}
|
|
250
|
+
switch (t.Kind()) {
|
|
251
|
+
case Array:
|
|
252
|
+
return `${t.Kind()}:${t.Len()}:${typeIdentityKey(t.Elem(), seen)}`
|
|
253
|
+
case Chan:
|
|
254
|
+
case Ptr:
|
|
255
|
+
case Slice:
|
|
256
|
+
return `${t.Kind()}:${t.String()}:${typeIdentityKey(t.Elem(), seen)}`
|
|
257
|
+
case Map:
|
|
258
|
+
return `${t.Kind()}:${typeIdentityKey(t.Key(), seen)}:${typeIdentityKey(t.Elem(), seen)}`
|
|
259
|
+
case Func: {
|
|
260
|
+
if (t.Name() !== '') {
|
|
261
|
+
return `${t.Kind()}:named:${t.PkgPath()}:${t.Name()}`
|
|
262
|
+
}
|
|
263
|
+
const params = globalThis.Array.from(
|
|
264
|
+
{ length: t.NumIn() },
|
|
265
|
+
(_unused, idx) => typeIdentityKey(t.In(idx), seen),
|
|
266
|
+
)
|
|
267
|
+
const results = globalThis.Array.from(
|
|
268
|
+
{ length: t.NumOut() },
|
|
269
|
+
(_unused, idx) => typeIdentityKey(t.Out(idx), seen),
|
|
270
|
+
)
|
|
271
|
+
return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}:${t.IsVariadic()}:${params.join(',')}:${results.join(',')}`
|
|
272
|
+
}
|
|
273
|
+
default:
|
|
274
|
+
return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function typeUnderlyingIdentityKey(t: Type, seen = new Set<Type>()): string {
|
|
279
|
+
if (seen.has(t)) {
|
|
280
|
+
return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`
|
|
281
|
+
}
|
|
282
|
+
seen.add(t)
|
|
283
|
+
if (t instanceof BasicType) {
|
|
284
|
+
return `basic:${t.underlyingName()}`
|
|
285
|
+
}
|
|
286
|
+
if (t instanceof StructType) {
|
|
287
|
+
return t.underlyingIdentityKey(seen)
|
|
288
|
+
}
|
|
289
|
+
switch (t.Kind()) {
|
|
290
|
+
case Array:
|
|
291
|
+
return `array:${t.Len()}:${typeIdentityKey(t.Elem(), seen)}`
|
|
292
|
+
case Chan:
|
|
293
|
+
return `chan:${t.String()}:${typeIdentityKey(t.Elem(), seen)}`
|
|
294
|
+
case Ptr:
|
|
295
|
+
return `ptr:${typeIdentityKey(t.Elem(), seen)}`
|
|
296
|
+
case Slice:
|
|
297
|
+
return `slice:${typeIdentityKey(t.Elem(), seen)}`
|
|
298
|
+
case Map:
|
|
299
|
+
return `map:${typeIdentityKey(t.Key(), seen)}:${typeIdentityKey(
|
|
300
|
+
t.Elem(),
|
|
301
|
+
seen,
|
|
302
|
+
)}`
|
|
303
|
+
case Func: {
|
|
304
|
+
const params = globalThis.Array.from(
|
|
305
|
+
{ length: t.NumIn() },
|
|
306
|
+
(_unused, idx) => typeIdentityKey(t.In(idx), seen),
|
|
307
|
+
)
|
|
308
|
+
const results = globalThis.Array.from(
|
|
309
|
+
{ length: t.NumOut() },
|
|
310
|
+
(_unused, idx) => typeIdentityKey(t.Out(idx), seen),
|
|
311
|
+
)
|
|
312
|
+
return `func:${t.IsVariadic()}:${params.join(',')}:${results.join(',')}`
|
|
313
|
+
}
|
|
314
|
+
case Interface:
|
|
315
|
+
return `interface:${typeMethods(t).map(methodSignatureIdentityKey).join('|')}`
|
|
316
|
+
default:
|
|
317
|
+
return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function typeIsNamed(t: Type): boolean {
|
|
322
|
+
if (t.Kind() === Interface) {
|
|
323
|
+
return t.String() !== 'interface{}' && !t.String().startsWith('interface {')
|
|
324
|
+
}
|
|
325
|
+
if (t.Kind() === Struct || t.Kind() === Func) {
|
|
326
|
+
return t.Name() !== ''
|
|
327
|
+
}
|
|
328
|
+
if (t instanceof BasicType) {
|
|
329
|
+
return t.Kind() !== Invalid && t.Name() !== ''
|
|
330
|
+
}
|
|
331
|
+
return t.Name() !== ''
|
|
332
|
+
}
|
|
333
|
+
|
|
207
334
|
// Type is the representation of a Go type.
|
|
208
335
|
export interface Type {
|
|
209
336
|
// String returns a string representation of the type.
|
|
@@ -222,6 +349,26 @@ export interface Type {
|
|
|
222
349
|
// NumField returns a struct type's field count.
|
|
223
350
|
NumField(): number
|
|
224
351
|
|
|
352
|
+
// NumIn returns a function type's input count.
|
|
353
|
+
// Panics if the type's Kind is not Func.
|
|
354
|
+
NumIn(): number
|
|
355
|
+
|
|
356
|
+
// In returns a function type's i'th input type.
|
|
357
|
+
// Panics if the type's Kind is not Func or i is out of range.
|
|
358
|
+
In(i: number): Type
|
|
359
|
+
|
|
360
|
+
// NumOut returns a function type's output count.
|
|
361
|
+
// Panics if the type's Kind is not Func.
|
|
362
|
+
NumOut(): number
|
|
363
|
+
|
|
364
|
+
// Out returns a function type's i'th output type.
|
|
365
|
+
// Panics if the type's Kind is not Func or i is out of range.
|
|
366
|
+
Out(i: number): Type
|
|
367
|
+
|
|
368
|
+
// IsVariadic reports whether a function type's final input is variadic.
|
|
369
|
+
// Panics if the type's Kind is not Func.
|
|
370
|
+
IsVariadic(): boolean
|
|
371
|
+
|
|
225
372
|
// PkgPath returns the package path for named types, empty for unnamed types.
|
|
226
373
|
PkgPath(): string
|
|
227
374
|
|
|
@@ -281,6 +428,10 @@ export interface Type {
|
|
|
281
428
|
Comparable(): boolean
|
|
282
429
|
}
|
|
283
430
|
|
|
431
|
+
function nonFunctionTypePanic(method: string, t: Type): never {
|
|
432
|
+
throw new Error(`reflect: ${method} of non-func type ${t.String()}`)
|
|
433
|
+
}
|
|
434
|
+
|
|
284
435
|
// InvalidTypeInstance is a singleton type for invalid/zero reflect.Value
|
|
285
436
|
class InvalidTypeClass implements Type {
|
|
286
437
|
Kind(): Kind {
|
|
@@ -310,6 +461,21 @@ class InvalidTypeClass implements Type {
|
|
|
310
461
|
NumField(): number {
|
|
311
462
|
return 0
|
|
312
463
|
}
|
|
464
|
+
NumIn(): number {
|
|
465
|
+
return nonFunctionTypePanic('NumIn', this)
|
|
466
|
+
}
|
|
467
|
+
In(_i: number): Type {
|
|
468
|
+
return nonFunctionTypePanic('In', this)
|
|
469
|
+
}
|
|
470
|
+
NumOut(): number {
|
|
471
|
+
return nonFunctionTypePanic('NumOut', this)
|
|
472
|
+
}
|
|
473
|
+
Out(_i: number): Type {
|
|
474
|
+
return nonFunctionTypePanic('Out', this)
|
|
475
|
+
}
|
|
476
|
+
IsVariadic(): boolean {
|
|
477
|
+
return nonFunctionTypePanic('IsVariadic', this)
|
|
478
|
+
}
|
|
313
479
|
Field(_i: number): StructField {
|
|
314
480
|
throw new Error('reflect: Field of invalid type')
|
|
315
481
|
}
|
|
@@ -401,8 +567,9 @@ export class Value {
|
|
|
401
567
|
|
|
402
568
|
// Methods required by godoc.txt and used throughout the codebase
|
|
403
569
|
public Int(): number {
|
|
404
|
-
|
|
405
|
-
|
|
570
|
+
const value = this.numericValue()
|
|
571
|
+
if (value !== null && Number.isInteger(value)) {
|
|
572
|
+
return value
|
|
406
573
|
}
|
|
407
574
|
throw new Error(
|
|
408
575
|
'reflect: call of reflect.Value.Int on ' +
|
|
@@ -412,8 +579,9 @@ export class Value {
|
|
|
412
579
|
}
|
|
413
580
|
|
|
414
581
|
public Uint(): number {
|
|
415
|
-
|
|
416
|
-
|
|
582
|
+
const value = this.numericValue()
|
|
583
|
+
if (value !== null && value >= 0) {
|
|
584
|
+
return value
|
|
417
585
|
}
|
|
418
586
|
throw new Error(
|
|
419
587
|
'reflect: call of reflect.Value.Uint on ' +
|
|
@@ -423,8 +591,9 @@ export class Value {
|
|
|
423
591
|
}
|
|
424
592
|
|
|
425
593
|
public Float(): number {
|
|
426
|
-
|
|
427
|
-
|
|
594
|
+
const value = this.numericValue()
|
|
595
|
+
if (value !== null) {
|
|
596
|
+
return value
|
|
428
597
|
}
|
|
429
598
|
throw new Error(
|
|
430
599
|
'reflect: call of reflect.Value.Float on ' +
|
|
@@ -444,6 +613,23 @@ export class Value {
|
|
|
444
613
|
)
|
|
445
614
|
}
|
|
446
615
|
|
|
616
|
+
private numericValue(): number | null {
|
|
617
|
+
if (typeof this._value === 'number') {
|
|
618
|
+
return this._value
|
|
619
|
+
}
|
|
620
|
+
if (
|
|
621
|
+
this._value !== null &&
|
|
622
|
+
typeof this._value === 'object' &&
|
|
623
|
+
typeof (this._value as { valueOf?: unknown }).valueOf === 'function'
|
|
624
|
+
) {
|
|
625
|
+
const value = (this._value as { valueOf(): unknown }).valueOf()
|
|
626
|
+
if (typeof value === 'number') {
|
|
627
|
+
return value
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
return null
|
|
631
|
+
}
|
|
632
|
+
|
|
447
633
|
public String(): string {
|
|
448
634
|
if (typeof this._value === 'string') {
|
|
449
635
|
return this._value
|
|
@@ -456,6 +642,10 @@ export class Value {
|
|
|
456
642
|
}
|
|
457
643
|
|
|
458
644
|
public Len(): number {
|
|
645
|
+
if (this.Kind() === Slice || this.Kind() === Array) {
|
|
646
|
+
return $.len(this._value as any)
|
|
647
|
+
}
|
|
648
|
+
|
|
459
649
|
// Check for slice objects created by $.arrayToSlice
|
|
460
650
|
if (
|
|
461
651
|
this._value &&
|
|
@@ -519,8 +709,9 @@ export class Value {
|
|
|
519
709
|
}
|
|
520
710
|
|
|
521
711
|
public Index(i: number): Value {
|
|
522
|
-
if (
|
|
523
|
-
|
|
712
|
+
if (this.Kind() === Slice || this.Kind() === Array) {
|
|
713
|
+
const ref = $.indexRef(this._value as any, i) as $.VarRef<ReflectValue>
|
|
714
|
+
return new Value(ref.value, this._type.Elem(), ref)
|
|
524
715
|
}
|
|
525
716
|
throw new Error(
|
|
526
717
|
'reflect: call of reflect.Value.Index on ' +
|
|
@@ -576,6 +767,17 @@ export class Value {
|
|
|
576
767
|
const elemType = this._type.Elem()
|
|
577
768
|
return new Value(varRef.value, elemType, varRef)
|
|
578
769
|
}
|
|
770
|
+
if (
|
|
771
|
+
this._type.Kind() === Ptr &&
|
|
772
|
+
this._value &&
|
|
773
|
+
typeof this._value === 'object' &&
|
|
774
|
+
'__goValue' in this._value &&
|
|
775
|
+
$.isVarRef((this._value as { __goValue: unknown }).__goValue)
|
|
776
|
+
) {
|
|
777
|
+
const varRef = (this._value as { __goValue: $.VarRef<ReflectValue> })
|
|
778
|
+
.__goValue
|
|
779
|
+
return new Value(varRef.value, this._type.Elem(), varRef)
|
|
780
|
+
}
|
|
579
781
|
// For interfaces, return the underlying value
|
|
580
782
|
return new Value(this._value, this._type, this._parentVarRef)
|
|
581
783
|
}
|
|
@@ -590,17 +792,18 @@ export class Value {
|
|
|
590
792
|
}
|
|
591
793
|
|
|
592
794
|
const field = this.Type().Field(i)
|
|
795
|
+
const fieldKey = structFieldStorageKey(this.Type(), i)
|
|
593
796
|
if (!field) {
|
|
594
797
|
throw new Error('reflect: struct field index out of range')
|
|
595
798
|
}
|
|
596
799
|
|
|
597
800
|
const parentObj = this._value as Record<string, any>
|
|
598
|
-
let fieldVal = parentObj[
|
|
801
|
+
let fieldVal = parentObj[fieldKey]
|
|
599
802
|
if (fieldVal === undefined) {
|
|
600
803
|
fieldVal = null
|
|
601
804
|
}
|
|
602
805
|
// Pass parent struct and field name so Set() can update the struct
|
|
603
|
-
return new Value(fieldVal, field.Type, undefined, parentObj,
|
|
806
|
+
return new Value(fieldVal, field.Type, undefined, parentObj, fieldKey)
|
|
604
807
|
}
|
|
605
808
|
|
|
606
809
|
public FieldByIndex(index: $.Slice<number>): Value {
|
|
@@ -639,6 +842,9 @@ export class Value {
|
|
|
639
842
|
if (this._value === null || this._value === undefined) {
|
|
640
843
|
return 0
|
|
641
844
|
}
|
|
845
|
+
if ($.isOwnedPointerHandle(this._value)) {
|
|
846
|
+
return $.ownedPointerAddress(this._value)
|
|
847
|
+
}
|
|
642
848
|
if ($.isVarRef(this._value)) {
|
|
643
849
|
const address = this._value.__goAddress?.()
|
|
644
850
|
if (address !== undefined) {
|
|
@@ -663,12 +869,26 @@ export class Value {
|
|
|
663
869
|
return 0
|
|
664
870
|
}
|
|
665
871
|
|
|
666
|
-
public UnsafeAddr(): number |
|
|
872
|
+
public UnsafeAddr(): number | $.OwnedPointerHandle<ReflectValue> {
|
|
667
873
|
if (!this.CanAddr()) {
|
|
668
874
|
throw new ValueError({ Kind: this.Kind(), Method: 'UnsafeAddr' })
|
|
669
875
|
}
|
|
670
876
|
if (this._parentStruct && this._fieldName) {
|
|
671
|
-
|
|
877
|
+
const target = this._parentStruct
|
|
878
|
+
const key = this._fieldName
|
|
879
|
+
const ref = $.fieldRef(
|
|
880
|
+
target,
|
|
881
|
+
key as keyof typeof target,
|
|
882
|
+
) as $.VarRef<ReflectValue>
|
|
883
|
+
return {
|
|
884
|
+
__goOwnedPointer: true,
|
|
885
|
+
__goAddress: () => fieldPointerAddress(target, key),
|
|
886
|
+
__goRef: () => ref,
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
if (this._parentVarRef?.__goPointer) {
|
|
890
|
+
return this._parentVarRef
|
|
891
|
+
.__goPointer as $.OwnedPointerHandle<ReflectValue>
|
|
672
892
|
}
|
|
673
893
|
return this.Pointer()
|
|
674
894
|
}
|
|
@@ -704,6 +924,9 @@ export class Value {
|
|
|
704
924
|
if (this._parentStruct && this._fieldName) {
|
|
705
925
|
return new Value($.fieldRef(this._parentStruct, this._fieldName), ptrType)
|
|
706
926
|
}
|
|
927
|
+
if (this._parentVarRef) {
|
|
928
|
+
return new Value(this._parentVarRef, ptrType)
|
|
929
|
+
}
|
|
707
930
|
return new Value($.varRef(this._value), ptrType)
|
|
708
931
|
}
|
|
709
932
|
|
|
@@ -717,23 +940,9 @@ export class Value {
|
|
|
717
940
|
if (!this.CanSet()) {
|
|
718
941
|
throw new Error('reflect: assign to invalid value')
|
|
719
942
|
}
|
|
720
|
-
// Interface types can accept any value
|
|
721
|
-
if (this.Kind() === Interface) {
|
|
722
|
-
this._value = x.value
|
|
723
|
-
// Also update the parent VarRef if we were dereferenced from one
|
|
724
|
-
if (this._parentVarRef) {
|
|
725
|
-
this._parentVarRef.value = x.value
|
|
726
|
-
}
|
|
727
|
-
// Also update the parent struct field if this is a struct field
|
|
728
|
-
if (this._parentStruct && this._fieldName) {
|
|
729
|
-
this._parentStruct[this._fieldName] = x.value
|
|
730
|
-
}
|
|
731
|
-
return
|
|
732
|
-
}
|
|
733
|
-
// For other types, check if types are compatible (simplified check)
|
|
734
943
|
const thisType = this.Type()
|
|
735
944
|
const xType = x.Type()
|
|
736
|
-
if (
|
|
945
|
+
if (!xType.AssignableTo(thisType)) {
|
|
737
946
|
throw new Error('reflect: assign to wrong type')
|
|
738
947
|
}
|
|
739
948
|
this._value = x.value
|
|
@@ -768,22 +977,36 @@ export class Value {
|
|
|
768
977
|
if (typeof method !== 'function') {
|
|
769
978
|
return new Value()
|
|
770
979
|
}
|
|
771
|
-
|
|
980
|
+
const [signature] = methodSignatureByName(this.Type(), name)
|
|
981
|
+
const methodType =
|
|
982
|
+
signature ?
|
|
983
|
+
methodTypeFromSignature(signature, this.Type(), false)
|
|
984
|
+
: new FunctionType('func')
|
|
985
|
+
return new Value(method.bind(receiver), methodType)
|
|
772
986
|
}
|
|
773
987
|
|
|
774
|
-
public Call(inArgs: $.Slice<Value>):
|
|
988
|
+
public async Call(inArgs: $.Slice<Value>): Promise<$.Slice<Value>> {
|
|
775
989
|
if (this.Kind() !== Func || typeof this._value !== 'function') {
|
|
776
990
|
throw new ValueError({ Kind: this.Kind(), Method: 'Call' })
|
|
777
991
|
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
992
|
+
return await callReflectFunction(
|
|
993
|
+
this._value as (...args: unknown[]) => unknown,
|
|
994
|
+
this._type,
|
|
995
|
+
inArgs,
|
|
996
|
+
'Call',
|
|
997
|
+
)
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
public async CallSlice(inArgs: $.Slice<Value>): Promise<$.Slice<Value>> {
|
|
1001
|
+
if (this.Kind() !== Func || typeof this._value !== 'function') {
|
|
1002
|
+
throw new ValueError({ Kind: this.Kind(), Method: 'CallSlice' })
|
|
785
1003
|
}
|
|
786
|
-
return
|
|
1004
|
+
return await callReflectFunction(
|
|
1005
|
+
this._value as (...args: unknown[]) => unknown,
|
|
1006
|
+
this._type,
|
|
1007
|
+
inArgs,
|
|
1008
|
+
'CallSlice',
|
|
1009
|
+
)
|
|
787
1010
|
}
|
|
788
1011
|
|
|
789
1012
|
public IsZero(): boolean {
|
|
@@ -1118,10 +1341,7 @@ export class Value {
|
|
|
1118
1341
|
public Cap(): number {
|
|
1119
1342
|
const k = this.Kind()
|
|
1120
1343
|
if (k === Slice || k === Array) {
|
|
1121
|
-
|
|
1122
|
-
return this._value.length
|
|
1123
|
-
}
|
|
1124
|
-
return 0
|
|
1344
|
+
return $.cap(this._value as any)
|
|
1125
1345
|
}
|
|
1126
1346
|
if (k === Chan) {
|
|
1127
1347
|
return 0 // Simplified
|
|
@@ -1211,6 +1431,7 @@ export class BasicType implements Type {
|
|
|
1211
1431
|
private _name: string,
|
|
1212
1432
|
private _size: number = 8,
|
|
1213
1433
|
private _typeName: string = '',
|
|
1434
|
+
private _methods: $.MethodSignature[] = [],
|
|
1214
1435
|
) {}
|
|
1215
1436
|
|
|
1216
1437
|
public String(): string {
|
|
@@ -1221,6 +1442,10 @@ export class BasicType implements Type {
|
|
|
1221
1442
|
return this._kind
|
|
1222
1443
|
}
|
|
1223
1444
|
|
|
1445
|
+
public underlyingName(): string {
|
|
1446
|
+
return Kind_String(this._kind)
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1224
1449
|
public Comparable(): boolean {
|
|
1225
1450
|
return this._kind !== Func && this._kind !== Map && this._kind !== Slice
|
|
1226
1451
|
}
|
|
@@ -1237,6 +1462,26 @@ export class BasicType implements Type {
|
|
|
1237
1462
|
return 0
|
|
1238
1463
|
}
|
|
1239
1464
|
|
|
1465
|
+
public NumIn(): number {
|
|
1466
|
+
return nonFunctionTypePanic('NumIn', this)
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
public In(_i: number): Type {
|
|
1470
|
+
return nonFunctionTypePanic('In', this)
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
public NumOut(): number {
|
|
1474
|
+
return nonFunctionTypePanic('NumOut', this)
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
public Out(_i: number): Type {
|
|
1478
|
+
return nonFunctionTypePanic('Out', this)
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
public IsVariadic(): boolean {
|
|
1482
|
+
return nonFunctionTypePanic('IsVariadic', this)
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1240
1485
|
public PkgPath(): string {
|
|
1241
1486
|
if (this._typeName) {
|
|
1242
1487
|
const dotIndex = this._typeName.lastIndexOf('.')
|
|
@@ -1284,7 +1529,7 @@ export class BasicType implements Type {
|
|
|
1284
1529
|
if (u.Kind() !== Interface) {
|
|
1285
1530
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1286
1531
|
}
|
|
1287
|
-
return
|
|
1532
|
+
return typeImplementsInterface(this, u)
|
|
1288
1533
|
}
|
|
1289
1534
|
|
|
1290
1535
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1355,10 +1600,18 @@ export class BasicType implements Type {
|
|
|
1355
1600
|
}
|
|
1356
1601
|
|
|
1357
1602
|
public NumMethod(): number {
|
|
1358
|
-
return
|
|
1603
|
+
return typeMethods(this).length
|
|
1359
1604
|
}
|
|
1360
|
-
public MethodByName(
|
|
1361
|
-
return
|
|
1605
|
+
public MethodByName(name: string): [Method, boolean] {
|
|
1606
|
+
return typeMethodByName(this, name)
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
public methodSignatures(): $.MethodSignature[] {
|
|
1610
|
+
return this._methods
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
public mergeMethodSignatures(methods: $.MethodSignature[]): void {
|
|
1614
|
+
this._methods = mergeMethodSignatureList(this._methods, methods)
|
|
1362
1615
|
}
|
|
1363
1616
|
|
|
1364
1617
|
public Len(): number {
|
|
@@ -1432,6 +1685,26 @@ class SliceType implements Type {
|
|
|
1432
1685
|
return 0
|
|
1433
1686
|
}
|
|
1434
1687
|
|
|
1688
|
+
public NumIn(): number {
|
|
1689
|
+
return nonFunctionTypePanic('NumIn', this)
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
public In(_i: number): Type {
|
|
1693
|
+
return nonFunctionTypePanic('In', this)
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
public NumOut(): number {
|
|
1697
|
+
return nonFunctionTypePanic('NumOut', this)
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
public Out(_i: number): Type {
|
|
1701
|
+
return nonFunctionTypePanic('Out', this)
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
public IsVariadic(): boolean {
|
|
1705
|
+
return nonFunctionTypePanic('IsVariadic', this)
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1435
1708
|
public PkgPath(): string {
|
|
1436
1709
|
return ''
|
|
1437
1710
|
}
|
|
@@ -1466,7 +1739,7 @@ class SliceType implements Type {
|
|
|
1466
1739
|
if (u.Kind() !== Interface) {
|
|
1467
1740
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1468
1741
|
}
|
|
1469
|
-
return
|
|
1742
|
+
return typeImplementsInterface(this, u)
|
|
1470
1743
|
}
|
|
1471
1744
|
|
|
1472
1745
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1532,6 +1805,26 @@ class ArrayType implements Type {
|
|
|
1532
1805
|
return 0
|
|
1533
1806
|
}
|
|
1534
1807
|
|
|
1808
|
+
public NumIn(): number {
|
|
1809
|
+
return nonFunctionTypePanic('NumIn', this)
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
public In(_i: number): Type {
|
|
1813
|
+
return nonFunctionTypePanic('In', this)
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
public NumOut(): number {
|
|
1817
|
+
return nonFunctionTypePanic('NumOut', this)
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
public Out(_i: number): Type {
|
|
1821
|
+
return nonFunctionTypePanic('Out', this)
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
public IsVariadic(): boolean {
|
|
1825
|
+
return nonFunctionTypePanic('IsVariadic', this)
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1535
1828
|
public Len(): number {
|
|
1536
1829
|
return this._len
|
|
1537
1830
|
}
|
|
@@ -1570,7 +1863,7 @@ class ArrayType implements Type {
|
|
|
1570
1863
|
if (u.Kind() !== Interface) {
|
|
1571
1864
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1572
1865
|
}
|
|
1573
|
-
return
|
|
1866
|
+
return typeImplementsInterface(this, u)
|
|
1574
1867
|
}
|
|
1575
1868
|
|
|
1576
1869
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1607,7 +1900,10 @@ class ArrayType implements Type {
|
|
|
1607
1900
|
|
|
1608
1901
|
// Pointer type implementation
|
|
1609
1902
|
class PointerType implements Type {
|
|
1610
|
-
constructor(
|
|
1903
|
+
constructor(
|
|
1904
|
+
private _elemType: Type,
|
|
1905
|
+
private _methods: $.MethodSignature[] = [],
|
|
1906
|
+
) {}
|
|
1611
1907
|
|
|
1612
1908
|
public String(): string {
|
|
1613
1909
|
return '*' + this._elemType.String()
|
|
@@ -1633,6 +1929,26 @@ class PointerType implements Type {
|
|
|
1633
1929
|
return 0
|
|
1634
1930
|
}
|
|
1635
1931
|
|
|
1932
|
+
public NumIn(): number {
|
|
1933
|
+
return nonFunctionTypePanic('NumIn', this)
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
public In(_i: number): Type {
|
|
1937
|
+
return nonFunctionTypePanic('In', this)
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
public NumOut(): number {
|
|
1941
|
+
return nonFunctionTypePanic('NumOut', this)
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
public Out(_i: number): Type {
|
|
1945
|
+
return nonFunctionTypePanic('Out', this)
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
public IsVariadic(): boolean {
|
|
1949
|
+
return nonFunctionTypePanic('IsVariadic', this)
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1636
1952
|
public PkgPath(): string {
|
|
1637
1953
|
return ''
|
|
1638
1954
|
}
|
|
@@ -1667,9 +1983,7 @@ class PointerType implements Type {
|
|
|
1667
1983
|
if (u.Kind() !== Interface) {
|
|
1668
1984
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1669
1985
|
}
|
|
1670
|
-
|
|
1671
|
-
const elemTypeName = this._elemType.String()
|
|
1672
|
-
return typeImplementsInterface(elemTypeName, u)
|
|
1986
|
+
return typeImplementsInterface(this, u)
|
|
1673
1987
|
}
|
|
1674
1988
|
|
|
1675
1989
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1697,10 +2011,18 @@ class PointerType implements Type {
|
|
|
1697
2011
|
}
|
|
1698
2012
|
|
|
1699
2013
|
public NumMethod(): number {
|
|
1700
|
-
return
|
|
2014
|
+
return typeMethods(this).length
|
|
1701
2015
|
}
|
|
1702
2016
|
public MethodByName(name: string): [Method, boolean] {
|
|
1703
|
-
return typeMethodByName(this
|
|
2017
|
+
return typeMethodByName(this, name)
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
public methodSignatures(): $.MethodSignature[] {
|
|
2021
|
+
return this._methods
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
public mergeMethodSignatures(methods: $.MethodSignature[]): void {
|
|
2025
|
+
this._methods = mergeMethodSignatureList(this._methods, methods)
|
|
1704
2026
|
}
|
|
1705
2027
|
|
|
1706
2028
|
public Len(): number {
|
|
@@ -1713,10 +2035,54 @@ class PointerType implements Type {
|
|
|
1713
2035
|
}
|
|
1714
2036
|
|
|
1715
2037
|
// Function type implementation
|
|
2038
|
+
interface FunctionTypeDescriptor {
|
|
2039
|
+
name?: string
|
|
2040
|
+
signature?: string
|
|
2041
|
+
params?: Type[]
|
|
2042
|
+
results?: Type[]
|
|
2043
|
+
variadic?: boolean
|
|
2044
|
+
methods?: $.MethodSignature[]
|
|
2045
|
+
}
|
|
2046
|
+
|
|
1716
2047
|
class FunctionType implements Type {
|
|
1717
|
-
|
|
2048
|
+
private _name: string
|
|
2049
|
+
private _signature: string
|
|
2050
|
+
private _params: Type[]
|
|
2051
|
+
private _results: Type[]
|
|
2052
|
+
private _variadic: boolean
|
|
2053
|
+
private _hasSignature: boolean
|
|
2054
|
+
private _methods: $.MethodSignature[]
|
|
2055
|
+
|
|
2056
|
+
constructor(signatureOrDescriptor: string | FunctionTypeDescriptor) {
|
|
2057
|
+
if (typeof signatureOrDescriptor === 'string') {
|
|
2058
|
+
this._name = ''
|
|
2059
|
+
this._signature = signatureOrDescriptor
|
|
2060
|
+
this._params = []
|
|
2061
|
+
this._results = []
|
|
2062
|
+
this._variadic = false
|
|
2063
|
+
this._hasSignature = false
|
|
2064
|
+
this._methods = []
|
|
2065
|
+
return
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
this._name = signatureOrDescriptor.name ?? ''
|
|
2069
|
+
this._params = signatureOrDescriptor.params ?? []
|
|
2070
|
+
this._results = signatureOrDescriptor.results ?? []
|
|
2071
|
+
this._variadic = signatureOrDescriptor.variadic ?? false
|
|
2072
|
+
this._hasSignature =
|
|
2073
|
+
signatureOrDescriptor.signature !== undefined ||
|
|
2074
|
+
signatureOrDescriptor.params !== undefined ||
|
|
2075
|
+
signatureOrDescriptor.results !== undefined
|
|
2076
|
+
this._methods = signatureOrDescriptor.methods ?? []
|
|
2077
|
+
this._signature =
|
|
2078
|
+
signatureOrDescriptor.signature ??
|
|
2079
|
+
formatFunctionSignature(this._params, this._results, this._variadic)
|
|
2080
|
+
}
|
|
1718
2081
|
|
|
1719
2082
|
public String(): string {
|
|
2083
|
+
if (this._name !== '') {
|
|
2084
|
+
return this._name
|
|
2085
|
+
}
|
|
1720
2086
|
return this._signature
|
|
1721
2087
|
}
|
|
1722
2088
|
|
|
@@ -1740,12 +2106,54 @@ class FunctionType implements Type {
|
|
|
1740
2106
|
return 0
|
|
1741
2107
|
}
|
|
1742
2108
|
|
|
2109
|
+
public NumIn(): number {
|
|
2110
|
+
return this._params.length
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
public In(i: number): Type {
|
|
2114
|
+
if (i < 0 || i >= this._params.length) {
|
|
2115
|
+
throw new Error(
|
|
2116
|
+
`reflect: In index out of range [${i}] with length ${this._params.length}`,
|
|
2117
|
+
)
|
|
2118
|
+
}
|
|
2119
|
+
return this._params[i]
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
public NumOut(): number {
|
|
2123
|
+
return this._results.length
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
public Out(i: number): Type {
|
|
2127
|
+
if (i < 0 || i >= this._results.length) {
|
|
2128
|
+
throw new Error(
|
|
2129
|
+
`reflect: Out index out of range [${i}] with length ${this._results.length}`,
|
|
2130
|
+
)
|
|
2131
|
+
}
|
|
2132
|
+
return this._results[i]
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
public IsVariadic(): boolean {
|
|
2136
|
+
return this._variadic
|
|
2137
|
+
}
|
|
2138
|
+
|
|
1743
2139
|
public PkgPath(): string {
|
|
2140
|
+
if (this._name !== '') {
|
|
2141
|
+
const dotIndex = this._name.lastIndexOf('.')
|
|
2142
|
+
if (dotIndex > 0) {
|
|
2143
|
+
return this._name.substring(0, dotIndex)
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
1744
2146
|
return ''
|
|
1745
2147
|
}
|
|
1746
2148
|
|
|
1747
2149
|
public Name(): string {
|
|
1748
|
-
|
|
2150
|
+
if (this._name !== '') {
|
|
2151
|
+
const dotIndex = this._name.lastIndexOf('.')
|
|
2152
|
+
if (dotIndex >= 0) {
|
|
2153
|
+
return this._name.substring(dotIndex + 1)
|
|
2154
|
+
}
|
|
2155
|
+
return this._name
|
|
2156
|
+
}
|
|
1749
2157
|
return ''
|
|
1750
2158
|
}
|
|
1751
2159
|
|
|
@@ -1774,7 +2182,7 @@ class FunctionType implements Type {
|
|
|
1774
2182
|
if (u.Kind() !== Interface) {
|
|
1775
2183
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1776
2184
|
}
|
|
1777
|
-
return
|
|
2185
|
+
return typeImplementsInterface(this, u)
|
|
1778
2186
|
}
|
|
1779
2187
|
|
|
1780
2188
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1798,10 +2206,29 @@ class FunctionType implements Type {
|
|
|
1798
2206
|
}
|
|
1799
2207
|
|
|
1800
2208
|
public NumMethod(): number {
|
|
1801
|
-
return
|
|
2209
|
+
return typeMethods(this).length
|
|
1802
2210
|
}
|
|
1803
|
-
public MethodByName(
|
|
1804
|
-
return
|
|
2211
|
+
public MethodByName(name: string): [Method, boolean] {
|
|
2212
|
+
return typeMethodByName(this, name)
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
public methodSignatures(): $.MethodSignature[] {
|
|
2216
|
+
return this._methods
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
public mergeMethodSignatures(methods: $.MethodSignature[]): void {
|
|
2220
|
+
this._methods = mergeMethodSignatureList(this._methods, methods)
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
public mergeSignature(source: FunctionType): void {
|
|
2224
|
+
if (!source._hasSignature || this._hasSignature) {
|
|
2225
|
+
return
|
|
2226
|
+
}
|
|
2227
|
+
this._params = source._params
|
|
2228
|
+
this._results = source._results
|
|
2229
|
+
this._variadic = source._variadic
|
|
2230
|
+
this._signature = source._signature
|
|
2231
|
+
this._hasSignature = true
|
|
1805
2232
|
}
|
|
1806
2233
|
|
|
1807
2234
|
public Len(): number {
|
|
@@ -1813,59 +2240,316 @@ class FunctionType implements Type {
|
|
|
1813
2240
|
}
|
|
1814
2241
|
}
|
|
1815
2242
|
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
) {
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
2243
|
+
function formatFunctionSignature(
|
|
2244
|
+
params: Type[],
|
|
2245
|
+
results: Type[],
|
|
2246
|
+
variadic: boolean,
|
|
2247
|
+
): string {
|
|
2248
|
+
const paramStrings = params.map((param, index) => {
|
|
2249
|
+
const typeName = param.String()
|
|
2250
|
+
if (!variadic || index !== params.length - 1) {
|
|
2251
|
+
return typeName
|
|
2252
|
+
}
|
|
2253
|
+
if (typeName.startsWith('[]')) {
|
|
2254
|
+
return '...' + typeName.slice(2)
|
|
2255
|
+
}
|
|
2256
|
+
return '...' + typeName
|
|
2257
|
+
})
|
|
2258
|
+
let signature = `func(${paramStrings.join(', ')})`
|
|
2259
|
+
if (results.length === 1) {
|
|
2260
|
+
signature += ` ${results[0].String()}`
|
|
2261
|
+
} else if (results.length > 1) {
|
|
2262
|
+
signature += ` (${results.map((result) => result.String()).join(', ')})`
|
|
1825
2263
|
}
|
|
2264
|
+
return signature
|
|
2265
|
+
}
|
|
1826
2266
|
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
2267
|
+
async function callReflectFunction(
|
|
2268
|
+
fn: (...args: unknown[]) => unknown | Promise<unknown>,
|
|
2269
|
+
fnType: Type,
|
|
2270
|
+
inArgs: $.Slice<Value>,
|
|
2271
|
+
op: ReflectCallOp,
|
|
2272
|
+
): Promise<$.Slice<Value>> {
|
|
2273
|
+
const args = $.asArray(inArgs)
|
|
2274
|
+
const rawArgs = reflectCallRawArgs(fnType, args, op)
|
|
2275
|
+
const result = await fn(...rawArgs)
|
|
2276
|
+
return normalizeReflectCallResults(fnType, result)
|
|
2277
|
+
}
|
|
1830
2278
|
|
|
1831
|
-
|
|
1832
|
-
return false
|
|
1833
|
-
}
|
|
2279
|
+
type ReflectCallOp = 'Call' | 'CallSlice'
|
|
1834
2280
|
|
|
1835
|
-
|
|
1836
|
-
|
|
2281
|
+
function reflectCallRawArgs(
|
|
2282
|
+
fnType: Type,
|
|
2283
|
+
args: Value[],
|
|
2284
|
+
op: ReflectCallOp,
|
|
2285
|
+
): unknown[] {
|
|
2286
|
+
if (op === 'CallSlice') {
|
|
2287
|
+
return reflectCallSliceRawArgs(fnType, args)
|
|
1837
2288
|
}
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
return
|
|
2289
|
+
if (!fnType.IsVariadic()) {
|
|
2290
|
+
validateReflectCallInputCount(fnType, args.length)
|
|
2291
|
+
return args.map((arg, index) =>
|
|
2292
|
+
reflectCallValueInterface(op, arg, fnType.In(index), index),
|
|
2293
|
+
)
|
|
1841
2294
|
}
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
2295
|
+
const fixedCount = fnType.NumIn() - 1
|
|
2296
|
+
if (args.length < fixedCount) {
|
|
2297
|
+
throw new Error('reflect: Call with too few input arguments')
|
|
1845
2298
|
}
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
2299
|
+
const rawArgs: unknown[] = []
|
|
2300
|
+
for (let i = 0; i < fixedCount; i++) {
|
|
2301
|
+
rawArgs.push(reflectCallValueInterface(op, args[i], fnType.In(i), i))
|
|
1849
2302
|
}
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
2303
|
+
const variadicElemType = fnType.In(fixedCount).Elem()
|
|
2304
|
+
const variadicValues = args.slice(fixedCount)
|
|
2305
|
+
for (let i = 0; i < variadicValues.length; i++) {
|
|
2306
|
+
const value = variadicValues[i]
|
|
2307
|
+
if (!value.IsValid()) {
|
|
2308
|
+
throw new Error(`reflect: ${op} using zero Value argument`)
|
|
2309
|
+
}
|
|
2310
|
+
if (!value.Type().AssignableTo(variadicElemType)) {
|
|
2311
|
+
throw new Error(
|
|
2312
|
+
`reflect: cannot use ${value.Type().String()} as type ${variadicElemType.String()} in ${op}`,
|
|
2313
|
+
)
|
|
2314
|
+
}
|
|
1853
2315
|
}
|
|
2316
|
+
rawArgs.push($.arrayToSlice(variadicValues.map((value) => value.Interface())))
|
|
2317
|
+
return rawArgs
|
|
2318
|
+
}
|
|
1854
2319
|
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
2320
|
+
function reflectCallSliceRawArgs(fnType: Type, args: Value[]): unknown[] {
|
|
2321
|
+
if (!fnType.IsVariadic()) {
|
|
2322
|
+
throw new Error('reflect: CallSlice of non-variadic function')
|
|
1858
2323
|
}
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
throw new Error('reflect:
|
|
2324
|
+
const expected = fnType.NumIn()
|
|
2325
|
+
if (args.length < expected) {
|
|
2326
|
+
throw new Error('reflect: CallSlice with too few input arguments')
|
|
1862
2327
|
}
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
return typeFieldByName(this, name)
|
|
2328
|
+
if (args.length > expected) {
|
|
2329
|
+
throw new Error('reflect: CallSlice with too many input arguments')
|
|
1866
2330
|
}
|
|
2331
|
+
return args.map((arg, index) =>
|
|
2332
|
+
reflectCallValueInterface('CallSlice', arg, fnType.In(index), index),
|
|
2333
|
+
)
|
|
2334
|
+
}
|
|
1867
2335
|
|
|
1868
|
-
|
|
2336
|
+
function reflectCallValueInterface(
|
|
2337
|
+
op: ReflectCallOp,
|
|
2338
|
+
value: Value,
|
|
2339
|
+
target: Type,
|
|
2340
|
+
_index: number,
|
|
2341
|
+
): unknown {
|
|
2342
|
+
if (!value.IsValid()) {
|
|
2343
|
+
throw new Error(`reflect: ${op} using zero Value argument`)
|
|
2344
|
+
}
|
|
2345
|
+
if (!value.Type().AssignableTo(target)) {
|
|
2346
|
+
throw new Error(
|
|
2347
|
+
`reflect: ${op} using ${value.Type().String()} as type ${target.String()}`,
|
|
2348
|
+
)
|
|
2349
|
+
}
|
|
2350
|
+
return value.Interface()
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2353
|
+
function validateReflectCallInputCount(fnType: Type, actual: number): void {
|
|
2354
|
+
const expected = fnType.NumIn()
|
|
2355
|
+
if (actual !== expected) {
|
|
2356
|
+
throw new Error(
|
|
2357
|
+
`reflect: Call with ${actual} input arguments for function with ${expected} inputs`,
|
|
2358
|
+
)
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
function normalizeReflectCallResults(
|
|
2363
|
+
fnType: Type,
|
|
2364
|
+
result: unknown,
|
|
2365
|
+
): $.Slice<Value> {
|
|
2366
|
+
const expected = fnType.NumOut()
|
|
2367
|
+
if (expected === 0) {
|
|
2368
|
+
if (result !== undefined) {
|
|
2369
|
+
throw new Error(
|
|
2370
|
+
'reflect: Call returned 1 results for function with 0 outputs',
|
|
2371
|
+
)
|
|
2372
|
+
}
|
|
2373
|
+
return $.makeSlice<Value>(0)
|
|
2374
|
+
}
|
|
2375
|
+
if (expected === 1) {
|
|
2376
|
+
return $.arrayToSlice([new Value(result as ReflectValue, fnType.Out(0))])
|
|
2377
|
+
}
|
|
2378
|
+
if (!globalThis.Array.isArray(result)) {
|
|
2379
|
+
throw new Error(
|
|
2380
|
+
`reflect: Call returned 1 results for function with ${expected} outputs`,
|
|
2381
|
+
)
|
|
2382
|
+
}
|
|
2383
|
+
if (result.length !== expected) {
|
|
2384
|
+
throw new Error(
|
|
2385
|
+
`reflect: Call returned ${result.length} results for function with ${expected} outputs`,
|
|
2386
|
+
)
|
|
2387
|
+
}
|
|
2388
|
+
return $.arrayToSlice(
|
|
2389
|
+
result.map(
|
|
2390
|
+
(value, index) => new Value(value as ReflectValue, fnType.Out(index)),
|
|
2391
|
+
),
|
|
2392
|
+
)
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
export function MakeFunc(
|
|
2396
|
+
typ: Type | null,
|
|
2397
|
+
fn:
|
|
2398
|
+
| ((args: $.Slice<Value>) => $.Slice<Value> | Promise<$.Slice<Value>>)
|
|
2399
|
+
| null,
|
|
2400
|
+
): Value {
|
|
2401
|
+
if (!typ || typ.Kind() !== Func) {
|
|
2402
|
+
throw new Error('reflect: call of MakeFunc with non-Func type')
|
|
2403
|
+
}
|
|
2404
|
+
if (typeof fn !== 'function') {
|
|
2405
|
+
throw new Error('reflect.MakeFunc: nil implementation')
|
|
2406
|
+
}
|
|
2407
|
+
const typeInfo = functionTypeInfoFromType(typ)
|
|
2408
|
+
const wrapper = $.functionValue(async (...rawArgs: unknown[]) => {
|
|
2409
|
+
const args = makeFuncArgs(typ, rawArgs)
|
|
2410
|
+
const resultValues = $.asArray(await fn($.arrayToSlice(args)))
|
|
2411
|
+
validateMakeFuncResults(typ, resultValues)
|
|
2412
|
+
if (typ.NumOut() === 0) {
|
|
2413
|
+
return undefined
|
|
2414
|
+
}
|
|
2415
|
+
if (typ.NumOut() === 1) {
|
|
2416
|
+
return makeFuncReturnInterface(resultValues[0], typ.Out(0))
|
|
2417
|
+
}
|
|
2418
|
+
return resultValues.map((value, index) =>
|
|
2419
|
+
makeFuncReturnInterface(value, typ.Out(index)),
|
|
2420
|
+
)
|
|
2421
|
+
}, typeInfo)
|
|
2422
|
+
return new Value(wrapper, typ)
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
function makeFuncArgs(typ: Type, rawArgs: unknown[]): Value[] {
|
|
2426
|
+
validateReflectCallInputCount(typ, rawArgs.length)
|
|
2427
|
+
return rawArgs.map((arg, index) => {
|
|
2428
|
+
const value = ValueOf(arg as ReflectValue)
|
|
2429
|
+
const target = typ.In(index)
|
|
2430
|
+
if (!value.Type().AssignableTo(target)) {
|
|
2431
|
+
throw new Error(
|
|
2432
|
+
`reflect.MakeFunc: cannot use ${value.Type().String()} as type ${target.String()} in argument ${index}`,
|
|
2433
|
+
)
|
|
2434
|
+
}
|
|
2435
|
+
return value
|
|
2436
|
+
})
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
function validateMakeFuncResults(typ: Type, resultValues: Value[]): void {
|
|
2440
|
+
const expected = typ.NumOut()
|
|
2441
|
+
if (resultValues.length !== expected) {
|
|
2442
|
+
throw new Error(
|
|
2443
|
+
`reflect.MakeFunc: returned ${resultValues.length} results for function with ${expected} outputs`,
|
|
2444
|
+
)
|
|
2445
|
+
}
|
|
2446
|
+
for (let i = 0; i < resultValues.length; i++) {
|
|
2447
|
+
const result = resultValues[i]
|
|
2448
|
+
if (!result.IsValid()) {
|
|
2449
|
+
throw new Error(`reflect.MakeFunc: returned zero Value for result ${i}`)
|
|
2450
|
+
}
|
|
2451
|
+
const target = typ.Out(i)
|
|
2452
|
+
if (!result.Type().AssignableTo(target)) {
|
|
2453
|
+
throw new Error(
|
|
2454
|
+
`reflect.MakeFunc: cannot use ${result.Type().String()} as type ${target.String()} in result ${i}`,
|
|
2455
|
+
)
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
function makeFuncReturnInterface(value: Value, target: Type): unknown {
|
|
2461
|
+
const raw = value.Interface()
|
|
2462
|
+
if (target.Kind() === Interface) {
|
|
2463
|
+
return raw
|
|
2464
|
+
}
|
|
2465
|
+
return unwrapGoInterfaceBox(raw)
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
function unwrapGoInterfaceBox(value: unknown): unknown {
|
|
2469
|
+
if (
|
|
2470
|
+
value !== null &&
|
|
2471
|
+
value !== undefined &&
|
|
2472
|
+
typeof value === 'object' &&
|
|
2473
|
+
'__goValue' in value
|
|
2474
|
+
) {
|
|
2475
|
+
return (value as { __goValue: unknown }).__goValue
|
|
2476
|
+
}
|
|
2477
|
+
return value
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
// Map type implementation
|
|
2481
|
+
class MapType implements Type {
|
|
2482
|
+
constructor(
|
|
2483
|
+
private _keyType: Type,
|
|
2484
|
+
private _elemType: Type,
|
|
2485
|
+
) {}
|
|
2486
|
+
|
|
2487
|
+
public String(): string {
|
|
2488
|
+
return `map[${this._keyType.String()}]${this._elemType.String()}`
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
public Kind(): Kind {
|
|
2492
|
+
return Map
|
|
2493
|
+
}
|
|
2494
|
+
|
|
2495
|
+
public Comparable(): boolean {
|
|
2496
|
+
return false
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
public Size(): number {
|
|
2500
|
+
return 8 // map header size
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
public Elem(): Type {
|
|
2504
|
+
return this._elemType
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
public NumField(): number {
|
|
2508
|
+
return 0
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
public NumIn(): number {
|
|
2512
|
+
return nonFunctionTypePanic('NumIn', this)
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
public In(_i: number): Type {
|
|
2516
|
+
return nonFunctionTypePanic('In', this)
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2519
|
+
public NumOut(): number {
|
|
2520
|
+
return nonFunctionTypePanic('NumOut', this)
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
public Out(_i: number): Type {
|
|
2524
|
+
return nonFunctionTypePanic('Out', this)
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
public IsVariadic(): boolean {
|
|
2528
|
+
return nonFunctionTypePanic('IsVariadic', this)
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
public Key(): Type {
|
|
2532
|
+
return this._keyType
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
public PkgPath(): string {
|
|
2536
|
+
return ''
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
public Name(): string {
|
|
2540
|
+
// Map types are unnamed composite types
|
|
2541
|
+
return ''
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
public Field(_i: number): StructField {
|
|
2545
|
+
throw new Error('reflect: Field of non-struct type')
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
public FieldByName(name: string): [StructField, boolean] {
|
|
2549
|
+
return typeFieldByName(this, name)
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
public FieldByNameFunc(
|
|
1869
2553
|
match: (name: string) => boolean,
|
|
1870
2554
|
): [StructField, boolean] {
|
|
1871
2555
|
return typeFieldByNameFunc(this, match)
|
|
@@ -1878,7 +2562,7 @@ class MapType implements Type {
|
|
|
1878
2562
|
if (u.Kind() !== Interface) {
|
|
1879
2563
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1880
2564
|
}
|
|
1881
|
-
return
|
|
2565
|
+
return typeImplementsInterface(this, u)
|
|
1882
2566
|
}
|
|
1883
2567
|
|
|
1884
2568
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1918,61 +2602,174 @@ class MapType implements Type {
|
|
|
1918
2602
|
}
|
|
1919
2603
|
|
|
1920
2604
|
// Struct type implementation
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
*
|
|
1925
|
-
* @param typeName The name of the type to check (e.g., "main.MyType")
|
|
1926
|
-
* @param interfaceType The interface type that must be implemented
|
|
1927
|
-
* @returns True if the type implements the interface, false otherwise
|
|
1928
|
-
*/
|
|
1929
|
-
function typeImplementsInterface(
|
|
1930
|
-
typeName: string,
|
|
1931
|
-
interfaceType: Type,
|
|
1932
|
-
): boolean {
|
|
1933
|
-
// Get the interface name and look it up in the type registry
|
|
1934
|
-
const interfaceName =
|
|
1935
|
-
interfaceType instanceof InterfaceType ?
|
|
1936
|
-
interfaceType.registeredName() || interfaceType.String()
|
|
1937
|
-
: interfaceType.String()
|
|
1938
|
-
const interfaceTypeInfo = builtinGetTypeByName(interfaceName)
|
|
1939
|
-
|
|
1940
|
-
if (!interfaceTypeInfo || !isInterfaceTypeInfo(interfaceTypeInfo)) {
|
|
1941
|
-
return false
|
|
2605
|
+
function typeImplementsInterface(t: Type, interfaceType: Type): boolean {
|
|
2606
|
+
if (interfaceType.Kind() !== Interface) {
|
|
2607
|
+
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1942
2608
|
}
|
|
2609
|
+
const requiredMethods = typeMethods(interfaceType)
|
|
2610
|
+
if (requiredMethods.length === 0) {
|
|
2611
|
+
return true
|
|
2612
|
+
}
|
|
2613
|
+
const methods = typeMethods(t)
|
|
2614
|
+
return requiredMethods.every((requiredMethod) => {
|
|
2615
|
+
const method = methods.find(
|
|
2616
|
+
(candidate) => candidate.name === requiredMethod.name,
|
|
2617
|
+
)
|
|
2618
|
+
return (
|
|
2619
|
+
method !== undefined && methodSignatureIdentical(method, requiredMethod)
|
|
2620
|
+
)
|
|
2621
|
+
})
|
|
2622
|
+
}
|
|
1943
2623
|
|
|
1944
|
-
|
|
1945
|
-
|
|
2624
|
+
function methodSignatureIdentical(
|
|
2625
|
+
actual: $.MethodSignature,
|
|
2626
|
+
required: $.MethodSignature,
|
|
2627
|
+
): boolean {
|
|
2628
|
+
return (
|
|
2629
|
+
methodArgListIdentical(actual.args, required.args) &&
|
|
2630
|
+
methodArgListIdentical(actual.returns, required.returns)
|
|
2631
|
+
)
|
|
2632
|
+
}
|
|
1946
2633
|
|
|
1947
|
-
|
|
2634
|
+
function methodArgListIdentical(
|
|
2635
|
+
actual: $.MethodArg[],
|
|
2636
|
+
required: $.MethodArg[],
|
|
2637
|
+
): boolean {
|
|
2638
|
+
if (actual.length !== required.length) {
|
|
1948
2639
|
return false
|
|
1949
2640
|
}
|
|
2641
|
+
return actual.every(
|
|
2642
|
+
(arg, index) =>
|
|
2643
|
+
methodArgIdentityKey(arg) === methodArgIdentityKey(required[index]),
|
|
2644
|
+
)
|
|
2645
|
+
}
|
|
1950
2646
|
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
2647
|
+
function methodArgIdentityKey(arg: $.MethodArg): string {
|
|
2648
|
+
return typeInfoIdentityKey(arg.type, new Set())
|
|
2649
|
+
}
|
|
1954
2650
|
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
2651
|
+
function methodSignatureIdentityKey(method: $.MethodSignature): string {
|
|
2652
|
+
const args = method.args.map(methodArgIdentityKey).join(',')
|
|
2653
|
+
const returns = method.returns.map(methodArgIdentityKey).join(',')
|
|
2654
|
+
return `${method.name}(${args})(${returns})`
|
|
2655
|
+
}
|
|
1958
2656
|
|
|
1959
|
-
|
|
1960
|
-
|
|
2657
|
+
function mergeMethodSignatureList(
|
|
2658
|
+
existing: $.MethodSignature[],
|
|
2659
|
+
incoming: $.MethodSignature[],
|
|
2660
|
+
): $.MethodSignature[] {
|
|
2661
|
+
if (incoming.length === 0) {
|
|
2662
|
+
return existing
|
|
2663
|
+
}
|
|
2664
|
+
const merged = [...existing]
|
|
2665
|
+
for (const method of incoming) {
|
|
2666
|
+
const existingIndex = merged.findIndex(
|
|
2667
|
+
(candidate) => candidate.name === method.name,
|
|
2668
|
+
)
|
|
2669
|
+
if (existingIndex === -1) {
|
|
2670
|
+
merged.push(method)
|
|
2671
|
+
continue
|
|
1961
2672
|
}
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
2673
|
+
if (
|
|
2674
|
+
methodSignatureIdentityKey(merged[existingIndex]) !==
|
|
2675
|
+
methodSignatureIdentityKey(method)
|
|
2676
|
+
) {
|
|
2677
|
+
merged[existingIndex] = method
|
|
1966
2678
|
}
|
|
2679
|
+
}
|
|
2680
|
+
return merged.sort((left, right) => left.name.localeCompare(right.name))
|
|
2681
|
+
}
|
|
1967
2682
|
|
|
1968
|
-
|
|
1969
|
-
|
|
2683
|
+
function typeInfoIdentityKey(
|
|
2684
|
+
info: $.TypeInfo | string,
|
|
2685
|
+
seen: Set<string>,
|
|
2686
|
+
): string {
|
|
2687
|
+
if (typeof info === 'string') {
|
|
2688
|
+
const registered = builtinGetTypeByName(info)
|
|
2689
|
+
if (!registered) {
|
|
2690
|
+
return `named:${info}`
|
|
1970
2691
|
}
|
|
1971
|
-
|
|
1972
|
-
|
|
2692
|
+
const registeredName = registered.name ?? info
|
|
2693
|
+
if (registeredName !== '') {
|
|
2694
|
+
return `named:${registeredName}`
|
|
2695
|
+
}
|
|
2696
|
+
if (seen.has(info)) {
|
|
2697
|
+
return `named:${info}`
|
|
2698
|
+
}
|
|
2699
|
+
seen.add(info)
|
|
2700
|
+
const key = typeInfoIdentityKey(registered, seen)
|
|
2701
|
+
seen.delete(info)
|
|
2702
|
+
return key
|
|
2703
|
+
}
|
|
2704
|
+
switch (info.kind) {
|
|
2705
|
+
case $.TypeKind.Basic:
|
|
2706
|
+
if (info.typeName) {
|
|
2707
|
+
return `named:${info.typeName}`
|
|
2708
|
+
}
|
|
2709
|
+
return `basic:${info.name ?? 'unknown'}`
|
|
2710
|
+
case $.TypeKind.Interface:
|
|
2711
|
+
if (info.name) {
|
|
2712
|
+
return `named:${info.name}`
|
|
2713
|
+
}
|
|
2714
|
+
return `interface:${(info.methods ?? [])
|
|
2715
|
+
.map(methodSignatureIdentityKey)
|
|
2716
|
+
.join('|')}`
|
|
2717
|
+
case $.TypeKind.Struct:
|
|
2718
|
+
if (info.name) {
|
|
2719
|
+
return `named:${info.name}`
|
|
2720
|
+
}
|
|
2721
|
+
return `struct:${(info.fields ?? [])
|
|
2722
|
+
.map(
|
|
2723
|
+
(field) =>
|
|
2724
|
+
[
|
|
2725
|
+
field.name,
|
|
2726
|
+
field.pkgPath ?? '',
|
|
2727
|
+
field.tag ?? '',
|
|
2728
|
+
field.anonymous === true ? 'anonymous' : 'named',
|
|
2729
|
+
typeInfoIdentityKey(field.type, seen),
|
|
2730
|
+
].join('\u0000'),
|
|
2731
|
+
)
|
|
2732
|
+
.join('\u0001')}`
|
|
2733
|
+
case $.TypeKind.Pointer:
|
|
2734
|
+
return `ptr:${typeInfoIdentityKey(
|
|
2735
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
2736
|
+
seen,
|
|
2737
|
+
)}`
|
|
2738
|
+
case $.TypeKind.Slice:
|
|
2739
|
+
return `slice:${typeInfoIdentityKey(
|
|
2740
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
2741
|
+
seen,
|
|
2742
|
+
)}`
|
|
2743
|
+
case $.TypeKind.Array:
|
|
2744
|
+
return `array:${info.length}:${typeInfoIdentityKey(
|
|
2745
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
2746
|
+
seen,
|
|
2747
|
+
)}`
|
|
2748
|
+
case $.TypeKind.Map:
|
|
2749
|
+
return `map:${typeInfoIdentityKey(
|
|
2750
|
+
info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
2751
|
+
seen,
|
|
2752
|
+
)}:${typeInfoIdentityKey(
|
|
2753
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
2754
|
+
seen,
|
|
2755
|
+
)}`
|
|
2756
|
+
case $.TypeKind.Function:
|
|
2757
|
+
if (info.name) {
|
|
2758
|
+
return `named:${info.name}`
|
|
2759
|
+
}
|
|
2760
|
+
return `func:${info.isVariadic === true}:${(info.params ?? [])
|
|
2761
|
+
.map((param) => typeInfoIdentityKey(param, seen))
|
|
2762
|
+
.join(',')}:${(info.results ?? [])
|
|
2763
|
+
.map((result) => typeInfoIdentityKey(result, seen))
|
|
2764
|
+
.join(',')}`
|
|
2765
|
+
case $.TypeKind.Channel:
|
|
2766
|
+
return `chan:${info.direction ?? 'both'}:${typeInfoIdentityKey(
|
|
2767
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
2768
|
+
seen,
|
|
2769
|
+
)}`
|
|
2770
|
+
default:
|
|
2771
|
+
return 'unknown'
|
|
1973
2772
|
}
|
|
1974
|
-
|
|
1975
|
-
return true
|
|
1976
2773
|
}
|
|
1977
2774
|
|
|
1978
2775
|
function typeFieldByName(t: Type, name: string): [StructField, boolean] {
|
|
@@ -1986,8 +2783,7 @@ function typeFieldByNameFunc(
|
|
|
1986
2783
|
if (t.Kind() !== Struct) {
|
|
1987
2784
|
throw new Error('reflect: FieldByName of non-struct type')
|
|
1988
2785
|
}
|
|
1989
|
-
for (
|
|
1990
|
-
const field = t.Field(i)
|
|
2786
|
+
for (const field of visibleStructFields(t)) {
|
|
1991
2787
|
if (match(field.Name)) {
|
|
1992
2788
|
return [field, true]
|
|
1993
2789
|
}
|
|
@@ -1995,6 +2791,59 @@ function typeFieldByNameFunc(
|
|
|
1995
2791
|
return [new StructField(), false]
|
|
1996
2792
|
}
|
|
1997
2793
|
|
|
2794
|
+
export function visibleStructFields(t: Type): StructField[] {
|
|
2795
|
+
const fields: StructField[] = []
|
|
2796
|
+
const byName = new globalThis.Map<string, number>()
|
|
2797
|
+
const visiting = new Set<Type>()
|
|
2798
|
+
const index: number[] = []
|
|
2799
|
+
|
|
2800
|
+
const walk = (typ: Type): void => {
|
|
2801
|
+
if (visiting.has(typ)) {
|
|
2802
|
+
return
|
|
2803
|
+
}
|
|
2804
|
+
visiting.add(typ)
|
|
2805
|
+
for (let i = 0; i < typ.NumField(); i++) {
|
|
2806
|
+
const field = typ.Field(i).clone()
|
|
2807
|
+
index.push(i)
|
|
2808
|
+
|
|
2809
|
+
let add = true
|
|
2810
|
+
const oldIndex = byName.get(field.Name)
|
|
2811
|
+
if (oldIndex !== undefined) {
|
|
2812
|
+
const old = fields[oldIndex]
|
|
2813
|
+
if (index.length === old.Index.length) {
|
|
2814
|
+
old.Name = ''
|
|
2815
|
+
add = false
|
|
2816
|
+
} else if (index.length < old.Index.length) {
|
|
2817
|
+
old.Name = ''
|
|
2818
|
+
} else {
|
|
2819
|
+
add = false
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
if (add) {
|
|
2823
|
+
field.Index = [...index]
|
|
2824
|
+
byName.set(field.Name, fields.length)
|
|
2825
|
+
fields.push(field)
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2828
|
+
if (field.Anonymous) {
|
|
2829
|
+
let fieldType = field.Type
|
|
2830
|
+
if (fieldType.Kind() === Ptr) {
|
|
2831
|
+
fieldType = fieldType.Elem()
|
|
2832
|
+
}
|
|
2833
|
+
if (fieldType.Kind() === Struct) {
|
|
2834
|
+
walk(fieldType)
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2837
|
+
|
|
2838
|
+
index.pop()
|
|
2839
|
+
}
|
|
2840
|
+
visiting.delete(typ)
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2843
|
+
walk(t)
|
|
2844
|
+
return fields.filter((field) => field.Name !== '')
|
|
2845
|
+
}
|
|
2846
|
+
|
|
1998
2847
|
function zeroMethod(): Method {
|
|
1999
2848
|
return {
|
|
2000
2849
|
Name: '',
|
|
@@ -2007,17 +2856,65 @@ function zeroMethod(): Method {
|
|
|
2007
2856
|
function methodFromSignature(
|
|
2008
2857
|
signature: $.MethodSignature,
|
|
2009
2858
|
index: number,
|
|
2859
|
+
receiver: Type,
|
|
2010
2860
|
): Method {
|
|
2011
2861
|
return {
|
|
2012
2862
|
Name: signature.name,
|
|
2013
|
-
Type:
|
|
2863
|
+
Type: methodTypeFromSignature(
|
|
2864
|
+
signature,
|
|
2865
|
+
receiver,
|
|
2866
|
+
receiver.Kind() !== Interface,
|
|
2867
|
+
),
|
|
2014
2868
|
Func: () => undefined,
|
|
2015
2869
|
Index: index,
|
|
2016
2870
|
}
|
|
2017
2871
|
}
|
|
2018
2872
|
|
|
2873
|
+
function methodTypeFromSignature(
|
|
2874
|
+
signature: $.MethodSignature,
|
|
2875
|
+
receiver: Type,
|
|
2876
|
+
includeReceiver: boolean,
|
|
2877
|
+
): Type {
|
|
2878
|
+
const params = signature.args.map(methodArgType)
|
|
2879
|
+
if (includeReceiver) {
|
|
2880
|
+
params.unshift(receiver)
|
|
2881
|
+
}
|
|
2882
|
+
return new FunctionType({
|
|
2883
|
+
params,
|
|
2884
|
+
results: signature.returns.map(methodArgType),
|
|
2885
|
+
})
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2888
|
+
function methodArgType(arg: $.MethodArg): Type {
|
|
2889
|
+
return typeFromTypeInfoWithSeen(arg.type, new Set())
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2019
2892
|
function typeMethods(t: Type): $.MethodSignature[] {
|
|
2020
|
-
|
|
2893
|
+
let typeInfo = builtinGetTypeByName(t.String())
|
|
2894
|
+
if (!typeInfo && t.Kind() === Ptr) {
|
|
2895
|
+
typeInfo = builtinGetTypeByName(t.Elem().String())
|
|
2896
|
+
}
|
|
2897
|
+
if (!typeInfo && t instanceof InterfaceType) {
|
|
2898
|
+
const registeredName = t.registeredName()
|
|
2899
|
+
if (registeredName) {
|
|
2900
|
+
typeInfo = builtinGetTypeByName(registeredName)
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
if (!typeInfo && t instanceof InterfaceType) {
|
|
2904
|
+
return t.methodSignatures()
|
|
2905
|
+
}
|
|
2906
|
+
if (!typeInfo && t instanceof PointerType) {
|
|
2907
|
+
return mergeMethodSignatureList(
|
|
2908
|
+
typeMethods(t.Elem()),
|
|
2909
|
+
t.methodSignatures(),
|
|
2910
|
+
)
|
|
2911
|
+
}
|
|
2912
|
+
if (!typeInfo && t instanceof BasicType) {
|
|
2913
|
+
return t.methodSignatures()
|
|
2914
|
+
}
|
|
2915
|
+
if (!typeInfo && t instanceof FunctionType) {
|
|
2916
|
+
return t.methodSignatures()
|
|
2917
|
+
}
|
|
2021
2918
|
if (!typeInfo) {
|
|
2022
2919
|
return []
|
|
2023
2920
|
}
|
|
@@ -2027,30 +2924,119 @@ function typeMethods(t: Type): $.MethodSignature[] {
|
|
|
2027
2924
|
return []
|
|
2028
2925
|
}
|
|
2029
2926
|
|
|
2030
|
-
function
|
|
2927
|
+
function methodSignatureByName(
|
|
2928
|
+
t: Type,
|
|
2929
|
+
name: string,
|
|
2930
|
+
): [$.MethodSignature | undefined, number] {
|
|
2031
2931
|
const methods = typeMethods(t)
|
|
2032
2932
|
const index = methods.findIndex((method) => method.name === name)
|
|
2033
2933
|
if (index === -1) {
|
|
2934
|
+
return [undefined, -1]
|
|
2935
|
+
}
|
|
2936
|
+
return [methods[index], index]
|
|
2937
|
+
}
|
|
2938
|
+
|
|
2939
|
+
function typeMethodByName(t: Type, name: string): [Method, boolean] {
|
|
2940
|
+
const [signature, index] = methodSignatureByName(t, name)
|
|
2941
|
+
if (!signature) {
|
|
2034
2942
|
return [zeroMethod(), false]
|
|
2035
2943
|
}
|
|
2036
|
-
return [methodFromSignature(
|
|
2944
|
+
return [methodFromSignature(signature, index, t), true]
|
|
2037
2945
|
}
|
|
2038
2946
|
|
|
2039
2947
|
function typeAssignableTo(t: Type, u: Type | null): boolean {
|
|
2040
2948
|
if (u === null) {
|
|
2041
2949
|
return false
|
|
2042
2950
|
}
|
|
2043
|
-
|
|
2951
|
+
if (typeIdentityKey(t) === typeIdentityKey(u)) {
|
|
2952
|
+
return true
|
|
2953
|
+
}
|
|
2954
|
+
if (
|
|
2955
|
+
(!typeIsNamed(t) || !typeIsNamed(u)) &&
|
|
2956
|
+
typeUnderlyingIdentityKey(t) === typeUnderlyingIdentityKey(u)
|
|
2957
|
+
) {
|
|
2958
|
+
return true
|
|
2959
|
+
}
|
|
2960
|
+
if (u.Kind() !== Interface) {
|
|
2961
|
+
return false
|
|
2962
|
+
}
|
|
2963
|
+
return t.Implements(u)
|
|
2964
|
+
}
|
|
2965
|
+
|
|
2966
|
+
export function structFieldStorageKey(t: Type, i: number): string {
|
|
2967
|
+
if (t instanceof StructType) {
|
|
2968
|
+
return t.fieldKey(i)
|
|
2969
|
+
}
|
|
2970
|
+
return t.Field(i).Name
|
|
2971
|
+
}
|
|
2972
|
+
|
|
2973
|
+
interface StructFieldDescriptor {
|
|
2974
|
+
name: string
|
|
2975
|
+
key: string
|
|
2976
|
+
type: Type
|
|
2977
|
+
tag?: string
|
|
2978
|
+
pkgPath: string
|
|
2979
|
+
anonymous: boolean
|
|
2980
|
+
index: number[]
|
|
2981
|
+
offset: number
|
|
2982
|
+
exported: boolean
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
function typeAlignment(typ: Type): number {
|
|
2986
|
+
switch (typ.Kind()) {
|
|
2987
|
+
case Bool:
|
|
2988
|
+
case Int8:
|
|
2989
|
+
case Uint8:
|
|
2990
|
+
return 1
|
|
2991
|
+
case Int16:
|
|
2992
|
+
case Uint16:
|
|
2993
|
+
return 2
|
|
2994
|
+
case Int32:
|
|
2995
|
+
case Uint32:
|
|
2996
|
+
case Float32:
|
|
2997
|
+
case Complex64:
|
|
2998
|
+
return 4
|
|
2999
|
+
case Array:
|
|
3000
|
+
return typeAlignment(typ.Elem())
|
|
3001
|
+
case Struct: {
|
|
3002
|
+
let align = 1
|
|
3003
|
+
for (let i = 0; i < typ.NumField(); i++) {
|
|
3004
|
+
align = Math.max(align, typeAlignment(typ.Field(i).Type))
|
|
3005
|
+
}
|
|
3006
|
+
return align
|
|
3007
|
+
}
|
|
3008
|
+
default:
|
|
3009
|
+
return 8
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
|
|
3013
|
+
function alignOffset(offset: number, alignment: number): number {
|
|
3014
|
+
if (alignment <= 1) {
|
|
3015
|
+
return offset
|
|
3016
|
+
}
|
|
3017
|
+
return Math.ceil(offset / alignment) * alignment
|
|
3018
|
+
}
|
|
3019
|
+
|
|
3020
|
+
function structDescriptorSize(fields: StructFieldDescriptor[]): number {
|
|
3021
|
+
let size = 0
|
|
3022
|
+
let alignment = 1
|
|
3023
|
+
for (const field of fields) {
|
|
3024
|
+
alignment = Math.max(alignment, typeAlignment(field.type))
|
|
3025
|
+
size = Math.max(size, field.offset + field.type.Size())
|
|
3026
|
+
}
|
|
3027
|
+
return alignOffset(size, alignment)
|
|
2044
3028
|
}
|
|
2045
3029
|
|
|
2046
3030
|
class StructType implements Type {
|
|
2047
3031
|
constructor(
|
|
2048
3032
|
private _name: string,
|
|
2049
|
-
private _fields:
|
|
3033
|
+
private _fields: StructFieldDescriptor[] = [],
|
|
3034
|
+
private _pkgPath = '',
|
|
3035
|
+
private _string = _name,
|
|
2050
3036
|
) {}
|
|
2051
3037
|
|
|
2052
3038
|
public String(): string {
|
|
2053
|
-
return this.
|
|
3039
|
+
return this._string
|
|
2054
3040
|
}
|
|
2055
3041
|
|
|
2056
3042
|
public Kind(): Kind {
|
|
@@ -2062,8 +3048,7 @@ class StructType implements Type {
|
|
|
2062
3048
|
}
|
|
2063
3049
|
|
|
2064
3050
|
public Size(): number {
|
|
2065
|
-
|
|
2066
|
-
return this._fields.reduce((sum, field) => sum + field.type.Size(), 0)
|
|
3051
|
+
return structDescriptorSize(this._fields)
|
|
2067
3052
|
}
|
|
2068
3053
|
|
|
2069
3054
|
public Elem(): Type {
|
|
@@ -2074,7 +3059,33 @@ class StructType implements Type {
|
|
|
2074
3059
|
return this._fields.length
|
|
2075
3060
|
}
|
|
2076
3061
|
|
|
3062
|
+
public NumIn(): number {
|
|
3063
|
+
return nonFunctionTypePanic('NumIn', this)
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
public In(_i: number): Type {
|
|
3067
|
+
return nonFunctionTypePanic('In', this)
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
public NumOut(): number {
|
|
3071
|
+
return nonFunctionTypePanic('NumOut', this)
|
|
3072
|
+
}
|
|
3073
|
+
|
|
3074
|
+
public Out(_i: number): Type {
|
|
3075
|
+
return nonFunctionTypePanic('Out', this)
|
|
3076
|
+
}
|
|
3077
|
+
|
|
3078
|
+
public IsVariadic(): boolean {
|
|
3079
|
+
return nonFunctionTypePanic('IsVariadic', this)
|
|
3080
|
+
}
|
|
3081
|
+
|
|
2077
3082
|
public PkgPath(): string {
|
|
3083
|
+
if (this._pkgPath !== '') {
|
|
3084
|
+
return this._pkgPath
|
|
3085
|
+
}
|
|
3086
|
+
if (this._name === '') {
|
|
3087
|
+
return ''
|
|
3088
|
+
}
|
|
2078
3089
|
// Extract package path from full type name (e.g., "main.Person" -> "main")
|
|
2079
3090
|
const dotIndex = this._name.lastIndexOf('.')
|
|
2080
3091
|
if (dotIndex > 0) {
|
|
@@ -2084,6 +3095,9 @@ class StructType implements Type {
|
|
|
2084
3095
|
}
|
|
2085
3096
|
|
|
2086
3097
|
public Name(): string {
|
|
3098
|
+
if (this._name === '') {
|
|
3099
|
+
return ''
|
|
3100
|
+
}
|
|
2087
3101
|
// Extract type name from full type name (e.g., "main.Person" -> "Person")
|
|
2088
3102
|
const dotIndex = this._name.lastIndexOf('.')
|
|
2089
3103
|
if (dotIndex >= 0) {
|
|
@@ -2101,13 +3115,68 @@ class StructType implements Type {
|
|
|
2101
3115
|
const f = this._fields[i]
|
|
2102
3116
|
return new StructField({
|
|
2103
3117
|
Name: f.name,
|
|
2104
|
-
PkgPath:
|
|
3118
|
+
PkgPath: f.pkgPath,
|
|
2105
3119
|
Type: f.type,
|
|
2106
3120
|
Tag: f.tag ? new StructTag(f.tag) : undefined,
|
|
2107
|
-
|
|
3121
|
+
Offset: f.offset,
|
|
3122
|
+
Index: [...f.index],
|
|
3123
|
+
Anonymous: f.anonymous,
|
|
2108
3124
|
})
|
|
2109
3125
|
}
|
|
2110
3126
|
|
|
3127
|
+
public fieldKey(i: number): string {
|
|
3128
|
+
if (i < 0 || i >= this.NumField()) {
|
|
3129
|
+
throw new Error(
|
|
3130
|
+
`reflect: Field index out of range [${i}] with length ${this.NumField()}`,
|
|
3131
|
+
)
|
|
3132
|
+
}
|
|
3133
|
+
return this._fields[i].key
|
|
3134
|
+
}
|
|
3135
|
+
|
|
3136
|
+
public descriptors(): StructFieldDescriptor[] {
|
|
3137
|
+
return this._fields.map((field) => ({
|
|
3138
|
+
...field,
|
|
3139
|
+
index: [...field.index],
|
|
3140
|
+
}))
|
|
3141
|
+
}
|
|
3142
|
+
|
|
3143
|
+
public replaceDescriptors(fields: StructFieldDescriptor[]): void {
|
|
3144
|
+
this._fields = fields
|
|
3145
|
+
}
|
|
3146
|
+
|
|
3147
|
+
public identityKey(seen: Set<Type>): string {
|
|
3148
|
+
if (this._name !== '') {
|
|
3149
|
+
return `struct:${this._name}`
|
|
3150
|
+
}
|
|
3151
|
+
const fields = this._fields
|
|
3152
|
+
.map((field) =>
|
|
3153
|
+
[
|
|
3154
|
+
field.name,
|
|
3155
|
+
field.pkgPath,
|
|
3156
|
+
field.tag ?? '',
|
|
3157
|
+
field.anonymous ? 'anonymous' : 'named',
|
|
3158
|
+
typeIdentityKey(field.type, seen),
|
|
3159
|
+
].join('\u0000'),
|
|
3160
|
+
)
|
|
3161
|
+
.join('\u0001')
|
|
3162
|
+
return `struct:${this._pkgPath}:${this._name}:${fields}`
|
|
3163
|
+
}
|
|
3164
|
+
|
|
3165
|
+
public underlyingIdentityKey(seen: Set<Type>): string {
|
|
3166
|
+
const fields = this._fields
|
|
3167
|
+
.map((field) =>
|
|
3168
|
+
[
|
|
3169
|
+
field.name,
|
|
3170
|
+
field.pkgPath,
|
|
3171
|
+
field.tag ?? '',
|
|
3172
|
+
field.anonymous ? 'anonymous' : 'named',
|
|
3173
|
+
typeIdentityKey(field.type, seen),
|
|
3174
|
+
].join('\u0000'),
|
|
3175
|
+
)
|
|
3176
|
+
.join('\u0001')
|
|
3177
|
+
return `struct:${fields}`
|
|
3178
|
+
}
|
|
3179
|
+
|
|
2111
3180
|
public FieldByName(name: string): [StructField, boolean] {
|
|
2112
3181
|
return typeFieldByName(this, name)
|
|
2113
3182
|
}
|
|
@@ -2129,7 +3198,7 @@ class StructType implements Type {
|
|
|
2129
3198
|
if (u.Kind() !== Interface) {
|
|
2130
3199
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
2131
3200
|
}
|
|
2132
|
-
return typeImplementsInterface(this
|
|
3201
|
+
return typeImplementsInterface(this, u)
|
|
2133
3202
|
}
|
|
2134
3203
|
|
|
2135
3204
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -2170,82 +3239,42 @@ class StructType implements Type {
|
|
|
2170
3239
|
throw new Error('reflect: call of reflect.Type.Bits on struct Type')
|
|
2171
3240
|
}
|
|
2172
3241
|
|
|
2173
|
-
static createTypeFromFieldInfo(ti: any): Type {
|
|
3242
|
+
static createTypeFromFieldInfo(ti: any, seen = new Set<string>()): Type {
|
|
2174
3243
|
if (typeof ti === 'string') {
|
|
2175
|
-
|
|
2176
|
-
case 'string':
|
|
2177
|
-
return new BasicType(String, ti, 16)
|
|
2178
|
-
case 'int':
|
|
2179
|
-
case 'int32':
|
|
2180
|
-
case 'int64':
|
|
2181
|
-
case 'number':
|
|
2182
|
-
return new BasicType(Int, ti === 'number' ? 'int' : ti, 8)
|
|
2183
|
-
case 'bool':
|
|
2184
|
-
case 'boolean':
|
|
2185
|
-
return new BasicType(Bool, 'bool', 1)
|
|
2186
|
-
case 'float64':
|
|
2187
|
-
return new BasicType(Float64, ti, 8)
|
|
2188
|
-
case 'complex64':
|
|
2189
|
-
return new BasicType(Complex64, ti, 8)
|
|
2190
|
-
case 'complex128':
|
|
2191
|
-
return new BasicType(Complex128, ti, 16)
|
|
2192
|
-
case 'uint':
|
|
2193
|
-
case 'uint32':
|
|
2194
|
-
case 'uint64':
|
|
2195
|
-
return new BasicType(Uint, ti, 8)
|
|
2196
|
-
default:
|
|
2197
|
-
return new BasicType(Invalid, ti, 8)
|
|
2198
|
-
}
|
|
3244
|
+
return basicTypeFromName(ti === 'number' ? 'int' : ti)
|
|
2199
3245
|
} else if (ti && ti.kind) {
|
|
2200
3246
|
// Handle TypeInfo objects from the builtin type system
|
|
2201
3247
|
const name = ti.name || 'unknown'
|
|
2202
3248
|
const typeName = ti.typeName || ''
|
|
2203
3249
|
switch (ti.kind) {
|
|
2204
3250
|
case 'basic':
|
|
2205
|
-
|
|
2206
|
-
switch (name) {
|
|
2207
|
-
case 'string':
|
|
2208
|
-
return new BasicType(String, 'string', 16, typeName)
|
|
2209
|
-
case 'number':
|
|
2210
|
-
case 'int':
|
|
2211
|
-
case 'int32':
|
|
2212
|
-
case 'int64':
|
|
2213
|
-
return new BasicType(
|
|
2214
|
-
Int,
|
|
2215
|
-
name === 'number' ? 'int' : name,
|
|
2216
|
-
8,
|
|
2217
|
-
typeName,
|
|
2218
|
-
)
|
|
2219
|
-
case 'boolean':
|
|
2220
|
-
case 'bool':
|
|
2221
|
-
return new BasicType(Bool, 'bool', 1, typeName)
|
|
2222
|
-
case 'float64':
|
|
2223
|
-
return new BasicType(Float64, 'float64', 8, typeName)
|
|
2224
|
-
case 'complex64':
|
|
2225
|
-
return new BasicType(Complex64, 'complex64', 8, typeName)
|
|
2226
|
-
case 'complex128':
|
|
2227
|
-
return new BasicType(Complex128, 'complex128', 16, typeName)
|
|
2228
|
-
default:
|
|
2229
|
-
return new BasicType(Invalid, name, 8, typeName)
|
|
2230
|
-
}
|
|
3251
|
+
return basicTypeFromName(name === 'number' ? 'int' : name, typeName)
|
|
2231
3252
|
case 'slice':
|
|
2232
3253
|
if (ti.elemType) {
|
|
2233
3254
|
return new SliceType(
|
|
2234
|
-
StructType.createTypeFromFieldInfo(ti.elemType),
|
|
3255
|
+
StructType.createTypeFromFieldInfo(ti.elemType, seen),
|
|
2235
3256
|
)
|
|
2236
3257
|
}
|
|
2237
3258
|
return new SliceType(new BasicType(Invalid, 'unknown', 8))
|
|
2238
3259
|
case 'pointer':
|
|
2239
3260
|
if (ti.elemType) {
|
|
2240
3261
|
return new PointerType(
|
|
2241
|
-
StructType.createTypeFromFieldInfo(ti.elemType),
|
|
3262
|
+
StructType.createTypeFromFieldInfo(ti.elemType, seen),
|
|
2242
3263
|
)
|
|
2243
3264
|
}
|
|
2244
3265
|
return new PointerType(new BasicType(Invalid, 'unknown', 8))
|
|
2245
3266
|
case 'interface':
|
|
2246
|
-
return
|
|
2247
|
-
case 'struct':
|
|
2248
|
-
|
|
3267
|
+
return interfaceTypeFromInfo(ti, seen)
|
|
3268
|
+
case 'struct': {
|
|
3269
|
+
const structName = ti.name ?? ''
|
|
3270
|
+
const fields = structFieldsFromTypeInfo(ti, seen)
|
|
3271
|
+
return new StructType(
|
|
3272
|
+
structName,
|
|
3273
|
+
fields,
|
|
3274
|
+
'',
|
|
3275
|
+
structName === '' ? structTypeString(fields) : structName,
|
|
3276
|
+
)
|
|
3277
|
+
}
|
|
2249
3278
|
default:
|
|
2250
3279
|
return new BasicType(Invalid, name, 8)
|
|
2251
3280
|
}
|
|
@@ -2254,20 +3283,64 @@ class StructType implements Type {
|
|
|
2254
3283
|
}
|
|
2255
3284
|
}
|
|
2256
3285
|
|
|
3286
|
+
function basicTypeFromName(name: string, typeName = ''): BasicType {
|
|
3287
|
+
switch (name) {
|
|
3288
|
+
case 'string':
|
|
3289
|
+
return new BasicType(String, 'string', 16, typeName)
|
|
3290
|
+
case 'bool':
|
|
3291
|
+
case 'boolean':
|
|
3292
|
+
return new BasicType(Bool, 'bool', 1, typeName)
|
|
3293
|
+
case 'int':
|
|
3294
|
+
return new BasicType(Int, 'int', 8, typeName)
|
|
3295
|
+
case 'int8':
|
|
3296
|
+
return new BasicType(Int8, 'int8', 1, typeName)
|
|
3297
|
+
case 'int16':
|
|
3298
|
+
return new BasicType(Int16, 'int16', 2, typeName)
|
|
3299
|
+
case 'int32':
|
|
3300
|
+
return new BasicType(Int32, 'int32', 4, typeName)
|
|
3301
|
+
case 'int64':
|
|
3302
|
+
return new BasicType(Int64, 'int64', 8, typeName)
|
|
3303
|
+
case 'uint':
|
|
3304
|
+
return new BasicType(Uint, 'uint', 8, typeName)
|
|
3305
|
+
case 'uint8':
|
|
3306
|
+
case 'byte':
|
|
3307
|
+
return new BasicType(Uint8, name, 1, typeName)
|
|
3308
|
+
case 'uint16':
|
|
3309
|
+
return new BasicType(Uint16, 'uint16', 2, typeName)
|
|
3310
|
+
case 'uint32':
|
|
3311
|
+
return new BasicType(Uint32, 'uint32', 4, typeName)
|
|
3312
|
+
case 'uint64':
|
|
3313
|
+
return new BasicType(Uint64, 'uint64', 8, typeName)
|
|
3314
|
+
case 'uintptr':
|
|
3315
|
+
return new BasicType(Uintptr, 'uintptr', 8, typeName)
|
|
3316
|
+
case 'float32':
|
|
3317
|
+
return new BasicType(Float32, 'float32', 4, typeName)
|
|
3318
|
+
case 'float64':
|
|
3319
|
+
return new BasicType(Float64, 'float64', 8, typeName)
|
|
3320
|
+
case 'complex64':
|
|
3321
|
+
return new BasicType(Complex64, 'complex64', 8, typeName)
|
|
3322
|
+
case 'complex128':
|
|
3323
|
+
return new BasicType(Complex128, 'complex128', 16, typeName)
|
|
3324
|
+
default:
|
|
3325
|
+
return new BasicType(Invalid, name, 8, typeName)
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3328
|
+
|
|
2257
3329
|
function structFieldsFromTypeInfo(
|
|
2258
3330
|
ti: $.StructTypeInfo,
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
return {
|
|
2263
|
-
name: fieldInfo.name ?? name,
|
|
2264
|
-
type: typeFromTypeInfo(fieldInfo.type),
|
|
2265
|
-
tag: fieldInfo.tag,
|
|
2266
|
-
}
|
|
2267
|
-
}
|
|
3331
|
+
seen = new Set<string>(),
|
|
3332
|
+
): StructFieldDescriptor[] {
|
|
3333
|
+
return (ti.fields || []).map((fieldInfo, index) => {
|
|
2268
3334
|
return {
|
|
2269
|
-
name,
|
|
2270
|
-
|
|
3335
|
+
name: fieldInfo.name,
|
|
3336
|
+
key: structFieldRuntimeKey(fieldInfo),
|
|
3337
|
+
type: typeFromTypeInfoWithSeen(fieldInfo.type, seen),
|
|
3338
|
+
tag: fieldInfo.tag,
|
|
3339
|
+
pkgPath: fieldInfo.pkgPath ?? '',
|
|
3340
|
+
anonymous: fieldInfo.anonymous ?? false,
|
|
3341
|
+
index: fieldInfo.index ? [...fieldInfo.index] : [index],
|
|
3342
|
+
offset: fieldInfo.offset ?? index * 8,
|
|
3343
|
+
exported: fieldInfo.exported ?? (fieldInfo.pkgPath ?? '') === '',
|
|
2271
3344
|
}
|
|
2272
3345
|
})
|
|
2273
3346
|
}
|
|
@@ -2313,6 +3386,26 @@ class ChannelType implements Type {
|
|
|
2313
3386
|
return 0
|
|
2314
3387
|
}
|
|
2315
3388
|
|
|
3389
|
+
public NumIn(): number {
|
|
3390
|
+
return nonFunctionTypePanic('NumIn', this)
|
|
3391
|
+
}
|
|
3392
|
+
|
|
3393
|
+
public In(_i: number): Type {
|
|
3394
|
+
return nonFunctionTypePanic('In', this)
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
public NumOut(): number {
|
|
3398
|
+
return nonFunctionTypePanic('NumOut', this)
|
|
3399
|
+
}
|
|
3400
|
+
|
|
3401
|
+
public Out(_i: number): Type {
|
|
3402
|
+
return nonFunctionTypePanic('Out', this)
|
|
3403
|
+
}
|
|
3404
|
+
|
|
3405
|
+
public IsVariadic(): boolean {
|
|
3406
|
+
return nonFunctionTypePanic('IsVariadic', this)
|
|
3407
|
+
}
|
|
3408
|
+
|
|
2316
3409
|
public PkgPath(): string {
|
|
2317
3410
|
return ''
|
|
2318
3411
|
}
|
|
@@ -2347,7 +3440,7 @@ class ChannelType implements Type {
|
|
|
2347
3440
|
if (u.Kind() !== Interface) {
|
|
2348
3441
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
2349
3442
|
}
|
|
2350
|
-
return
|
|
3443
|
+
return typeImplementsInterface(this, u)
|
|
2351
3444
|
}
|
|
2352
3445
|
|
|
2353
3446
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -2395,6 +3488,7 @@ class InterfaceType implements Type {
|
|
|
2395
3488
|
constructor(
|
|
2396
3489
|
private _name: string = 'interface{}',
|
|
2397
3490
|
private _registeredName?: string,
|
|
3491
|
+
private _methods: $.MethodSignature[] = [],
|
|
2398
3492
|
) {}
|
|
2399
3493
|
|
|
2400
3494
|
public String(): string {
|
|
@@ -2421,6 +3515,26 @@ class InterfaceType implements Type {
|
|
|
2421
3515
|
return 0
|
|
2422
3516
|
}
|
|
2423
3517
|
|
|
3518
|
+
public NumIn(): number {
|
|
3519
|
+
return nonFunctionTypePanic('NumIn', this)
|
|
3520
|
+
}
|
|
3521
|
+
|
|
3522
|
+
public In(_i: number): Type {
|
|
3523
|
+
return nonFunctionTypePanic('In', this)
|
|
3524
|
+
}
|
|
3525
|
+
|
|
3526
|
+
public NumOut(): number {
|
|
3527
|
+
return nonFunctionTypePanic('NumOut', this)
|
|
3528
|
+
}
|
|
3529
|
+
|
|
3530
|
+
public Out(_i: number): Type {
|
|
3531
|
+
return nonFunctionTypePanic('Out', this)
|
|
3532
|
+
}
|
|
3533
|
+
|
|
3534
|
+
public IsVariadic(): boolean {
|
|
3535
|
+
return nonFunctionTypePanic('IsVariadic', this)
|
|
3536
|
+
}
|
|
3537
|
+
|
|
2424
3538
|
public PkgPath(): string {
|
|
2425
3539
|
if (this._name === 'interface{}' || this._name.startsWith('interface {')) {
|
|
2426
3540
|
return ''
|
|
@@ -2461,8 +3575,14 @@ class InterfaceType implements Type {
|
|
|
2461
3575
|
throw new Error('reflect: Key of non-map type')
|
|
2462
3576
|
}
|
|
2463
3577
|
|
|
2464
|
-
public Implements(
|
|
2465
|
-
|
|
3578
|
+
public Implements(u: Type | null): boolean {
|
|
3579
|
+
if (!u) {
|
|
3580
|
+
return false
|
|
3581
|
+
}
|
|
3582
|
+
if (u.Kind() !== Interface) {
|
|
3583
|
+
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
3584
|
+
}
|
|
3585
|
+
return typeImplementsInterface(this, u)
|
|
2466
3586
|
}
|
|
2467
3587
|
|
|
2468
3588
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -2510,6 +3630,10 @@ class InterfaceType implements Type {
|
|
|
2510
3630
|
public registeredName(): string | undefined {
|
|
2511
3631
|
return this._registeredName
|
|
2512
3632
|
}
|
|
3633
|
+
|
|
3634
|
+
public methodSignatures(): $.MethodSignature[] {
|
|
3635
|
+
return this._methods
|
|
3636
|
+
}
|
|
2513
3637
|
}
|
|
2514
3638
|
|
|
2515
3639
|
function getTypeOf(value: ReflectValue): Type {
|
|
@@ -2557,24 +3681,20 @@ function getTypeOf(value: ReflectValue): Type {
|
|
|
2557
3681
|
typeInfo.params &&
|
|
2558
3682
|
typeInfo.results
|
|
2559
3683
|
) {
|
|
3684
|
+
if (funcWithMeta.__goTypeName && !typeInfo.name) {
|
|
3685
|
+
return functionTypeFromInfo({
|
|
3686
|
+
...typeInfo,
|
|
3687
|
+
name: funcWithMeta.__goTypeName,
|
|
3688
|
+
})
|
|
3689
|
+
}
|
|
2560
3690
|
return functionTypeFromInfo(typeInfo)
|
|
2561
3691
|
}
|
|
2562
3692
|
}
|
|
2563
3693
|
|
|
2564
3694
|
// Then check for __goTypeName which indicates a typed function
|
|
2565
3695
|
if (funcWithMeta.__goTypeName) {
|
|
2566
|
-
// This is a typed Go function - try to reconstruct the signature
|
|
2567
3696
|
const typeName = funcWithMeta.__goTypeName
|
|
2568
|
-
|
|
2569
|
-
// For known Go function types, construct proper signatures
|
|
2570
|
-
if (typeName === 'Greeter') {
|
|
2571
|
-
return new FunctionType('func(string) string')
|
|
2572
|
-
} else if (typeName === 'Adder') {
|
|
2573
|
-
return new FunctionType('func(int, int) int')
|
|
2574
|
-
}
|
|
2575
|
-
|
|
2576
|
-
// Generic fallback for typed functions
|
|
2577
|
-
return new FunctionType(`func`) // Could be enhanced with parameter parsing
|
|
3697
|
+
return new FunctionType({ name: typeName })
|
|
2578
3698
|
}
|
|
2579
3699
|
|
|
2580
3700
|
// For untyped functions, try to parse the signature
|
|
@@ -2614,6 +3734,15 @@ function getTypeOf(value: ReflectValue): Type {
|
|
|
2614
3734
|
return new PointerType(elemType)
|
|
2615
3735
|
}
|
|
2616
3736
|
|
|
3737
|
+
if (
|
|
3738
|
+
'__goTypeInfo' in value &&
|
|
3739
|
+
(value as { __goTypeInfo?: $.TypeInfo | string }).__goTypeInfo
|
|
3740
|
+
) {
|
|
3741
|
+
return typeFromTypeInfo(
|
|
3742
|
+
(value as { __goTypeInfo: $.TypeInfo | string }).__goTypeInfo,
|
|
3743
|
+
)
|
|
3744
|
+
}
|
|
3745
|
+
|
|
2617
3746
|
if (
|
|
2618
3747
|
'real' in value &&
|
|
2619
3748
|
'imag' in value &&
|
|
@@ -2699,6 +3828,19 @@ function getTypeOf(value: ReflectValue): Type {
|
|
|
2699
3828
|
}
|
|
2700
3829
|
|
|
2701
3830
|
// Check if it has a constructor with __typeInfo for proper struct names
|
|
3831
|
+
if (
|
|
3832
|
+
value &&
|
|
3833
|
+
typeof value === 'object' &&
|
|
3834
|
+
value.constructor &&
|
|
3835
|
+
'__reflectType' in value.constructor
|
|
3836
|
+
) {
|
|
3837
|
+
const reflectType = (value.constructor as { __reflectType?: Type })
|
|
3838
|
+
.__reflectType
|
|
3839
|
+
if (reflectType) {
|
|
3840
|
+
return reflectType
|
|
3841
|
+
}
|
|
3842
|
+
}
|
|
3843
|
+
|
|
2702
3844
|
if (
|
|
2703
3845
|
value &&
|
|
2704
3846
|
typeof value === 'object' &&
|
|
@@ -2706,34 +3848,19 @@ function getTypeOf(value: ReflectValue): Type {
|
|
|
2706
3848
|
'__typeInfo' in value.constructor
|
|
2707
3849
|
) {
|
|
2708
3850
|
const typeInfo = (
|
|
2709
|
-
value.constructor as { __typeInfo?:
|
|
3851
|
+
value.constructor as { __typeInfo?: $.StructTypeInfo }
|
|
2710
3852
|
).__typeInfo
|
|
2711
|
-
if (typeInfo && typeInfo
|
|
2712
|
-
const
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
: `main.${typeInfo.name}`
|
|
2716
|
-
const regTypeInfo = builtinGetTypeByName(typeName)
|
|
2717
|
-
let fields: Array<{ name: string; type: Type; tag?: string }> = []
|
|
2718
|
-
if (regTypeInfo && isStructTypeInfo(regTypeInfo)) {
|
|
2719
|
-
fields = Object.entries(regTypeInfo.fields || {}).map(
|
|
2720
|
-
([name, fieldInfo]) => {
|
|
2721
|
-
// Check if fieldInfo is a StructFieldInfo with type and tag
|
|
2722
|
-
if (isStructFieldInfo(fieldInfo)) {
|
|
2723
|
-
return {
|
|
2724
|
-
name: fieldInfo.name ?? name,
|
|
2725
|
-
type: StructType.createTypeFromFieldInfo(fieldInfo.type),
|
|
2726
|
-
tag: fieldInfo.tag,
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
// Otherwise it's just the type info directly (backwards compatible)
|
|
2730
|
-
return {
|
|
2731
|
-
name,
|
|
2732
|
-
type: StructType.createTypeFromFieldInfo(fieldInfo),
|
|
2733
|
-
}
|
|
2734
|
-
},
|
|
2735
|
-
)
|
|
3853
|
+
if (typeInfo && isStructTypeInfo(typeInfo)) {
|
|
3854
|
+
const name = typeInfo.name ?? ''
|
|
3855
|
+
if (name === '') {
|
|
3856
|
+
return new StructType('', structFieldsFromTypeInfo(typeInfo))
|
|
2736
3857
|
}
|
|
3858
|
+
const typeName = name.includes('.') ? name : `main.${name}`
|
|
3859
|
+
const regTypeInfo = builtinGetTypeByName(typeName)
|
|
3860
|
+
const fields =
|
|
3861
|
+
regTypeInfo && isStructTypeInfo(regTypeInfo) ?
|
|
3862
|
+
structFieldsFromTypeInfo(regTypeInfo)
|
|
3863
|
+
: structFieldsFromTypeInfo(typeInfo)
|
|
2737
3864
|
return new StructType(typeName, fields)
|
|
2738
3865
|
}
|
|
2739
3866
|
}
|
|
@@ -2797,20 +3924,168 @@ export function ChanOf(dir: ChanDir, t: Type): Type {
|
|
|
2797
3924
|
return internType(new ChannelType(t, dir))
|
|
2798
3925
|
}
|
|
2799
3926
|
|
|
3927
|
+
export function StructOf(fields: $.Slice<StructField>): Type {
|
|
3928
|
+
const inputFields = $.asArray(fields)
|
|
3929
|
+
const descriptors: StructFieldDescriptor[] = []
|
|
3930
|
+
const names = new Set<string>()
|
|
3931
|
+
let pkgPath = ''
|
|
3932
|
+
let offset = 0
|
|
3933
|
+
for (const [idx, field] of inputFields.entries()) {
|
|
3934
|
+
validateStructOfField(field, idx)
|
|
3935
|
+
if (field.PkgPath !== '') {
|
|
3936
|
+
if (pkgPath === '') {
|
|
3937
|
+
pkgPath = field.PkgPath
|
|
3938
|
+
} else if (pkgPath !== field.PkgPath) {
|
|
3939
|
+
throw new Error(
|
|
3940
|
+
`reflect.Struct: fields with different PkgPath ${pkgPath} and ${field.PkgPath}`,
|
|
3941
|
+
)
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3944
|
+
if (names.has(field.Name) && field.Name !== '_') {
|
|
3945
|
+
throw new Error(`reflect.StructOf: duplicate field ${field.Name}`)
|
|
3946
|
+
}
|
|
3947
|
+
names.add(field.Name)
|
|
3948
|
+
|
|
3949
|
+
const fieldOffset = alignOffset(offset, typeAlignment(field.Type))
|
|
3950
|
+
const tag = field.Tag?.toString()
|
|
3951
|
+
const descriptor: StructFieldDescriptor = {
|
|
3952
|
+
name: field.Name,
|
|
3953
|
+
key: field.Name === '_' ? `_${idx}` : field.Name,
|
|
3954
|
+
type: field.Type,
|
|
3955
|
+
...(tag ? { tag } : {}),
|
|
3956
|
+
pkgPath: field.PkgPath,
|
|
3957
|
+
anonymous: field.Anonymous,
|
|
3958
|
+
index: [idx],
|
|
3959
|
+
offset: fieldOffset,
|
|
3960
|
+
exported: field.IsExported(),
|
|
3961
|
+
}
|
|
3962
|
+
descriptors.push(descriptor)
|
|
3963
|
+
offset = fieldOffset + field.Type.Size()
|
|
3964
|
+
}
|
|
3965
|
+
return internType(
|
|
3966
|
+
new StructType('', descriptors, '', structTypeString(descriptors)),
|
|
3967
|
+
)
|
|
3968
|
+
}
|
|
3969
|
+
|
|
3970
|
+
function validateStructOfField(field: StructField, idx: number): void {
|
|
3971
|
+
if (field.Name === '') {
|
|
3972
|
+
throw new Error(`reflect.StructOf: field ${idx} has no name`)
|
|
3973
|
+
}
|
|
3974
|
+
if (!isValidStructFieldName(field.Name)) {
|
|
3975
|
+
throw new Error(`reflect.StructOf: field ${idx} has invalid name`)
|
|
3976
|
+
}
|
|
3977
|
+
if (!field.Type) {
|
|
3978
|
+
throw new Error(`reflect.StructOf: field ${idx} has no type`)
|
|
3979
|
+
}
|
|
3980
|
+
if (field.Anonymous && field.PkgPath !== '') {
|
|
3981
|
+
throw new Error(
|
|
3982
|
+
`reflect.StructOf: field "${field.Name}" is anonymous but has PkgPath set`,
|
|
3983
|
+
)
|
|
3984
|
+
}
|
|
3985
|
+
if (field.IsExported() && isUnexportedStructFieldName(field.Name)) {
|
|
3986
|
+
throw new Error(
|
|
3987
|
+
`reflect.StructOf: field "${field.Name}" is unexported but missing PkgPath`,
|
|
3988
|
+
)
|
|
3989
|
+
}
|
|
3990
|
+
validateAnonymousStructOfField(field)
|
|
3991
|
+
}
|
|
3992
|
+
|
|
3993
|
+
function isValidStructFieldName(name: string): boolean {
|
|
3994
|
+
return /^[\p{L}_][\p{L}\p{N}_]*$/u.test(name)
|
|
3995
|
+
}
|
|
3996
|
+
|
|
3997
|
+
function isUnexportedStructFieldName(name: string): boolean {
|
|
3998
|
+
const first = name.charCodeAt(0)
|
|
3999
|
+
return name[0] === '_' || (first >= 97 && first <= 122)
|
|
4000
|
+
}
|
|
4001
|
+
|
|
4002
|
+
function validateAnonymousStructOfField(field: StructField): void {
|
|
4003
|
+
if (!field.Anonymous) {
|
|
4004
|
+
return
|
|
4005
|
+
}
|
|
4006
|
+
const typ = field.Type
|
|
4007
|
+
if (typ.Kind() === Ptr) {
|
|
4008
|
+
const elem = typ.Elem()
|
|
4009
|
+
if (elem.Kind() === Ptr || elem.Kind() === Interface) {
|
|
4010
|
+
throw new Error(
|
|
4011
|
+
`reflect.StructOf: illegal embedded field type ${typ.String()}`,
|
|
4012
|
+
)
|
|
4013
|
+
}
|
|
4014
|
+
if (embeddedMethodCount(typ) > 0) {
|
|
4015
|
+
throw new Error('reflect: embedded type with methods not implemented')
|
|
4016
|
+
}
|
|
4017
|
+
return
|
|
4018
|
+
}
|
|
4019
|
+
if (embeddedMethodCount(typ) > 0) {
|
|
4020
|
+
throw new Error('reflect: embedded type with methods not implemented')
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
|
|
4024
|
+
function embeddedMethodCount(typ: Type): number {
|
|
4025
|
+
if (typ.Kind() === Ptr) {
|
|
4026
|
+
return Math.max(typ.NumMethod(), typ.Elem().NumMethod())
|
|
4027
|
+
}
|
|
4028
|
+
return typ.NumMethod()
|
|
4029
|
+
}
|
|
4030
|
+
|
|
4031
|
+
function structTypeString(fields: StructFieldDescriptor[]): string {
|
|
4032
|
+
if (fields.length === 0) {
|
|
4033
|
+
return 'struct {}'
|
|
4034
|
+
}
|
|
4035
|
+
return `struct { ${fields.map(structFieldString).join('; ')} }`
|
|
4036
|
+
}
|
|
4037
|
+
|
|
4038
|
+
function structFieldString(field: StructFieldDescriptor): string {
|
|
4039
|
+
const tag = field.tag ? ` ${JSON.stringify(field.tag)}` : ''
|
|
4040
|
+
const prefix = field.anonymous ? '' : `${field.name} `
|
|
4041
|
+
return `${prefix}${field.type.String()}${tag}`
|
|
4042
|
+
}
|
|
4043
|
+
|
|
4044
|
+
export function FuncOf(
|
|
4045
|
+
inTypes: $.Slice<Type | null>,
|
|
4046
|
+
outTypes: $.Slice<Type | null>,
|
|
4047
|
+
variadic: boolean,
|
|
4048
|
+
): Type {
|
|
4049
|
+
const params = $.asArray(inTypes).map(funcOfType)
|
|
4050
|
+
const results = $.asArray(outTypes).map(funcOfType)
|
|
4051
|
+
if (
|
|
4052
|
+
variadic &&
|
|
4053
|
+
(params.length === 0 || params[params.length - 1].Kind() !== Slice)
|
|
4054
|
+
) {
|
|
4055
|
+
throw new Error('reflect.FuncOf: last arg of variadic func must be slice')
|
|
4056
|
+
}
|
|
4057
|
+
if (params.length + results.length > 128) {
|
|
4058
|
+
throw new Error('reflect.FuncOf: too many arguments')
|
|
4059
|
+
}
|
|
4060
|
+
return internType(new FunctionType({ params, results, variadic }))
|
|
4061
|
+
}
|
|
4062
|
+
|
|
4063
|
+
function funcOfType(typ: Type | null | undefined): Type {
|
|
4064
|
+
if (!typ) {
|
|
4065
|
+
throw new Error('reflect.FuncOf: nil Type')
|
|
4066
|
+
}
|
|
4067
|
+
return typ
|
|
4068
|
+
}
|
|
4069
|
+
|
|
2800
4070
|
export function TypeFor(typeArgs?: $.GenericTypeArgs): Type {
|
|
2801
4071
|
const descriptor = typeArgs?.T
|
|
4072
|
+
const methodSignatures = genericMethodSignatures(descriptor)
|
|
2802
4073
|
if (descriptor?.type) {
|
|
2803
|
-
return internType(
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
4074
|
+
return internType(
|
|
4075
|
+
typeWithMethodSignatures(
|
|
4076
|
+
typeFromTypeInfo(descriptor.type),
|
|
4077
|
+
methodSignatures,
|
|
4078
|
+
),
|
|
4079
|
+
)
|
|
4080
|
+
}
|
|
4081
|
+
if (methodSignatures.length !== 0) {
|
|
4082
|
+
return internType(
|
|
4083
|
+
new InterfaceType(
|
|
4084
|
+
interfaceTypeString(methodSignatures),
|
|
4085
|
+
undefined,
|
|
4086
|
+
methodSignatures,
|
|
4087
|
+
),
|
|
4088
|
+
)
|
|
2814
4089
|
}
|
|
2815
4090
|
if (descriptor?.zero) {
|
|
2816
4091
|
return internType(getTypeOf(descriptor.zero()))
|
|
@@ -2818,113 +4093,475 @@ export function TypeFor(typeArgs?: $.GenericTypeArgs): Type {
|
|
|
2818
4093
|
return internType(new InterfaceType('interface{}'))
|
|
2819
4094
|
}
|
|
2820
4095
|
|
|
4096
|
+
function genericMethodSignatures(
|
|
4097
|
+
descriptor: $.GenericTypeDescriptor | undefined,
|
|
4098
|
+
): $.MethodSignature[] {
|
|
4099
|
+
if (!descriptor) {
|
|
4100
|
+
return []
|
|
4101
|
+
}
|
|
4102
|
+
if (descriptor.methodSignatures && descriptor.methodSignatures.length !== 0) {
|
|
4103
|
+
return descriptor.methodSignatures
|
|
4104
|
+
}
|
|
4105
|
+
if (!descriptor.methods) {
|
|
4106
|
+
return []
|
|
4107
|
+
}
|
|
4108
|
+
return Object.keys(descriptor.methods).map((method) => ({
|
|
4109
|
+
name: method,
|
|
4110
|
+
args: [],
|
|
4111
|
+
returns: [],
|
|
4112
|
+
}))
|
|
4113
|
+
}
|
|
4114
|
+
|
|
4115
|
+
function typeWithMethodSignatures(
|
|
4116
|
+
typ: Type,
|
|
4117
|
+
methods: $.MethodSignature[],
|
|
4118
|
+
): Type {
|
|
4119
|
+
if (methods.length === 0) {
|
|
4120
|
+
return typ
|
|
4121
|
+
}
|
|
4122
|
+
if (typ instanceof BasicType) {
|
|
4123
|
+
typ.mergeMethodSignatures(methods)
|
|
4124
|
+
return typ
|
|
4125
|
+
}
|
|
4126
|
+
if (typ instanceof PointerType) {
|
|
4127
|
+
typ.mergeMethodSignatures(methods)
|
|
4128
|
+
return typ
|
|
4129
|
+
}
|
|
4130
|
+
if (typ instanceof FunctionType) {
|
|
4131
|
+
typ.mergeMethodSignatures(methods)
|
|
4132
|
+
return typ
|
|
4133
|
+
}
|
|
4134
|
+
return typ
|
|
4135
|
+
}
|
|
4136
|
+
|
|
2821
4137
|
function typeFromTypeInfo(info: $.TypeInfo | string): Type {
|
|
4138
|
+
return typeFromTypeInfoWithSeen(info, new Set())
|
|
4139
|
+
}
|
|
4140
|
+
|
|
4141
|
+
function typeFromTypeInfoWithSeen(
|
|
4142
|
+
info: $.TypeInfo | string,
|
|
4143
|
+
seen: Set<string>,
|
|
4144
|
+
): Type {
|
|
2822
4145
|
if (typeof info === 'string') {
|
|
2823
4146
|
const registered = builtinGetTypeByName(info)
|
|
2824
4147
|
if (registered) {
|
|
2825
|
-
|
|
4148
|
+
const typ = typeFromTypeInfoWithSeen(registered, seen)
|
|
4149
|
+
return internType(typ)
|
|
2826
4150
|
}
|
|
2827
|
-
return internType(StructType.createTypeFromFieldInfo(info))
|
|
4151
|
+
return internType(StructType.createTypeFromFieldInfo(info, seen))
|
|
4152
|
+
}
|
|
4153
|
+
const recursiveName = recursiveTypeInfoName(info)
|
|
4154
|
+
if (recursiveName !== '') {
|
|
4155
|
+
const constructing = constructingRegisteredTypes.get(recursiveName)
|
|
4156
|
+
if (constructing) {
|
|
4157
|
+
return constructing
|
|
4158
|
+
}
|
|
4159
|
+
if (seen.has(recursiveName)) {
|
|
4160
|
+
return internType(shallowTypeFromRegisteredInfo(recursiveName, info))
|
|
4161
|
+
}
|
|
4162
|
+
if (info.kind === $.TypeKind.Struct) {
|
|
4163
|
+
const typ = new StructType(recursiveName, [])
|
|
4164
|
+
constructingRegisteredTypes.set(recursiveName, typ)
|
|
4165
|
+
seen.add(recursiveName)
|
|
4166
|
+
try {
|
|
4167
|
+
typ.replaceDescriptors(structFieldsFromTypeInfo(info, seen))
|
|
4168
|
+
return internType(typ)
|
|
4169
|
+
} finally {
|
|
4170
|
+
seen.delete(recursiveName)
|
|
4171
|
+
constructingRegisteredTypes.delete(recursiveName)
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4174
|
+
seen.add(recursiveName)
|
|
4175
|
+
const typ = typeFromStructuredTypeInfoWithSeen(info, seen)
|
|
4176
|
+
seen.delete(recursiveName)
|
|
4177
|
+
return internType(typ)
|
|
4178
|
+
}
|
|
4179
|
+
return internType(typeFromStructuredTypeInfoWithSeen(info, seen))
|
|
4180
|
+
}
|
|
4181
|
+
|
|
4182
|
+
function recursiveTypeInfoName(info: $.TypeInfo): string {
|
|
4183
|
+
if (info.kind === $.TypeKind.Basic) {
|
|
4184
|
+
return info.typeName ?? ''
|
|
2828
4185
|
}
|
|
4186
|
+
return info.name ?? ''
|
|
4187
|
+
}
|
|
4188
|
+
|
|
4189
|
+
function typeFromStructuredTypeInfoWithSeen(
|
|
4190
|
+
info: $.TypeInfo,
|
|
4191
|
+
seen: Set<string>,
|
|
4192
|
+
): Type {
|
|
2829
4193
|
switch (info.kind) {
|
|
2830
4194
|
case $.TypeKind.Array:
|
|
2831
|
-
return
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
),
|
|
2836
|
-
info.length,
|
|
4195
|
+
return new ArrayType(
|
|
4196
|
+
typeFromTypeInfoWithSeen(
|
|
4197
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4198
|
+
seen,
|
|
2837
4199
|
),
|
|
4200
|
+
info.length,
|
|
2838
4201
|
)
|
|
2839
4202
|
case $.TypeKind.Basic:
|
|
2840
|
-
return
|
|
4203
|
+
return StructType.createTypeFromFieldInfo(info, seen)
|
|
2841
4204
|
case $.TypeKind.Channel:
|
|
2842
|
-
return
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
),
|
|
2847
|
-
chanDirFromTypeInfo(info.direction),
|
|
4205
|
+
return new ChannelType(
|
|
4206
|
+
typeFromTypeInfoWithSeen(
|
|
4207
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4208
|
+
seen,
|
|
2848
4209
|
),
|
|
4210
|
+
chanDirFromTypeInfo(info.direction),
|
|
2849
4211
|
)
|
|
2850
4212
|
case $.TypeKind.Function:
|
|
2851
|
-
return
|
|
4213
|
+
return functionTypeFromInfo(info, seen)
|
|
2852
4214
|
case $.TypeKind.Interface:
|
|
2853
|
-
return
|
|
4215
|
+
return interfaceTypeFromInfo(info, seen)
|
|
2854
4216
|
case $.TypeKind.Map:
|
|
2855
|
-
return
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
4217
|
+
return new MapType(
|
|
4218
|
+
typeFromTypeInfoWithSeen(
|
|
4219
|
+
info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4220
|
+
seen,
|
|
4221
|
+
),
|
|
4222
|
+
typeFromTypeInfoWithSeen(
|
|
4223
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4224
|
+
seen,
|
|
2863
4225
|
),
|
|
2864
4226
|
)
|
|
2865
4227
|
case $.TypeKind.Slice:
|
|
2866
|
-
return
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
),
|
|
4228
|
+
return new SliceType(
|
|
4229
|
+
typeFromTypeInfoWithSeen(
|
|
4230
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4231
|
+
seen,
|
|
2871
4232
|
),
|
|
2872
4233
|
)
|
|
2873
4234
|
case $.TypeKind.Struct:
|
|
2874
|
-
return
|
|
4235
|
+
return StructType.createTypeFromFieldInfo(info, seen)
|
|
2875
4236
|
case $.TypeKind.Pointer:
|
|
2876
|
-
return
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
),
|
|
4237
|
+
return new PointerType(
|
|
4238
|
+
typeFromTypeInfoWithSeen(
|
|
4239
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4240
|
+
seen,
|
|
2881
4241
|
),
|
|
2882
4242
|
)
|
|
2883
4243
|
default:
|
|
2884
|
-
return
|
|
4244
|
+
return StructType.createTypeFromFieldInfo(info, seen)
|
|
2885
4245
|
}
|
|
2886
4246
|
}
|
|
2887
4247
|
|
|
2888
|
-
function
|
|
2889
|
-
|
|
2890
|
-
|
|
4248
|
+
function shallowTypeFromRegisteredInfo(name: string, info: $.TypeInfo): Type {
|
|
4249
|
+
switch (info.kind) {
|
|
4250
|
+
case $.TypeKind.Interface:
|
|
4251
|
+
return new InterfaceType(name, name, info.methods ?? [])
|
|
4252
|
+
case $.TypeKind.Struct:
|
|
4253
|
+
return new StructType(name, [])
|
|
4254
|
+
case $.TypeKind.Function:
|
|
4255
|
+
return new FunctionType({ name })
|
|
4256
|
+
case $.TypeKind.Basic:
|
|
4257
|
+
return StructType.createTypeFromFieldInfo({
|
|
4258
|
+
kind: $.TypeKind.Basic,
|
|
4259
|
+
name: info.name ?? 'unknown',
|
|
4260
|
+
typeName: info.typeName ?? name,
|
|
4261
|
+
})
|
|
4262
|
+
default:
|
|
4263
|
+
return StructType.createTypeFromFieldInfo(name)
|
|
2891
4264
|
}
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
4265
|
+
}
|
|
4266
|
+
|
|
4267
|
+
function functionTypeFromInfo(
|
|
4268
|
+
info: $.FunctionTypeInfo,
|
|
4269
|
+
seen = new Set<string>(),
|
|
4270
|
+
): Type {
|
|
4271
|
+
const params = (info.params ?? []).map((param) =>
|
|
4272
|
+
typeFromTypeInfoWithSeen(param, seen),
|
|
4273
|
+
)
|
|
4274
|
+
const results = (info.results ?? []).map((result) =>
|
|
4275
|
+
typeFromTypeInfoWithSeen(result, seen),
|
|
4276
|
+
)
|
|
4277
|
+
return new FunctionType({
|
|
4278
|
+
name: info.name,
|
|
4279
|
+
params,
|
|
4280
|
+
results,
|
|
4281
|
+
variadic: info.isVariadic ?? false,
|
|
2902
4282
|
})
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
4283
|
+
}
|
|
4284
|
+
|
|
4285
|
+
function functionTypeInfoFromType(typ: Type): $.FunctionTypeInfo {
|
|
4286
|
+
const params: (string | $.TypeInfo)[] = []
|
|
4287
|
+
for (let i = 0; i < typ.NumIn(); i++) {
|
|
4288
|
+
params.push(typeInfoFromReflectType(typ.In(i)))
|
|
4289
|
+
}
|
|
4290
|
+
const results: (string | $.TypeInfo)[] = []
|
|
4291
|
+
for (let i = 0; i < typ.NumOut(); i++) {
|
|
4292
|
+
results.push(typeInfoFromReflectType(typ.Out(i)))
|
|
4293
|
+
}
|
|
4294
|
+
const info: $.FunctionTypeInfo = {
|
|
4295
|
+
kind: $.TypeKind.Function,
|
|
4296
|
+
params,
|
|
4297
|
+
results,
|
|
4298
|
+
}
|
|
4299
|
+
if (typ.Name() !== '') {
|
|
4300
|
+
info.name = typ.String()
|
|
2907
4301
|
}
|
|
2908
|
-
if (
|
|
2909
|
-
|
|
4302
|
+
if (typ.IsVariadic()) {
|
|
4303
|
+
info.isVariadic = true
|
|
2910
4304
|
}
|
|
2911
|
-
return
|
|
4305
|
+
return info
|
|
2912
4306
|
}
|
|
2913
4307
|
|
|
2914
|
-
function
|
|
2915
|
-
|
|
4308
|
+
export function typeInfoFromReflectType(typ: Type): string | $.TypeInfo {
|
|
4309
|
+
if (typ.PkgPath() !== '' && typ.Name() !== '') {
|
|
4310
|
+
return typ.String()
|
|
4311
|
+
}
|
|
4312
|
+
switch (typ.Kind()) {
|
|
4313
|
+
case Bool:
|
|
4314
|
+
case Int:
|
|
4315
|
+
case Int8:
|
|
4316
|
+
case Int16:
|
|
4317
|
+
case Int32:
|
|
4318
|
+
case Int64:
|
|
4319
|
+
case Uint:
|
|
4320
|
+
case Uint8:
|
|
4321
|
+
case Uint16:
|
|
4322
|
+
case Uint32:
|
|
4323
|
+
case Uint64:
|
|
4324
|
+
case Uintptr:
|
|
4325
|
+
case Float32:
|
|
4326
|
+
case Float64:
|
|
4327
|
+
case Complex64:
|
|
4328
|
+
case Complex128:
|
|
4329
|
+
case String:
|
|
4330
|
+
case UnsafePointer:
|
|
4331
|
+
return { kind: $.TypeKind.Basic, name: typ.String() }
|
|
4332
|
+
case Interface:
|
|
4333
|
+
return {
|
|
4334
|
+
kind: $.TypeKind.Interface,
|
|
4335
|
+
methods: typeMethods(typ).map((method) => ({
|
|
4336
|
+
name: method.name,
|
|
4337
|
+
args: method.args,
|
|
4338
|
+
returns: method.returns,
|
|
4339
|
+
})),
|
|
4340
|
+
}
|
|
4341
|
+
case Slice:
|
|
4342
|
+
return {
|
|
4343
|
+
kind: $.TypeKind.Slice,
|
|
4344
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
4345
|
+
}
|
|
4346
|
+
case Array:
|
|
4347
|
+
return {
|
|
4348
|
+
kind: $.TypeKind.Array,
|
|
4349
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
4350
|
+
length: typ.Len(),
|
|
4351
|
+
}
|
|
4352
|
+
case Ptr:
|
|
4353
|
+
return {
|
|
4354
|
+
kind: $.TypeKind.Pointer,
|
|
4355
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
4356
|
+
}
|
|
4357
|
+
case Map:
|
|
4358
|
+
return {
|
|
4359
|
+
kind: $.TypeKind.Map,
|
|
4360
|
+
keyType: typeInfoFromReflectType(typ.Key()),
|
|
4361
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
4362
|
+
}
|
|
4363
|
+
case Chan:
|
|
4364
|
+
return {
|
|
4365
|
+
kind: $.TypeKind.Channel,
|
|
4366
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
4367
|
+
direction: channelDirectionFromString(typ.String()),
|
|
4368
|
+
}
|
|
4369
|
+
case Func:
|
|
4370
|
+
return functionTypeInfoFromType(typ)
|
|
4371
|
+
case Struct: {
|
|
4372
|
+
const fields =
|
|
4373
|
+
typ instanceof StructType ?
|
|
4374
|
+
typ.descriptors()
|
|
4375
|
+
: globalThis.Array.from({ length: typ.NumField() }, (_unused, idx) => {
|
|
4376
|
+
const field = typ.Field(idx)
|
|
4377
|
+
return {
|
|
4378
|
+
name: field.Name,
|
|
4379
|
+
key: structFieldStorageKey(typ, idx),
|
|
4380
|
+
type: field.Type,
|
|
4381
|
+
tag: field.Tag?.toString(),
|
|
4382
|
+
pkgPath: field.PkgPath,
|
|
4383
|
+
anonymous: field.Anonymous,
|
|
4384
|
+
index: [...field.Index],
|
|
4385
|
+
offset: field.Offset,
|
|
4386
|
+
exported: field.IsExported(),
|
|
4387
|
+
}
|
|
4388
|
+
})
|
|
4389
|
+
return {
|
|
4390
|
+
kind: $.TypeKind.Struct,
|
|
4391
|
+
name: typ.Name() === '' ? '' : typ.String(),
|
|
4392
|
+
methods: [],
|
|
4393
|
+
fields: fields.map((field) => ({
|
|
4394
|
+
name: field.name,
|
|
4395
|
+
key: field.key,
|
|
4396
|
+
type: typeInfoFromReflectType(field.type),
|
|
4397
|
+
...(field.tag ? { tag: field.tag } : {}),
|
|
4398
|
+
...(field.pkgPath ? { pkgPath: field.pkgPath } : {}),
|
|
4399
|
+
...(field.anonymous ? { anonymous: true } : {}),
|
|
4400
|
+
index: [...field.index],
|
|
4401
|
+
offset: field.offset,
|
|
4402
|
+
exported: field.exported,
|
|
4403
|
+
})),
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
default:
|
|
4407
|
+
return typ.String()
|
|
4408
|
+
}
|
|
2916
4409
|
}
|
|
2917
4410
|
|
|
2918
|
-
function
|
|
2919
|
-
|
|
2920
|
-
|
|
4411
|
+
function channelDirectionFromString(
|
|
4412
|
+
typeName: string,
|
|
4413
|
+
): 'send' | 'receive' | 'both' {
|
|
4414
|
+
if (typeName.startsWith('<-chan ')) {
|
|
4415
|
+
return 'receive'
|
|
4416
|
+
}
|
|
4417
|
+
if (typeName.startsWith('chan<- ')) {
|
|
4418
|
+
return 'send'
|
|
4419
|
+
}
|
|
4420
|
+
return 'both'
|
|
4421
|
+
}
|
|
4422
|
+
|
|
4423
|
+
function interfaceTypeFromInfo(
|
|
4424
|
+
info: $.InterfaceTypeInfo,
|
|
4425
|
+
seen = new Set<string>(),
|
|
4426
|
+
): Type {
|
|
4427
|
+
const methods = info.methods ?? []
|
|
4428
|
+
if (methods.length === 0) {
|
|
4429
|
+
return new InterfaceType('interface{}', info.name, methods)
|
|
2921
4430
|
}
|
|
2922
4431
|
return new InterfaceType(
|
|
2923
|
-
|
|
4432
|
+
interfaceTypeString(methods, seen),
|
|
2924
4433
|
info.name,
|
|
4434
|
+
methods,
|
|
2925
4435
|
)
|
|
2926
4436
|
}
|
|
2927
4437
|
|
|
4438
|
+
function interfaceTypeString(
|
|
4439
|
+
methods: $.MethodSignature[],
|
|
4440
|
+
seen = new Set<string>(),
|
|
4441
|
+
): string {
|
|
4442
|
+
return `interface { ${methods
|
|
4443
|
+
.map((method) => interfaceMethodString(method, seen))
|
|
4444
|
+
.join('; ')} }`
|
|
4445
|
+
}
|
|
4446
|
+
|
|
4447
|
+
function interfaceMethodString(
|
|
4448
|
+
method: $.MethodSignature,
|
|
4449
|
+
seen: Set<string>,
|
|
4450
|
+
): string {
|
|
4451
|
+
const args = method.args.map((arg) => methodArgString(arg, seen)).join(', ')
|
|
4452
|
+
const returns = method.returns.map((arg) => methodArgString(arg, seen))
|
|
4453
|
+
if (returns.length === 0) {
|
|
4454
|
+
return `${method.name}(${args})`
|
|
4455
|
+
}
|
|
4456
|
+
if (returns.length === 1) {
|
|
4457
|
+
return `${method.name}(${args}) ${returns[0]}`
|
|
4458
|
+
}
|
|
4459
|
+
return `${method.name}(${args}) (${returns.join(', ')})`
|
|
4460
|
+
}
|
|
4461
|
+
|
|
4462
|
+
function structTypeInfoString(
|
|
4463
|
+
info: $.StructTypeInfo,
|
|
4464
|
+
seen: Set<string>,
|
|
4465
|
+
): string {
|
|
4466
|
+
if (info.name) {
|
|
4467
|
+
return info.name
|
|
4468
|
+
}
|
|
4469
|
+
const fields = info.fields ?? []
|
|
4470
|
+
if (fields.length === 0) {
|
|
4471
|
+
return 'struct {}'
|
|
4472
|
+
}
|
|
4473
|
+
return `struct { ${fields
|
|
4474
|
+
.map((field) => structFieldInfoString(field, seen))
|
|
4475
|
+
.join('; ')} }`
|
|
4476
|
+
}
|
|
4477
|
+
|
|
4478
|
+
function structFieldInfoString(
|
|
4479
|
+
field: $.StructFieldInfo,
|
|
4480
|
+
seen: Set<string>,
|
|
4481
|
+
): string {
|
|
4482
|
+
const tag = field.tag ? ` ${JSON.stringify(field.tag)}` : ''
|
|
4483
|
+
const prefix = field.anonymous ? '' : `${field.name} `
|
|
4484
|
+
return `${prefix}${typeInfoString(field.type, seen)}${tag}`
|
|
4485
|
+
}
|
|
4486
|
+
|
|
4487
|
+
function methodArgString(arg: $.MethodArg, seen: Set<string>): string {
|
|
4488
|
+
return typeInfoString(arg.type, seen)
|
|
4489
|
+
}
|
|
4490
|
+
|
|
4491
|
+
function typeInfoString(info: $.TypeInfo | string, seen: Set<string>): string {
|
|
4492
|
+
if (typeof info === 'string') {
|
|
4493
|
+
return info
|
|
4494
|
+
}
|
|
4495
|
+
switch (info.kind) {
|
|
4496
|
+
case $.TypeKind.Basic:
|
|
4497
|
+
return info.typeName ?? info.name ?? 'unknown'
|
|
4498
|
+
case $.TypeKind.Interface: {
|
|
4499
|
+
const name = info.name ?? ''
|
|
4500
|
+
if (name !== '' && seen.has(name)) {
|
|
4501
|
+
return name
|
|
4502
|
+
}
|
|
4503
|
+
if (info.methods.length === 0) {
|
|
4504
|
+
return 'interface{}'
|
|
4505
|
+
}
|
|
4506
|
+
if (name !== '') {
|
|
4507
|
+
seen.add(name)
|
|
4508
|
+
}
|
|
4509
|
+
const text = interfaceTypeString(info.methods, seen)
|
|
4510
|
+
if (name !== '') {
|
|
4511
|
+
seen.delete(name)
|
|
4512
|
+
}
|
|
4513
|
+
return text
|
|
4514
|
+
}
|
|
4515
|
+
case $.TypeKind.Struct:
|
|
4516
|
+
return structTypeInfoString(info, seen)
|
|
4517
|
+
case $.TypeKind.Pointer:
|
|
4518
|
+
return `*${typeInfoString(
|
|
4519
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4520
|
+
seen,
|
|
4521
|
+
)}`
|
|
4522
|
+
case $.TypeKind.Slice:
|
|
4523
|
+
return `[]${typeInfoString(
|
|
4524
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4525
|
+
seen,
|
|
4526
|
+
)}`
|
|
4527
|
+
case $.TypeKind.Array:
|
|
4528
|
+
return `[${info.length}]${typeInfoString(
|
|
4529
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4530
|
+
seen,
|
|
4531
|
+
)}`
|
|
4532
|
+
case $.TypeKind.Map:
|
|
4533
|
+
return `map[${typeInfoString(
|
|
4534
|
+
info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4535
|
+
seen,
|
|
4536
|
+
)}]${typeInfoString(
|
|
4537
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4538
|
+
seen,
|
|
4539
|
+
)}`
|
|
4540
|
+
case $.TypeKind.Function: {
|
|
4541
|
+
const params = (info.params ?? [])
|
|
4542
|
+
.map((param) => typeInfoString(param, seen))
|
|
4543
|
+
.join(', ')
|
|
4544
|
+
const results = (info.results ?? []).map((result) =>
|
|
4545
|
+
typeInfoString(result, seen),
|
|
4546
|
+
)
|
|
4547
|
+
if (results.length === 0) {
|
|
4548
|
+
return `func(${params})`
|
|
4549
|
+
}
|
|
4550
|
+
if (results.length === 1) {
|
|
4551
|
+
return `func(${params}) ${results[0]}`
|
|
4552
|
+
}
|
|
4553
|
+
return `func(${params}) (${results.join(', ')})`
|
|
4554
|
+
}
|
|
4555
|
+
case $.TypeKind.Channel:
|
|
4556
|
+
return `chan ${typeInfoString(
|
|
4557
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4558
|
+
seen,
|
|
4559
|
+
)}`
|
|
4560
|
+
default:
|
|
4561
|
+
return 'unknown'
|
|
4562
|
+
}
|
|
4563
|
+
}
|
|
4564
|
+
|
|
2928
4565
|
function chanDirFromTypeInfo(direction?: 'send' | 'receive' | 'both'): ChanDir {
|
|
2929
4566
|
switch (direction) {
|
|
2930
4567
|
case 'send':
|
|
@@ -2942,38 +4579,16 @@ function chanDirFromTypeInfo(direction?: 'send' | 'receive' | 'both'): ChanDir {
|
|
|
2942
4579
|
*/
|
|
2943
4580
|
export function getInterfaceTypeByName(name: string): Type {
|
|
2944
4581
|
const typeInfo = builtinGetTypeByName(name)
|
|
2945
|
-
if (typeInfo && typeInfo
|
|
2946
|
-
return new InterfaceType(name, name)
|
|
4582
|
+
if (typeInfo && isInterfaceTypeInfo(typeInfo)) {
|
|
4583
|
+
return new InterfaceType(name, name, typeInfo.methods ?? [])
|
|
2947
4584
|
}
|
|
2948
4585
|
return new InterfaceType('interface{}')
|
|
2949
4586
|
}
|
|
2950
4587
|
|
|
2951
4588
|
export function getInterfaceLiteralTypeByName(name: string): Type {
|
|
2952
4589
|
const typeInfo = builtinGetTypeByName(name)
|
|
2953
|
-
if (typeInfo && typeInfo
|
|
2954
|
-
|
|
2955
|
-
if (methods.length === 0) {
|
|
2956
|
-
return new InterfaceType('interface{}', name)
|
|
2957
|
-
}
|
|
2958
|
-
const methodSigs = methods
|
|
2959
|
-
.map((m: any) => {
|
|
2960
|
-
const args =
|
|
2961
|
-
m.args
|
|
2962
|
-
?.map((a: any) => (typeof a === 'string' ? a : 'any'))
|
|
2963
|
-
.join(', ') || ''
|
|
2964
|
-
const returns = m.returns?.map((r: any) =>
|
|
2965
|
-
typeof r === 'string' ? r : 'any',
|
|
2966
|
-
)
|
|
2967
|
-
let returnSig = ''
|
|
2968
|
-
if (returns && returns.length === 1) {
|
|
2969
|
-
returnSig = ` ${returns[0]}`
|
|
2970
|
-
} else if (returns && returns.length > 1) {
|
|
2971
|
-
returnSig = ` (${returns.join(', ')})`
|
|
2972
|
-
}
|
|
2973
|
-
return `${m.name}(${args})${returnSig}`
|
|
2974
|
-
})
|
|
2975
|
-
.join('; ')
|
|
2976
|
-
return new InterfaceType(`interface { ${methodSigs} }`, name)
|
|
4590
|
+
if (typeInfo && isInterfaceTypeInfo(typeInfo)) {
|
|
4591
|
+
return interfaceTypeFromInfo(typeInfo)
|
|
2977
4592
|
}
|
|
2978
4593
|
return new InterfaceType('interface{}')
|
|
2979
4594
|
}
|