goscript 0.1.4 → 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} +7 -0
- package/cmd/goscript/cmd-test.go +14 -0
- package/cmd/goscript/cmd-test_test.go +1 -1
- 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 +273 -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 +392 -127
- package/compiler/lowering_bench_test.go +41 -27
- 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/protobuf-ts-binding.go +514 -0
- package/compiler/protobuf-ts-binding_test.go +172 -0
- package/compiler/semantic-model-types.go +9 -4
- package/compiler/semantic-model.go +282 -70
- package/compiler/semantic-model_test.go +82 -1
- package/compiler/service.go +20 -1
- package/compiler/skeleton_test.go +62 -8
- package/compiler/typescript-emitter.go +128 -13
- package/dist/gs/builtin/slice.d.ts +2 -1
- package/dist/gs/builtin/slice.js +29 -4
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +13 -5
- package/dist/gs/builtin/type.js +153 -60
- 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 +10 -3
- package/dist/gs/compress/zlib/index.js +50 -16
- package/dist/gs/compress/zlib/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/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/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 +4 -2
- 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 +2 -0
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +5 -0
- package/dist/gs/math/bits/index.js +16 -4
- 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 +300 -5
- package/dist/gs/net/http/index.js +1598 -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.js +1 -1
- 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 +25 -6
- package/dist/gs/reflect/type.js +1418 -228
- 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.js +9 -5
- 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/syscall/env.js +22 -14
- package/dist/gs/syscall/env.js.map +1 -1
- package/dist/gs/testing/testing.js +55 -13
- 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/runtime-contract.test.ts +218 -21
- package/gs/builtin/slice.ts +44 -4
- package/gs/builtin/type.ts +226 -59
- 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 +62 -1
- package/gs/compress/zlib/index.ts +53 -16
- package/gs/compress/zlib/parity.json +51 -0
- 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/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/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.ts +4 -4
- package/gs/io/fs/sub.ts +8 -1
- package/gs/io/io.ts +1 -0
- package/gs/io/parity.json +162 -0
- package/gs/math/bits/index.test.ts +14 -1
- package/gs/math/bits/index.ts +23 -4
- 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 +781 -12
- package/gs/net/http/index.ts +1860 -139
- 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/index.test.ts +9 -0
- package/gs/os/index.ts +1 -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/root_js.gs.ts +1 -1
- package/gs/os/types.gs.ts +1 -1
- package/gs/os/types_js.gs.ts +1 -1
- package/gs/os/types_unix.gs.ts +1 -1
- package/gs/path/path.ts +11 -7
- 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 +1897 -317
- package/gs/reflect/typefor.test.ts +510 -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/parity.json +186 -0
- package/gs/strings/reader.ts +9 -5
- 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/syscall/env.ts +29 -14
- package/gs/testing/testing.test.ts +67 -0
- package/gs/testing/testing.ts +87 -19
- 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 -926
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -38
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1361
- 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
|
}
|
|
@@ -476,6 +642,10 @@ export class Value {
|
|
|
476
642
|
}
|
|
477
643
|
|
|
478
644
|
public Len(): number {
|
|
645
|
+
if (this.Kind() === Slice || this.Kind() === Array) {
|
|
646
|
+
return $.len(this._value as any)
|
|
647
|
+
}
|
|
648
|
+
|
|
479
649
|
// Check for slice objects created by $.arrayToSlice
|
|
480
650
|
if (
|
|
481
651
|
this._value &&
|
|
@@ -539,8 +709,9 @@ export class Value {
|
|
|
539
709
|
}
|
|
540
710
|
|
|
541
711
|
public Index(i: number): Value {
|
|
542
|
-
if (
|
|
543
|
-
|
|
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)
|
|
544
715
|
}
|
|
545
716
|
throw new Error(
|
|
546
717
|
'reflect: call of reflect.Value.Index on ' +
|
|
@@ -621,17 +792,18 @@ export class Value {
|
|
|
621
792
|
}
|
|
622
793
|
|
|
623
794
|
const field = this.Type().Field(i)
|
|
795
|
+
const fieldKey = structFieldStorageKey(this.Type(), i)
|
|
624
796
|
if (!field) {
|
|
625
797
|
throw new Error('reflect: struct field index out of range')
|
|
626
798
|
}
|
|
627
799
|
|
|
628
800
|
const parentObj = this._value as Record<string, any>
|
|
629
|
-
let fieldVal = parentObj[
|
|
801
|
+
let fieldVal = parentObj[fieldKey]
|
|
630
802
|
if (fieldVal === undefined) {
|
|
631
803
|
fieldVal = null
|
|
632
804
|
}
|
|
633
805
|
// Pass parent struct and field name so Set() can update the struct
|
|
634
|
-
return new Value(fieldVal, field.Type, undefined, parentObj,
|
|
806
|
+
return new Value(fieldVal, field.Type, undefined, parentObj, fieldKey)
|
|
635
807
|
}
|
|
636
808
|
|
|
637
809
|
public FieldByIndex(index: $.Slice<number>): Value {
|
|
@@ -670,6 +842,9 @@ export class Value {
|
|
|
670
842
|
if (this._value === null || this._value === undefined) {
|
|
671
843
|
return 0
|
|
672
844
|
}
|
|
845
|
+
if ($.isOwnedPointerHandle(this._value)) {
|
|
846
|
+
return $.ownedPointerAddress(this._value)
|
|
847
|
+
}
|
|
673
848
|
if ($.isVarRef(this._value)) {
|
|
674
849
|
const address = this._value.__goAddress?.()
|
|
675
850
|
if (address !== undefined) {
|
|
@@ -694,12 +869,26 @@ export class Value {
|
|
|
694
869
|
return 0
|
|
695
870
|
}
|
|
696
871
|
|
|
697
|
-
public UnsafeAddr(): number |
|
|
872
|
+
public UnsafeAddr(): number | $.OwnedPointerHandle<ReflectValue> {
|
|
698
873
|
if (!this.CanAddr()) {
|
|
699
874
|
throw new ValueError({ Kind: this.Kind(), Method: 'UnsafeAddr' })
|
|
700
875
|
}
|
|
701
876
|
if (this._parentStruct && this._fieldName) {
|
|
702
|
-
|
|
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>
|
|
703
892
|
}
|
|
704
893
|
return this.Pointer()
|
|
705
894
|
}
|
|
@@ -735,6 +924,9 @@ export class Value {
|
|
|
735
924
|
if (this._parentStruct && this._fieldName) {
|
|
736
925
|
return new Value($.fieldRef(this._parentStruct, this._fieldName), ptrType)
|
|
737
926
|
}
|
|
927
|
+
if (this._parentVarRef) {
|
|
928
|
+
return new Value(this._parentVarRef, ptrType)
|
|
929
|
+
}
|
|
738
930
|
return new Value($.varRef(this._value), ptrType)
|
|
739
931
|
}
|
|
740
932
|
|
|
@@ -748,23 +940,9 @@ export class Value {
|
|
|
748
940
|
if (!this.CanSet()) {
|
|
749
941
|
throw new Error('reflect: assign to invalid value')
|
|
750
942
|
}
|
|
751
|
-
// Interface types can accept any value
|
|
752
|
-
if (this.Kind() === Interface) {
|
|
753
|
-
this._value = x.value
|
|
754
|
-
// Also update the parent VarRef if we were dereferenced from one
|
|
755
|
-
if (this._parentVarRef) {
|
|
756
|
-
this._parentVarRef.value = x.value
|
|
757
|
-
}
|
|
758
|
-
// Also update the parent struct field if this is a struct field
|
|
759
|
-
if (this._parentStruct && this._fieldName) {
|
|
760
|
-
this._parentStruct[this._fieldName] = x.value
|
|
761
|
-
}
|
|
762
|
-
return
|
|
763
|
-
}
|
|
764
|
-
// For other types, check if types are compatible (simplified check)
|
|
765
943
|
const thisType = this.Type()
|
|
766
944
|
const xType = x.Type()
|
|
767
|
-
if (
|
|
945
|
+
if (!xType.AssignableTo(thisType)) {
|
|
768
946
|
throw new Error('reflect: assign to wrong type')
|
|
769
947
|
}
|
|
770
948
|
this._value = x.value
|
|
@@ -799,22 +977,36 @@ export class Value {
|
|
|
799
977
|
if (typeof method !== 'function') {
|
|
800
978
|
return new Value()
|
|
801
979
|
}
|
|
802
|
-
|
|
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)
|
|
803
986
|
}
|
|
804
987
|
|
|
805
|
-
public Call(inArgs: $.Slice<Value>):
|
|
988
|
+
public async Call(inArgs: $.Slice<Value>): Promise<$.Slice<Value>> {
|
|
806
989
|
if (this.Kind() !== Func || typeof this._value !== 'function') {
|
|
807
990
|
throw new ValueError({ Kind: this.Kind(), Method: 'Call' })
|
|
808
991
|
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
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' })
|
|
816
1003
|
}
|
|
817
|
-
return
|
|
1004
|
+
return await callReflectFunction(
|
|
1005
|
+
this._value as (...args: unknown[]) => unknown,
|
|
1006
|
+
this._type,
|
|
1007
|
+
inArgs,
|
|
1008
|
+
'CallSlice',
|
|
1009
|
+
)
|
|
818
1010
|
}
|
|
819
1011
|
|
|
820
1012
|
public IsZero(): boolean {
|
|
@@ -1149,10 +1341,7 @@ export class Value {
|
|
|
1149
1341
|
public Cap(): number {
|
|
1150
1342
|
const k = this.Kind()
|
|
1151
1343
|
if (k === Slice || k === Array) {
|
|
1152
|
-
|
|
1153
|
-
return this._value.length
|
|
1154
|
-
}
|
|
1155
|
-
return 0
|
|
1344
|
+
return $.cap(this._value as any)
|
|
1156
1345
|
}
|
|
1157
1346
|
if (k === Chan) {
|
|
1158
1347
|
return 0 // Simplified
|
|
@@ -1242,6 +1431,7 @@ export class BasicType implements Type {
|
|
|
1242
1431
|
private _name: string,
|
|
1243
1432
|
private _size: number = 8,
|
|
1244
1433
|
private _typeName: string = '',
|
|
1434
|
+
private _methods: $.MethodSignature[] = [],
|
|
1245
1435
|
) {}
|
|
1246
1436
|
|
|
1247
1437
|
public String(): string {
|
|
@@ -1252,6 +1442,10 @@ export class BasicType implements Type {
|
|
|
1252
1442
|
return this._kind
|
|
1253
1443
|
}
|
|
1254
1444
|
|
|
1445
|
+
public underlyingName(): string {
|
|
1446
|
+
return Kind_String(this._kind)
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1255
1449
|
public Comparable(): boolean {
|
|
1256
1450
|
return this._kind !== Func && this._kind !== Map && this._kind !== Slice
|
|
1257
1451
|
}
|
|
@@ -1268,6 +1462,26 @@ export class BasicType implements Type {
|
|
|
1268
1462
|
return 0
|
|
1269
1463
|
}
|
|
1270
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
|
+
|
|
1271
1485
|
public PkgPath(): string {
|
|
1272
1486
|
if (this._typeName) {
|
|
1273
1487
|
const dotIndex = this._typeName.lastIndexOf('.')
|
|
@@ -1315,7 +1529,7 @@ export class BasicType implements Type {
|
|
|
1315
1529
|
if (u.Kind() !== Interface) {
|
|
1316
1530
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1317
1531
|
}
|
|
1318
|
-
return
|
|
1532
|
+
return typeImplementsInterface(this, u)
|
|
1319
1533
|
}
|
|
1320
1534
|
|
|
1321
1535
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1386,10 +1600,18 @@ export class BasicType implements Type {
|
|
|
1386
1600
|
}
|
|
1387
1601
|
|
|
1388
1602
|
public NumMethod(): number {
|
|
1389
|
-
return
|
|
1603
|
+
return typeMethods(this).length
|
|
1390
1604
|
}
|
|
1391
|
-
public MethodByName(
|
|
1392
|
-
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)
|
|
1393
1615
|
}
|
|
1394
1616
|
|
|
1395
1617
|
public Len(): number {
|
|
@@ -1463,6 +1685,26 @@ class SliceType implements Type {
|
|
|
1463
1685
|
return 0
|
|
1464
1686
|
}
|
|
1465
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
|
+
|
|
1466
1708
|
public PkgPath(): string {
|
|
1467
1709
|
return ''
|
|
1468
1710
|
}
|
|
@@ -1497,7 +1739,7 @@ class SliceType implements Type {
|
|
|
1497
1739
|
if (u.Kind() !== Interface) {
|
|
1498
1740
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1499
1741
|
}
|
|
1500
|
-
return
|
|
1742
|
+
return typeImplementsInterface(this, u)
|
|
1501
1743
|
}
|
|
1502
1744
|
|
|
1503
1745
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1563,6 +1805,26 @@ class ArrayType implements Type {
|
|
|
1563
1805
|
return 0
|
|
1564
1806
|
}
|
|
1565
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
|
+
|
|
1566
1828
|
public Len(): number {
|
|
1567
1829
|
return this._len
|
|
1568
1830
|
}
|
|
@@ -1601,7 +1863,7 @@ class ArrayType implements Type {
|
|
|
1601
1863
|
if (u.Kind() !== Interface) {
|
|
1602
1864
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1603
1865
|
}
|
|
1604
|
-
return
|
|
1866
|
+
return typeImplementsInterface(this, u)
|
|
1605
1867
|
}
|
|
1606
1868
|
|
|
1607
1869
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1638,7 +1900,10 @@ class ArrayType implements Type {
|
|
|
1638
1900
|
|
|
1639
1901
|
// Pointer type implementation
|
|
1640
1902
|
class PointerType implements Type {
|
|
1641
|
-
constructor(
|
|
1903
|
+
constructor(
|
|
1904
|
+
private _elemType: Type,
|
|
1905
|
+
private _methods: $.MethodSignature[] = [],
|
|
1906
|
+
) {}
|
|
1642
1907
|
|
|
1643
1908
|
public String(): string {
|
|
1644
1909
|
return '*' + this._elemType.String()
|
|
@@ -1664,6 +1929,26 @@ class PointerType implements Type {
|
|
|
1664
1929
|
return 0
|
|
1665
1930
|
}
|
|
1666
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
|
+
|
|
1667
1952
|
public PkgPath(): string {
|
|
1668
1953
|
return ''
|
|
1669
1954
|
}
|
|
@@ -1698,9 +1983,7 @@ class PointerType implements Type {
|
|
|
1698
1983
|
if (u.Kind() !== Interface) {
|
|
1699
1984
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1700
1985
|
}
|
|
1701
|
-
|
|
1702
|
-
const elemTypeName = this._elemType.String()
|
|
1703
|
-
return typeImplementsInterface(elemTypeName, u)
|
|
1986
|
+
return typeImplementsInterface(this, u)
|
|
1704
1987
|
}
|
|
1705
1988
|
|
|
1706
1989
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1728,10 +2011,18 @@ class PointerType implements Type {
|
|
|
1728
2011
|
}
|
|
1729
2012
|
|
|
1730
2013
|
public NumMethod(): number {
|
|
1731
|
-
return
|
|
2014
|
+
return typeMethods(this).length
|
|
1732
2015
|
}
|
|
1733
2016
|
public MethodByName(name: string): [Method, boolean] {
|
|
1734
|
-
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)
|
|
1735
2026
|
}
|
|
1736
2027
|
|
|
1737
2028
|
public Len(): number {
|
|
@@ -1744,10 +2035,54 @@ class PointerType implements Type {
|
|
|
1744
2035
|
}
|
|
1745
2036
|
|
|
1746
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
|
+
|
|
1747
2047
|
class FunctionType implements Type {
|
|
1748
|
-
|
|
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
|
+
}
|
|
1749
2081
|
|
|
1750
2082
|
public String(): string {
|
|
2083
|
+
if (this._name !== '') {
|
|
2084
|
+
return this._name
|
|
2085
|
+
}
|
|
1751
2086
|
return this._signature
|
|
1752
2087
|
}
|
|
1753
2088
|
|
|
@@ -1771,12 +2106,54 @@ class FunctionType implements Type {
|
|
|
1771
2106
|
return 0
|
|
1772
2107
|
}
|
|
1773
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
|
+
|
|
1774
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
|
+
}
|
|
1775
2146
|
return ''
|
|
1776
2147
|
}
|
|
1777
2148
|
|
|
1778
2149
|
public Name(): string {
|
|
1779
|
-
|
|
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
|
+
}
|
|
1780
2157
|
return ''
|
|
1781
2158
|
}
|
|
1782
2159
|
|
|
@@ -1805,7 +2182,7 @@ class FunctionType implements Type {
|
|
|
1805
2182
|
if (u.Kind() !== Interface) {
|
|
1806
2183
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
1807
2184
|
}
|
|
1808
|
-
return
|
|
2185
|
+
return typeImplementsInterface(this, u)
|
|
1809
2186
|
}
|
|
1810
2187
|
|
|
1811
2188
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1829,10 +2206,29 @@ class FunctionType implements Type {
|
|
|
1829
2206
|
}
|
|
1830
2207
|
|
|
1831
2208
|
public NumMethod(): number {
|
|
1832
|
-
return
|
|
2209
|
+
return typeMethods(this).length
|
|
1833
2210
|
}
|
|
1834
|
-
public MethodByName(
|
|
1835
|
-
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
|
|
1836
2232
|
}
|
|
1837
2233
|
|
|
1838
2234
|
public Len(): number {
|
|
@@ -1844,72 +2240,329 @@ class FunctionType implements Type {
|
|
|
1844
2240
|
}
|
|
1845
2241
|
}
|
|
1846
2242
|
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
) {
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
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(', ')})`
|
|
1856
2263
|
}
|
|
2264
|
+
return signature
|
|
2265
|
+
}
|
|
1857
2266
|
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
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
|
+
}
|
|
1861
2278
|
|
|
1862
|
-
|
|
1863
|
-
return false
|
|
1864
|
-
}
|
|
2279
|
+
type ReflectCallOp = 'Call' | 'CallSlice'
|
|
1865
2280
|
|
|
1866
|
-
|
|
1867
|
-
|
|
2281
|
+
function reflectCallRawArgs(
|
|
2282
|
+
fnType: Type,
|
|
2283
|
+
args: Value[],
|
|
2284
|
+
op: ReflectCallOp,
|
|
2285
|
+
): unknown[] {
|
|
2286
|
+
if (op === 'CallSlice') {
|
|
2287
|
+
return reflectCallSliceRawArgs(fnType, args)
|
|
1868
2288
|
}
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
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
|
+
)
|
|
1872
2294
|
}
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
2295
|
+
const fixedCount = fnType.NumIn() - 1
|
|
2296
|
+
if (args.length < fixedCount) {
|
|
2297
|
+
throw new Error('reflect: Call with too few input arguments')
|
|
1876
2298
|
}
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
2299
|
+
const rawArgs: unknown[] = []
|
|
2300
|
+
for (let i = 0; i < fixedCount; i++) {
|
|
2301
|
+
rawArgs.push(reflectCallValueInterface(op, args[i], fnType.In(i), i))
|
|
1880
2302
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
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
|
+
}
|
|
1884
2315
|
}
|
|
2316
|
+
rawArgs.push($.arrayToSlice(variadicValues.map((value) => value.Interface())))
|
|
2317
|
+
return rawArgs
|
|
2318
|
+
}
|
|
1885
2319
|
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
2320
|
+
function reflectCallSliceRawArgs(fnType: Type, args: Value[]): unknown[] {
|
|
2321
|
+
if (!fnType.IsVariadic()) {
|
|
2322
|
+
throw new Error('reflect: CallSlice of non-variadic function')
|
|
1889
2323
|
}
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
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')
|
|
2327
|
+
}
|
|
2328
|
+
if (args.length > expected) {
|
|
2329
|
+
throw new Error('reflect: CallSlice with too many input arguments')
|
|
1893
2330
|
}
|
|
2331
|
+
return args.map((arg, index) =>
|
|
2332
|
+
reflectCallValueInterface('CallSlice', arg, fnType.In(index), index),
|
|
2333
|
+
)
|
|
2334
|
+
}
|
|
1894
2335
|
|
|
1895
|
-
|
|
1896
|
-
|
|
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`)
|
|
1897
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
|
+
}
|
|
1898
2352
|
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
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
|
+
)
|
|
1903
2359
|
}
|
|
2360
|
+
}
|
|
1904
2361
|
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
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
|
+
)
|
|
1911
2372
|
}
|
|
1912
|
-
return
|
|
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(
|
|
2553
|
+
match: (name: string) => boolean,
|
|
2554
|
+
): [StructField, boolean] {
|
|
2555
|
+
return typeFieldByNameFunc(this, match)
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
public Implements(u: Type | null): boolean {
|
|
2559
|
+
if (!u) {
|
|
2560
|
+
return false
|
|
2561
|
+
}
|
|
2562
|
+
if (u.Kind() !== Interface) {
|
|
2563
|
+
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
2564
|
+
}
|
|
2565
|
+
return typeImplementsInterface(this, u)
|
|
1913
2566
|
}
|
|
1914
2567
|
|
|
1915
2568
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -1949,61 +2602,174 @@ class MapType implements Type {
|
|
|
1949
2602
|
}
|
|
1950
2603
|
|
|
1951
2604
|
// Struct type implementation
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
*/
|
|
1960
|
-
function typeImplementsInterface(
|
|
1961
|
-
typeName: string,
|
|
1962
|
-
interfaceType: Type,
|
|
1963
|
-
): boolean {
|
|
1964
|
-
// Get the interface name and look it up in the type registry
|
|
1965
|
-
const interfaceName =
|
|
1966
|
-
interfaceType instanceof InterfaceType ?
|
|
1967
|
-
interfaceType.registeredName() || interfaceType.String()
|
|
1968
|
-
: interfaceType.String()
|
|
1969
|
-
const interfaceTypeInfo = builtinGetTypeByName(interfaceName)
|
|
1970
|
-
|
|
1971
|
-
if (!interfaceTypeInfo || !isInterfaceTypeInfo(interfaceTypeInfo)) {
|
|
1972
|
-
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')
|
|
2608
|
+
}
|
|
2609
|
+
const requiredMethods = typeMethods(interfaceType)
|
|
2610
|
+
if (requiredMethods.length === 0) {
|
|
2611
|
+
return true
|
|
1973
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
|
+
}
|
|
1974
2623
|
|
|
1975
|
-
|
|
1976
|
-
|
|
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
|
+
}
|
|
1977
2633
|
|
|
1978
|
-
|
|
2634
|
+
function methodArgListIdentical(
|
|
2635
|
+
actual: $.MethodArg[],
|
|
2636
|
+
required: $.MethodArg[],
|
|
2637
|
+
): boolean {
|
|
2638
|
+
if (actual.length !== required.length) {
|
|
1979
2639
|
return false
|
|
1980
2640
|
}
|
|
2641
|
+
return actual.every(
|
|
2642
|
+
(arg, index) =>
|
|
2643
|
+
methodArgIdentityKey(arg) === methodArgIdentityKey(required[index]),
|
|
2644
|
+
)
|
|
2645
|
+
}
|
|
1981
2646
|
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
2647
|
+
function methodArgIdentityKey(arg: $.MethodArg): string {
|
|
2648
|
+
return typeInfoIdentityKey(arg.type, new Set())
|
|
2649
|
+
}
|
|
1985
2650
|
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
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
|
+
}
|
|
1989
2656
|
|
|
1990
|
-
|
|
1991
|
-
|
|
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
|
|
1992
2672
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
2673
|
+
if (
|
|
2674
|
+
methodSignatureIdentityKey(merged[existingIndex]) !==
|
|
2675
|
+
methodSignatureIdentityKey(method)
|
|
2676
|
+
) {
|
|
2677
|
+
merged[existingIndex] = method
|
|
1997
2678
|
}
|
|
2679
|
+
}
|
|
2680
|
+
return merged.sort((left, right) => left.name.localeCompare(right.name))
|
|
2681
|
+
}
|
|
1998
2682
|
|
|
1999
|
-
|
|
2000
|
-
|
|
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}`
|
|
2001
2691
|
}
|
|
2002
|
-
|
|
2003
|
-
|
|
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'
|
|
2004
2772
|
}
|
|
2005
|
-
|
|
2006
|
-
return true
|
|
2007
2773
|
}
|
|
2008
2774
|
|
|
2009
2775
|
function typeFieldByName(t: Type, name: string): [StructField, boolean] {
|
|
@@ -2017,8 +2783,7 @@ function typeFieldByNameFunc(
|
|
|
2017
2783
|
if (t.Kind() !== Struct) {
|
|
2018
2784
|
throw new Error('reflect: FieldByName of non-struct type')
|
|
2019
2785
|
}
|
|
2020
|
-
for (
|
|
2021
|
-
const field = t.Field(i)
|
|
2786
|
+
for (const field of visibleStructFields(t)) {
|
|
2022
2787
|
if (match(field.Name)) {
|
|
2023
2788
|
return [field, true]
|
|
2024
2789
|
}
|
|
@@ -2026,6 +2791,59 @@ function typeFieldByNameFunc(
|
|
|
2026
2791
|
return [new StructField(), false]
|
|
2027
2792
|
}
|
|
2028
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
|
+
|
|
2029
2847
|
function zeroMethod(): Method {
|
|
2030
2848
|
return {
|
|
2031
2849
|
Name: '',
|
|
@@ -2038,17 +2856,65 @@ function zeroMethod(): Method {
|
|
|
2038
2856
|
function methodFromSignature(
|
|
2039
2857
|
signature: $.MethodSignature,
|
|
2040
2858
|
index: number,
|
|
2859
|
+
receiver: Type,
|
|
2041
2860
|
): Method {
|
|
2042
2861
|
return {
|
|
2043
2862
|
Name: signature.name,
|
|
2044
|
-
Type:
|
|
2863
|
+
Type: methodTypeFromSignature(
|
|
2864
|
+
signature,
|
|
2865
|
+
receiver,
|
|
2866
|
+
receiver.Kind() !== Interface,
|
|
2867
|
+
),
|
|
2045
2868
|
Func: () => undefined,
|
|
2046
2869
|
Index: index,
|
|
2047
2870
|
}
|
|
2048
2871
|
}
|
|
2049
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
|
+
|
|
2050
2892
|
function typeMethods(t: Type): $.MethodSignature[] {
|
|
2051
|
-
|
|
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
|
+
}
|
|
2052
2918
|
if (!typeInfo) {
|
|
2053
2919
|
return []
|
|
2054
2920
|
}
|
|
@@ -2058,30 +2924,119 @@ function typeMethods(t: Type): $.MethodSignature[] {
|
|
|
2058
2924
|
return []
|
|
2059
2925
|
}
|
|
2060
2926
|
|
|
2061
|
-
function
|
|
2927
|
+
function methodSignatureByName(
|
|
2928
|
+
t: Type,
|
|
2929
|
+
name: string,
|
|
2930
|
+
): [$.MethodSignature | undefined, number] {
|
|
2062
2931
|
const methods = typeMethods(t)
|
|
2063
2932
|
const index = methods.findIndex((method) => method.name === name)
|
|
2064
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) {
|
|
2065
2942
|
return [zeroMethod(), false]
|
|
2066
2943
|
}
|
|
2067
|
-
return [methodFromSignature(
|
|
2944
|
+
return [methodFromSignature(signature, index, t), true]
|
|
2068
2945
|
}
|
|
2069
2946
|
|
|
2070
2947
|
function typeAssignableTo(t: Type, u: Type | null): boolean {
|
|
2071
2948
|
if (u === null) {
|
|
2072
2949
|
return false
|
|
2073
2950
|
}
|
|
2074
|
-
|
|
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)
|
|
2075
3028
|
}
|
|
2076
3029
|
|
|
2077
3030
|
class StructType implements Type {
|
|
2078
3031
|
constructor(
|
|
2079
3032
|
private _name: string,
|
|
2080
|
-
private _fields:
|
|
3033
|
+
private _fields: StructFieldDescriptor[] = [],
|
|
3034
|
+
private _pkgPath = '',
|
|
3035
|
+
private _string = _name,
|
|
2081
3036
|
) {}
|
|
2082
3037
|
|
|
2083
3038
|
public String(): string {
|
|
2084
|
-
return this.
|
|
3039
|
+
return this._string
|
|
2085
3040
|
}
|
|
2086
3041
|
|
|
2087
3042
|
public Kind(): Kind {
|
|
@@ -2093,8 +3048,7 @@ class StructType implements Type {
|
|
|
2093
3048
|
}
|
|
2094
3049
|
|
|
2095
3050
|
public Size(): number {
|
|
2096
|
-
|
|
2097
|
-
return this._fields.reduce((sum, field) => sum + field.type.Size(), 0)
|
|
3051
|
+
return structDescriptorSize(this._fields)
|
|
2098
3052
|
}
|
|
2099
3053
|
|
|
2100
3054
|
public Elem(): Type {
|
|
@@ -2105,7 +3059,33 @@ class StructType implements Type {
|
|
|
2105
3059
|
return this._fields.length
|
|
2106
3060
|
}
|
|
2107
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
|
+
|
|
2108
3082
|
public PkgPath(): string {
|
|
3083
|
+
if (this._pkgPath !== '') {
|
|
3084
|
+
return this._pkgPath
|
|
3085
|
+
}
|
|
3086
|
+
if (this._name === '') {
|
|
3087
|
+
return ''
|
|
3088
|
+
}
|
|
2109
3089
|
// Extract package path from full type name (e.g., "main.Person" -> "main")
|
|
2110
3090
|
const dotIndex = this._name.lastIndexOf('.')
|
|
2111
3091
|
if (dotIndex > 0) {
|
|
@@ -2115,6 +3095,9 @@ class StructType implements Type {
|
|
|
2115
3095
|
}
|
|
2116
3096
|
|
|
2117
3097
|
public Name(): string {
|
|
3098
|
+
if (this._name === '') {
|
|
3099
|
+
return ''
|
|
3100
|
+
}
|
|
2118
3101
|
// Extract type name from full type name (e.g., "main.Person" -> "Person")
|
|
2119
3102
|
const dotIndex = this._name.lastIndexOf('.')
|
|
2120
3103
|
if (dotIndex >= 0) {
|
|
@@ -2132,13 +3115,68 @@ class StructType implements Type {
|
|
|
2132
3115
|
const f = this._fields[i]
|
|
2133
3116
|
return new StructField({
|
|
2134
3117
|
Name: f.name,
|
|
2135
|
-
PkgPath:
|
|
3118
|
+
PkgPath: f.pkgPath,
|
|
2136
3119
|
Type: f.type,
|
|
2137
3120
|
Tag: f.tag ? new StructTag(f.tag) : undefined,
|
|
2138
|
-
|
|
3121
|
+
Offset: f.offset,
|
|
3122
|
+
Index: [...f.index],
|
|
3123
|
+
Anonymous: f.anonymous,
|
|
2139
3124
|
})
|
|
2140
3125
|
}
|
|
2141
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
|
+
|
|
2142
3180
|
public FieldByName(name: string): [StructField, boolean] {
|
|
2143
3181
|
return typeFieldByName(this, name)
|
|
2144
3182
|
}
|
|
@@ -2160,7 +3198,7 @@ class StructType implements Type {
|
|
|
2160
3198
|
if (u.Kind() !== Interface) {
|
|
2161
3199
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
2162
3200
|
}
|
|
2163
|
-
return typeImplementsInterface(this
|
|
3201
|
+
return typeImplementsInterface(this, u)
|
|
2164
3202
|
}
|
|
2165
3203
|
|
|
2166
3204
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -2201,7 +3239,7 @@ class StructType implements Type {
|
|
|
2201
3239
|
throw new Error('reflect: call of reflect.Type.Bits on struct Type')
|
|
2202
3240
|
}
|
|
2203
3241
|
|
|
2204
|
-
static createTypeFromFieldInfo(ti: any): Type {
|
|
3242
|
+
static createTypeFromFieldInfo(ti: any, seen = new Set<string>()): Type {
|
|
2205
3243
|
if (typeof ti === 'string') {
|
|
2206
3244
|
return basicTypeFromName(ti === 'number' ? 'int' : ti)
|
|
2207
3245
|
} else if (ti && ti.kind) {
|
|
@@ -2214,21 +3252,29 @@ class StructType implements Type {
|
|
|
2214
3252
|
case 'slice':
|
|
2215
3253
|
if (ti.elemType) {
|
|
2216
3254
|
return new SliceType(
|
|
2217
|
-
StructType.createTypeFromFieldInfo(ti.elemType),
|
|
3255
|
+
StructType.createTypeFromFieldInfo(ti.elemType, seen),
|
|
2218
3256
|
)
|
|
2219
3257
|
}
|
|
2220
3258
|
return new SliceType(new BasicType(Invalid, 'unknown', 8))
|
|
2221
3259
|
case 'pointer':
|
|
2222
3260
|
if (ti.elemType) {
|
|
2223
3261
|
return new PointerType(
|
|
2224
|
-
StructType.createTypeFromFieldInfo(ti.elemType),
|
|
3262
|
+
StructType.createTypeFromFieldInfo(ti.elemType, seen),
|
|
2225
3263
|
)
|
|
2226
3264
|
}
|
|
2227
3265
|
return new PointerType(new BasicType(Invalid, 'unknown', 8))
|
|
2228
3266
|
case 'interface':
|
|
2229
|
-
return
|
|
2230
|
-
case 'struct':
|
|
2231
|
-
|
|
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
|
+
}
|
|
2232
3278
|
default:
|
|
2233
3279
|
return new BasicType(Invalid, name, 8)
|
|
2234
3280
|
}
|
|
@@ -2282,18 +3328,19 @@ function basicTypeFromName(name: string, typeName = ''): BasicType {
|
|
|
2282
3328
|
|
|
2283
3329
|
function structFieldsFromTypeInfo(
|
|
2284
3330
|
ti: $.StructTypeInfo,
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
return {
|
|
2289
|
-
name: fieldInfo.name ?? name,
|
|
2290
|
-
type: typeFromTypeInfo(fieldInfo.type),
|
|
2291
|
-
tag: fieldInfo.tag,
|
|
2292
|
-
}
|
|
2293
|
-
}
|
|
3331
|
+
seen = new Set<string>(),
|
|
3332
|
+
): StructFieldDescriptor[] {
|
|
3333
|
+
return (ti.fields || []).map((fieldInfo, index) => {
|
|
2294
3334
|
return {
|
|
2295
|
-
name,
|
|
2296
|
-
|
|
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 ?? '') === '',
|
|
2297
3344
|
}
|
|
2298
3345
|
})
|
|
2299
3346
|
}
|
|
@@ -2339,6 +3386,26 @@ class ChannelType implements Type {
|
|
|
2339
3386
|
return 0
|
|
2340
3387
|
}
|
|
2341
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
|
+
|
|
2342
3409
|
public PkgPath(): string {
|
|
2343
3410
|
return ''
|
|
2344
3411
|
}
|
|
@@ -2373,7 +3440,7 @@ class ChannelType implements Type {
|
|
|
2373
3440
|
if (u.Kind() !== Interface) {
|
|
2374
3441
|
throw new Error('reflect: non-interface type passed to Type.Implements')
|
|
2375
3442
|
}
|
|
2376
|
-
return
|
|
3443
|
+
return typeImplementsInterface(this, u)
|
|
2377
3444
|
}
|
|
2378
3445
|
|
|
2379
3446
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -2421,6 +3488,7 @@ class InterfaceType implements Type {
|
|
|
2421
3488
|
constructor(
|
|
2422
3489
|
private _name: string = 'interface{}',
|
|
2423
3490
|
private _registeredName?: string,
|
|
3491
|
+
private _methods: $.MethodSignature[] = [],
|
|
2424
3492
|
) {}
|
|
2425
3493
|
|
|
2426
3494
|
public String(): string {
|
|
@@ -2447,6 +3515,26 @@ class InterfaceType implements Type {
|
|
|
2447
3515
|
return 0
|
|
2448
3516
|
}
|
|
2449
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
|
+
|
|
2450
3538
|
public PkgPath(): string {
|
|
2451
3539
|
if (this._name === 'interface{}' || this._name.startsWith('interface {')) {
|
|
2452
3540
|
return ''
|
|
@@ -2487,8 +3575,14 @@ class InterfaceType implements Type {
|
|
|
2487
3575
|
throw new Error('reflect: Key of non-map type')
|
|
2488
3576
|
}
|
|
2489
3577
|
|
|
2490
|
-
public Implements(
|
|
2491
|
-
|
|
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)
|
|
2492
3586
|
}
|
|
2493
3587
|
|
|
2494
3588
|
public AssignableTo(u: Type | null): boolean {
|
|
@@ -2536,6 +3630,10 @@ class InterfaceType implements Type {
|
|
|
2536
3630
|
public registeredName(): string | undefined {
|
|
2537
3631
|
return this._registeredName
|
|
2538
3632
|
}
|
|
3633
|
+
|
|
3634
|
+
public methodSignatures(): $.MethodSignature[] {
|
|
3635
|
+
return this._methods
|
|
3636
|
+
}
|
|
2539
3637
|
}
|
|
2540
3638
|
|
|
2541
3639
|
function getTypeOf(value: ReflectValue): Type {
|
|
@@ -2583,24 +3681,20 @@ function getTypeOf(value: ReflectValue): Type {
|
|
|
2583
3681
|
typeInfo.params &&
|
|
2584
3682
|
typeInfo.results
|
|
2585
3683
|
) {
|
|
3684
|
+
if (funcWithMeta.__goTypeName && !typeInfo.name) {
|
|
3685
|
+
return functionTypeFromInfo({
|
|
3686
|
+
...typeInfo,
|
|
3687
|
+
name: funcWithMeta.__goTypeName,
|
|
3688
|
+
})
|
|
3689
|
+
}
|
|
2586
3690
|
return functionTypeFromInfo(typeInfo)
|
|
2587
3691
|
}
|
|
2588
3692
|
}
|
|
2589
3693
|
|
|
2590
3694
|
// Then check for __goTypeName which indicates a typed function
|
|
2591
3695
|
if (funcWithMeta.__goTypeName) {
|
|
2592
|
-
// This is a typed Go function - try to reconstruct the signature
|
|
2593
3696
|
const typeName = funcWithMeta.__goTypeName
|
|
2594
|
-
|
|
2595
|
-
// For known Go function types, construct proper signatures
|
|
2596
|
-
if (typeName === 'Greeter') {
|
|
2597
|
-
return new FunctionType('func(string) string')
|
|
2598
|
-
} else if (typeName === 'Adder') {
|
|
2599
|
-
return new FunctionType('func(int, int) int')
|
|
2600
|
-
}
|
|
2601
|
-
|
|
2602
|
-
// Generic fallback for typed functions
|
|
2603
|
-
return new FunctionType(`func`) // Could be enhanced with parameter parsing
|
|
3697
|
+
return new FunctionType({ name: typeName })
|
|
2604
3698
|
}
|
|
2605
3699
|
|
|
2606
3700
|
// For untyped functions, try to parse the signature
|
|
@@ -2734,6 +3828,19 @@ function getTypeOf(value: ReflectValue): Type {
|
|
|
2734
3828
|
}
|
|
2735
3829
|
|
|
2736
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
|
+
|
|
2737
3844
|
if (
|
|
2738
3845
|
value &&
|
|
2739
3846
|
typeof value === 'object' &&
|
|
@@ -2741,34 +3848,19 @@ function getTypeOf(value: ReflectValue): Type {
|
|
|
2741
3848
|
'__typeInfo' in value.constructor
|
|
2742
3849
|
) {
|
|
2743
3850
|
const typeInfo = (
|
|
2744
|
-
value.constructor as { __typeInfo?:
|
|
3851
|
+
value.constructor as { __typeInfo?: $.StructTypeInfo }
|
|
2745
3852
|
).__typeInfo
|
|
2746
|
-
if (typeInfo && typeInfo
|
|
2747
|
-
const
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
: `main.${typeInfo.name}`
|
|
2751
|
-
const regTypeInfo = builtinGetTypeByName(typeName)
|
|
2752
|
-
let fields: Array<{ name: string; type: Type; tag?: string }> = []
|
|
2753
|
-
if (regTypeInfo && isStructTypeInfo(regTypeInfo)) {
|
|
2754
|
-
fields = Object.entries(regTypeInfo.fields || {}).map(
|
|
2755
|
-
([name, fieldInfo]) => {
|
|
2756
|
-
// Check if fieldInfo is a StructFieldInfo with type and tag
|
|
2757
|
-
if (isStructFieldInfo(fieldInfo)) {
|
|
2758
|
-
return {
|
|
2759
|
-
name: fieldInfo.name ?? name,
|
|
2760
|
-
type: StructType.createTypeFromFieldInfo(fieldInfo.type),
|
|
2761
|
-
tag: fieldInfo.tag,
|
|
2762
|
-
}
|
|
2763
|
-
}
|
|
2764
|
-
// Otherwise it's just the type info directly (backwards compatible)
|
|
2765
|
-
return {
|
|
2766
|
-
name,
|
|
2767
|
-
type: StructType.createTypeFromFieldInfo(fieldInfo),
|
|
2768
|
-
}
|
|
2769
|
-
},
|
|
2770
|
-
)
|
|
3853
|
+
if (typeInfo && isStructTypeInfo(typeInfo)) {
|
|
3854
|
+
const name = typeInfo.name ?? ''
|
|
3855
|
+
if (name === '') {
|
|
3856
|
+
return new StructType('', structFieldsFromTypeInfo(typeInfo))
|
|
2771
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)
|
|
2772
3864
|
return new StructType(typeName, fields)
|
|
2773
3865
|
}
|
|
2774
3866
|
}
|
|
@@ -2832,20 +3924,168 @@ export function ChanOf(dir: ChanDir, t: Type): Type {
|
|
|
2832
3924
|
return internType(new ChannelType(t, dir))
|
|
2833
3925
|
}
|
|
2834
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
|
+
|
|
2835
4070
|
export function TypeFor(typeArgs?: $.GenericTypeArgs): Type {
|
|
2836
4071
|
const descriptor = typeArgs?.T
|
|
4072
|
+
const methodSignatures = genericMethodSignatures(descriptor)
|
|
2837
4073
|
if (descriptor?.type) {
|
|
2838
|
-
return internType(
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
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
|
+
)
|
|
2849
4089
|
}
|
|
2850
4090
|
if (descriptor?.zero) {
|
|
2851
4091
|
return internType(getTypeOf(descriptor.zero()))
|
|
@@ -2853,113 +4093,475 @@ export function TypeFor(typeArgs?: $.GenericTypeArgs): Type {
|
|
|
2853
4093
|
return internType(new InterfaceType('interface{}'))
|
|
2854
4094
|
}
|
|
2855
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
|
+
|
|
2856
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 {
|
|
2857
4145
|
if (typeof info === 'string') {
|
|
2858
4146
|
const registered = builtinGetTypeByName(info)
|
|
2859
4147
|
if (registered) {
|
|
2860
|
-
|
|
4148
|
+
const typ = typeFromTypeInfoWithSeen(registered, seen)
|
|
4149
|
+
return internType(typ)
|
|
2861
4150
|
}
|
|
2862
|
-
return internType(StructType.createTypeFromFieldInfo(info))
|
|
4151
|
+
return internType(StructType.createTypeFromFieldInfo(info, seen))
|
|
2863
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 ?? ''
|
|
4185
|
+
}
|
|
4186
|
+
return info.name ?? ''
|
|
4187
|
+
}
|
|
4188
|
+
|
|
4189
|
+
function typeFromStructuredTypeInfoWithSeen(
|
|
4190
|
+
info: $.TypeInfo,
|
|
4191
|
+
seen: Set<string>,
|
|
4192
|
+
): Type {
|
|
2864
4193
|
switch (info.kind) {
|
|
2865
4194
|
case $.TypeKind.Array:
|
|
2866
|
-
return
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
),
|
|
2871
|
-
info.length,
|
|
4195
|
+
return new ArrayType(
|
|
4196
|
+
typeFromTypeInfoWithSeen(
|
|
4197
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4198
|
+
seen,
|
|
2872
4199
|
),
|
|
4200
|
+
info.length,
|
|
2873
4201
|
)
|
|
2874
4202
|
case $.TypeKind.Basic:
|
|
2875
|
-
return
|
|
4203
|
+
return StructType.createTypeFromFieldInfo(info, seen)
|
|
2876
4204
|
case $.TypeKind.Channel:
|
|
2877
|
-
return
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
),
|
|
2882
|
-
chanDirFromTypeInfo(info.direction),
|
|
4205
|
+
return new ChannelType(
|
|
4206
|
+
typeFromTypeInfoWithSeen(
|
|
4207
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4208
|
+
seen,
|
|
2883
4209
|
),
|
|
4210
|
+
chanDirFromTypeInfo(info.direction),
|
|
2884
4211
|
)
|
|
2885
4212
|
case $.TypeKind.Function:
|
|
2886
|
-
return
|
|
4213
|
+
return functionTypeFromInfo(info, seen)
|
|
2887
4214
|
case $.TypeKind.Interface:
|
|
2888
|
-
return
|
|
4215
|
+
return interfaceTypeFromInfo(info, seen)
|
|
2889
4216
|
case $.TypeKind.Map:
|
|
2890
|
-
return
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
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,
|
|
2898
4225
|
),
|
|
2899
4226
|
)
|
|
2900
4227
|
case $.TypeKind.Slice:
|
|
2901
|
-
return
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
),
|
|
4228
|
+
return new SliceType(
|
|
4229
|
+
typeFromTypeInfoWithSeen(
|
|
4230
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4231
|
+
seen,
|
|
2906
4232
|
),
|
|
2907
4233
|
)
|
|
2908
4234
|
case $.TypeKind.Struct:
|
|
2909
|
-
return
|
|
4235
|
+
return StructType.createTypeFromFieldInfo(info, seen)
|
|
2910
4236
|
case $.TypeKind.Pointer:
|
|
2911
|
-
return
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
),
|
|
4237
|
+
return new PointerType(
|
|
4238
|
+
typeFromTypeInfoWithSeen(
|
|
4239
|
+
info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' },
|
|
4240
|
+
seen,
|
|
2916
4241
|
),
|
|
2917
4242
|
)
|
|
2918
4243
|
default:
|
|
2919
|
-
return
|
|
4244
|
+
return StructType.createTypeFromFieldInfo(info, seen)
|
|
2920
4245
|
}
|
|
2921
4246
|
}
|
|
2922
4247
|
|
|
2923
|
-
function
|
|
2924
|
-
|
|
2925
|
-
|
|
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)
|
|
2926
4264
|
}
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
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,
|
|
2937
4282
|
})
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
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)))
|
|
2942
4293
|
}
|
|
2943
|
-
|
|
2944
|
-
|
|
4294
|
+
const info: $.FunctionTypeInfo = {
|
|
4295
|
+
kind: $.TypeKind.Function,
|
|
4296
|
+
params,
|
|
4297
|
+
results,
|
|
4298
|
+
}
|
|
4299
|
+
if (typ.Name() !== '') {
|
|
4300
|
+
info.name = typ.String()
|
|
4301
|
+
}
|
|
4302
|
+
if (typ.IsVariadic()) {
|
|
4303
|
+
info.isVariadic = true
|
|
4304
|
+
}
|
|
4305
|
+
return info
|
|
4306
|
+
}
|
|
4307
|
+
|
|
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()
|
|
2945
4408
|
}
|
|
2946
|
-
return new FunctionType(signature)
|
|
2947
4409
|
}
|
|
2948
4410
|
|
|
2949
|
-
function
|
|
2950
|
-
|
|
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'
|
|
2951
4421
|
}
|
|
2952
4422
|
|
|
2953
|
-
function interfaceTypeFromInfo(
|
|
2954
|
-
|
|
2955
|
-
|
|
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)
|
|
2956
4430
|
}
|
|
2957
4431
|
return new InterfaceType(
|
|
2958
|
-
|
|
4432
|
+
interfaceTypeString(methods, seen),
|
|
2959
4433
|
info.name,
|
|
4434
|
+
methods,
|
|
2960
4435
|
)
|
|
2961
4436
|
}
|
|
2962
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
|
+
|
|
2963
4565
|
function chanDirFromTypeInfo(direction?: 'send' | 'receive' | 'both'): ChanDir {
|
|
2964
4566
|
switch (direction) {
|
|
2965
4567
|
case 'send':
|
|
@@ -2977,38 +4579,16 @@ function chanDirFromTypeInfo(direction?: 'send' | 'receive' | 'both'): ChanDir {
|
|
|
2977
4579
|
*/
|
|
2978
4580
|
export function getInterfaceTypeByName(name: string): Type {
|
|
2979
4581
|
const typeInfo = builtinGetTypeByName(name)
|
|
2980
|
-
if (typeInfo && typeInfo
|
|
2981
|
-
return new InterfaceType(name, name)
|
|
4582
|
+
if (typeInfo && isInterfaceTypeInfo(typeInfo)) {
|
|
4583
|
+
return new InterfaceType(name, name, typeInfo.methods ?? [])
|
|
2982
4584
|
}
|
|
2983
4585
|
return new InterfaceType('interface{}')
|
|
2984
4586
|
}
|
|
2985
4587
|
|
|
2986
4588
|
export function getInterfaceLiteralTypeByName(name: string): Type {
|
|
2987
4589
|
const typeInfo = builtinGetTypeByName(name)
|
|
2988
|
-
if (typeInfo && typeInfo
|
|
2989
|
-
|
|
2990
|
-
if (methods.length === 0) {
|
|
2991
|
-
return new InterfaceType('interface{}', name)
|
|
2992
|
-
}
|
|
2993
|
-
const methodSigs = methods
|
|
2994
|
-
.map((m: any) => {
|
|
2995
|
-
const args =
|
|
2996
|
-
m.args
|
|
2997
|
-
?.map((a: any) => (typeof a === 'string' ? a : 'any'))
|
|
2998
|
-
.join(', ') || ''
|
|
2999
|
-
const returns = m.returns?.map((r: any) =>
|
|
3000
|
-
typeof r === 'string' ? r : 'any',
|
|
3001
|
-
)
|
|
3002
|
-
let returnSig = ''
|
|
3003
|
-
if (returns && returns.length === 1) {
|
|
3004
|
-
returnSig = ` ${returns[0]}`
|
|
3005
|
-
} else if (returns && returns.length > 1) {
|
|
3006
|
-
returnSig = ` (${returns.join(', ')})`
|
|
3007
|
-
}
|
|
3008
|
-
return `${m.name}(${args})${returnSig}`
|
|
3009
|
-
})
|
|
3010
|
-
.join('; ')
|
|
3011
|
-
return new InterfaceType(`interface { ${methodSigs} }`, name)
|
|
4590
|
+
if (typeInfo && isInterfaceTypeInfo(typeInfo)) {
|
|
4591
|
+
return interfaceTypeFromInfo(typeInfo)
|
|
3012
4592
|
}
|
|
3013
4593
|
return new InterfaceType('interface{}')
|
|
3014
4594
|
}
|