goscript 0.0.58 → 0.0.59
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 +40 -33
- package/compiler/analysis.go +115 -19
- package/compiler/assignment.go +163 -217
- package/compiler/compiler.go +35 -31
- package/compiler/composite-lit.go +233 -196
- package/compiler/constraint.go +88 -0
- package/compiler/decl.go +82 -24
- package/compiler/expr-call-async.go +20 -34
- package/compiler/expr-call-builtins.go +19 -0
- package/compiler/expr-call-helpers.go +0 -28
- package/compiler/expr-call-make.go +93 -343
- package/compiler/expr-call-type-conversion.go +221 -249
- package/compiler/expr-call.go +70 -69
- package/compiler/expr-selector.go +21 -24
- package/compiler/expr.go +3 -60
- package/compiler/protobuf.go +180 -36
- package/compiler/spec-value.go +132 -24
- package/compiler/spec.go +14 -55
- package/compiler/stmt-assign.go +338 -356
- package/compiler/stmt-range.go +4 -24
- package/compiler/stmt.go +92 -203
- package/compiler/type-utils.go +185 -0
- package/compiler/type.go +26 -80
- package/dist/gs/builtin/slice.d.ts +1 -1
- package/dist/gs/builtin/slice.js +3 -0
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.js +8 -2
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/fmt/fmt.js +113 -16
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/runtime/runtime.d.ts +1 -1
- package/dist/gs/runtime/runtime.js +1 -1
- package/dist/gs/slices/slices.d.ts +23 -0
- package/dist/gs/slices/slices.js +61 -0
- package/dist/gs/slices/slices.js.map +1 -1
- package/go.mod +8 -8
- package/go.sum +14 -14
- package/gs/builtin/slice.ts +5 -2
- package/gs/builtin/type.ts +13 -6
- package/gs/fmt/fmt.test.ts +176 -0
- package/gs/fmt/fmt.ts +109 -18
- package/gs/runtime/runtime.ts +1 -1
- package/gs/slices/slices.ts +68 -0
- package/package.json +3 -3
package/compiler/assignment.go
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
package compiler
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
+
"fmt"
|
|
4
5
|
"go/ast"
|
|
5
6
|
"go/token"
|
|
6
7
|
"go/types"
|
|
7
|
-
|
|
8
|
-
"golang.org/x/tools/go/packages"
|
|
9
8
|
)
|
|
10
9
|
|
|
11
10
|
// writeAssignmentCore handles the central logic for translating Go assignment
|
|
@@ -37,75 +36,19 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
37
36
|
// Handle blank identifier (_) on the LHS for single assignments
|
|
38
37
|
if len(lhs) == 1 && len(rhs) == 1 {
|
|
39
38
|
if ident, ok := lhs[0].(*ast.Ident); ok && ident.Name == "_" {
|
|
40
|
-
|
|
41
|
-
c.tsw.WriteLiterally("/* _ = */ ")
|
|
42
|
-
if err := c.WriteValueExpr(rhs[0]); err != nil {
|
|
43
|
-
return err
|
|
44
|
-
}
|
|
45
|
-
return nil
|
|
39
|
+
return c.writeBlankIdentifierAssign(rhs[0])
|
|
46
40
|
}
|
|
47
41
|
|
|
48
|
-
// Handle the special case of "*p = val" (assignment to dereferenced pointer)
|
|
42
|
+
// Handle the special case of "*p = val" or "*p += val" (assignment to dereferenced pointer)
|
|
49
43
|
if starExpr, ok := lhs[0].(*ast.StarExpr); ok {
|
|
50
|
-
|
|
51
|
-
// Write "p!.value = " for the underlying value
|
|
52
|
-
if err := c.WriteValueExpr(starExpr.X); err != nil { // p in *p
|
|
53
|
-
return err
|
|
54
|
-
}
|
|
55
|
-
c.tsw.WriteLiterally("!.value = ") // Add non-null assertion for TS safety
|
|
56
|
-
|
|
57
|
-
// Handle the RHS expression (potentially adding .clone() for structs)
|
|
58
|
-
if shouldApplyClone(c.pkg, rhs[0]) {
|
|
59
|
-
// When cloning for value assignment, mark the result as struct value
|
|
60
|
-
c.tsw.WriteLiterally("$.markAsStructValue(")
|
|
61
|
-
if err := c.WriteValueExpr(rhs[0]); err != nil {
|
|
62
|
-
return err
|
|
63
|
-
}
|
|
64
|
-
c.tsw.WriteLiterally(".clone())")
|
|
65
|
-
} else {
|
|
66
|
-
if err := c.WriteValueExpr(rhs[0]); err != nil {
|
|
67
|
-
return err
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return nil
|
|
44
|
+
return c.writePointerDerefAssign(starExpr, rhs[0], tok)
|
|
71
45
|
}
|
|
72
46
|
|
|
73
47
|
// Handle variable referenced variables in declarations
|
|
74
48
|
if addDeclaration && tok == token.DEFINE {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
var lhsObj types.Object
|
|
79
|
-
|
|
80
|
-
if ident, ok := lhs[0].(*ast.Ident); ok {
|
|
81
|
-
lhsIdent = ident
|
|
82
|
-
// Get the types.Object from the identifier
|
|
83
|
-
if use, ok := c.pkg.TypesInfo.Uses[ident]; ok {
|
|
84
|
-
lhsObj = use
|
|
85
|
-
} else if def, ok := c.pkg.TypesInfo.Defs[ident]; ok {
|
|
86
|
-
lhsObj = def
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Check if this variable needs to be variable referenced
|
|
90
|
-
if lhsObj != nil && c.analysis.NeedsVarRef(lhsObj) {
|
|
91
|
-
isLHSVarRefed = true
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Handle short declaration of variable referenced variables
|
|
96
|
-
if isLHSVarRefed && lhsIdent != nil {
|
|
97
|
-
c.tsw.WriteLiterally("let ")
|
|
98
|
-
// Just write the identifier name without .value
|
|
99
|
-
c.tsw.WriteLiterally(c.sanitizeIdentifier(lhsIdent.Name))
|
|
100
|
-
// No type annotation, allow TypeScript to infer it from varRef.
|
|
101
|
-
c.tsw.WriteLiterally(" = ")
|
|
102
|
-
|
|
103
|
-
// Create the variable reference for the initializer
|
|
104
|
-
c.tsw.WriteLiterally("$.varRef(")
|
|
105
|
-
if err := c.WriteValueExpr(rhs[0]); err != nil {
|
|
106
|
-
return err
|
|
107
|
-
}
|
|
108
|
-
c.tsw.WriteLiterally(")")
|
|
49
|
+
if handled, err := c.writeVarRefShortDecl(lhs[0], rhs[0]); err != nil {
|
|
50
|
+
return err
|
|
51
|
+
} else if handled {
|
|
109
52
|
return nil
|
|
110
53
|
}
|
|
111
54
|
|
|
@@ -115,82 +58,7 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
115
58
|
|
|
116
59
|
// Special case for multi-variable assignment to handle array element swaps
|
|
117
60
|
if len(lhs) > 1 && len(rhs) > 1 {
|
|
118
|
-
|
|
119
|
-
// Identify if we're dealing with array index expressions that might need null assertions
|
|
120
|
-
allIndexExprs := true
|
|
121
|
-
for _, expr := range append(lhs, rhs...) {
|
|
122
|
-
_, isIndexExpr := expr.(*ast.IndexExpr)
|
|
123
|
-
if !isIndexExpr {
|
|
124
|
-
allIndexExprs = false
|
|
125
|
-
break
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Add semicolon before destructuring assignment to prevent TypeScript
|
|
130
|
-
// from interpreting it as array access on the previous line
|
|
131
|
-
if tok != token.DEFINE {
|
|
132
|
-
c.tsw.WriteLiterally(";")
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Use array destructuring for multi-variable assignments
|
|
136
|
-
c.tsw.WriteLiterally("[")
|
|
137
|
-
for i, l := range lhs {
|
|
138
|
-
if i != 0 {
|
|
139
|
-
c.tsw.WriteLiterally(", ")
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Handle blank identifier
|
|
143
|
-
if ident, ok := l.(*ast.Ident); ok && ident.Name == "_" {
|
|
144
|
-
// If it's a blank identifier, we write nothing,
|
|
145
|
-
// leaving an empty slot in the destructuring array.
|
|
146
|
-
} else if indexExpr, ok := l.(*ast.IndexExpr); ok && allIndexExprs { // MODIFICATION: Added 'else if'
|
|
147
|
-
// Note: We don't use WriteIndexExpr here because we need direct array access for swapping
|
|
148
|
-
if err := c.WriteValueExpr(indexExpr.X); err != nil {
|
|
149
|
-
return err
|
|
150
|
-
}
|
|
151
|
-
c.tsw.WriteLiterally("!") // non-null assertion
|
|
152
|
-
c.tsw.WriteLiterally("[")
|
|
153
|
-
if err := c.WriteValueExpr(indexExpr.Index); err != nil {
|
|
154
|
-
return err
|
|
155
|
-
}
|
|
156
|
-
c.tsw.WriteLiterally("]")
|
|
157
|
-
} else {
|
|
158
|
-
// Normal case - write the entire expression
|
|
159
|
-
if err := c.WriteValueExpr(l); err != nil {
|
|
160
|
-
return err
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
c.tsw.WriteLiterally("] = [")
|
|
165
|
-
for i, r := range rhs {
|
|
166
|
-
if i != 0 {
|
|
167
|
-
c.tsw.WriteLiterally(", ")
|
|
168
|
-
}
|
|
169
|
-
if indexExpr, ok := r.(*ast.IndexExpr); ok && allIndexExprs {
|
|
170
|
-
// Note: We don't use WriteIndexExpr here because we need direct array access for swapping
|
|
171
|
-
if err := c.WriteValueExpr(indexExpr.X); err != nil {
|
|
172
|
-
return err
|
|
173
|
-
}
|
|
174
|
-
c.tsw.WriteLiterally("!")
|
|
175
|
-
c.tsw.WriteLiterally("[")
|
|
176
|
-
if err := c.WriteValueExpr(indexExpr.Index); err != nil {
|
|
177
|
-
return err
|
|
178
|
-
}
|
|
179
|
-
c.tsw.WriteLiterally("]")
|
|
180
|
-
} else if callExpr, isCallExpr := r.(*ast.CallExpr); isCallExpr {
|
|
181
|
-
// If the RHS is a function call, write it as a call
|
|
182
|
-
if err := c.WriteCallExpr(callExpr); err != nil {
|
|
183
|
-
return err
|
|
184
|
-
}
|
|
185
|
-
} else {
|
|
186
|
-
// Normal case - write the entire expression
|
|
187
|
-
if err := c.WriteValueExpr(r); err != nil {
|
|
188
|
-
return err
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
c.tsw.WriteLiterally("]")
|
|
193
|
-
return nil
|
|
61
|
+
return c.writeMultiVarAssign(lhs, rhs, tok)
|
|
194
62
|
}
|
|
195
63
|
|
|
196
64
|
// --- Logic for assignments ---
|
|
@@ -259,13 +127,8 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
259
127
|
// Determine if LHS is variable referenced
|
|
260
128
|
isLHSVarRefed := false
|
|
261
129
|
var lhsObj types.Object
|
|
262
|
-
|
|
263
130
|
// Get the types.Object from the identifier
|
|
264
|
-
|
|
265
|
-
lhsObj = use
|
|
266
|
-
} else if def, ok := c.pkg.TypesInfo.Defs[lhsExprIdent]; ok {
|
|
267
|
-
lhsObj = def
|
|
268
|
-
}
|
|
131
|
+
lhsObj = c.objectOfIdent(lhsExprIdent)
|
|
269
132
|
|
|
270
133
|
// Check if this variable needs to be variable referenced
|
|
271
134
|
if lhsObj != nil && c.analysis.NeedsVarRef(lhsObj) {
|
|
@@ -290,20 +153,8 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
290
153
|
// Continue, we've already written part of the mapSet() function call
|
|
291
154
|
} else {
|
|
292
155
|
c.tsw.WriteLiterally(" ")
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
if tok == token.AND_NOT_ASSIGN {
|
|
296
|
-
// Transform x &^= y to x &= ~(y)
|
|
297
|
-
c.tsw.WriteLiterally("&= ~(")
|
|
298
|
-
} else {
|
|
299
|
-
tokStr, ok := TokenToTs(tok) // Use explicit gstypes alias
|
|
300
|
-
if !ok {
|
|
301
|
-
c.tsw.WriteLiterally("?= ")
|
|
302
|
-
c.tsw.WriteCommentLine("Unknown token " + tok.String())
|
|
303
|
-
} else {
|
|
304
|
-
c.tsw.WriteLiterally(tokStr)
|
|
305
|
-
}
|
|
306
|
-
c.tsw.WriteLiterally(" ")
|
|
156
|
+
if err := c.writeAssignmentOperator(tok); err != nil {
|
|
157
|
+
return err
|
|
307
158
|
}
|
|
308
159
|
}
|
|
309
160
|
|
|
@@ -327,10 +178,7 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
327
178
|
// Check if RHS is an identifier (variable name)
|
|
328
179
|
rhsIdent, rhsIsIdent := r.(*ast.Ident)
|
|
329
180
|
if rhsIsIdent {
|
|
330
|
-
rhsObj = c.
|
|
331
|
-
if rhsObj == nil {
|
|
332
|
-
rhsObj = c.pkg.TypesInfo.Defs[rhsIdent]
|
|
333
|
-
}
|
|
181
|
+
rhsObj = c.objectOfIdent(rhsIdent)
|
|
334
182
|
|
|
335
183
|
// Important: For struct copying, we need to check if the variable itself is variable referenced
|
|
336
184
|
// Important: For struct copying, we need to check if the variable needs variable referenced access
|
|
@@ -440,73 +288,171 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
440
288
|
return nil
|
|
441
289
|
}
|
|
442
290
|
|
|
443
|
-
//
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
//
|
|
450
|
-
|
|
451
|
-
//
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
291
|
+
// writeBlankIdentifierAssign handles assignment to blank identifier (_)
|
|
292
|
+
func (c *GoToTSCompiler) writeBlankIdentifierAssign(rhs ast.Expr) error {
|
|
293
|
+
c.tsw.WriteLiterally("/* _ = */ ")
|
|
294
|
+
return c.WriteValueExpr(rhs)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// writePointerDerefAssign handles assignments to dereferenced pointers (*p = val)
|
|
298
|
+
func (c *GoToTSCompiler) writePointerDerefAssign(starExpr *ast.StarExpr, rhs ast.Expr, tok token.Token) error {
|
|
299
|
+
// Write pointer dereference
|
|
300
|
+
if ident, ok := starExpr.X.(*ast.Ident); ok {
|
|
301
|
+
obj := c.objectOfIdent(ident)
|
|
302
|
+
if obj != nil && c.analysis.NeedsVarRef(obj) {
|
|
303
|
+
c.WriteIdent(ident, true)
|
|
304
|
+
c.tsw.WriteLiterally("!.value")
|
|
305
|
+
} else {
|
|
306
|
+
c.WriteIdent(ident, false)
|
|
307
|
+
c.tsw.WriteLiterally("!.value")
|
|
308
|
+
}
|
|
309
|
+
} else {
|
|
310
|
+
if err := c.WriteValueExpr(starExpr.X); err != nil {
|
|
311
|
+
return err
|
|
312
|
+
}
|
|
313
|
+
c.tsw.WriteLiterally("!.value")
|
|
464
314
|
}
|
|
465
315
|
|
|
466
|
-
//
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
} else if obj := pkg.TypesInfo.Defs[ident]; obj != nil {
|
|
475
|
-
// Also check Defs map for definitions
|
|
476
|
-
exprType = obj.Type()
|
|
316
|
+
// Write assignment operator
|
|
317
|
+
if tok == token.AND_NOT_ASSIGN {
|
|
318
|
+
c.tsw.WriteLiterally(" &= ~(")
|
|
319
|
+
} else {
|
|
320
|
+
c.tsw.WriteLiterally(" ")
|
|
321
|
+
tokStr, ok := TokenToTs(tok)
|
|
322
|
+
if !ok {
|
|
323
|
+
return fmt.Errorf("unknown assignment token: %s", tok.String())
|
|
477
324
|
}
|
|
325
|
+
c.tsw.WriteLiterally(tokStr)
|
|
326
|
+
c.tsw.WriteLiterally(" ")
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Write RHS with cloning if needed
|
|
330
|
+
if shouldApplyClone(c.pkg, rhs) {
|
|
331
|
+
c.tsw.WriteLiterally("$.markAsStructValue(")
|
|
332
|
+
if err := c.WriteValueExpr(rhs); err != nil {
|
|
333
|
+
return err
|
|
334
|
+
}
|
|
335
|
+
c.tsw.WriteLiterally(".clone())")
|
|
336
|
+
} else {
|
|
337
|
+
if err := c.WriteValueExpr(rhs); err != nil {
|
|
338
|
+
return err
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if tok == token.AND_NOT_ASSIGN {
|
|
343
|
+
c.tsw.WriteLiterally(")")
|
|
478
344
|
}
|
|
479
345
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
346
|
+
return nil
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// writeVarRefShortDecl handles short declarations of varrefed variables
|
|
350
|
+
// Returns true if handled, false otherwise
|
|
351
|
+
func (c *GoToTSCompiler) writeVarRefShortDecl(lhs, rhs ast.Expr) (bool, error) {
|
|
352
|
+
ident, ok := lhs.(*ast.Ident)
|
|
353
|
+
if !ok {
|
|
354
|
+
return false, nil
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
obj := c.objectOfIdent(ident)
|
|
358
|
+
if obj == nil || !c.analysis.NeedsVarRef(obj) {
|
|
359
|
+
return false, nil
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
c.tsw.WriteLiterally("let ")
|
|
363
|
+
c.tsw.WriteLiterally(c.sanitizeIdentifier(ident.Name))
|
|
364
|
+
c.tsw.WriteLiterally(" = $.varRef(")
|
|
365
|
+
if err := c.WriteValueExpr(rhs); err != nil {
|
|
366
|
+
return false, err
|
|
367
|
+
}
|
|
368
|
+
c.tsw.WriteLiterally(")")
|
|
369
|
+
return true, nil
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// writeMultiVarAssign handles multi-variable assignments with array destructuring
|
|
373
|
+
func (c *GoToTSCompiler) writeMultiVarAssign(lhs, rhs []ast.Expr, tok token.Token) error {
|
|
374
|
+
// Check if all expressions are index expressions (for swap optimization)
|
|
375
|
+
allIndexExprs := true
|
|
376
|
+
for _, expr := range append(lhs, rhs...) {
|
|
377
|
+
if _, isIndexExpr := expr.(*ast.IndexExpr); !isIndexExpr {
|
|
378
|
+
allIndexExprs = false
|
|
379
|
+
break
|
|
484
380
|
}
|
|
485
381
|
}
|
|
486
382
|
|
|
487
|
-
//
|
|
488
|
-
if
|
|
489
|
-
|
|
383
|
+
// Add semicolon to prevent TypeScript parsing issues
|
|
384
|
+
if tok != token.DEFINE {
|
|
385
|
+
c.tsw.WriteLiterally(";")
|
|
490
386
|
}
|
|
491
387
|
|
|
492
|
-
//
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
388
|
+
// Write LHS array destructuring pattern
|
|
389
|
+
c.tsw.WriteLiterally("[")
|
|
390
|
+
for i, l := range lhs {
|
|
391
|
+
if i != 0 {
|
|
392
|
+
c.tsw.WriteLiterally(", ")
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if ident, ok := l.(*ast.Ident); ok && ident.Name == "_" {
|
|
396
|
+
// Blank identifier - leave empty slot
|
|
397
|
+
} else if indexExpr, ok := l.(*ast.IndexExpr); ok && allIndexExprs {
|
|
398
|
+
if err := c.WriteValueExpr(indexExpr.X); err != nil {
|
|
399
|
+
return err
|
|
400
|
+
}
|
|
401
|
+
c.tsw.WriteLiterally("![")
|
|
402
|
+
if err := c.WriteValueExpr(indexExpr.Index); err != nil {
|
|
403
|
+
return err
|
|
404
|
+
}
|
|
405
|
+
c.tsw.WriteLiterally("]")
|
|
406
|
+
} else {
|
|
407
|
+
if err := c.WriteValueExpr(l); err != nil {
|
|
408
|
+
return err
|
|
409
|
+
}
|
|
410
|
+
}
|
|
496
411
|
}
|
|
497
412
|
|
|
498
|
-
//
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
413
|
+
// Write RHS array
|
|
414
|
+
c.tsw.WriteLiterally("] = [")
|
|
415
|
+
for i, r := range rhs {
|
|
416
|
+
if i != 0 {
|
|
417
|
+
c.tsw.WriteLiterally(", ")
|
|
502
418
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
419
|
+
|
|
420
|
+
if indexExpr, ok := r.(*ast.IndexExpr); ok && allIndexExprs {
|
|
421
|
+
if err := c.WriteValueExpr(indexExpr.X); err != nil {
|
|
422
|
+
return err
|
|
423
|
+
}
|
|
424
|
+
c.tsw.WriteLiterally("![")
|
|
425
|
+
if err := c.WriteValueExpr(indexExpr.Index); err != nil {
|
|
426
|
+
return err
|
|
427
|
+
}
|
|
428
|
+
c.tsw.WriteLiterally("]")
|
|
429
|
+
} else if callExpr, isCallExpr := r.(*ast.CallExpr); isCallExpr {
|
|
430
|
+
if err := c.WriteCallExpr(callExpr); err != nil {
|
|
431
|
+
return err
|
|
432
|
+
}
|
|
433
|
+
} else {
|
|
434
|
+
if err := c.WriteValueExpr(r); err != nil {
|
|
435
|
+
return err
|
|
436
|
+
}
|
|
508
437
|
}
|
|
509
438
|
}
|
|
439
|
+
c.tsw.WriteLiterally("]")
|
|
510
440
|
|
|
511
|
-
return
|
|
441
|
+
return nil
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// writeAssignmentOperator writes the TypeScript assignment operator
|
|
445
|
+
func (c *GoToTSCompiler) writeAssignmentOperator(tok token.Token) error {
|
|
446
|
+
if tok == token.AND_NOT_ASSIGN {
|
|
447
|
+
c.tsw.WriteLiterally("&= ~(")
|
|
448
|
+
return nil
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
tokStr, ok := TokenToTs(tok)
|
|
452
|
+
if !ok {
|
|
453
|
+
return fmt.Errorf("unknown assignment token: %s", tok.String())
|
|
454
|
+
}
|
|
455
|
+
c.tsw.WriteLiterally(tokStr)
|
|
456
|
+
c.tsw.WriteLiterally(" ")
|
|
457
|
+
return nil
|
|
512
458
|
}
|
package/compiler/compiler.go
CHANGED
|
@@ -249,10 +249,14 @@ func (c *Compiler) CompilePackages(ctx context.Context, patterns ...string) (*Co
|
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
//
|
|
252
|
+
// Fail fast on packages that failed to load to avoid hiding errors
|
|
253
253
|
if len(pkg.Errors) > 0 {
|
|
254
|
-
|
|
255
|
-
|
|
254
|
+
var msgs []string
|
|
255
|
+
for _, e := range pkg.Errors {
|
|
256
|
+
// packages.Error is a struct; collect all messages
|
|
257
|
+
msgs = append(msgs, e.Error())
|
|
258
|
+
}
|
|
259
|
+
return nil, fmt.Errorf("package %s has load errors: %s", pkg.PkgPath, strings.Join(msgs, "; "))
|
|
256
260
|
}
|
|
257
261
|
|
|
258
262
|
pkgCompiler, err := NewPackageCompiler(c.le, &c.config, pkg, allPackages)
|
|
@@ -593,7 +597,7 @@ func (c *FileCompiler) Compile(ctx context.Context) error {
|
|
|
593
597
|
goWriter := NewGoToTSCompiler(c.codeWriter, c.pkg, c.Analysis)
|
|
594
598
|
|
|
595
599
|
// Add import for the goscript runtime using namespace import and alias
|
|
596
|
-
c.codeWriter.WriteLinef("import * as $ from %q
|
|
600
|
+
c.codeWriter.WriteLinef("import * as $ from %q", "@goscript/builtin/index.js")
|
|
597
601
|
|
|
598
602
|
// Check if there are any .pb.go files in this package and add imports for them
|
|
599
603
|
if err := c.addProtobufImports(); err != nil {
|
|
@@ -641,28 +645,14 @@ func (c *FileCompiler) Compile(ctx context.Context) error {
|
|
|
641
645
|
// Filter out protobuf types - they should be imported from .pb.js files, not .gs.js files
|
|
642
646
|
var nonProtobufTypes []string
|
|
643
647
|
for _, typeName := range typeImports {
|
|
644
|
-
// Check if this type is a protobuf type by looking
|
|
648
|
+
// Check if this type is a protobuf type by looking at its type info
|
|
645
649
|
isProtobuf := false
|
|
646
650
|
if typeObj := c.pkg.Types.Scope().Lookup(typeName); typeObj != nil {
|
|
647
651
|
objType := typeObj.Type()
|
|
648
652
|
if namedType, ok := objType.(*types.Named); ok {
|
|
649
|
-
|
|
650
|
-
if
|
|
651
|
-
|
|
652
|
-
if obj.Pkg() == c.pkg.Types {
|
|
653
|
-
// Check if there's a .pb.go file in the package that exports this type
|
|
654
|
-
// For now, we'll use a simple heuristic: if the type name ends with "Msg"
|
|
655
|
-
// and there's a .pb.go file in the package, assume it's a protobuf type
|
|
656
|
-
if strings.HasSuffix(typeName, "Msg") {
|
|
657
|
-
// Check if there are any .pb.go files in this package
|
|
658
|
-
for _, fileName := range c.pkg.CompiledGoFiles {
|
|
659
|
-
if strings.HasSuffix(fileName, ".pb.go") {
|
|
660
|
-
isProtobuf = true
|
|
661
|
-
break
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
}
|
|
653
|
+
// Use the same detection logic as codegen
|
|
654
|
+
if goWriter.isProtobufType(namedType) {
|
|
655
|
+
isProtobuf = true
|
|
666
656
|
}
|
|
667
657
|
}
|
|
668
658
|
}
|
|
@@ -720,6 +710,21 @@ func NewGoToTSCompiler(tsw *TSCodeWriter, pkg *packages.Package, analysis *Analy
|
|
|
720
710
|
}
|
|
721
711
|
}
|
|
722
712
|
|
|
713
|
+
// objectOfIdent returns the types.Object associated with the identifier.
|
|
714
|
+
// It checks Uses first, then Defs, and returns nil if neither is found.
|
|
715
|
+
func (c *GoToTSCompiler) objectOfIdent(ident *ast.Ident) types.Object {
|
|
716
|
+
if ident == nil || c.pkg == nil || c.pkg.TypesInfo == nil {
|
|
717
|
+
return nil
|
|
718
|
+
}
|
|
719
|
+
if obj := c.pkg.TypesInfo.Uses[ident]; obj != nil {
|
|
720
|
+
return obj
|
|
721
|
+
}
|
|
722
|
+
if obj := c.pkg.TypesInfo.Defs[ident]; obj != nil {
|
|
723
|
+
return obj
|
|
724
|
+
}
|
|
725
|
+
return nil
|
|
726
|
+
}
|
|
727
|
+
|
|
723
728
|
// getDeterministicID generates a deterministic unique ID based on file position
|
|
724
729
|
// This replaces the non-deterministic Pos() values to ensure reproducible builds
|
|
725
730
|
func (c *GoToTSCompiler) getDeterministicID(pos token.Pos) string {
|
|
@@ -778,11 +783,7 @@ func (c *GoToTSCompiler) WriteIdent(exp *ast.Ident, accessVarRefedValue bool) {
|
|
|
778
783
|
}
|
|
779
784
|
|
|
780
785
|
// Use TypesInfo to find the object associated with the identifier
|
|
781
|
-
|
|
782
|
-
obj = c.pkg.TypesInfo.Uses[exp]
|
|
783
|
-
if obj == nil {
|
|
784
|
-
obj = c.pkg.TypesInfo.Defs[exp]
|
|
785
|
-
}
|
|
786
|
+
obj := c.objectOfIdent(exp)
|
|
786
787
|
|
|
787
788
|
// Check if this identifier refers to a constant
|
|
788
789
|
if obj != nil {
|
|
@@ -1143,8 +1144,11 @@ func (c *Compiler) ReadGsPackageMetadata(gsSourcePath string) (*GsPackageMetadat
|
|
|
1143
1144
|
metaFilePath := filepath.Join(gsSourcePath, "meta.json")
|
|
1144
1145
|
content, err := gs.GsOverrides.ReadFile(metaFilePath)
|
|
1145
1146
|
if err != nil {
|
|
1146
|
-
//
|
|
1147
|
-
|
|
1147
|
+
// Only treat missing file as "no metadata"; surface other errors
|
|
1148
|
+
if os.IsNotExist(err) {
|
|
1149
|
+
return metadata, nil
|
|
1150
|
+
}
|
|
1151
|
+
return nil, fmt.Errorf("failed to read meta.json in %s: %w", gsSourcePath, err)
|
|
1148
1152
|
}
|
|
1149
1153
|
|
|
1150
1154
|
// Parse the JSON content
|
|
@@ -1181,8 +1185,8 @@ func (c *Compiler) copyGsPackageWithDependencies(packagePath string, processedPa
|
|
|
1181
1185
|
// Read metadata to get dependencies
|
|
1182
1186
|
metadata, err := c.ReadGsPackageMetadata(gsSourcePath)
|
|
1183
1187
|
if err != nil {
|
|
1184
|
-
|
|
1185
|
-
metadata
|
|
1188
|
+
// Surface metadata errors instead of silently continuing
|
|
1189
|
+
return fmt.Errorf("failed to read metadata for gs package %s: %w", packagePath, err)
|
|
1186
1190
|
}
|
|
1187
1191
|
|
|
1188
1192
|
// Log dependencies if any are found
|