goscript 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cmd/goscript-wasm/main.go +38 -6
- package/compiler/diagnostic.go +104 -12
- package/compiler/diagnostic_test.go +106 -0
- package/compiler/gotest/runner.go +1 -17
- package/compiler/gotest/runner_test.go +20 -0
- package/compiler/index.test.ts +23 -0
- package/compiler/lowered-program.go +9 -7
- package/compiler/lowering.go +359 -72
- package/compiler/lowering_bench_test.go +1 -0
- package/compiler/lowering_internal_test.go +18 -0
- package/compiler/protobuf-ts-binding.go +65 -12
- package/compiler/protobuf-ts-binding_test.go +230 -0
- package/compiler/runtime-contract.go +4 -0
- package/compiler/runtime-contract_test.go +2 -0
- package/compiler/service.go +1 -0
- package/compiler/skeleton_test.go +56 -2
- package/compiler/wasm/compile_test.go +37 -4
- package/compiler/wasm-api.go +57 -7
- package/dist/gs/builtin/hostio.js +5 -0
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +11 -1
- package/dist/gs/builtin/slice.js +158 -2
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +30 -5
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +1 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +17 -11
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
- package/dist/gs/internal/byteorder/index.js +2 -2
- package/dist/gs/internal/byteorder/index.js.map +1 -1
- package/dist/gs/reflect/type.js +57 -0
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/sync/atomic/doc_64.gs.js +7 -6
- package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
- package/gs/builtin/hostio.test.ts +16 -0
- package/gs/builtin/hostio.ts +7 -0
- package/gs/builtin/runtime-contract.test.ts +28 -0
- package/gs/builtin/slice.ts +225 -20
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +162 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +41 -5
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +18 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +17 -11
- package/gs/internal/byteorder/index.test.ts +2 -2
- package/gs/internal/byteorder/index.ts +2 -2
- package/gs/reflect/type.ts +64 -0
- package/gs/reflect/typefor.test.ts +21 -1
- package/gs/sync/atomic/doc_64.gs.ts +6 -7
- package/gs/sync/atomic/doc_64.test.ts +43 -0
- package/package.json +1 -1
package/compiler/lowering.go
CHANGED
|
@@ -28,6 +28,8 @@ type LoweringOwner struct {
|
|
|
28
28
|
type LoweringOptions struct {
|
|
29
29
|
// SourceRoot is the request source root that may contain sibling protobuf TypeScript files.
|
|
30
30
|
SourceRoot string
|
|
31
|
+
// DisplayRoot is the request root used to format source file names in diagnostics.
|
|
32
|
+
DisplayRoot string
|
|
31
33
|
// OutputPath is the TypeScript output root used for generated relative imports.
|
|
32
34
|
OutputPath string
|
|
33
35
|
// ProtobufTypeScriptBinding binds .pb.go files to sibling .pb.ts files.
|
|
@@ -141,6 +143,7 @@ func (o *LoweringOwner) lowerPackage(
|
|
|
141
143
|
lazyPackageVarsByPkg,
|
|
142
144
|
runtimeMethodSets,
|
|
143
145
|
protobufAdapter,
|
|
146
|
+
options.DisplayRoot,
|
|
144
147
|
)
|
|
145
148
|
diagnostics = append(diagnostics, fileDiagnostics...)
|
|
146
149
|
rewriteProtobufTypeScriptBindingFile(loweredFile, binding)
|
|
@@ -160,6 +163,7 @@ func (o *LoweringOwner) lowerPackage(
|
|
|
160
163
|
lazyPackageVarsByPkg,
|
|
161
164
|
runtimeMethodSets,
|
|
162
165
|
false,
|
|
166
|
+
options.DisplayRoot,
|
|
163
167
|
)
|
|
164
168
|
diagnostics = append(diagnostics, fileDiagnostics...)
|
|
165
169
|
if loweredFile != nil {
|
|
@@ -195,6 +199,7 @@ func (o *LoweringOwner) lowerFile(
|
|
|
195
199
|
lazyPackageVarsByPkg map[string]map[types.Object]bool,
|
|
196
200
|
runtimeMethodSets runtimeMethodSetCache,
|
|
197
201
|
protobufTypeScriptAdapter bool,
|
|
202
|
+
displayRoot string,
|
|
198
203
|
) (*loweredFile, []Diagnostic) {
|
|
199
204
|
associatedMethods := o.methodDeclsForFileTypes(semPkg, file)
|
|
200
205
|
relevantImportFiles := map[string]bool{sourcePath: true}
|
|
@@ -315,6 +320,7 @@ func (o *LoweringOwner) lowerFile(
|
|
|
315
320
|
tempNames: newTempNameOwner(),
|
|
316
321
|
topLevel: true,
|
|
317
322
|
protobufTSAdapter: protobufTypeScriptAdapter,
|
|
323
|
+
displayRoot: displayRoot,
|
|
318
324
|
}
|
|
319
325
|
var diagnostics []Diagnostic
|
|
320
326
|
var packageInitCalls []string
|
|
@@ -1120,6 +1126,28 @@ type lowerFileContext struct {
|
|
|
1120
1126
|
switchBreak bool
|
|
1121
1127
|
topLevel bool
|
|
1122
1128
|
protobufTSAdapter bool
|
|
1129
|
+
displayRoot string
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
func (ctx lowerFileContext) diagnosticPosition(pos token.Pos) *DiagnosticPosition {
|
|
1133
|
+
if ctx.semPkg == nil {
|
|
1134
|
+
return nil
|
|
1135
|
+
}
|
|
1136
|
+
return diagnosticPositionFromSource(sourcePos(ctx.semPkg.source, pos), ctx.displayRoot)
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
func loweringUnsupportedAt(ctx lowerFileContext, node ast.Node, kind string, subject string, detail string) Diagnostic {
|
|
1140
|
+
diag := loweringUnsupported(kind, subject, detail)
|
|
1141
|
+
if node != nil {
|
|
1142
|
+
diag.Position = ctx.diagnosticPosition(node.Pos())
|
|
1143
|
+
}
|
|
1144
|
+
return diag
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
func loweringUnsupportedPos(ctx lowerFileContext, pos token.Pos, kind string, subject string, detail string) Diagnostic {
|
|
1148
|
+
diag := loweringUnsupported(kind, subject, detail)
|
|
1149
|
+
diag.Position = ctx.diagnosticPosition(pos)
|
|
1150
|
+
return diag
|
|
1123
1151
|
}
|
|
1124
1152
|
|
|
1125
1153
|
type tempNameOwner struct {
|
|
@@ -1208,7 +1236,7 @@ func (o *LoweringOwner) lowerDecl(ctx lowerFileContext, decl ast.Decl) ([]lowere
|
|
|
1208
1236
|
if receiver := receiverNamedTypeFromDecl(ctx, typed); receiver != nil && namedStructType(receiver) == nil {
|
|
1209
1237
|
fn, diagnostics := o.lowerNamedReceiverMethodDecl(ctx, typed, receiver)
|
|
1210
1238
|
if fn == nil {
|
|
1211
|
-
return nil, []Diagnostic{
|
|
1239
|
+
return nil, []Diagnostic{loweringUnsupportedAt(ctx, typed, "function", typed.Name.Name, "missing type information")}
|
|
1212
1240
|
}
|
|
1213
1241
|
return []loweredDecl{{function: fn}}, diagnostics
|
|
1214
1242
|
}
|
|
@@ -1216,11 +1244,11 @@ func (o *LoweringOwner) lowerDecl(ctx lowerFileContext, decl ast.Decl) ([]lowere
|
|
|
1216
1244
|
}
|
|
1217
1245
|
fn, diagnostics := o.lowerFuncDecl(ctx, typed)
|
|
1218
1246
|
if fn == nil {
|
|
1219
|
-
return nil, []Diagnostic{
|
|
1247
|
+
return nil, []Diagnostic{loweringUnsupportedAt(ctx, typed, "function", typed.Name.Name, "missing type information")}
|
|
1220
1248
|
}
|
|
1221
1249
|
return []loweredDecl{{function: fn}}, diagnostics
|
|
1222
1250
|
default:
|
|
1223
|
-
return nil, []Diagnostic{
|
|
1251
|
+
return nil, []Diagnostic{loweringUnsupportedAt(ctx, decl, "declaration", ctx.semPkg.pkgPath, "unsupported declaration kind")}
|
|
1224
1252
|
}
|
|
1225
1253
|
}
|
|
1226
1254
|
|
|
@@ -1268,7 +1296,7 @@ func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([
|
|
|
1268
1296
|
value = o.lowerValueForTarget(ctx, typed.Values[idx], obj.Type(), lowered)
|
|
1269
1297
|
value = o.lowerTopLevelInitializerValue(ctx, typed.Values[idx], value)
|
|
1270
1298
|
} else if len(embedPatterns) != 0 {
|
|
1271
|
-
embedded, embedDiagnostics := o.lowerGoEmbedValue(ctx, obj.Type(), embedPatterns)
|
|
1299
|
+
embedded, embedDiagnostics := o.lowerGoEmbedValue(ctx, typed.Pos(), obj.Type(), embedPatterns)
|
|
1272
1300
|
diagnostics = append(diagnostics, embedDiagnostics...)
|
|
1273
1301
|
if embedded != "" {
|
|
1274
1302
|
value = embedded
|
|
@@ -1359,7 +1387,7 @@ func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([
|
|
|
1359
1387
|
}
|
|
1360
1388
|
}
|
|
1361
1389
|
default:
|
|
1362
|
-
diagnostics = append(diagnostics,
|
|
1390
|
+
diagnostics = append(diagnostics, loweringUnsupportedAt(ctx, typed, "declaration", ctx.semPkg.pkgPath, "unsupported general declaration"))
|
|
1363
1391
|
}
|
|
1364
1392
|
}
|
|
1365
1393
|
return decls, diagnostics
|
|
@@ -2144,16 +2172,17 @@ func goEmbedPatterns(groups ...*ast.CommentGroup) []string {
|
|
|
2144
2172
|
|
|
2145
2173
|
func (o *LoweringOwner) lowerGoEmbedValue(
|
|
2146
2174
|
ctx lowerFileContext,
|
|
2175
|
+
diagPos token.Pos,
|
|
2147
2176
|
typ types.Type,
|
|
2148
2177
|
patterns []string,
|
|
2149
2178
|
) (string, []Diagnostic) {
|
|
2150
2179
|
if isEmbedFSType(typ) {
|
|
2151
|
-
return o.lowerGoEmbedFSValue(ctx, patterns)
|
|
2180
|
+
return o.lowerGoEmbedFSValue(ctx, diagPos, patterns)
|
|
2152
2181
|
}
|
|
2153
2182
|
if len(patterns) != 1 {
|
|
2154
|
-
return "", []Diagnostic{
|
|
2183
|
+
return "", []Diagnostic{loweringUnsupportedPos(ctx, diagPos, "declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern list")}
|
|
2155
2184
|
}
|
|
2156
|
-
cleanPattern, diagnostics := cleanGoEmbedFilePattern(ctx, patterns[0])
|
|
2185
|
+
cleanPattern, diagnostics := cleanGoEmbedFilePattern(ctx, diagPos, patterns[0])
|
|
2157
2186
|
if len(diagnostics) != 0 {
|
|
2158
2187
|
return "", diagnostics
|
|
2159
2188
|
}
|
|
@@ -2167,7 +2196,7 @@ func (o *LoweringOwner) lowerGoEmbedValue(
|
|
|
2167
2196
|
if slice, ok := types.Unalias(typ).Underlying().(*types.Slice); ok && isByteType(slice.Elem()) {
|
|
2168
2197
|
return byteSliceLiteral(data), nil
|
|
2169
2198
|
}
|
|
2170
|
-
diag :=
|
|
2199
|
+
diag := loweringUnsupportedPos(ctx, diagPos, "declaration", ctx.semPkg.pkgPath, "unsupported go:embed target type")
|
|
2171
2200
|
diag.Detail = "target type: " + types.TypeString(typ, func(pkg *types.Package) string {
|
|
2172
2201
|
if pkg == nil {
|
|
2173
2202
|
return ""
|
|
@@ -2177,18 +2206,18 @@ func (o *LoweringOwner) lowerGoEmbedValue(
|
|
|
2177
2206
|
return "", []Diagnostic{diag}
|
|
2178
2207
|
}
|
|
2179
2208
|
|
|
2180
|
-
func (o *LoweringOwner) lowerGoEmbedFSValue(ctx lowerFileContext, patterns []string) (string, []Diagnostic) {
|
|
2209
|
+
func (o *LoweringOwner) lowerGoEmbedFSValue(ctx lowerFileContext, diagPos token.Pos, patterns []string) (string, []Diagnostic) {
|
|
2181
2210
|
embedAlias := ctx.importPaths["embed"]
|
|
2182
2211
|
if embedAlias == "" {
|
|
2183
|
-
return "", []Diagnostic{
|
|
2212
|
+
return "", []Diagnostic{loweringUnsupportedPos(ctx, diagPos, "declaration", ctx.semPkg.pkgPath, "unsupported go:embed FS import")}
|
|
2184
2213
|
}
|
|
2185
2214
|
if len(patterns) == 0 {
|
|
2186
|
-
return "", []Diagnostic{
|
|
2215
|
+
return "", []Diagnostic{loweringUnsupportedPos(ctx, diagPos, "declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern list")}
|
|
2187
2216
|
}
|
|
2188
2217
|
|
|
2189
2218
|
filesByPath := make(map[string][]byte)
|
|
2190
2219
|
for _, pattern := range patterns {
|
|
2191
|
-
files, diagnostics := expandGoEmbedPattern(ctx, pattern)
|
|
2220
|
+
files, diagnostics := expandGoEmbedPattern(ctx, diagPos, pattern)
|
|
2192
2221
|
if len(diagnostics) != 0 {
|
|
2193
2222
|
return "", diagnostics
|
|
2194
2223
|
}
|
|
@@ -2214,25 +2243,25 @@ type goEmbedFile struct {
|
|
|
2214
2243
|
data []byte
|
|
2215
2244
|
}
|
|
2216
2245
|
|
|
2217
|
-
func cleanGoEmbedFilePattern(ctx lowerFileContext, pattern string) (string, []Diagnostic) {
|
|
2218
|
-
cleanPattern, _, diagnostics := cleanGoEmbedPattern(ctx, pattern)
|
|
2246
|
+
func cleanGoEmbedFilePattern(ctx lowerFileContext, diagPos token.Pos, pattern string) (string, []Diagnostic) {
|
|
2247
|
+
cleanPattern, _, diagnostics := cleanGoEmbedPattern(ctx, diagPos, pattern)
|
|
2219
2248
|
if len(diagnostics) != 0 {
|
|
2220
2249
|
return "", diagnostics
|
|
2221
2250
|
}
|
|
2222
2251
|
if strings.Contains(cleanPattern, "*") {
|
|
2223
|
-
return "", []Diagnostic{
|
|
2252
|
+
return "", []Diagnostic{loweringUnsupportedPos(ctx, diagPos, "declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern")}
|
|
2224
2253
|
}
|
|
2225
2254
|
info, err := os.Stat(filepath.Join(filepath.Dir(ctx.sourcePath), filepath.FromSlash(cleanPattern)))
|
|
2226
2255
|
if err != nil {
|
|
2227
2256
|
return "", []Diagnostic{goEmbedReadDiagnostic(ctx, err)}
|
|
2228
2257
|
}
|
|
2229
2258
|
if info.IsDir() {
|
|
2230
|
-
return "", []Diagnostic{
|
|
2259
|
+
return "", []Diagnostic{loweringUnsupportedPos(ctx, diagPos, "declaration", ctx.semPkg.pkgPath, "unsupported go:embed directory target")}
|
|
2231
2260
|
}
|
|
2232
2261
|
return cleanPattern, nil
|
|
2233
2262
|
}
|
|
2234
2263
|
|
|
2235
|
-
func cleanGoEmbedPattern(ctx lowerFileContext, pattern string) (string, bool, []Diagnostic) {
|
|
2264
|
+
func cleanGoEmbedPattern(ctx lowerFileContext, diagPos token.Pos, pattern string) (string, bool, []Diagnostic) {
|
|
2236
2265
|
pattern = strings.Trim(pattern, "`\"")
|
|
2237
2266
|
all := false
|
|
2238
2267
|
if strings.HasPrefix(pattern, "all:") {
|
|
@@ -2245,13 +2274,13 @@ func cleanGoEmbedPattern(ctx lowerFileContext, pattern string) (string, bool, []
|
|
|
2245
2274
|
cleanPattern == "." ||
|
|
2246
2275
|
cleanPattern == ".." ||
|
|
2247
2276
|
strings.HasPrefix(cleanPattern, "../") {
|
|
2248
|
-
return "", false, []Diagnostic{
|
|
2277
|
+
return "", false, []Diagnostic{loweringUnsupportedPos(ctx, diagPos, "declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern")}
|
|
2249
2278
|
}
|
|
2250
2279
|
return cleanPattern, all, nil
|
|
2251
2280
|
}
|
|
2252
2281
|
|
|
2253
|
-
func expandGoEmbedPattern(ctx lowerFileContext, pattern string) ([]goEmbedFile, []Diagnostic) {
|
|
2254
|
-
cleanPattern, all, diagnostics := cleanGoEmbedPattern(ctx, pattern)
|
|
2282
|
+
func expandGoEmbedPattern(ctx lowerFileContext, diagPos token.Pos, pattern string) ([]goEmbedFile, []Diagnostic) {
|
|
2283
|
+
cleanPattern, all, diagnostics := cleanGoEmbedPattern(ctx, diagPos, pattern)
|
|
2255
2284
|
if len(diagnostics) != 0 {
|
|
2256
2285
|
return nil, diagnostics
|
|
2257
2286
|
}
|
|
@@ -2260,17 +2289,17 @@ func expandGoEmbedPattern(ctx lowerFileContext, pattern string) ([]goEmbedFile,
|
|
|
2260
2289
|
if strings.Contains(cleanPattern, "*") {
|
|
2261
2290
|
matches, err := filepath.Glob(filepath.Join(pkgDir, filepath.FromSlash(cleanPattern)))
|
|
2262
2291
|
if err != nil {
|
|
2263
|
-
return nil, []Diagnostic{
|
|
2292
|
+
return nil, []Diagnostic{loweringUnsupportedPos(ctx, diagPos, "declaration", ctx.semPkg.pkgPath, "unsupported go:embed pattern")}
|
|
2264
2293
|
}
|
|
2265
2294
|
if len(matches) == 0 {
|
|
2266
|
-
return nil, []Diagnostic{
|
|
2295
|
+
return nil, []Diagnostic{loweringUnsupportedPos(ctx, diagPos, "declaration", ctx.semPkg.pkgPath, "go:embed pattern matched no files")}
|
|
2267
2296
|
}
|
|
2268
2297
|
paths = matches
|
|
2269
2298
|
}
|
|
2270
2299
|
|
|
2271
2300
|
var files []goEmbedFile
|
|
2272
2301
|
for _, path := range paths {
|
|
2273
|
-
collected, diagnostics := collectGoEmbedPath(ctx, pkgDir, path, all)
|
|
2302
|
+
collected, diagnostics := collectGoEmbedPath(ctx, diagPos, pkgDir, path, all)
|
|
2274
2303
|
if len(diagnostics) != 0 {
|
|
2275
2304
|
return nil, diagnostics
|
|
2276
2305
|
}
|
|
@@ -2282,7 +2311,7 @@ func expandGoEmbedPattern(ctx lowerFileContext, pattern string) ([]goEmbedFile,
|
|
|
2282
2311
|
return files, nil
|
|
2283
2312
|
}
|
|
2284
2313
|
|
|
2285
|
-
func collectGoEmbedPath(ctx lowerFileContext, pkgDir, absPath string, all bool) ([]goEmbedFile, []Diagnostic) {
|
|
2314
|
+
func collectGoEmbedPath(ctx lowerFileContext, diagPos token.Pos, pkgDir, absPath string, all bool) ([]goEmbedFile, []Diagnostic) {
|
|
2286
2315
|
info, err := os.Stat(absPath)
|
|
2287
2316
|
if err != nil {
|
|
2288
2317
|
return nil, []Diagnostic{goEmbedReadDiagnostic(ctx, err)}
|
|
@@ -2319,7 +2348,7 @@ func collectGoEmbedPath(ctx lowerFileContext, pkgDir, absPath string, all bool)
|
|
|
2319
2348
|
return nil, []Diagnostic{goEmbedReadDiagnostic(ctx, err)}
|
|
2320
2349
|
}
|
|
2321
2350
|
if len(files) == 0 {
|
|
2322
|
-
return nil, []Diagnostic{
|
|
2351
|
+
return nil, []Diagnostic{loweringUnsupportedPos(ctx, diagPos, "declaration", ctx.semPkg.pkgPath, "go:embed directory matched no files")}
|
|
2323
2352
|
}
|
|
2324
2353
|
return files, nil
|
|
2325
2354
|
}
|
|
@@ -2440,7 +2469,7 @@ func (o *LoweringOwner) lowerInterfaceType(ctx lowerFileContext, semType *semant
|
|
|
2440
2469
|
}
|
|
2441
2470
|
code = code + "\n\n" + o.runtimeOwner.QualifiedHelper(RuntimeHelperRegisterInterfaceType) +
|
|
2442
2471
|
"(\n\t" + strconv.Quote(runtimeNamedTypeName(semType.named)) +
|
|
2443
|
-
",\n\tnull,\n\t" + o.runtimeMethodSignatures(iface) + "\n)"
|
|
2472
|
+
",\n\tnull,\n\t" + o.runtimeMethodSignatures(iface) + "\n);"
|
|
2444
2473
|
return loweredDecl{code: code, typeIndexExport: typeIndexExport, sideEffect: true}
|
|
2445
2474
|
}
|
|
2446
2475
|
|
|
@@ -2521,12 +2550,13 @@ func (o *LoweringOwner) runtimeMethodReturns(tuple *types.Tuple, seen map[types.
|
|
|
2521
2550
|
|
|
2522
2551
|
func (o *LoweringOwner) lowerStructType(ctx lowerFileContext, semType *semanticType) (*loweredStruct, []Diagnostic) {
|
|
2523
2552
|
lowered := &loweredStruct{
|
|
2524
|
-
exported:
|
|
2525
|
-
indexExported:
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2553
|
+
exported: ctx.topLevel,
|
|
2554
|
+
indexExported: ctx.topLevel && ast.IsExported(semType.name),
|
|
2555
|
+
protobufPreserveJSON: ctx.protobufTSAdapter && o.protobufTypeScriptAdapterPreserveJSON(ctx, semType, make(map[*types.Named]bool)),
|
|
2556
|
+
name: safeIdentifier(semType.name),
|
|
2557
|
+
typeName: runtimeNamedTypeName(semType.named),
|
|
2558
|
+
cloneMethod: "clone",
|
|
2559
|
+
fields: make([]loweredStructField, 0, len(semType.fields)),
|
|
2530
2560
|
}
|
|
2531
2561
|
for idx, field := range semType.fields {
|
|
2532
2562
|
structValue := isStructValueType(field.typ)
|
|
@@ -2569,7 +2599,11 @@ func (o *LoweringOwner) lowerStructType(ctx lowerFileContext, semType *semanticT
|
|
|
2569
2599
|
var diagnostics []Diagnostic
|
|
2570
2600
|
for _, methodDecl := range methodDecls {
|
|
2571
2601
|
lowerDecl := methodDecl
|
|
2572
|
-
|
|
2602
|
+
methodSourcePath := sourcePos(ctx.semPkg.source, methodDecl.Pos()).file
|
|
2603
|
+
if ctx.protobufTSAdapter &&
|
|
2604
|
+
methodSourcePath == ctx.sourcePath &&
|
|
2605
|
+
protobufTypeScriptBindingReplacesMethodName(methodDecl.Name.Name) &&
|
|
2606
|
+
!(lowered.protobufPreserveJSON && protobufTypeScriptBindingJSONMethodName(methodDecl.Name.Name)) {
|
|
2573
2607
|
bodyless := *methodDecl
|
|
2574
2608
|
bodyless.Body = nil
|
|
2575
2609
|
lowerDecl = &bodyless
|
|
@@ -2590,6 +2624,133 @@ func (o *LoweringOwner) lowerStructType(ctx lowerFileContext, semType *semanticT
|
|
|
2590
2624
|
return lowered, diagnostics
|
|
2591
2625
|
}
|
|
2592
2626
|
|
|
2627
|
+
func (o *LoweringOwner) protobufTypeScriptAdapterPreserveJSON(
|
|
2628
|
+
ctx lowerFileContext,
|
|
2629
|
+
semType *semanticType,
|
|
2630
|
+
seen map[*types.Named]bool,
|
|
2631
|
+
) bool {
|
|
2632
|
+
if semType == nil || semType.named == nil {
|
|
2633
|
+
return false
|
|
2634
|
+
}
|
|
2635
|
+
named := semType.named.Origin()
|
|
2636
|
+
if named == nil || seen[named] {
|
|
2637
|
+
return false
|
|
2638
|
+
}
|
|
2639
|
+
seen[named] = true
|
|
2640
|
+
for _, methodDecl := range o.methodDeclsForType(ctx, named) {
|
|
2641
|
+
if methodDecl == nil || !protobufTypeScriptBindingJSONMethodName(methodDecl.Name.Name) {
|
|
2642
|
+
continue
|
|
2643
|
+
}
|
|
2644
|
+
if sourcePos(ctx.semPkg.source, methodDecl.Pos()).file != ctx.sourcePath {
|
|
2645
|
+
return true
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
for _, field := range semType.fields {
|
|
2649
|
+
if o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, field.typ, seen) {
|
|
2650
|
+
return true
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
return false
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2656
|
+
func (o *LoweringOwner) protobufTypeScriptAdapterTypeHasCustomJSON(
|
|
2657
|
+
ctx lowerFileContext,
|
|
2658
|
+
typ types.Type,
|
|
2659
|
+
seen map[*types.Named]bool,
|
|
2660
|
+
) bool {
|
|
2661
|
+
if typ == nil {
|
|
2662
|
+
return false
|
|
2663
|
+
}
|
|
2664
|
+
if alias, ok := typ.(*types.Alias); ok {
|
|
2665
|
+
if o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, alias.Rhs(), seen) {
|
|
2666
|
+
return true
|
|
2667
|
+
}
|
|
2668
|
+
if args := alias.TypeArgs(); args != nil {
|
|
2669
|
+
for t := range args.Types() {
|
|
2670
|
+
if o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, t, seen) {
|
|
2671
|
+
return true
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
return false
|
|
2676
|
+
}
|
|
2677
|
+
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
2678
|
+
if o.protobufTypeScriptAdapterNamedTypeHasCustomJSON(ctx, named) {
|
|
2679
|
+
return true
|
|
2680
|
+
}
|
|
2681
|
+
if obj := named.Obj(); obj != nil && obj.Pkg() != nil && obj.Pkg().Path() == ctx.semPkg.pkgPath {
|
|
2682
|
+
semType := ctx.model.types[named]
|
|
2683
|
+
if semType == nil {
|
|
2684
|
+
semType = ctx.model.types[named.Origin()]
|
|
2685
|
+
}
|
|
2686
|
+
if semType != nil && o.protobufTypeScriptAdapterPreserveJSON(ctx, semType, seen) {
|
|
2687
|
+
return true
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
origin := named.Origin()
|
|
2691
|
+
if origin != nil {
|
|
2692
|
+
if seen[origin] {
|
|
2693
|
+
return false
|
|
2694
|
+
}
|
|
2695
|
+
seen[origin] = true
|
|
2696
|
+
}
|
|
2697
|
+
if args := named.TypeArgs(); args != nil {
|
|
2698
|
+
for t := range args.Types() {
|
|
2699
|
+
if o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, t, seen) {
|
|
2700
|
+
return true
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
if o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, named.Underlying(), seen) {
|
|
2705
|
+
return true
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
2709
|
+
case *types.Pointer:
|
|
2710
|
+
return o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, typed.Elem(), seen)
|
|
2711
|
+
case *types.Slice:
|
|
2712
|
+
return o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, typed.Elem(), seen)
|
|
2713
|
+
case *types.Array:
|
|
2714
|
+
return o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, typed.Elem(), seen)
|
|
2715
|
+
case *types.Map:
|
|
2716
|
+
return o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, typed.Key(), seen) ||
|
|
2717
|
+
o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, typed.Elem(), seen)
|
|
2718
|
+
case *types.Struct:
|
|
2719
|
+
for field := range typed.Fields() {
|
|
2720
|
+
if o.protobufTypeScriptAdapterTypeHasCustomJSON(ctx, field.Type(), seen) {
|
|
2721
|
+
return true
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
return false
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
func (o *LoweringOwner) protobufTypeScriptAdapterNamedTypeHasCustomJSON(
|
|
2729
|
+
ctx lowerFileContext,
|
|
2730
|
+
named *types.Named,
|
|
2731
|
+
) bool {
|
|
2732
|
+
if named == nil {
|
|
2733
|
+
return false
|
|
2734
|
+
}
|
|
2735
|
+
methodSet := types.NewMethodSet(types.NewPointer(named))
|
|
2736
|
+
for _, name := range []string{"MarshalJSON", "MarshalProtoJSON", "UnmarshalJSON", "UnmarshalProtoJSON"} {
|
|
2737
|
+
selection := methodSet.Lookup(nil, name)
|
|
2738
|
+
if selection == nil {
|
|
2739
|
+
continue
|
|
2740
|
+
}
|
|
2741
|
+
method, ok := selection.Obj().(*types.Func)
|
|
2742
|
+
if !ok {
|
|
2743
|
+
continue
|
|
2744
|
+
}
|
|
2745
|
+
sourcePath := sourcePos(ctx.semPkg.source, method.Pos()).file
|
|
2746
|
+
if sourcePath == "" || strings.HasSuffix(sourcePath, ".pb.go") {
|
|
2747
|
+
continue
|
|
2748
|
+
}
|
|
2749
|
+
return true
|
|
2750
|
+
}
|
|
2751
|
+
return false
|
|
2752
|
+
}
|
|
2753
|
+
|
|
2593
2754
|
func (o *LoweringOwner) lowerEmbeddedMethodForwarders(
|
|
2594
2755
|
ctx lowerFileContext,
|
|
2595
2756
|
field semanticField,
|
|
@@ -2627,6 +2788,7 @@ func (o *LoweringOwner) lowerEmbeddedMethodForwarders(
|
|
|
2627
2788
|
targetType := o.tsEmbeddedForwarderTargetType(ctx, field.typ)
|
|
2628
2789
|
lowered := loweredFunction{
|
|
2629
2790
|
async: async,
|
|
2791
|
+
sourcePath: ctx.sourcePath,
|
|
2630
2792
|
name: methodMemberName(method.Name()),
|
|
2631
2793
|
runtimeName: method.Name(),
|
|
2632
2794
|
runtimeSignature: o.runtimeMethodSignature(method, make(map[types.Type]bool)),
|
|
@@ -2770,6 +2932,7 @@ func (o *LoweringOwner) lowerNamedReceiverMethodDecl(
|
|
|
2770
2932
|
exported: ctx.topLevel,
|
|
2771
2933
|
indexExported: ctx.topLevel && (ast.IsExported(receiver.Obj().Name()) || ast.IsExported(decl.Name.Name)),
|
|
2772
2934
|
async: async,
|
|
2935
|
+
sourcePath: sourcePos(ctx.semPkg.source, decl.Pos()).file,
|
|
2773
2936
|
name: methodFunctionName(receiver, decl.Name.Name),
|
|
2774
2937
|
result: asyncResultType(result, async),
|
|
2775
2938
|
deferState: deferState,
|
|
@@ -2844,6 +3007,7 @@ func (o *LoweringOwner) lowerFuncDecl(ctx lowerFileContext, decl *ast.FuncDecl)
|
|
|
2844
3007
|
indexExported: ctx.topLevel && !blankName && !initFunc && (ast.IsExported(decl.Name.Name) || decl.Name.Name == "main"),
|
|
2845
3008
|
init: initFunc,
|
|
2846
3009
|
async: async,
|
|
3010
|
+
sourcePath: sourcePos(ctx.semPkg.source, decl.Pos()).file,
|
|
2847
3011
|
name: name,
|
|
2848
3012
|
runtimeName: runtimeName,
|
|
2849
3013
|
result: asyncResultType(result, async),
|
|
@@ -3329,9 +3493,9 @@ func (o *LoweringOwner) lowerStmtInto(ctx lowerFileContext, stmt ast.Stmt, out [
|
|
|
3329
3493
|
if ctx.gotoLabels[label] {
|
|
3330
3494
|
return append(out, loweredStmt{text: "continue " + label}), nil
|
|
3331
3495
|
}
|
|
3332
|
-
return out, []Diagnostic{
|
|
3496
|
+
return out, []Diagnostic{loweringUnsupportedAt(ctx, typed, "statement", ctx.semPkg.pkgPath, "unsupported goto branch to "+label)}
|
|
3333
3497
|
default:
|
|
3334
|
-
return out, []Diagnostic{
|
|
3498
|
+
return out, []Diagnostic{loweringUnsupportedAt(ctx, typed, "statement", ctx.semPkg.pkgPath, "unsupported labeled branch")}
|
|
3335
3499
|
}
|
|
3336
3500
|
}
|
|
3337
3501
|
switch typed.Tok {
|
|
@@ -3352,12 +3516,12 @@ func (o *LoweringOwner) lowerStmtInto(ctx lowerFileContext, stmt ast.Stmt, out [
|
|
|
3352
3516
|
case token.FALLTHROUGH:
|
|
3353
3517
|
return append(out, loweredStmt{text: "fallthrough"}), nil
|
|
3354
3518
|
default:
|
|
3355
|
-
return out, []Diagnostic{
|
|
3519
|
+
return out, []Diagnostic{loweringUnsupportedAt(ctx, typed, "statement", ctx.semPkg.pkgPath, "unsupported branch")}
|
|
3356
3520
|
}
|
|
3357
3521
|
case *ast.EmptyStmt:
|
|
3358
3522
|
return out, nil
|
|
3359
3523
|
default:
|
|
3360
|
-
return out, []Diagnostic{
|
|
3524
|
+
return out, []Diagnostic{loweringUnsupportedAt(ctx, typed, "statement", ctx.semPkg.pkgPath, "unsupported statement kind")}
|
|
3361
3525
|
}
|
|
3362
3526
|
}
|
|
3363
3527
|
|
|
@@ -3388,7 +3552,7 @@ func (o *LoweringOwner) lowerElse(ctx lowerFileContext, stmt ast.Stmt) ([]lowere
|
|
|
3388
3552
|
case *ast.IfStmt:
|
|
3389
3553
|
return o.lowerStmt(ctx, typed)
|
|
3390
3554
|
default:
|
|
3391
|
-
return nil, []Diagnostic{
|
|
3555
|
+
return nil, []Diagnostic{loweringUnsupportedAt(ctx, typed, "statement", ctx.semPkg.pkgPath, "unsupported else statement")}
|
|
3392
3556
|
}
|
|
3393
3557
|
}
|
|
3394
3558
|
|
|
@@ -5617,7 +5781,7 @@ func (o *LoweringOwner) lowerRangeStmt(ctx lowerFileContext, stmt *ast.RangeStmt
|
|
|
5617
5781
|
if isFunctionType(rangeType) {
|
|
5618
5782
|
signature := rangeFunctionSignature(rangeType)
|
|
5619
5783
|
if signature == nil {
|
|
5620
|
-
return loweredStmt{}, append(diagnostics,
|
|
5784
|
+
return loweredStmt{}, append(diagnostics, loweringUnsupportedAt(ctx, stmt, "statement", ctx.semPkg.pkgPath, "unsupported function range signature"))
|
|
5621
5785
|
}
|
|
5622
5786
|
lowered, funcDiagnostics := o.lowerRangeFuncStmt(ctx, stmt, rangeValue, signature)
|
|
5623
5787
|
diagnostics = append(diagnostics, funcDiagnostics...)
|
|
@@ -5697,7 +5861,7 @@ func (o *LoweringOwner) lowerRangeFuncStmt(
|
|
|
5697
5861
|
) (loweredStmt, []Diagnostic) {
|
|
5698
5862
|
yieldSignature, ok := types.Unalias(signature.Params().At(0).Type()).Underlying().(*types.Signature)
|
|
5699
5863
|
if !ok {
|
|
5700
|
-
return loweredStmt{}, []Diagnostic{
|
|
5864
|
+
return loweredStmt{}, []Diagnostic{loweringUnsupportedAt(ctx, stmt, "statement", ctx.semPkg.pkgPath, "unsupported function range yield signature")}
|
|
5701
5865
|
}
|
|
5702
5866
|
keyName := rangeKeyName(stmt.Key)
|
|
5703
5867
|
valueName := rangeKeyName(stmt.Value)
|
|
@@ -5780,7 +5944,7 @@ func (o *LoweringOwner) lowerSelectStmt(ctx lowerFileContext, stmt *ast.SelectSt
|
|
|
5780
5944
|
for _, raw := range stmt.Body.List {
|
|
5781
5945
|
clause, ok := raw.(*ast.CommClause)
|
|
5782
5946
|
if !ok {
|
|
5783
|
-
diagnostics = append(diagnostics,
|
|
5947
|
+
diagnostics = append(diagnostics, loweringUnsupportedAt(ctx, raw, "statement", ctx.semPkg.pkgPath, "unsupported select clause"))
|
|
5784
5948
|
continue
|
|
5785
5949
|
}
|
|
5786
5950
|
switch comm := clause.Comm.(type) {
|
|
@@ -5833,7 +5997,7 @@ func (o *LoweringOwner) lowerSelectStmt(ctx lowerFileContext, stmt *ast.SelectSt
|
|
|
5833
5997
|
})
|
|
5834
5998
|
caseID++
|
|
5835
5999
|
default:
|
|
5836
|
-
diagnostics = append(diagnostics,
|
|
6000
|
+
diagnostics = append(diagnostics, loweringUnsupportedAt(ctx, comm, "statement", ctx.semPkg.pkgPath, "unsupported select communication"))
|
|
5837
6001
|
}
|
|
5838
6002
|
}
|
|
5839
6003
|
lowered.returns = selectCasesReturn(lowered.cases)
|
|
@@ -5937,7 +6101,7 @@ func (o *LoweringOwner) lowerSelectReceiveComm(
|
|
|
5937
6101
|
}
|
|
5938
6102
|
receive, ok := receiveExpr.(*ast.UnaryExpr)
|
|
5939
6103
|
if !ok || receive.Op != token.ARROW {
|
|
5940
|
-
return "null", nil, []Diagnostic{
|
|
6104
|
+
return "null", nil, []Diagnostic{loweringUnsupportedAt(ctx, receiveExpr, "statement", ctx.semPkg.pkgPath, "unsupported select receive")}
|
|
5941
6105
|
}
|
|
5942
6106
|
channel, diagnostics := o.lowerExpr(ctx, receive.X)
|
|
5943
6107
|
if assign == nil {
|
|
@@ -5995,7 +6159,7 @@ func (o *LoweringOwner) lowerSwitchStmt(ctx lowerFileContext, stmt *ast.SwitchSt
|
|
|
5995
6159
|
for _, raw := range stmt.Body.List {
|
|
5996
6160
|
clause, ok := raw.(*ast.CaseClause)
|
|
5997
6161
|
if !ok {
|
|
5998
|
-
diagnostics = append(diagnostics,
|
|
6162
|
+
diagnostics = append(diagnostics, loweringUnsupportedAt(ctx, raw, "statement", ctx.semPkg.pkgPath, "unsupported switch clause"))
|
|
5999
6163
|
continue
|
|
6000
6164
|
}
|
|
6001
6165
|
bodyStmts := clause.Body
|
|
@@ -6090,7 +6254,7 @@ func (o *LoweringOwner) lowerTypeSwitchStmt(ctx lowerFileContext, stmt *ast.Type
|
|
|
6090
6254
|
valueExpr, varName, varRef, assignDiagnostics := o.lowerTypeSwitchAssign(ctx, stmt.Assign)
|
|
6091
6255
|
diagnostics = append(diagnostics, assignDiagnostics...)
|
|
6092
6256
|
if valueExpr == "" {
|
|
6093
|
-
return lowered, append(diagnostics,
|
|
6257
|
+
return lowered, append(diagnostics, loweringUnsupportedAt(ctx, stmt.Assign, "statement", ctx.semPkg.pkgPath, "unsupported type switch assignment"))
|
|
6094
6258
|
}
|
|
6095
6259
|
|
|
6096
6260
|
switchIR := &loweredTypeSwitch{
|
|
@@ -6101,7 +6265,7 @@ func (o *LoweringOwner) lowerTypeSwitchStmt(ctx lowerFileContext, stmt *ast.Type
|
|
|
6101
6265
|
for _, clauseStmt := range stmt.Body.List {
|
|
6102
6266
|
clause, ok := clauseStmt.(*ast.CaseClause)
|
|
6103
6267
|
if !ok {
|
|
6104
|
-
diagnostics = append(diagnostics,
|
|
6268
|
+
diagnostics = append(diagnostics, loweringUnsupportedAt(ctx, clauseStmt, "statement", ctx.semPkg.pkgPath, "unsupported type switch clause"))
|
|
6105
6269
|
continue
|
|
6106
6270
|
}
|
|
6107
6271
|
body, bodyDiagnostics := o.lowerStmtList(ctx.withoutRangeBreak().withSwitchBreak(), clause.Body)
|
|
@@ -6537,13 +6701,21 @@ func (o *LoweringOwner) lowerExpr(ctx lowerFileContext, expr ast.Expr) (string,
|
|
|
6537
6701
|
return lowerPrefixUnaryExpr(typed.Op, value), diagnostics
|
|
6538
6702
|
}
|
|
6539
6703
|
if typed.Op == token.XOR {
|
|
6540
|
-
if bits, ok := unsignedIntegerBits(ctx.semPkg.source.TypesInfo.TypeOf(typed)); ok
|
|
6541
|
-
|
|
6542
|
-
|
|
6704
|
+
if bits, ok := unsignedIntegerBits(ctx.semPkg.source.TypesInfo.TypeOf(typed)); ok {
|
|
6705
|
+
if bits <= 32 {
|
|
6706
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint) +
|
|
6707
|
+
"(~" + value + ", " + strconv.Itoa(bits) + ")", diagnostics
|
|
6708
|
+
}
|
|
6709
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Xor) +
|
|
6710
|
+
"(" + value + ", -1n)", diagnostics
|
|
6711
|
+
}
|
|
6712
|
+
if bits, ok := signedIntegerBits(ctx.semPkg.source.TypesInfo.TypeOf(typed)); ok && bits > 32 {
|
|
6713
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperInt64Xor) +
|
|
6714
|
+
"(" + value + ", -1n)", diagnostics
|
|
6543
6715
|
}
|
|
6544
6716
|
return "~" + value, diagnostics
|
|
6545
6717
|
}
|
|
6546
|
-
return value, append(diagnostics,
|
|
6718
|
+
return value, append(diagnostics, loweringUnsupportedAt(ctx, typed, "expression", ctx.semPkg.pkgPath, "unsupported unary operator"))
|
|
6547
6719
|
case *ast.StarExpr:
|
|
6548
6720
|
return o.lowerPointerValueExpr(ctx, typed.X)
|
|
6549
6721
|
case *ast.ParenExpr:
|
|
@@ -6567,7 +6739,7 @@ func (o *LoweringOwner) lowerExpr(ctx lowerFileContext, expr ast.Expr) (string,
|
|
|
6567
6739
|
case *ast.IndexListExpr:
|
|
6568
6740
|
return o.lowerExpr(ctx, typed.X)
|
|
6569
6741
|
default:
|
|
6570
|
-
return "undefined", []Diagnostic{
|
|
6742
|
+
return "undefined", []Diagnostic{loweringUnsupportedAt(ctx, typed, "expression", ctx.semPkg.pkgPath, "unsupported expression kind")}
|
|
6571
6743
|
}
|
|
6572
6744
|
}
|
|
6573
6745
|
|
|
@@ -6933,7 +7105,7 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
6933
7105
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperRecover) + "(" + strings.Join(args, ", ") + ")", diagnostics
|
|
6934
7106
|
case "close":
|
|
6935
7107
|
if len(args) != 1 {
|
|
6936
|
-
return "undefined", append(diagnostics,
|
|
7108
|
+
return "undefined", append(diagnostics, loweringUnsupportedAt(ctx, expr, "call", ctx.semPkg.pkgPath, "close requires one argument"))
|
|
6937
7109
|
}
|
|
6938
7110
|
return args[0] + "!.close()", diagnostics
|
|
6939
7111
|
}
|
|
@@ -7030,9 +7202,9 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
7030
7202
|
call := o.lowerCallableExpr(ctx, expr.Fun, callee) + "(" + strings.Join(args, ", ") + ")"
|
|
7031
7203
|
return o.awaitCallIfNeeded(ctx, expr.Fun, call), append(diagnostics, calleeDiagnostics...)
|
|
7032
7204
|
}
|
|
7033
|
-
return "undefined", append(diagnostics,
|
|
7205
|
+
return "undefined", append(diagnostics, loweringUnsupportedAt(ctx, expr.Fun, "call", ctx.semPkg.pkgPath, fmt.Sprintf("unsupported call target %T", expr.Fun)))
|
|
7034
7206
|
}
|
|
7035
|
-
return "undefined", append(diagnostics,
|
|
7207
|
+
return "undefined", append(diagnostics, loweringUnsupportedAt(ctx, expr.Fun, "call", ctx.semPkg.pkgPath, fmt.Sprintf("unsupported call target %T", expr.Fun)))
|
|
7036
7208
|
}
|
|
7037
7209
|
|
|
7038
7210
|
func (o *LoweringOwner) lowerCallableExpr(ctx lowerFileContext, expr ast.Expr, callee string) string {
|
|
@@ -7321,11 +7493,11 @@ func unsafePackageFunction(ctx lowerFileContext, expr ast.Expr, name string) boo
|
|
|
7321
7493
|
|
|
7322
7494
|
func (o *LoweringOwner) lowerMakeExpr(ctx lowerFileContext, expr *ast.CallExpr) (string, []Diagnostic) {
|
|
7323
7495
|
if len(expr.Args) < 1 {
|
|
7324
|
-
return "undefined", []Diagnostic{
|
|
7496
|
+
return "undefined", []Diagnostic{loweringUnsupportedAt(ctx, expr, "call", ctx.semPkg.pkgPath, "make requires a type argument")}
|
|
7325
7497
|
}
|
|
7326
7498
|
targetType := typeFromExpr(ctx, expr.Args[0])
|
|
7327
7499
|
if targetType == nil {
|
|
7328
|
-
return "undefined", []Diagnostic{
|
|
7500
|
+
return "undefined", []Diagnostic{loweringUnsupportedAt(ctx, expr.Args[0], "call", ctx.semPkg.pkgPath, "make requires a type expression")}
|
|
7329
7501
|
}
|
|
7330
7502
|
switch typed := types.Unalias(targetType).Underlying().(type) {
|
|
7331
7503
|
case *types.Slice:
|
|
@@ -7378,13 +7550,13 @@ func (o *LoweringOwner) lowerMakeExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
7378
7550
|
"<" + o.tsTypeFor(ctx, typed.Elem()) + ">(" + capacity + ", " +
|
|
7379
7551
|
o.lowerZeroValueExprFor(ctx, typed.Elem()) + ", " + strconv.Quote(channelDirectionString(typed.Dir())) + ")", diagnostics
|
|
7380
7552
|
default:
|
|
7381
|
-
return "undefined", []Diagnostic{
|
|
7553
|
+
return "undefined", []Diagnostic{loweringUnsupportedAt(ctx, expr.Args[0], "call", ctx.semPkg.pkgPath, "unsupported make type")}
|
|
7382
7554
|
}
|
|
7383
7555
|
}
|
|
7384
7556
|
|
|
7385
7557
|
func (o *LoweringOwner) lowerNewExpr(ctx lowerFileContext, expr *ast.CallExpr) (string, []Diagnostic) {
|
|
7386
7558
|
if len(expr.Args) != 1 {
|
|
7387
|
-
return "undefined", []Diagnostic{
|
|
7559
|
+
return "undefined", []Diagnostic{loweringUnsupportedAt(ctx, expr, "call", ctx.semPkg.pkgPath, "new requires one type argument")}
|
|
7388
7560
|
}
|
|
7389
7561
|
typ := typeFromExpr(ctx, expr.Args[0])
|
|
7390
7562
|
if named := namedStructType(typ); named != nil {
|
|
@@ -7400,7 +7572,7 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
7400
7572
|
targetType types.Type,
|
|
7401
7573
|
) (string, []Diagnostic) {
|
|
7402
7574
|
if len(expr.Args) != 1 {
|
|
7403
|
-
return "undefined", []Diagnostic{
|
|
7575
|
+
return "undefined", []Diagnostic{loweringUnsupportedAt(ctx, expr, "call", ctx.semPkg.pkgPath, "unsupported conversion arity")}
|
|
7404
7576
|
}
|
|
7405
7577
|
value, diagnostics := o.lowerExpr(ctx, expr.Args[0])
|
|
7406
7578
|
sourceType := ctx.semPkg.source.TypesInfo.TypeOf(expr.Args[0])
|
|
@@ -8371,7 +8543,7 @@ func (o *LoweringOwner) lowerAddressExpr(ctx lowerFileContext, expr ast.Expr) (s
|
|
|
8371
8543
|
case *ast.IndexExpr:
|
|
8372
8544
|
return o.lowerIndexAddressExpr(ctx, typed)
|
|
8373
8545
|
default:
|
|
8374
|
-
return "undefined", []Diagnostic{
|
|
8546
|
+
return "undefined", []Diagnostic{loweringUnsupportedAt(ctx, typed, "expression", ctx.semPkg.pkgPath, "unsupported address expression")}
|
|
8375
8547
|
}
|
|
8376
8548
|
}
|
|
8377
8549
|
|
|
@@ -8430,7 +8602,7 @@ func (o *LoweringOwner) lowerIndexAddressExpr(ctx lowerFileContext, expr *ast.In
|
|
|
8430
8602
|
diagnostics := append(targetDiagnostics, indexDiagnostics...)
|
|
8431
8603
|
targetType := ctx.semPkg.source.TypesInfo.TypeOf(expr.X)
|
|
8432
8604
|
if isStringType(targetType) || isMapType(targetType) {
|
|
8433
|
-
return "undefined", append(diagnostics,
|
|
8605
|
+
return "undefined", append(diagnostics, loweringUnsupportedAt(ctx, expr, "expression", ctx.semPkg.pkgPath, "unsupported address expression"))
|
|
8434
8606
|
}
|
|
8435
8607
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexRef) + "(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + index + ")", diagnostics
|
|
8436
8608
|
}
|
|
@@ -8458,7 +8630,7 @@ func (o *LoweringOwner) lowerUnsafePointerIntegerExpr(
|
|
|
8458
8630
|
if !ok || len(call.Args) != 1 || !isUnsafePointerType(typeFromExpr(ctx, call.Fun)) {
|
|
8459
8631
|
return "", nil, false
|
|
8460
8632
|
}
|
|
8461
|
-
return o.
|
|
8633
|
+
return o.lowerIndexByteAddressIntegerExpr(ctx, call.Args[0])
|
|
8462
8634
|
}
|
|
8463
8635
|
|
|
8464
8636
|
func (o *LoweringOwner) lowerIndexAddressIntegerExpr(
|
|
@@ -8484,6 +8656,30 @@ func (o *LoweringOwner) lowerIndexAddressIntegerExpr(
|
|
|
8484
8656
|
"(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + index + ")", diagnostics, true
|
|
8485
8657
|
}
|
|
8486
8658
|
|
|
8659
|
+
func (o *LoweringOwner) lowerIndexByteAddressIntegerExpr(
|
|
8660
|
+
ctx lowerFileContext,
|
|
8661
|
+
expr ast.Expr,
|
|
8662
|
+
) (string, []Diagnostic, bool) {
|
|
8663
|
+
address, ok := unwrapParenExpr(expr).(*ast.UnaryExpr)
|
|
8664
|
+
if !ok || address.Op != token.AND {
|
|
8665
|
+
return "", nil, false
|
|
8666
|
+
}
|
|
8667
|
+
indexExpr, ok := unwrapParenExpr(address.X).(*ast.IndexExpr)
|
|
8668
|
+
if !ok {
|
|
8669
|
+
return "", nil, false
|
|
8670
|
+
}
|
|
8671
|
+
target, targetDiagnostics := o.lowerExpr(ctx, indexExpr.X)
|
|
8672
|
+
index, indexDiagnostics := o.lowerExpr(ctx, indexExpr.Index)
|
|
8673
|
+
diagnostics := append(targetDiagnostics, indexDiagnostics...)
|
|
8674
|
+
targetType := ctx.semPkg.source.TypesInfo.TypeOf(indexExpr.X)
|
|
8675
|
+
if isStringType(targetType) || isMapType(targetType) {
|
|
8676
|
+
return "", diagnostics, false
|
|
8677
|
+
}
|
|
8678
|
+
elementSize := goScriptElementByteSize(ctx, indexElementType(targetType))
|
|
8679
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexByteAddress) +
|
|
8680
|
+
"(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + index + ", " + strconv.FormatInt(elementSize, 10) + ")", diagnostics, true
|
|
8681
|
+
}
|
|
8682
|
+
|
|
8487
8683
|
func (o *LoweringOwner) lowerPointerValueExpr(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
8488
8684
|
if value, diagnostics, ok := o.lowerUnsafeStringPointerValue(ctx, expr); ok {
|
|
8489
8685
|
return value, diagnostics
|
|
@@ -8491,6 +8687,12 @@ func (o *LoweringOwner) lowerPointerValueExpr(ctx lowerFileContext, expr ast.Exp
|
|
|
8491
8687
|
if value, diagnostics, ok := o.lowerUnsafeStringByteSlicePointerValue(ctx, expr); ok {
|
|
8492
8688
|
return value, diagnostics
|
|
8493
8689
|
}
|
|
8690
|
+
if ref, diagnostics, ok := o.lowerUnsafeArrayPointerRefExpr(ctx, expr); ok {
|
|
8691
|
+
return ref + ".value", diagnostics
|
|
8692
|
+
}
|
|
8693
|
+
if ref, diagnostics, ok := o.lowerUnsafePointerRefExpr(ctx, expr); ok {
|
|
8694
|
+
return ref + ".value", diagnostics
|
|
8695
|
+
}
|
|
8494
8696
|
base, diagnostics := o.lowerExpr(ctx, expr)
|
|
8495
8697
|
typeArg := ""
|
|
8496
8698
|
if pointer, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(expr)).Underlying().(*types.Pointer); ok {
|
|
@@ -8622,8 +8824,13 @@ func (o *LoweringOwner) lowerUnsafeArrayPointerConversion(
|
|
|
8622
8824
|
return "", nil, false
|
|
8623
8825
|
}
|
|
8624
8826
|
ref, diagnostics := o.lowerAddressExpr(ctx, index)
|
|
8827
|
+
sourceElementSize := goScriptElementByteSize(ctx, indexElementType(ctx.semPkg.source.TypesInfo.TypeOf(index.X)))
|
|
8828
|
+
targetElementSize := goScriptElementByteSize(ctx, array.Elem())
|
|
8625
8829
|
helper := o.runtimeOwner.QualifiedHelper(RuntimeHelperArrayPointerFromIndexRef) +
|
|
8626
|
-
"<" + o.tsTypeFor(ctx, array.Elem()) + ">(" + ref + ", " +
|
|
8830
|
+
"<" + o.tsTypeFor(ctx, array.Elem()) + ">(" + ref + ", " +
|
|
8831
|
+
strconv.FormatInt(array.Len(), 10) + ", " +
|
|
8832
|
+
strconv.FormatInt(sourceElementSize, 10) + ", " +
|
|
8833
|
+
strconv.FormatInt(targetElementSize, 10) + ")"
|
|
8627
8834
|
return "(" + helper + " as unknown as " + o.tsTypeFor(ctx, targetType) + ")", diagnostics, true
|
|
8628
8835
|
}
|
|
8629
8836
|
|
|
@@ -8717,6 +8924,12 @@ func sameLoweredSourceExpr(ctx lowerFileContext, left ast.Expr, right ast.Expr)
|
|
|
8717
8924
|
}
|
|
8718
8925
|
|
|
8719
8926
|
func (o *LoweringOwner) lowerPointerStorageExpr(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
8927
|
+
if ref, diagnostics, ok := o.lowerUnsafeArrayPointerRefExpr(ctx, expr); ok {
|
|
8928
|
+
return ref + ".value", diagnostics
|
|
8929
|
+
}
|
|
8930
|
+
if ref, diagnostics, ok := o.lowerUnsafePointerRefExpr(ctx, expr); ok {
|
|
8931
|
+
return ref + ".value", diagnostics
|
|
8932
|
+
}
|
|
8720
8933
|
if ref, diagnostics, ok := o.lowerUnsafePointerStorageExpr(ctx, expr); ok {
|
|
8721
8934
|
return ref, diagnostics
|
|
8722
8935
|
}
|
|
@@ -8724,6 +8937,42 @@ func (o *LoweringOwner) lowerPointerStorageExpr(ctx lowerFileContext, expr ast.E
|
|
|
8724
8937
|
return base + "!.value", diagnostics
|
|
8725
8938
|
}
|
|
8726
8939
|
|
|
8940
|
+
func (o *LoweringOwner) lowerUnsafeArrayPointerRefExpr(
|
|
8941
|
+
ctx lowerFileContext,
|
|
8942
|
+
expr ast.Expr,
|
|
8943
|
+
) (string, []Diagnostic, bool) {
|
|
8944
|
+
call, ok := unwrapParenExpr(expr).(*ast.CallExpr)
|
|
8945
|
+
if !ok || len(call.Args) != 1 {
|
|
8946
|
+
return "", nil, false
|
|
8947
|
+
}
|
|
8948
|
+
targetType := typeFromExpr(ctx, call.Fun)
|
|
8949
|
+
if targetType == nil {
|
|
8950
|
+
return "", nil, false
|
|
8951
|
+
}
|
|
8952
|
+
return o.lowerUnsafeArrayPointerConversion(ctx, targetType, call.Args[0])
|
|
8953
|
+
}
|
|
8954
|
+
|
|
8955
|
+
func (o *LoweringOwner) lowerUnsafePointerRefExpr(
|
|
8956
|
+
ctx lowerFileContext,
|
|
8957
|
+
expr ast.Expr,
|
|
8958
|
+
) (string, []Diagnostic, bool) {
|
|
8959
|
+
call, ok := unwrapParenExpr(expr).(*ast.CallExpr)
|
|
8960
|
+
if !ok || len(call.Args) != 1 {
|
|
8961
|
+
return "", nil, false
|
|
8962
|
+
}
|
|
8963
|
+
targetType := typeFromExpr(ctx, call.Fun)
|
|
8964
|
+
if targetType == nil {
|
|
8965
|
+
return "", nil, false
|
|
8966
|
+
}
|
|
8967
|
+
pointer, _ := types.Unalias(targetType).Underlying().(*types.Pointer)
|
|
8968
|
+
if pointer == nil || !isUnsafePointerType(ctx.semPkg.source.TypesInfo.TypeOf(call.Args[0])) {
|
|
8969
|
+
return "", nil, false
|
|
8970
|
+
}
|
|
8971
|
+
value, diagnostics := o.lowerExpr(ctx, call.Args[0])
|
|
8972
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperUnsafePointerRef) +
|
|
8973
|
+
"<" + o.tsTypeFor(ctx, pointer.Elem()) + ">(" + value + ")", diagnostics, true
|
|
8974
|
+
}
|
|
8975
|
+
|
|
8727
8976
|
func (o *LoweringOwner) lowerUnsafePointerStorageExpr(
|
|
8728
8977
|
ctx lowerFileContext,
|
|
8729
8978
|
expr ast.Expr,
|
|
@@ -8893,15 +9142,11 @@ func (o *LoweringOwner) lowerCompositeLit(
|
|
|
8893
9142
|
if mapType, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(lit)).Underlying().(*types.Map); ok {
|
|
8894
9143
|
return o.lowerMapCompositeLit(ctx, lit, mapType)
|
|
8895
9144
|
}
|
|
8896
|
-
position := sourcePos(ctx.semPkg.source, lit.Pos())
|
|
8897
9145
|
detail := "unsupported composite literal"
|
|
8898
|
-
if position.file != "" {
|
|
8899
|
-
detail += " at " + filepath.Base(position.file) + ":" + strconv.Itoa(position.line)
|
|
8900
|
-
}
|
|
8901
9146
|
if typ := ctx.semPkg.source.TypesInfo.TypeOf(lit); typ != nil {
|
|
8902
9147
|
detail += " of type " + typ.String()
|
|
8903
9148
|
}
|
|
8904
|
-
return "undefined", []Diagnostic{
|
|
9149
|
+
return "undefined", []Diagnostic{loweringUnsupportedAt(ctx, lit, "expression", ctx.semPkg.pkgPath, detail)}
|
|
8905
9150
|
}
|
|
8906
9151
|
|
|
8907
9152
|
func (o *LoweringOwner) lowerStructCompositeLit(
|
|
@@ -8936,7 +9181,7 @@ func (o *LoweringOwner) lowerStructCompositeLit(
|
|
|
8936
9181
|
fieldType = field.Type()
|
|
8937
9182
|
}
|
|
8938
9183
|
if fieldName == "" {
|
|
8939
|
-
diagnostics = append(diagnostics,
|
|
9184
|
+
diagnostics = append(diagnostics, loweringUnsupportedAt(ctx, elt, "expression", ctx.semPkg.pkgPath, "unsupported struct literal field"))
|
|
8940
9185
|
continue
|
|
8941
9186
|
}
|
|
8942
9187
|
value, valueDiagnostics := o.lowerExpr(ctx, valueExpr)
|
|
@@ -9047,7 +9292,7 @@ func (o *LoweringOwner) lowerAnonymousStructCompositeLit(
|
|
|
9047
9292
|
fieldType = field.Type()
|
|
9048
9293
|
}
|
|
9049
9294
|
if fieldName == "" {
|
|
9050
|
-
diagnostics = append(diagnostics,
|
|
9295
|
+
diagnostics = append(diagnostics, loweringUnsupportedAt(ctx, elt, "expression", ctx.semPkg.pkgPath, "unsupported anonymous struct literal field"))
|
|
9051
9296
|
continue
|
|
9052
9297
|
}
|
|
9053
9298
|
value, valueDiagnostics := o.lowerExpr(ctx, valueExpr)
|
|
@@ -9156,7 +9401,7 @@ func (o *LoweringOwner) lowerMapCompositeLit(
|
|
|
9156
9401
|
for _, elt := range lit.Elts {
|
|
9157
9402
|
keyed, ok := elt.(*ast.KeyValueExpr)
|
|
9158
9403
|
if !ok {
|
|
9159
|
-
diagnostics = append(diagnostics,
|
|
9404
|
+
diagnostics = append(diagnostics, loweringUnsupportedAt(ctx, elt, "expression", ctx.semPkg.pkgPath, "unsupported map literal entry"))
|
|
9160
9405
|
continue
|
|
9161
9406
|
}
|
|
9162
9407
|
key, keyDiagnostics := o.lowerExpr(ctx, keyed.Key)
|
|
@@ -10398,6 +10643,42 @@ func isMapType(typ types.Type) bool {
|
|
|
10398
10643
|
return ok
|
|
10399
10644
|
}
|
|
10400
10645
|
|
|
10646
|
+
func indexElementType(typ types.Type) types.Type {
|
|
10647
|
+
if pointer, ok := types.Unalias(typ).Underlying().(*types.Pointer); ok {
|
|
10648
|
+
typ = pointer.Elem()
|
|
10649
|
+
}
|
|
10650
|
+
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
10651
|
+
case *types.Slice:
|
|
10652
|
+
return typed.Elem()
|
|
10653
|
+
case *types.Array:
|
|
10654
|
+
return typed.Elem()
|
|
10655
|
+
default:
|
|
10656
|
+
return nil
|
|
10657
|
+
}
|
|
10658
|
+
}
|
|
10659
|
+
|
|
10660
|
+
func goScriptElementByteSize(ctx lowerFileContext, typ types.Type) int64 {
|
|
10661
|
+
if typ == nil {
|
|
10662
|
+
return 1
|
|
10663
|
+
}
|
|
10664
|
+
if sizes := ctx.semPkg.source.TypesSizes; sizes != nil {
|
|
10665
|
+
if size := sizes.Sizeof(typ); size > 0 {
|
|
10666
|
+
return size
|
|
10667
|
+
}
|
|
10668
|
+
}
|
|
10669
|
+
if bits, ok := integerBits(typ); ok && bits > 0 {
|
|
10670
|
+
return int64((bits + 7) / 8)
|
|
10671
|
+
}
|
|
10672
|
+
if isFloatType(typ) {
|
|
10673
|
+
basic, _ := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10674
|
+
if basic != nil && basic.Kind() == types.Float32 {
|
|
10675
|
+
return 4
|
|
10676
|
+
}
|
|
10677
|
+
return 8
|
|
10678
|
+
}
|
|
10679
|
+
return 1
|
|
10680
|
+
}
|
|
10681
|
+
|
|
10401
10682
|
func isChannelType(typ types.Type) bool {
|
|
10402
10683
|
if typ == nil {
|
|
10403
10684
|
return false
|
|
@@ -10471,6 +10752,9 @@ func isFloatType(typ types.Type) bool {
|
|
|
10471
10752
|
}
|
|
10472
10753
|
|
|
10473
10754
|
func unsignedIntegerBits(typ types.Type) (int, bool) {
|
|
10755
|
+
if typ == nil {
|
|
10756
|
+
return 0, false
|
|
10757
|
+
}
|
|
10474
10758
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10475
10759
|
if !ok || basic.Info()&types.IsUnsigned == 0 {
|
|
10476
10760
|
return 0, false
|
|
@@ -10488,6 +10772,9 @@ func unsignedIntegerBits(typ types.Type) (int, bool) {
|
|
|
10488
10772
|
}
|
|
10489
10773
|
|
|
10490
10774
|
func signedIntegerBits(typ types.Type) (int, bool) {
|
|
10775
|
+
if typ == nil {
|
|
10776
|
+
return 0, false
|
|
10777
|
+
}
|
|
10491
10778
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10492
10779
|
if !ok || basic.Info()&types.IsInteger == 0 || basic.Info()&types.IsUnsigned != 0 {
|
|
10493
10780
|
return 0, false
|