goscript 0.0.33 → 0.0.35
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/compiler/analysis.go +30 -22
- package/compiler/analysis_test.go +14 -0
- package/compiler/assignment.go +45 -7
- package/compiler/builtin_test.go +2 -0
- package/compiler/compiler.go +15 -89
- package/compiler/compiler_test.go +0 -53
- package/compiler/composite-lit.go +60 -17
- package/compiler/decl.go +1 -1
- package/compiler/expr-call.go +347 -30
- package/compiler/expr-selector.go +28 -2
- package/compiler/expr.go +79 -38
- package/compiler/lit.go +112 -3
- package/compiler/primitive.go +6 -6
- package/compiler/protobuf.go +0 -5
- package/compiler/sanitize.go +101 -0
- package/compiler/spec-value.go +25 -18
- package/compiler/stmt-assign.go +128 -91
- package/compiler/stmt-for.go +78 -1
- package/compiler/stmt-range.go +333 -461
- package/compiler/stmt.go +46 -9
- package/compiler/type.go +14 -11
- package/dist/gs/builtin/builtin.d.ts +8 -0
- package/dist/gs/builtin/builtin.js +31 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/map.d.ts +4 -4
- package/dist/gs/builtin/map.js +12 -6
- package/dist/gs/builtin/map.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +14 -8
- package/dist/gs/builtin/slice.js +131 -31
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/errors.d.ts +13 -0
- package/dist/gs/github.com/pkg/errors/errors.js +232 -0
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/go113.d.ts +4 -0
- package/dist/gs/github.com/pkg/errors/go113.js +34 -0
- package/dist/gs/github.com/pkg/errors/go113.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/index.d.ts +3 -0
- package/dist/gs/github.com/pkg/errors/index.js +4 -0
- package/dist/gs/github.com/pkg/errors/index.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/stack.d.ts +32 -0
- package/dist/gs/github.com/pkg/errors/stack.js +111 -0
- package/dist/gs/github.com/pkg/errors/stack.js.map +1 -0
- package/dist/gs/maps/index.d.ts +2 -0
- package/dist/gs/maps/index.js +3 -0
- package/dist/gs/maps/index.js.map +1 -0
- package/dist/gs/maps/iter.d.ts +7 -0
- package/dist/gs/maps/iter.gs.d.ts +7 -0
- package/dist/gs/maps/iter.gs.js +65 -0
- package/dist/gs/maps/iter.gs.js.map +1 -0
- package/dist/gs/maps/iter.js +57 -0
- package/dist/gs/maps/iter.js.map +1 -0
- package/dist/gs/maps/maps.d.ts +7 -0
- package/dist/gs/maps/maps.gs.d.ts +7 -0
- package/dist/gs/maps/maps.gs.js +79 -0
- package/dist/gs/maps/maps.gs.js.map +1 -0
- package/dist/gs/maps/maps.js +67 -0
- package/dist/gs/maps/maps.js.map +1 -0
- package/dist/gs/math/abs.gs.d.ts +1 -0
- package/dist/gs/math/abs.gs.js +10 -0
- package/dist/gs/math/abs.gs.js.map +1 -0
- package/dist/gs/math/acosh.gs.d.ts +2 -0
- package/dist/gs/math/acosh.gs.js +14 -0
- package/dist/gs/math/acosh.gs.js.map +1 -0
- package/dist/gs/math/asin.gs.d.ts +4 -0
- package/dist/gs/math/asin.gs.js +24 -0
- package/dist/gs/math/asin.gs.js.map +1 -0
- package/dist/gs/math/asinh.gs.d.ts +2 -0
- package/dist/gs/math/asinh.gs.js +14 -0
- package/dist/gs/math/asinh.gs.js.map +1 -0
- package/dist/gs/math/atan.gs.d.ts +4 -0
- package/dist/gs/math/atan.gs.js +22 -0
- package/dist/gs/math/atan.gs.js.map +1 -0
- package/dist/gs/math/atan2.gs.d.ts +2 -0
- package/dist/gs/math/atan2.gs.js +30 -0
- package/dist/gs/math/atan2.gs.js.map +1 -0
- package/dist/gs/math/atanh.gs.d.ts +2 -0
- package/dist/gs/math/atanh.gs.js +16 -0
- package/dist/gs/math/atanh.gs.js.map +1 -0
- package/dist/gs/math/bits.gs.d.ts +5 -0
- package/dist/gs/math/bits.gs.js +46 -0
- package/dist/gs/math/bits.gs.js.map +1 -0
- package/dist/gs/math/cbrt.gs.d.ts +2 -0
- package/dist/gs/math/cbrt.gs.js +14 -0
- package/dist/gs/math/cbrt.gs.js.map +1 -0
- package/dist/gs/math/const.gs.d.ts +30 -0
- package/dist/gs/math/const.gs.js +61 -0
- package/dist/gs/math/const.gs.js.map +1 -0
- package/dist/gs/math/copysign.gs.d.ts +1 -0
- package/dist/gs/math/copysign.gs.js +20 -0
- package/dist/gs/math/copysign.gs.js.map +1 -0
- package/dist/gs/math/dim.gs.d.ts +5 -0
- package/dist/gs/math/dim.gs.js +69 -0
- package/dist/gs/math/dim.gs.js.map +1 -0
- package/dist/gs/math/erf.gs.d.ts +4 -0
- package/dist/gs/math/erf.gs.js +336 -0
- package/dist/gs/math/erf.gs.js.map +1 -0
- package/dist/gs/math/erfinv.gs.d.ts +2 -0
- package/dist/gs/math/erfinv.gs.js +118 -0
- package/dist/gs/math/erfinv.gs.js.map +1 -0
- package/dist/gs/math/exp.gs.d.ts +5 -0
- package/dist/gs/math/exp.gs.js +30 -0
- package/dist/gs/math/exp.gs.js.map +1 -0
- package/dist/gs/math/expm1.gs.d.ts +2 -0
- package/dist/gs/math/expm1.gs.js +17 -0
- package/dist/gs/math/expm1.gs.js.map +1 -0
- package/dist/gs/math/floor.gs.d.ts +8 -0
- package/dist/gs/math/floor.gs.js +75 -0
- package/dist/gs/math/floor.gs.js.map +1 -0
- package/dist/gs/math/fma.gs.d.ts +1 -0
- package/dist/gs/math/fma.gs.js +8 -0
- package/dist/gs/math/fma.gs.js.map +1 -0
- package/dist/gs/math/frexp.gs.d.ts +2 -0
- package/dist/gs/math/frexp.gs.js +28 -0
- package/dist/gs/math/frexp.gs.js.map +1 -0
- package/dist/gs/math/gamma.gs.d.ts +3 -0
- package/dist/gs/math/gamma.gs.js +149 -0
- package/dist/gs/math/gamma.gs.js.map +1 -0
- package/dist/gs/math/hypot.gs.d.ts +2 -0
- package/dist/gs/math/hypot.gs.js +16 -0
- package/dist/gs/math/hypot.gs.js.map +1 -0
- package/dist/gs/math/index.d.ts +44 -0
- package/dist/gs/math/index.js +45 -0
- package/dist/gs/math/index.js.map +1 -0
- package/dist/gs/math/j0.gs.d.ts +4 -0
- package/dist/gs/math/j0.gs.js +228 -0
- package/dist/gs/math/j0.gs.js.map +1 -0
- package/dist/gs/math/j1.gs.d.ts +4 -0
- package/dist/gs/math/j1.gs.js +211 -0
- package/dist/gs/math/j1.gs.js.map +1 -0
- package/dist/gs/math/jn.gs.d.ts +2 -0
- package/dist/gs/math/jn.gs.js +412 -0
- package/dist/gs/math/jn.gs.js.map +1 -0
- package/dist/gs/math/ldexp.gs.d.ts +2 -0
- package/dist/gs/math/ldexp.gs.js +20 -0
- package/dist/gs/math/ldexp.gs.js.map +1 -0
- package/dist/gs/math/lgamma.gs.d.ts +2 -0
- package/dist/gs/math/lgamma.gs.js +243 -0
- package/dist/gs/math/lgamma.gs.js.map +1 -0
- package/dist/gs/math/log.gs.d.ts +2 -0
- package/dist/gs/math/log.gs.js +16 -0
- package/dist/gs/math/log.gs.js.map +1 -0
- package/dist/gs/math/log10.gs.d.ts +4 -0
- package/dist/gs/math/log10.gs.js +17 -0
- package/dist/gs/math/log10.gs.js.map +1 -0
- package/dist/gs/math/log1p.gs.d.ts +2 -0
- package/dist/gs/math/log1p.gs.js +17 -0
- package/dist/gs/math/log1p.gs.js.map +1 -0
- package/dist/gs/math/logb.gs.d.ts +3 -0
- package/dist/gs/math/logb.gs.js +43 -0
- package/dist/gs/math/logb.gs.js.map +1 -0
- package/dist/gs/math/mod.gs.d.ts +2 -0
- package/dist/gs/math/mod.gs.js +26 -0
- package/dist/gs/math/mod.gs.js.map +1 -0
- package/dist/gs/math/modf.gs.d.ts +2 -0
- package/dist/gs/math/modf.gs.js +24 -0
- package/dist/gs/math/modf.gs.js.map +1 -0
- package/dist/gs/math/nextafter.gs.d.ts +2 -0
- package/dist/gs/math/nextafter.gs.js +66 -0
- package/dist/gs/math/nextafter.gs.js.map +1 -0
- package/dist/gs/math/pow.gs.d.ts +3 -0
- package/dist/gs/math/pow.gs.js +40 -0
- package/dist/gs/math/pow.gs.js.map +1 -0
- package/dist/gs/math/pow10.gs.d.ts +1 -0
- package/dist/gs/math/pow10.gs.js +14 -0
- package/dist/gs/math/pow10.gs.js.map +1 -0
- package/dist/gs/math/remainder.gs.d.ts +2 -0
- package/dist/gs/math/remainder.gs.js +25 -0
- package/dist/gs/math/remainder.gs.js.map +1 -0
- package/dist/gs/math/signbit.gs.d.ts +1 -0
- package/dist/gs/math/signbit.gs.js +5 -0
- package/dist/gs/math/signbit.gs.js.map +1 -0
- package/dist/gs/math/sin.gs.d.ts +4 -0
- package/dist/gs/math/sin.gs.js +29 -0
- package/dist/gs/math/sin.gs.js.map +1 -0
- package/dist/gs/math/sincos.gs.d.ts +1 -0
- package/dist/gs/math/sincos.gs.js +11 -0
- package/dist/gs/math/sincos.gs.js.map +1 -0
- package/dist/gs/math/sinh.gs.d.ts +4 -0
- package/dist/gs/math/sinh.gs.js +27 -0
- package/dist/gs/math/sinh.gs.js.map +1 -0
- package/dist/gs/math/sqrt.gs.d.ts +2 -0
- package/dist/gs/math/sqrt.gs.js +15 -0
- package/dist/gs/math/sqrt.gs.js.map +1 -0
- package/dist/gs/math/tan.gs.d.ts +2 -0
- package/dist/gs/math/tan.gs.js +17 -0
- package/dist/gs/math/tan.gs.js.map +1 -0
- package/dist/gs/math/tanh.gs.d.ts +2 -0
- package/dist/gs/math/tanh.gs.js +17 -0
- package/dist/gs/math/tanh.gs.js.map +1 -0
- package/dist/gs/math/trig_reduce.gs.d.ts +1 -0
- package/dist/gs/math/trig_reduce.gs.js +62 -0
- package/dist/gs/math/trig_reduce.gs.js.map +1 -0
- package/dist/gs/math/unsafe.gs.d.ts +4 -0
- package/dist/gs/math/unsafe.gs.js +47 -0
- package/dist/gs/math/unsafe.gs.js.map +1 -0
- package/dist/gs/slices/slices.d.ts +6 -0
- package/dist/gs/slices/slices.js +8 -0
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/strconv/atob.gs.d.ts +4 -0
- package/dist/gs/strconv/atob.gs.js +42 -0
- package/dist/gs/strconv/atob.gs.js.map +1 -0
- package/dist/gs/strconv/atof.gs.d.ts +2 -0
- package/dist/gs/strconv/atof.gs.js +51 -0
- package/dist/gs/strconv/atof.gs.js.map +1 -0
- package/dist/gs/strconv/atoi.gs.d.ts +33 -0
- package/dist/gs/strconv/atoi.gs.js +200 -0
- package/dist/gs/strconv/atoi.gs.js.map +1 -0
- package/dist/gs/strconv/doc.gs.d.ts +1 -0
- package/dist/gs/strconv/doc.gs.js +2 -0
- package/dist/gs/strconv/doc.gs.js.map +1 -0
- package/dist/gs/strconv/ftoa.gs.d.ts +3 -0
- package/dist/gs/strconv/ftoa.gs.js +58 -0
- package/dist/gs/strconv/ftoa.gs.js.map +1 -0
- package/dist/gs/strconv/index.d.ts +6 -0
- package/dist/gs/strconv/index.js +7 -0
- package/dist/gs/strconv/index.js.map +1 -0
- package/dist/gs/strconv/itoa.gs.d.ts +6 -0
- package/dist/gs/strconv/itoa.gs.js +37 -0
- package/dist/gs/strconv/itoa.gs.js.map +1 -0
- package/dist/gs/strconv/quote.gs.d.ts +19 -0
- package/dist/gs/strconv/quote.gs.js +217 -0
- package/dist/gs/strconv/quote.gs.js.map +1 -0
- package/dist/gs/strings/index.d.ts +3 -0
- package/dist/gs/strings/index.js +4 -0
- package/dist/gs/strings/index.js.map +1 -1
- package/dist/gs/strings/replace.d.ts +0 -74
- package/dist/gs/strings/replace.js +6 -204
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/search.d.ts +0 -1
- package/dist/gs/strings/search.js +0 -21
- package/dist/gs/strings/search.js.map +1 -1
- package/gs/builtin/builtin.ts +40 -0
- package/gs/builtin/map.ts +12 -7
- package/gs/builtin/slice.ts +174 -34
- package/gs/github.com/pkg/errors/errors.ts +307 -0
- package/gs/github.com/pkg/errors/go113.ts +39 -0
- package/gs/github.com/pkg/errors/index.ts +3 -0
- package/gs/github.com/pkg/errors/stack.ts +127 -0
- package/gs/maps/index.ts +2 -0
- package/gs/maps/iter.ts +67 -0
- package/gs/maps/maps.ts +89 -0
- package/gs/math/TODO.md +156 -0
- package/gs/math/abs.gs.test.ts +29 -0
- package/gs/math/abs.gs.ts +13 -0
- package/gs/math/acosh.gs.test.ts +39 -0
- package/gs/math/acosh.gs.ts +21 -0
- package/gs/math/asin.gs.test.ts +66 -0
- package/gs/math/asin.gs.ts +27 -0
- package/gs/math/asinh.gs.test.ts +37 -0
- package/gs/math/asinh.gs.ts +21 -0
- package/gs/math/atan.gs.test.ts +49 -0
- package/gs/math/atan.gs.ts +27 -0
- package/gs/math/atan2.gs.test.ts +55 -0
- package/gs/math/atan2.gs.ts +37 -0
- package/gs/math/atanh.gs.test.ts +47 -0
- package/gs/math/atanh.gs.ts +21 -0
- package/gs/math/bits.gs.test.ts +88 -0
- package/gs/math/bits.gs.ts +61 -0
- package/gs/math/cbrt.gs.test.ts +57 -0
- package/gs/math/cbrt.gs.ts +20 -0
- package/gs/math/const.gs.test.ts +54 -0
- package/gs/math/const.gs.ts +93 -0
- package/gs/math/copysign.gs.test.ts +44 -0
- package/gs/math/copysign.gs.ts +27 -0
- package/gs/math/dim.gs.test.ts +102 -0
- package/gs/math/dim.gs.ts +84 -0
- package/gs/math/erf.gs.test.ts +92 -0
- package/gs/math/erf.gs.ts +409 -0
- package/gs/math/erfinv.gs.test.ts +104 -0
- package/gs/math/erfinv.gs.ts +169 -0
- package/gs/math/exp.gs.test.ts +82 -0
- package/gs/math/exp.gs.ts +39 -0
- package/gs/math/expm1.gs.test.ts +48 -0
- package/gs/math/expm1.gs.ts +23 -0
- package/gs/math/floor.gs.test.ts +146 -0
- package/gs/math/floor.gs.ts +88 -0
- package/gs/math/fma.gs.test.ts +83 -0
- package/gs/math/fma.gs.ts +7 -0
- package/gs/math/frexp.gs.test.ts +146 -0
- package/gs/math/frexp.gs.ts +37 -0
- package/gs/math/gamma.gs.test.ts +66 -0
- package/gs/math/gamma.gs.ts +158 -0
- package/gs/math/hypot.gs.test.ts +73 -0
- package/gs/math/hypot.gs.ts +23 -0
- package/gs/math/index.ts +44 -0
- package/gs/math/j0.gs.test.ts +74 -0
- package/gs/math/j0.gs.ts +257 -0
- package/gs/math/j1.gs.test.ts +81 -0
- package/gs/math/j1.gs.ts +231 -0
- package/gs/math/jn.gs.test.ts +133 -0
- package/gs/math/jn.gs.ts +447 -0
- package/gs/math/ldexp.gs.test.ts +128 -0
- package/gs/math/ldexp.gs.ts +28 -0
- package/gs/math/lgamma.gs.test.ts +102 -0
- package/gs/math/lgamma.gs.ts +251 -0
- package/gs/math/log.gs.test.ts +40 -0
- package/gs/math/log.gs.ts +21 -0
- package/gs/math/log10.gs.test.ts +80 -0
- package/gs/math/log10.gs.ts +25 -0
- package/gs/math/log1p.gs.test.ts +55 -0
- package/gs/math/log1p.gs.ts +24 -0
- package/gs/math/logb.gs.test.ts +87 -0
- package/gs/math/logb.gs.ts +54 -0
- package/gs/math/mod.gs.test.ts +64 -0
- package/gs/math/mod.gs.ts +36 -0
- package/gs/math/modf.gs.test.ts +80 -0
- package/gs/math/modf.gs.ts +32 -0
- package/gs/math/nextafter.gs.test.ts +107 -0
- package/gs/math/nextafter.gs.ts +71 -0
- package/gs/math/pow.gs.test.ts +103 -0
- package/gs/math/pow.gs.ts +55 -0
- package/gs/math/pow10.gs.test.ts +58 -0
- package/gs/math/pow10.gs.ts +19 -0
- package/gs/math/remainder.gs.test.ts +70 -0
- package/gs/math/remainder.gs.ts +33 -0
- package/gs/math/signbit.gs.test.ts +33 -0
- package/gs/math/signbit.gs.ts +8 -0
- package/gs/math/sin.gs.test.ts +83 -0
- package/gs/math/sin.gs.ts +38 -0
- package/gs/math/sincos.gs.test.ts +91 -0
- package/gs/math/sincos.gs.ts +15 -0
- package/gs/math/sinh.gs.test.ts +66 -0
- package/gs/math/sinh.gs.ts +34 -0
- package/gs/math/sqrt.gs.test.ts +49 -0
- package/gs/math/sqrt.gs.ts +20 -0
- package/gs/math/tan.gs.test.ts +50 -0
- package/gs/math/tan.gs.ts +23 -0
- package/gs/math/tanh.gs.test.ts +52 -0
- package/gs/math/tanh.gs.ts +23 -0
- package/gs/math/trig_reduce.gs.ts +66 -0
- package/gs/math/unsafe.gs.ts +52 -0
- package/gs/slices/slices.ts +9 -0
- package/gs/strconv/atob.gs.ts +45 -0
- package/gs/strconv/atof.gs.ts +60 -0
- package/gs/strconv/atoi.gs.ts +243 -0
- package/gs/strconv/doc.gs.ts +2 -0
- package/gs/strconv/ftoa.gs.ts +66 -0
- package/gs/strconv/index.ts +6 -0
- package/gs/strconv/itoa.gs.ts +41 -0
- package/gs/strconv/quote.gs.ts +245 -0
- package/gs/strings/index.ts +4 -0
- package/gs/strings/replace.ts +9 -237
- package/gs/strings/search.ts +0 -28
- package/package.json +1 -1
- package/gs/stringslite/godoc.txt +0 -17
- package/gs/stringslite/index.ts +0 -1
- package/gs/stringslite/strings.ts +0 -82
package/compiler/stmt-assign.go
CHANGED
|
@@ -222,10 +222,25 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
// For simple cases without selector expressions, use array destructuring
|
|
225
|
+
// Add semicolon before destructuring assignment to prevent TypeScript
|
|
226
|
+
// from interpreting it as array access on the previous line
|
|
227
|
+
if tok != token.DEFINE {
|
|
228
|
+
c.tsw.WriteLiterally(";")
|
|
229
|
+
}
|
|
225
230
|
c.tsw.WriteLiterally("[")
|
|
226
231
|
|
|
232
|
+
// Find the last non-blank identifier to avoid trailing commas
|
|
233
|
+
lastNonBlankIndex := -1
|
|
234
|
+
for i := len(lhs) - 1; i >= 0; i-- {
|
|
235
|
+
if ident, ok := lhs[i].(*ast.Ident); !ok || ident.Name != "_" {
|
|
236
|
+
lastNonBlankIndex = i
|
|
237
|
+
break
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
227
241
|
for i, lhsExpr := range lhs {
|
|
228
|
-
|
|
242
|
+
// Write comma before non-first elements
|
|
243
|
+
if i > 0 {
|
|
229
244
|
c.tsw.WriteLiterally(", ")
|
|
230
245
|
}
|
|
231
246
|
|
|
@@ -234,6 +249,7 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
234
249
|
if ident.Name != "_" {
|
|
235
250
|
c.WriteIdent(ident, false)
|
|
236
251
|
}
|
|
252
|
+
// For blank identifiers, we write nothing (empty slot)
|
|
237
253
|
} else if selectorExpr, ok := lhsExpr.(*ast.SelectorExpr); ok {
|
|
238
254
|
// Handle selector expressions (e.g., a.b) by using WriteValueExpr
|
|
239
255
|
if err := c.WriteValueExpr(selectorExpr); err != nil {
|
|
@@ -263,6 +279,11 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
263
279
|
// Should not happen for valid Go code in this context, but handle defensively
|
|
264
280
|
return errors.Errorf("unhandled LHS expression in destructuring: %T", lhsExpr)
|
|
265
281
|
}
|
|
282
|
+
|
|
283
|
+
// Stop writing if we've reached the last non-blank element
|
|
284
|
+
if i == lastNonBlankIndex {
|
|
285
|
+
break
|
|
286
|
+
}
|
|
266
287
|
}
|
|
267
288
|
c.tsw.WriteLiterally("] = ")
|
|
268
289
|
|
|
@@ -276,122 +297,106 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
276
297
|
}
|
|
277
298
|
|
|
278
299
|
// writeMapLookupWithExists handles the map comma-ok idiom: value, exists := myMap[key]
|
|
279
|
-
//
|
|
300
|
+
// Uses array destructuring with the tuple-returning $.mapGet function
|
|
280
301
|
writeMapLookupWithExists := func(lhs []ast.Expr, indexExpr *ast.IndexExpr, tok token.Token) error {
|
|
281
302
|
// First check that we have exactly two LHS expressions (value and exists)
|
|
282
303
|
if len(lhs) != 2 {
|
|
283
304
|
return fmt.Errorf("map comma-ok idiom requires exactly 2 variables on LHS, got %d", len(lhs))
|
|
284
305
|
}
|
|
285
306
|
|
|
286
|
-
// Check for blank identifiers
|
|
307
|
+
// Check for blank identifiers
|
|
287
308
|
valueIsBlank := false
|
|
288
309
|
existsIsBlank := false
|
|
289
|
-
var valueName string
|
|
290
|
-
var existsName string
|
|
291
310
|
|
|
292
|
-
if valIdent, ok := lhs[0].(*ast.Ident); ok {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
} else {
|
|
299
|
-
return fmt.Errorf("unhandled LHS expression type for value in map comma-ok: %T", lhs[0])
|
|
311
|
+
if valIdent, ok := lhs[0].(*ast.Ident); ok && valIdent.Name == "_" {
|
|
312
|
+
valueIsBlank = true
|
|
313
|
+
}
|
|
314
|
+
if existsIdent, ok := lhs[1].(*ast.Ident); ok && existsIdent.Name == "_" {
|
|
315
|
+
existsIsBlank = true
|
|
300
316
|
}
|
|
301
317
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
} else {
|
|
306
|
-
existsName = existsIdent.Name
|
|
307
|
-
}
|
|
318
|
+
// Use array destructuring with mapGet tuple return
|
|
319
|
+
if tok == token.DEFINE {
|
|
320
|
+
c.tsw.WriteLiterally("let ")
|
|
308
321
|
} else {
|
|
309
|
-
|
|
322
|
+
// Add semicolon before destructuring assignment to prevent TypeScript
|
|
323
|
+
// from interpreting it as array access on the previous line
|
|
324
|
+
c.tsw.WriteLiterally(";")
|
|
310
325
|
}
|
|
311
326
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
c.tsw.WriteLine("")
|
|
319
|
-
}
|
|
320
|
-
if !existsIsBlank {
|
|
321
|
-
c.tsw.WriteLiterally("let ")
|
|
322
|
-
c.tsw.WriteLiterally(existsName)
|
|
323
|
-
c.tsw.WriteLiterally(": boolean") // exists is always boolean
|
|
324
|
-
c.tsw.WriteLine("")
|
|
327
|
+
c.tsw.WriteLiterally("[")
|
|
328
|
+
|
|
329
|
+
// Write LHS variables, handling blanks
|
|
330
|
+
if !valueIsBlank {
|
|
331
|
+
if err := c.WriteValueExpr(lhs[0]); err != nil {
|
|
332
|
+
return err
|
|
325
333
|
}
|
|
326
334
|
}
|
|
335
|
+
// Note: for blank identifiers, we just omit the variable name entirely
|
|
336
|
+
|
|
337
|
+
c.tsw.WriteLiterally(", ")
|
|
327
338
|
|
|
328
|
-
// Assign 'exists'
|
|
329
339
|
if !existsIsBlank {
|
|
330
|
-
c.
|
|
331
|
-
c.tsw.WriteLiterally(" = ")
|
|
332
|
-
c.tsw.WriteLiterally("$.mapHas(")
|
|
333
|
-
if err := c.WriteValueExpr(indexExpr.X); err != nil { // Map
|
|
340
|
+
if err := c.WriteValueExpr(lhs[1]); err != nil {
|
|
334
341
|
return err
|
|
335
342
|
}
|
|
336
|
-
c.tsw.WriteLiterally(", ")
|
|
337
|
-
if err := c.WriteValueExpr(indexExpr.Index); err != nil { // Key
|
|
338
|
-
return err
|
|
339
|
-
}
|
|
340
|
-
c.tsw.WriteLiterally(")")
|
|
341
|
-
c.tsw.WriteLine("")
|
|
342
343
|
}
|
|
344
|
+
// Note: for blank identifiers, we just omit the variable name entirely
|
|
343
345
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
346
|
+
c.tsw.WriteLiterally("] = $.mapGet(")
|
|
347
|
+
|
|
348
|
+
// Write map expression
|
|
349
|
+
if err := c.WriteValueExpr(indexExpr.X); err != nil {
|
|
350
|
+
return err
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
c.tsw.WriteLiterally(", ")
|
|
354
|
+
|
|
355
|
+
// Write key expression
|
|
356
|
+
if err := c.WriteValueExpr(indexExpr.Index); err != nil {
|
|
357
|
+
return err
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
c.tsw.WriteLiterally(", ")
|
|
361
|
+
|
|
362
|
+
// Write the zero value for the map's value type
|
|
363
|
+
if tv, ok := c.pkg.TypesInfo.Types[indexExpr.X]; ok {
|
|
364
|
+
if mapType, isMap := tv.Type.Underlying().(*types.Map); isMap {
|
|
365
|
+
c.WriteZeroValueForType(mapType.Elem())
|
|
366
|
+
} else if typeParam, isTypeParam := tv.Type.(*types.TypeParam); isTypeParam {
|
|
367
|
+
// Handle type parameter constrained to be a map type
|
|
368
|
+
constraint := typeParam.Constraint()
|
|
369
|
+
if constraint != nil {
|
|
370
|
+
underlying := constraint.Underlying()
|
|
371
|
+
if iface, isInterface := underlying.(*types.Interface); isInterface {
|
|
372
|
+
if hasMapConstraint(iface) {
|
|
373
|
+
// Get the value type from the constraint
|
|
374
|
+
mapValueType := getMapValueTypeFromConstraint(iface)
|
|
375
|
+
if mapValueType != nil {
|
|
376
|
+
c.WriteZeroValueForType(mapValueType)
|
|
377
|
+
} else {
|
|
378
|
+
c.tsw.WriteLiterally("null")
|
|
379
|
+
}
|
|
380
|
+
} else {
|
|
381
|
+
c.tsw.WriteLiterally("null")
|
|
382
|
+
}
|
|
383
|
+
} else {
|
|
384
|
+
c.tsw.WriteLiterally("null")
|
|
385
|
+
}
|
|
361
386
|
} else {
|
|
362
|
-
// Fallback zero value if type info is missing or not a map
|
|
363
387
|
c.tsw.WriteLiterally("null")
|
|
364
388
|
}
|
|
365
389
|
} else {
|
|
390
|
+
// Fallback zero value if type info is missing or not a map
|
|
366
391
|
c.tsw.WriteLiterally("null")
|
|
367
392
|
}
|
|
368
|
-
|
|
369
|
-
c.tsw.
|
|
370
|
-
} else if existsIsBlank {
|
|
371
|
-
// If both are blank, still evaluate for side effects (though .has/.get are usually pure)
|
|
372
|
-
// We add a ; otherwise TypeScript thinks we are invoking a function.
|
|
373
|
-
c.tsw.WriteLiterally(";(") // Wrap in parens to make it an expression statement
|
|
374
|
-
c.tsw.WriteLiterally("$.mapHas(")
|
|
375
|
-
if err := c.WriteValueExpr(indexExpr.X); err != nil { // Map
|
|
376
|
-
return err
|
|
377
|
-
}
|
|
378
|
-
c.tsw.WriteLiterally(", ")
|
|
379
|
-
if err := c.WriteValueExpr(indexExpr.Index); err != nil { // Key
|
|
380
|
-
return err
|
|
381
|
-
}
|
|
382
|
-
c.tsw.WriteLiterally("), ") // Evaluate .has
|
|
383
|
-
c.tsw.WriteLiterally("$.mapGet(")
|
|
384
|
-
if err := c.WriteValueExpr(indexExpr.X); err != nil { // Map
|
|
385
|
-
return err
|
|
386
|
-
}
|
|
387
|
-
c.tsw.WriteLiterally(", ")
|
|
388
|
-
if err := c.WriteValueExpr(indexExpr.Index); err != nil { // Key
|
|
389
|
-
return err
|
|
390
|
-
}
|
|
391
|
-
c.tsw.WriteLiterally(", null))") // Evaluate .get with null as default
|
|
392
|
-
c.tsw.WriteLine("")
|
|
393
|
+
} else {
|
|
394
|
+
c.tsw.WriteLiterally("null")
|
|
393
395
|
}
|
|
394
396
|
|
|
397
|
+
c.tsw.WriteLiterally(")")
|
|
398
|
+
c.tsw.WriteLine("")
|
|
399
|
+
|
|
395
400
|
return nil
|
|
396
401
|
}
|
|
397
402
|
|
|
@@ -417,6 +422,8 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
417
422
|
}
|
|
418
423
|
return nil
|
|
419
424
|
}
|
|
425
|
+
// Handle general function calls that return multiple values
|
|
426
|
+
return writeMultiVarAssignFromCall(exp.Lhs, callExpr, exp.Tok)
|
|
420
427
|
}
|
|
421
428
|
|
|
422
429
|
if typeAssertExpr, ok := rhsExpr.(*ast.TypeAssertExpr); ok {
|
|
@@ -428,10 +435,22 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
428
435
|
if c.pkg != nil && c.pkg.TypesInfo != nil {
|
|
429
436
|
tv, ok := c.pkg.TypesInfo.Types[indexExpr.X]
|
|
430
437
|
if ok {
|
|
431
|
-
// Check if it's a map type
|
|
438
|
+
// Check if it's a concrete map type
|
|
432
439
|
if _, isMap := tv.Type.Underlying().(*types.Map); isMap {
|
|
433
440
|
return writeMapLookupWithExists(exp.Lhs, indexExpr, exp.Tok)
|
|
434
441
|
}
|
|
442
|
+
// Check if it's a type parameter constrained to be a map type
|
|
443
|
+
if typeParam, isTypeParam := tv.Type.(*types.TypeParam); isTypeParam {
|
|
444
|
+
constraint := typeParam.Constraint()
|
|
445
|
+
if constraint != nil {
|
|
446
|
+
underlying := constraint.Underlying()
|
|
447
|
+
if iface, isInterface := underlying.(*types.Interface); isInterface {
|
|
448
|
+
if hasMapConstraint(iface) {
|
|
449
|
+
return writeMapLookupWithExists(exp.Lhs, indexExpr, exp.Tok)
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
435
454
|
}
|
|
436
455
|
}
|
|
437
456
|
}
|
|
@@ -441,8 +460,6 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
441
460
|
return c.writeChannelReceiveWithOk(exp.Lhs, unaryExpr, exp.Tok)
|
|
442
461
|
}
|
|
443
462
|
// If LHS count is not 2, fall through to error or other handling
|
|
444
|
-
} else if callExpr, ok := rhsExpr.(*ast.CallExpr); ok {
|
|
445
|
-
return writeMultiVarAssignFromCall(exp.Lhs, callExpr, exp.Tok)
|
|
446
463
|
}
|
|
447
464
|
// If none of the specific multi-assign patterns match, fall through to the error check below
|
|
448
465
|
}
|
|
@@ -463,7 +480,27 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
463
480
|
|
|
464
481
|
// Ensure LHS and RHS have the same length for valid Go code in these cases
|
|
465
482
|
if len(exp.Lhs) != len(exp.Rhs) {
|
|
466
|
-
|
|
483
|
+
// Special case: allow multiple LHS with single RHS if RHS can produce multiple values
|
|
484
|
+
// This handles cases like: x, y := getValue() where getValue() returns multiple values
|
|
485
|
+
// or other expressions that can produce multiple values
|
|
486
|
+
if len(exp.Rhs) == 1 {
|
|
487
|
+
// Allow single RHS expressions that can produce multiple values:
|
|
488
|
+
// - Function calls that return multiple values
|
|
489
|
+
// - Type assertions with comma-ok
|
|
490
|
+
// - Map lookups with comma-ok
|
|
491
|
+
// - Channel receives with comma-ok
|
|
492
|
+
// The Go type checker should have already verified this is valid
|
|
493
|
+
rhsExpr := exp.Rhs[0]
|
|
494
|
+
switch rhsExpr.(type) {
|
|
495
|
+
case *ast.CallExpr, *ast.TypeAssertExpr, *ast.IndexExpr, *ast.UnaryExpr:
|
|
496
|
+
// These expression types can potentially produce multiple values
|
|
497
|
+
// Let the general assignment logic handle them
|
|
498
|
+
default:
|
|
499
|
+
return fmt.Errorf("invalid assignment statement: LHS count (%d) != RHS count (%d)", len(exp.Lhs), len(exp.Rhs))
|
|
500
|
+
}
|
|
501
|
+
} else {
|
|
502
|
+
return fmt.Errorf("invalid assignment statement: LHS count (%d) != RHS count (%d)", len(exp.Lhs), len(exp.Rhs))
|
|
503
|
+
}
|
|
467
504
|
}
|
|
468
505
|
|
|
469
506
|
// Handle multi-variable assignment (e.g., swaps) using writeAssignmentCore
|
package/compiler/stmt-for.go
CHANGED
|
@@ -4,6 +4,7 @@ import (
|
|
|
4
4
|
"fmt"
|
|
5
5
|
"go/ast"
|
|
6
6
|
"go/token"
|
|
7
|
+
"go/types"
|
|
7
8
|
|
|
8
9
|
"github.com/pkg/errors"
|
|
9
10
|
)
|
|
@@ -64,7 +65,25 @@ func (c *GoToTSCompiler) WriteStmtForInit(stmt ast.Stmt) error {
|
|
|
64
65
|
case *ast.AssignStmt:
|
|
65
66
|
// Handle assignment in init (e.g., i := 0 or i = 0)
|
|
66
67
|
// For TypeScript for-loop init, we need to handle multi-variable declarations differently
|
|
67
|
-
if s.Tok == token.DEFINE && len(s.Lhs) > 1 && len(s.Rhs)
|
|
68
|
+
if s.Tok == token.DEFINE && len(s.Lhs) > 1 && len(s.Rhs) == 1 {
|
|
69
|
+
// Handle the case where we have multiple LHS variables but only one RHS expression
|
|
70
|
+
// Use array destructuring for all cases including map comma-ok idiom
|
|
71
|
+
rhsExpr := s.Rhs[0]
|
|
72
|
+
c.tsw.WriteLiterally("let [")
|
|
73
|
+
for i, lhs := range s.Lhs {
|
|
74
|
+
if i > 0 {
|
|
75
|
+
c.tsw.WriteLiterally(", ")
|
|
76
|
+
}
|
|
77
|
+
if err := c.WriteValueExpr(lhs); err != nil {
|
|
78
|
+
return err
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
c.tsw.WriteLiterally("] = ")
|
|
82
|
+
if err := c.writeDestructuringValue(rhsExpr); err != nil {
|
|
83
|
+
return err
|
|
84
|
+
}
|
|
85
|
+
return nil
|
|
86
|
+
} else if s.Tok == token.DEFINE && len(s.Lhs) > 1 && len(s.Rhs) > 0 {
|
|
68
87
|
// For loop initialization with multiple variables (e.g., let i = 0, j = 10)
|
|
69
88
|
c.tsw.WriteLiterally("let ")
|
|
70
89
|
|
|
@@ -121,6 +140,64 @@ func (c *GoToTSCompiler) WriteStmtForInit(stmt ast.Stmt) error {
|
|
|
121
140
|
}
|
|
122
141
|
}
|
|
123
142
|
|
|
143
|
+
// writeDestructuringValue writes a value expression in a destructuring context.
|
|
144
|
+
// For map index expressions, it generates the full tuple without [0] indexing.
|
|
145
|
+
func (c *GoToTSCompiler) writeDestructuringValue(expr ast.Expr) error {
|
|
146
|
+
// Check if this is a map index expression that should return a tuple
|
|
147
|
+
if indexExpr, ok := expr.(*ast.IndexExpr); ok {
|
|
148
|
+
if tv, ok := c.pkg.TypesInfo.Types[indexExpr.X]; ok {
|
|
149
|
+
underlyingType := tv.Type.Underlying()
|
|
150
|
+
// Check if it's a map type
|
|
151
|
+
if mapType, isMap := underlyingType.(*types.Map); isMap {
|
|
152
|
+
c.tsw.WriteLiterally("$.mapGet(")
|
|
153
|
+
if err := c.WriteValueExpr(indexExpr.X); err != nil {
|
|
154
|
+
return err
|
|
155
|
+
}
|
|
156
|
+
c.tsw.WriteLiterally(", ")
|
|
157
|
+
if err := c.WriteValueExpr(indexExpr.Index); err != nil {
|
|
158
|
+
return err
|
|
159
|
+
}
|
|
160
|
+
c.tsw.WriteLiterally(", ")
|
|
161
|
+
// Write the zero value as the default value for mapGet
|
|
162
|
+
c.WriteZeroValueForType(mapType.Elem())
|
|
163
|
+
c.tsw.WriteLiterally(")") // Don't add [0] for destructuring
|
|
164
|
+
return nil
|
|
165
|
+
}
|
|
166
|
+
// Check if it's a type parameter constrained to be a map type
|
|
167
|
+
if typeParam, isTypeParam := tv.Type.(*types.TypeParam); isTypeParam {
|
|
168
|
+
constraint := typeParam.Constraint()
|
|
169
|
+
if constraint != nil {
|
|
170
|
+
underlying := constraint.Underlying()
|
|
171
|
+
if iface, isInterface := underlying.(*types.Interface); isInterface {
|
|
172
|
+
if hasMapConstraint(iface) {
|
|
173
|
+
c.tsw.WriteLiterally("$.mapGet(")
|
|
174
|
+
if err := c.WriteValueExpr(indexExpr.X); err != nil {
|
|
175
|
+
return err
|
|
176
|
+
}
|
|
177
|
+
c.tsw.WriteLiterally(", ")
|
|
178
|
+
if err := c.WriteValueExpr(indexExpr.Index); err != nil {
|
|
179
|
+
return err
|
|
180
|
+
}
|
|
181
|
+
c.tsw.WriteLiterally(", ")
|
|
182
|
+
// Generate the zero value as the default value for mapGet
|
|
183
|
+
mapValueType := getMapValueTypeFromConstraint(iface)
|
|
184
|
+
if mapValueType != nil {
|
|
185
|
+
c.WriteZeroValueForType(mapValueType)
|
|
186
|
+
} else {
|
|
187
|
+
c.tsw.WriteLiterally("null")
|
|
188
|
+
}
|
|
189
|
+
c.tsw.WriteLiterally(")") // Don't add [0] for destructuring
|
|
190
|
+
return nil
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// For non-map expressions, use the regular WriteValueExpr
|
|
198
|
+
return c.WriteValueExpr(expr)
|
|
199
|
+
}
|
|
200
|
+
|
|
124
201
|
// WriteStmtForPost translates the post-iteration part of a Go `for` loop header
|
|
125
202
|
// (e.g., `i++` or `i, j = i+1, j-1` in `for ...; i++`) into its TypeScript
|
|
126
203
|
// equivalent.
|