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-range.go
CHANGED
|
@@ -46,503 +46,375 @@ func (c *GoToTSCompiler) WriteStmtRange(exp *ast.RangeStmt) error {
|
|
|
46
46
|
iterType := c.pkg.TypesInfo.TypeOf(exp.X)
|
|
47
47
|
underlying := iterType.Underlying()
|
|
48
48
|
|
|
49
|
-
// Handle map types
|
|
50
|
-
if
|
|
51
|
-
|
|
52
|
-
c.tsw.WriteLiterally("for (const [k, v] of ")
|
|
53
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
54
|
-
return fmt.Errorf("failed to write range loop map expression: %w", err)
|
|
55
|
-
}
|
|
56
|
-
c.tsw.WriteLiterally(".entries()) {")
|
|
57
|
-
c.tsw.Indent(1)
|
|
58
|
-
c.tsw.WriteLine("")
|
|
59
|
-
// If a key variable is provided and is not blank, declare it as a constant
|
|
60
|
-
if exp.Key != nil {
|
|
61
|
-
if ident, ok := exp.Key.(*ast.Ident); ok && ident.Name != "_" {
|
|
62
|
-
c.tsw.WriteLiterally("const ")
|
|
63
|
-
c.WriteIdent(ident, false)
|
|
64
|
-
c.tsw.WriteLiterally(" = k")
|
|
65
|
-
c.tsw.WriteLine("")
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
// If a value variable is provided and is not blank, use the value from entries()
|
|
69
|
-
if exp.Value != nil {
|
|
70
|
-
if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
|
|
71
|
-
c.tsw.WriteLiterally("const ")
|
|
72
|
-
c.WriteIdent(ident, false)
|
|
73
|
-
c.tsw.WriteLiterally(" = v")
|
|
74
|
-
c.tsw.WriteLine("")
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
// Write the loop body
|
|
78
|
-
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
79
|
-
return fmt.Errorf("failed to write range loop map body: %w", err)
|
|
80
|
-
}
|
|
81
|
-
c.tsw.Indent(-1)
|
|
82
|
-
c.tsw.WriteLine("}")
|
|
83
|
-
return nil
|
|
49
|
+
// Handle map types (both concrete maps and type parameters constrained to maps)
|
|
50
|
+
if c.isMapType(iterType, underlying) {
|
|
51
|
+
return c.writeMapRange(exp)
|
|
84
52
|
}
|
|
85
53
|
|
|
86
54
|
// Handle basic types (string, integer)
|
|
87
55
|
if basic, ok := underlying.(*types.Basic); ok {
|
|
88
56
|
if basic.Info()&types.IsString != 0 {
|
|
89
|
-
|
|
90
|
-
c.tsw.WriteLine("{")
|
|
91
|
-
c.tsw.Indent(1)
|
|
92
|
-
|
|
93
|
-
// Convert the string to runes using $.stringToRunes
|
|
94
|
-
c.tsw.WriteLiterally("const _runes = $.stringToRunes(")
|
|
95
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
96
|
-
return fmt.Errorf("failed to write range loop string conversion expression: %w", err)
|
|
97
|
-
}
|
|
98
|
-
c.tsw.WriteLiterally(")")
|
|
99
|
-
c.tsw.WriteLine("")
|
|
100
|
-
|
|
101
|
-
// Determine the index variable name for the generated loop
|
|
102
|
-
indexVarName := "i" // Default name
|
|
103
|
-
if exp.Key != nil {
|
|
104
|
-
if keyIdent, ok := exp.Key.(*ast.Ident); ok && keyIdent.Name != "_" {
|
|
105
|
-
indexVarName = keyIdent.Name
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
c.tsw.WriteLiterallyf("for (let %s = 0; %s < _runes.length; %s++) {", indexVarName, indexVarName, indexVarName)
|
|
109
|
-
c.tsw.Indent(1)
|
|
110
|
-
c.tsw.WriteLine("")
|
|
111
|
-
// Declare value if provided and not blank
|
|
112
|
-
if exp.Value != nil {
|
|
113
|
-
if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
|
|
114
|
-
c.tsw.WriteLiterally("const ")
|
|
115
|
-
c.WriteIdent(ident, false)
|
|
116
|
-
c.tsw.WriteLiterally(" = _runes[i]") // TODO: should be indexVarName?
|
|
117
|
-
c.tsw.WriteLine("")
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
121
|
-
return fmt.Errorf("failed to write range loop string body: %w", err)
|
|
122
|
-
}
|
|
123
|
-
c.tsw.Indent(-1)
|
|
124
|
-
c.tsw.WriteLine("}")
|
|
125
|
-
|
|
126
|
-
// outer }
|
|
127
|
-
c.tsw.Indent(-1)
|
|
128
|
-
c.tsw.WriteLine("}")
|
|
129
|
-
return nil
|
|
57
|
+
return c.writeStringRange(exp)
|
|
130
58
|
} else if basic.Info()&types.IsInteger != 0 {
|
|
131
|
-
|
|
132
|
-
if exp.Value != nil {
|
|
133
|
-
return errors.Errorf("ranging over an integer supports key variable only (not value variable): %v", exp)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Handle ranging over an integer (Go 1.22+)
|
|
137
|
-
// Determine the index variable name for the generated loop
|
|
138
|
-
indexVarName := "_i" // Default name
|
|
139
|
-
if exp.Key != nil {
|
|
140
|
-
if keyIdent, ok := exp.Key.(*ast.Ident); ok && keyIdent.Name != "_" {
|
|
141
|
-
indexVarName = keyIdent.Name
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
c.tsw.WriteLiterallyf("for (let %s = 0; %s < ", indexVarName, indexVarName)
|
|
146
|
-
if err := c.WriteValueExpr(exp.X); err != nil { // This is N
|
|
147
|
-
return fmt.Errorf("failed to write range loop integer expression: %w", err)
|
|
148
|
-
}
|
|
149
|
-
c.tsw.WriteLiterallyf("; %s++) {", indexVarName)
|
|
150
|
-
|
|
151
|
-
// write body
|
|
152
|
-
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
153
|
-
return fmt.Errorf("failed to write range loop integer body: %w", err)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
c.tsw.Indent(-1)
|
|
157
|
-
c.tsw.WriteLine("}")
|
|
158
|
-
return nil
|
|
59
|
+
return c.writeIntegerRange(exp)
|
|
159
60
|
}
|
|
160
61
|
}
|
|
161
62
|
|
|
162
63
|
// Handle array and slice types
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if isArray || isSlice {
|
|
166
|
-
// Determine the index variable name for the generated loop
|
|
167
|
-
indexVarName := "_i" // Default name
|
|
168
|
-
if exp.Key != nil {
|
|
169
|
-
if keyIdent, ok := exp.Key.(*ast.Ident); ok && keyIdent.Name != "_" {
|
|
170
|
-
indexVarName = keyIdent.Name
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
// If both key and value are provided, use an index loop and assign both
|
|
174
|
-
if exp.Key != nil && exp.Value != nil {
|
|
175
|
-
c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
|
|
176
|
-
if err := c.WriteValueExpr(exp.X); err != nil { // Write the expression for the iterable
|
|
177
|
-
return fmt.Errorf("failed to write range loop array/slice expression (key and value): %w", err)
|
|
178
|
-
}
|
|
179
|
-
c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
|
|
180
|
-
c.tsw.Indent(1)
|
|
181
|
-
c.tsw.WriteLine("")
|
|
182
|
-
// Declare value if not blank
|
|
183
|
-
if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
|
|
184
|
-
c.tsw.WriteLiterally("const ")
|
|
185
|
-
c.WriteIdent(ident, false)
|
|
186
|
-
c.tsw.WriteLiterally(" = ")
|
|
187
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
188
|
-
return fmt.Errorf("failed to write range loop array/slice value expression: %w", err)
|
|
189
|
-
}
|
|
190
|
-
c.tsw.WriteLiterallyf("![%s]", indexVarName) // Use indexVarName with not-null assert
|
|
191
|
-
c.tsw.WriteLine("")
|
|
192
|
-
}
|
|
193
|
-
if err := c.WriteStmt(exp.Body); err != nil {
|
|
194
|
-
return fmt.Errorf("failed to write range loop array/slice body (key and value): %w", err)
|
|
195
|
-
}
|
|
196
|
-
c.tsw.Indent(-1)
|
|
197
|
-
c.tsw.WriteLine("}")
|
|
198
|
-
return nil
|
|
199
|
-
} else if exp.Key != nil && exp.Value == nil { // Only key provided
|
|
200
|
-
c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
|
|
201
|
-
// Write the expression for the iterable
|
|
202
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
203
|
-
return fmt.Errorf("failed to write expression for the iterable: %w", err)
|
|
204
|
-
}
|
|
205
|
-
c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
|
|
206
|
-
c.tsw.Indent(1)
|
|
207
|
-
c.tsw.WriteLine("")
|
|
208
|
-
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
209
|
-
return fmt.Errorf("failed to write range loop array/slice body (only key): %w", err)
|
|
210
|
-
}
|
|
211
|
-
c.tsw.Indent(-1)
|
|
212
|
-
c.tsw.WriteLine("}")
|
|
213
|
-
return nil
|
|
214
|
-
} else if exp.Key == nil && exp.Value != nil { // Only value provided
|
|
215
|
-
// I think this is impossible. See for_range_value_only test.
|
|
216
|
-
return errors.Errorf("unexpected value without key in for range expression: %v", exp)
|
|
217
|
-
} else {
|
|
218
|
-
// Fallback: simple index loop without declaring range variables, use _i
|
|
219
|
-
indexVarName := "_i"
|
|
220
|
-
c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
|
|
221
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
222
|
-
return fmt.Errorf("failed to write range loop array/slice length expression (fallback): %w", err)
|
|
223
|
-
}
|
|
224
|
-
c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
|
|
225
|
-
c.tsw.Indent(1)
|
|
226
|
-
c.tsw.WriteLine("")
|
|
227
|
-
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
228
|
-
return fmt.Errorf("failed to write range loop array/slice body (fallback): %w", err)
|
|
229
|
-
}
|
|
230
|
-
c.tsw.Indent(-1)
|
|
231
|
-
c.tsw.WriteLine("}")
|
|
232
|
-
return nil
|
|
233
|
-
}
|
|
64
|
+
if c.isArrayOrSlice(underlying) {
|
|
65
|
+
return c.writeArraySliceRange(exp, false)
|
|
234
66
|
}
|
|
235
67
|
|
|
236
68
|
// Handle pointer to array/slice types
|
|
237
69
|
if ptrType, ok := underlying.(*types.Pointer); ok {
|
|
238
70
|
elem := ptrType.Elem().Underlying()
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
if isArray || isSlice {
|
|
242
|
-
// For pointer to array/slice, we need to dereference the pointer
|
|
243
|
-
// Check if the pointer variable itself is varrefed
|
|
244
|
-
|
|
245
|
-
// Determine the index variable name for the generated loop
|
|
246
|
-
indexVarName := "_i" // Default name
|
|
247
|
-
if exp.Key != nil {
|
|
248
|
-
if keyIdent, ok := exp.Key.(*ast.Ident); ok && keyIdent.Name != "_" {
|
|
249
|
-
indexVarName = keyIdent.Name
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
// If both key and value are provided, use an index loop and assign both
|
|
253
|
-
if exp.Key != nil && exp.Value != nil {
|
|
254
|
-
c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
|
|
255
|
-
|
|
256
|
-
// Write the pointer expression - use WriteIdent to avoid automatic .value access
|
|
257
|
-
// since we'll add !.value for pointer dereference
|
|
258
|
-
if ident, ok := exp.X.(*ast.Ident); ok {
|
|
259
|
-
c.WriteIdent(ident, false) // Don't add .value here
|
|
260
|
-
} else {
|
|
261
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
262
|
-
return fmt.Errorf("failed to write range loop pointer array/slice expression (key and value): %w", err)
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
// Add dereference for the pointer: since we're ranging over a pointer to array/slice,
|
|
266
|
-
// we need to dereference to get to the array/slice
|
|
267
|
-
c.tsw.WriteLiterally("!.value")
|
|
268
|
-
c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
|
|
269
|
-
c.tsw.Indent(1)
|
|
270
|
-
c.tsw.WriteLine("")
|
|
271
|
-
// Declare value if not blank
|
|
272
|
-
if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
|
|
273
|
-
c.tsw.WriteLiterally("const ")
|
|
274
|
-
c.WriteIdent(ident, false)
|
|
275
|
-
c.tsw.WriteLiterally(" = ")
|
|
276
|
-
// Write the pointer expression again for value access
|
|
277
|
-
if identX, ok := exp.X.(*ast.Ident); ok {
|
|
278
|
-
c.WriteIdent(identX, false) // Don't add .value here
|
|
279
|
-
} else {
|
|
280
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
281
|
-
return fmt.Errorf("failed to write range loop pointer array/slice value expression: %w", err)
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
c.tsw.WriteLiterally("!.value![")
|
|
285
|
-
c.tsw.WriteLiterally(indexVarName)
|
|
286
|
-
c.tsw.WriteLiterally("]")
|
|
287
|
-
c.tsw.WriteLine("")
|
|
288
|
-
}
|
|
289
|
-
if err := c.WriteStmt(exp.Body); err != nil {
|
|
290
|
-
return fmt.Errorf("failed to write range loop pointer array/slice body (key and value): %w", err)
|
|
291
|
-
}
|
|
292
|
-
c.tsw.Indent(-1)
|
|
293
|
-
c.tsw.WriteLine("}")
|
|
294
|
-
return nil
|
|
295
|
-
} else if exp.Key != nil && exp.Value == nil { // Only key provided
|
|
296
|
-
c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
|
|
297
|
-
// Write the pointer expression - use WriteIdent to avoid automatic .value access
|
|
298
|
-
// since we'll add !.value for pointer dereference
|
|
299
|
-
if ident, ok := exp.X.(*ast.Ident); ok {
|
|
300
|
-
c.WriteIdent(ident, false) // Don't add .value here
|
|
301
|
-
} else {
|
|
302
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
303
|
-
return fmt.Errorf("failed to write expression for the pointer iterable: %w", err)
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
c.tsw.WriteLiterally("!.value")
|
|
307
|
-
c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
|
|
308
|
-
c.tsw.Indent(1)
|
|
309
|
-
c.tsw.WriteLine("")
|
|
310
|
-
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
311
|
-
return fmt.Errorf("failed to write range loop pointer array/slice body (only key): %w", err)
|
|
312
|
-
}
|
|
313
|
-
c.tsw.Indent(-1)
|
|
314
|
-
c.tsw.WriteLine("}")
|
|
315
|
-
return nil
|
|
316
|
-
} else if exp.Key == nil && exp.Value != nil { // Only value provided
|
|
317
|
-
// I think this is impossible. See for_range_value_only test.
|
|
318
|
-
return errors.Errorf("unexpected value without key in for range expression: %v", exp)
|
|
319
|
-
} else {
|
|
320
|
-
// Fallback: simple index loop without declaring range variables, use _i
|
|
321
|
-
indexVarName := "_i"
|
|
322
|
-
c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
|
|
323
|
-
// Write the pointer expression - use WriteIdent to avoid automatic .value access
|
|
324
|
-
// since we'll add !.value for pointer dereference
|
|
325
|
-
if ident, ok := exp.X.(*ast.Ident); ok {
|
|
326
|
-
c.WriteIdent(ident, false) // Don't add .value here
|
|
327
|
-
} else {
|
|
328
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
329
|
-
return fmt.Errorf("failed to write range loop pointer array/slice length expression (fallback): %w", err)
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
c.tsw.WriteLiterally("!.value")
|
|
333
|
-
c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
|
|
334
|
-
c.tsw.Indent(1)
|
|
335
|
-
c.tsw.WriteLine("")
|
|
336
|
-
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
337
|
-
return fmt.Errorf("failed to write range loop pointer array/slice body (fallback): %w", err)
|
|
338
|
-
}
|
|
339
|
-
c.tsw.Indent(-1)
|
|
340
|
-
c.tsw.WriteLine("}")
|
|
341
|
-
return nil
|
|
342
|
-
}
|
|
71
|
+
if c.isArrayOrSlice(elem) {
|
|
72
|
+
return c.writeArraySliceRange(exp, true)
|
|
343
73
|
}
|
|
344
74
|
}
|
|
345
75
|
|
|
346
76
|
// Handle iterator function signatures
|
|
347
77
|
if sig, ok := underlying.(*types.Signature); ok {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
params := sig.Params()
|
|
351
|
-
if params.Len() == 1 {
|
|
352
|
-
yieldParam := params.At(0).Type()
|
|
353
|
-
if yieldSig, ok := yieldParam.Underlying().(*types.Signature); ok {
|
|
354
|
-
yieldParams := yieldSig.Params()
|
|
355
|
-
yieldResults := yieldSig.Results()
|
|
356
|
-
|
|
357
|
-
// Verify the yield function returns bool
|
|
358
|
-
if yieldResults.Len() == 1 {
|
|
359
|
-
if basic, ok := yieldResults.At(0).Type().Underlying().(*types.Basic); ok && basic.Kind() == types.Bool {
|
|
360
|
-
// This is an iterator function
|
|
361
|
-
// Generate TypeScript code that calls the iterator with a yield function
|
|
362
|
-
|
|
363
|
-
if yieldParams.Len() == 0 {
|
|
364
|
-
// func(func() bool) - iterator with no values
|
|
365
|
-
c.tsw.WriteLiterally(";(() => {")
|
|
366
|
-
c.tsw.Indent(1)
|
|
367
|
-
c.tsw.WriteLine("")
|
|
368
|
-
c.tsw.WriteLiterally("let shouldContinue = true")
|
|
369
|
-
c.tsw.WriteLine("")
|
|
370
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
371
|
-
return fmt.Errorf("failed to write iterator expression: %w", err)
|
|
372
|
-
}
|
|
373
|
-
c.tsw.WriteLiterally("(() => {")
|
|
374
|
-
c.tsw.Indent(1)
|
|
375
|
-
c.tsw.WriteLine("")
|
|
376
|
-
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
377
|
-
return fmt.Errorf("failed to write iterator body: %w", err)
|
|
378
|
-
}
|
|
379
|
-
c.tsw.WriteLiterally("return shouldContinue")
|
|
380
|
-
c.tsw.WriteLine("")
|
|
381
|
-
c.tsw.Indent(-1)
|
|
382
|
-
c.tsw.WriteLiterally("})")
|
|
383
|
-
c.tsw.WriteLine("")
|
|
384
|
-
c.tsw.Indent(-1)
|
|
385
|
-
c.tsw.WriteLine("})()")
|
|
386
|
-
return nil
|
|
387
|
-
} else if yieldParams.Len() == 1 {
|
|
388
|
-
// func(func(V) bool) - iterator with one value
|
|
389
|
-
c.tsw.WriteLiterally(";(() => {")
|
|
390
|
-
c.tsw.Indent(1)
|
|
391
|
-
c.tsw.WriteLine("")
|
|
392
|
-
c.tsw.WriteLiterally("let shouldContinue = true")
|
|
393
|
-
c.tsw.WriteLine("")
|
|
394
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
395
|
-
return fmt.Errorf("failed to write iterator expression: %w", err)
|
|
396
|
-
}
|
|
397
|
-
c.tsw.WriteLiterally("((")
|
|
398
|
-
if exp.Value != nil {
|
|
399
|
-
if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
|
|
400
|
-
c.WriteIdent(ident, false)
|
|
401
|
-
} else {
|
|
402
|
-
c.tsw.WriteLiterally("v")
|
|
403
|
-
}
|
|
404
|
-
} else {
|
|
405
|
-
c.tsw.WriteLiterally("v")
|
|
406
|
-
}
|
|
407
|
-
c.tsw.WriteLiterally(") => {")
|
|
408
|
-
c.tsw.Indent(1)
|
|
409
|
-
c.tsw.WriteLine("")
|
|
410
|
-
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
411
|
-
return fmt.Errorf("failed to write iterator body: %w", err)
|
|
412
|
-
}
|
|
413
|
-
c.tsw.WriteLiterally("return shouldContinue")
|
|
414
|
-
c.tsw.WriteLine("")
|
|
415
|
-
c.tsw.Indent(-1)
|
|
416
|
-
c.tsw.WriteLiterally("})")
|
|
417
|
-
c.tsw.WriteLine("")
|
|
418
|
-
c.tsw.Indent(-1)
|
|
419
|
-
c.tsw.WriteLine("})()")
|
|
420
|
-
return nil
|
|
421
|
-
} else if yieldParams.Len() == 2 {
|
|
422
|
-
// func(func(K, V) bool) - iterator with key-value pairs
|
|
423
|
-
c.tsw.WriteLiterally(";(() => {")
|
|
424
|
-
c.tsw.Indent(1)
|
|
425
|
-
c.tsw.WriteLine("")
|
|
426
|
-
c.tsw.WriteLiterally("let shouldContinue = true")
|
|
427
|
-
c.tsw.WriteLine("")
|
|
428
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
429
|
-
return fmt.Errorf("failed to write iterator expression: %w", err)
|
|
430
|
-
}
|
|
431
|
-
c.tsw.WriteLiterally("((")
|
|
432
|
-
if exp.Key != nil {
|
|
433
|
-
if ident, ok := exp.Key.(*ast.Ident); ok && ident.Name != "_" {
|
|
434
|
-
c.WriteIdent(ident, false)
|
|
435
|
-
} else {
|
|
436
|
-
c.tsw.WriteLiterally("k")
|
|
437
|
-
}
|
|
438
|
-
} else {
|
|
439
|
-
c.tsw.WriteLiterally("k")
|
|
440
|
-
}
|
|
441
|
-
c.tsw.WriteLiterally(", ")
|
|
442
|
-
if exp.Value != nil {
|
|
443
|
-
if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
|
|
444
|
-
c.WriteIdent(ident, false)
|
|
445
|
-
} else {
|
|
446
|
-
c.tsw.WriteLiterally("v")
|
|
447
|
-
}
|
|
448
|
-
} else {
|
|
449
|
-
c.tsw.WriteLiterally("v")
|
|
450
|
-
}
|
|
451
|
-
c.tsw.WriteLiterally(") => {")
|
|
452
|
-
c.tsw.Indent(1)
|
|
453
|
-
c.tsw.WriteLine("")
|
|
454
|
-
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
455
|
-
return fmt.Errorf("failed to write iterator body: %w", err)
|
|
456
|
-
}
|
|
457
|
-
c.tsw.WriteLiterally("return shouldContinue")
|
|
458
|
-
c.tsw.WriteLine("")
|
|
459
|
-
c.tsw.Indent(-1)
|
|
460
|
-
c.tsw.WriteLiterally("})")
|
|
461
|
-
c.tsw.WriteLine("")
|
|
462
|
-
c.tsw.Indent(-1)
|
|
463
|
-
c.tsw.WriteLine("})()")
|
|
464
|
-
return nil
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
}
|
|
78
|
+
if c.isIteratorSignature(sig) {
|
|
79
|
+
return c.writeIteratorRange(exp, sig)
|
|
469
80
|
}
|
|
470
81
|
}
|
|
471
82
|
|
|
472
83
|
// Handle interface types that may represent iterators
|
|
473
84
|
if _, ok := underlying.(*types.Interface); ok {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
// We'll attempt to call them as iterator functions with a yield callback
|
|
85
|
+
return c.writeInterfaceIteratorRange(exp)
|
|
86
|
+
}
|
|
477
87
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
// we'll generate a generic iterator call pattern
|
|
88
|
+
return errors.Errorf("unsupported range loop type: %T for expression %v", underlying, exp)
|
|
89
|
+
}
|
|
481
90
|
|
|
482
|
-
|
|
483
|
-
c.tsw.Indent(1)
|
|
484
|
-
c.tsw.WriteLine("")
|
|
485
|
-
c.tsw.WriteLiterally("let shouldContinue = true")
|
|
486
|
-
c.tsw.WriteLine("")
|
|
91
|
+
// Helper functions
|
|
487
92
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
93
|
+
func (c *GoToTSCompiler) isMapType(iterType, underlying types.Type) bool {
|
|
94
|
+
if _, ok := underlying.(*types.Map); ok {
|
|
95
|
+
return true
|
|
96
|
+
}
|
|
97
|
+
if typeParam, isTypeParam := iterType.(*types.TypeParam); isTypeParam {
|
|
98
|
+
constraint := typeParam.Constraint()
|
|
99
|
+
if constraint != nil {
|
|
100
|
+
constraintUnderlying := constraint.Underlying()
|
|
101
|
+
if iface, isInterface := constraintUnderlying.(*types.Interface); isInterface {
|
|
102
|
+
return hasMapConstraint(iface)
|
|
103
|
+
}
|
|
491
104
|
}
|
|
105
|
+
}
|
|
106
|
+
return false
|
|
107
|
+
}
|
|
492
108
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
// Value-only iterator
|
|
511
|
-
c.tsw.WriteLiterally("((")
|
|
512
|
-
if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
|
|
513
|
-
c.WriteIdent(ident, false)
|
|
514
|
-
} else {
|
|
515
|
-
c.tsw.WriteLiterally("v")
|
|
516
|
-
}
|
|
517
|
-
c.tsw.WriteLiterally(") => {")
|
|
518
|
-
} else if exp.Key != nil {
|
|
519
|
-
// Key-only iterator (treating it as value for single-param iterator)
|
|
520
|
-
c.tsw.WriteLiterally("((")
|
|
521
|
-
if ident, ok := exp.Key.(*ast.Ident); ok && ident.Name != "_" {
|
|
522
|
-
c.WriteIdent(ident, false)
|
|
523
|
-
} else {
|
|
524
|
-
c.tsw.WriteLiterally("k")
|
|
109
|
+
func (c *GoToTSCompiler) isArrayOrSlice(underlying types.Type) bool {
|
|
110
|
+
_, isSlice := underlying.(*types.Slice)
|
|
111
|
+
_, isArray := underlying.(*types.Array)
|
|
112
|
+
return isArray || isSlice
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
func (c *GoToTSCompiler) isIteratorSignature(sig *types.Signature) bool {
|
|
116
|
+
params := sig.Params()
|
|
117
|
+
if params.Len() != 1 {
|
|
118
|
+
return false
|
|
119
|
+
}
|
|
120
|
+
yieldParam := params.At(0).Type()
|
|
121
|
+
if yieldSig, ok := yieldParam.Underlying().(*types.Signature); ok {
|
|
122
|
+
yieldResults := yieldSig.Results()
|
|
123
|
+
if yieldResults.Len() == 1 {
|
|
124
|
+
if basic, ok := yieldResults.At(0).Type().Underlying().(*types.Basic); ok && basic.Kind() == types.Bool {
|
|
125
|
+
return true
|
|
525
126
|
}
|
|
526
|
-
c.tsw.WriteLiterally(") => {")
|
|
527
|
-
} else {
|
|
528
|
-
// No variables iterator
|
|
529
|
-
c.tsw.WriteLiterally("(() => {")
|
|
530
127
|
}
|
|
128
|
+
}
|
|
129
|
+
return false
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
func (c *GoToTSCompiler) getIndexVarName(exp *ast.RangeStmt, defaultName string) string {
|
|
133
|
+
if exp.Key != nil {
|
|
134
|
+
if keyIdent, ok := exp.Key.(*ast.Ident); ok && keyIdent.Name != "_" {
|
|
135
|
+
return keyIdent.Name
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return defaultName
|
|
139
|
+
}
|
|
531
140
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
141
|
+
func (c *GoToTSCompiler) writeMapRange(exp *ast.RangeStmt) error {
|
|
142
|
+
keyVarName := "_k"
|
|
143
|
+
valueVarName := "_v"
|
|
144
|
+
|
|
145
|
+
if exp.Key != nil {
|
|
146
|
+
if ident, ok := exp.Key.(*ast.Ident); ok && ident.Name != "_" {
|
|
147
|
+
keyVarName = ident.Name
|
|
536
148
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
149
|
+
}
|
|
150
|
+
if exp.Value != nil {
|
|
151
|
+
if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
|
|
152
|
+
valueVarName = ident.Name
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
c.tsw.WriteLiterallyf("for (const [%s, %s] of ", keyVarName, valueVarName)
|
|
157
|
+
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
158
|
+
return fmt.Errorf("failed to write range loop map expression: %w", err)
|
|
159
|
+
}
|
|
160
|
+
c.tsw.WriteLiterally(".entries()) {")
|
|
161
|
+
c.tsw.Indent(1)
|
|
162
|
+
c.tsw.WriteLine("")
|
|
163
|
+
|
|
164
|
+
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
165
|
+
return fmt.Errorf("failed to write range loop map body: %w", err)
|
|
166
|
+
}
|
|
167
|
+
c.tsw.Indent(-1)
|
|
168
|
+
c.tsw.WriteLine("}")
|
|
169
|
+
return nil
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
func (c *GoToTSCompiler) writeStringRange(exp *ast.RangeStmt) error {
|
|
173
|
+
c.tsw.WriteLine("{")
|
|
174
|
+
c.tsw.Indent(1)
|
|
175
|
+
|
|
176
|
+
c.tsw.WriteLiterally("const _runes = $.stringToRunes(")
|
|
177
|
+
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
178
|
+
return fmt.Errorf("failed to write range loop string conversion expression: %w", err)
|
|
179
|
+
}
|
|
180
|
+
c.tsw.WriteLiterally(")")
|
|
181
|
+
c.tsw.WriteLine("")
|
|
182
|
+
|
|
183
|
+
indexVarName := c.getIndexVarName(exp, "i")
|
|
184
|
+
c.tsw.WriteLiterallyf("for (let %s = 0; %s < _runes.length; %s++) {", indexVarName, indexVarName, indexVarName)
|
|
185
|
+
c.tsw.Indent(1)
|
|
186
|
+
c.tsw.WriteLine("")
|
|
187
|
+
|
|
188
|
+
if exp.Value != nil {
|
|
189
|
+
if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
|
|
190
|
+
c.tsw.WriteLiterally("const ")
|
|
191
|
+
c.WriteIdent(ident, false)
|
|
192
|
+
c.tsw.WriteLiterally(" = _runes[i]") // TODO: should be indexVarName?
|
|
193
|
+
c.tsw.WriteLine("")
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
198
|
+
return fmt.Errorf("failed to write range loop string body: %w", err)
|
|
199
|
+
}
|
|
200
|
+
c.tsw.Indent(-1)
|
|
201
|
+
c.tsw.WriteLine("}")
|
|
202
|
+
c.tsw.Indent(-1)
|
|
203
|
+
c.tsw.WriteLine("}")
|
|
204
|
+
return nil
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
func (c *GoToTSCompiler) writeIntegerRange(exp *ast.RangeStmt) error {
|
|
208
|
+
if exp.Value != nil {
|
|
209
|
+
return errors.Errorf("ranging over an integer supports key variable only (not value variable): %v", exp)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
indexVarName := c.getIndexVarName(exp, "_i")
|
|
213
|
+
c.tsw.WriteLiterallyf("for (let %s = 0; %s < ", indexVarName, indexVarName)
|
|
214
|
+
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
215
|
+
return fmt.Errorf("failed to write range loop integer expression: %w", err)
|
|
216
|
+
}
|
|
217
|
+
c.tsw.WriteLiterallyf("; %s++) {", indexVarName)
|
|
218
|
+
|
|
219
|
+
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
220
|
+
return fmt.Errorf("failed to write range loop integer body: %w", err)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
c.tsw.Indent(-1)
|
|
224
|
+
c.tsw.WriteLine("}")
|
|
225
|
+
return nil
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
func (c *GoToTSCompiler) writeArraySliceRange(exp *ast.RangeStmt, isPointer bool) error {
|
|
229
|
+
indexVarName := c.getIndexVarName(exp, "_i")
|
|
230
|
+
|
|
231
|
+
// Handle the different cases
|
|
232
|
+
if exp.Key != nil && exp.Value != nil {
|
|
233
|
+
return c.writeArraySliceWithKeyValue(exp, indexVarName, isPointer)
|
|
234
|
+
} else if exp.Key != nil && exp.Value == nil {
|
|
235
|
+
return c.writeArraySliceKeyOnly(exp, indexVarName, isPointer)
|
|
236
|
+
} else if exp.Key == nil && exp.Value != nil {
|
|
237
|
+
return errors.Errorf("unexpected value without key in for range expression: %v", exp)
|
|
238
|
+
} else {
|
|
239
|
+
return c.writeArraySliceFallback(exp, isPointer)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
func (c *GoToTSCompiler) writeArraySliceWithKeyValue(exp *ast.RangeStmt, indexVarName string, isPointer bool) error {
|
|
244
|
+
c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
|
|
245
|
+
if err := c.writeArraySliceExpression(exp.X, isPointer); err != nil {
|
|
246
|
+
return fmt.Errorf("failed to write range loop array/slice expression (key and value): %w", err)
|
|
247
|
+
}
|
|
248
|
+
c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
|
|
249
|
+
c.tsw.Indent(1)
|
|
250
|
+
c.tsw.WriteLine("")
|
|
251
|
+
|
|
252
|
+
if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
|
|
253
|
+
c.tsw.WriteLiterally("const ")
|
|
254
|
+
c.WriteIdent(ident, false)
|
|
255
|
+
c.tsw.WriteLiterally(" = ")
|
|
256
|
+
if err := c.writeArraySliceExpression(exp.X, isPointer); err != nil {
|
|
257
|
+
return fmt.Errorf("failed to write range loop array/slice value expression: %w", err)
|
|
258
|
+
}
|
|
259
|
+
c.tsw.WriteLiterallyf("![%s]", indexVarName)
|
|
541
260
|
c.tsw.WriteLine("")
|
|
542
|
-
|
|
543
|
-
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if err := c.WriteStmt(exp.Body); err != nil {
|
|
264
|
+
return fmt.Errorf("failed to write range loop array/slice body (key and value): %w", err)
|
|
265
|
+
}
|
|
266
|
+
c.tsw.Indent(-1)
|
|
267
|
+
c.tsw.WriteLine("}")
|
|
268
|
+
return nil
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
func (c *GoToTSCompiler) writeArraySliceKeyOnly(exp *ast.RangeStmt, indexVarName string, isPointer bool) error {
|
|
272
|
+
c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
|
|
273
|
+
if err := c.writeArraySliceExpression(exp.X, isPointer); err != nil {
|
|
274
|
+
return fmt.Errorf("failed to write expression for the iterable: %w", err)
|
|
275
|
+
}
|
|
276
|
+
c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
|
|
277
|
+
c.tsw.Indent(1)
|
|
278
|
+
c.tsw.WriteLine("")
|
|
279
|
+
|
|
280
|
+
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
281
|
+
return fmt.Errorf("failed to write range loop array/slice body (only key): %w", err)
|
|
282
|
+
}
|
|
283
|
+
c.tsw.Indent(-1)
|
|
284
|
+
c.tsw.WriteLine("}")
|
|
285
|
+
return nil
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
func (c *GoToTSCompiler) writeArraySliceFallback(exp *ast.RangeStmt, isPointer bool) error {
|
|
289
|
+
indexVarName := "_i"
|
|
290
|
+
c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
|
|
291
|
+
if err := c.writeArraySliceExpression(exp.X, isPointer); err != nil {
|
|
292
|
+
return fmt.Errorf("failed to write range loop array/slice length expression (fallback): %w", err)
|
|
293
|
+
}
|
|
294
|
+
c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
|
|
295
|
+
c.tsw.Indent(1)
|
|
296
|
+
c.tsw.WriteLine("")
|
|
297
|
+
|
|
298
|
+
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
299
|
+
return fmt.Errorf("failed to write range loop array/slice body (fallback): %w", err)
|
|
300
|
+
}
|
|
301
|
+
c.tsw.Indent(-1)
|
|
302
|
+
c.tsw.WriteLine("}")
|
|
303
|
+
return nil
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
func (c *GoToTSCompiler) writeArraySliceExpression(expr ast.Expr, isPointer bool) error {
|
|
307
|
+
if isPointer {
|
|
308
|
+
if ident, ok := expr.(*ast.Ident); ok {
|
|
309
|
+
c.WriteIdent(ident, false)
|
|
310
|
+
} else {
|
|
311
|
+
if err := c.WriteValueExpr(expr); err != nil {
|
|
312
|
+
return err
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
c.tsw.WriteLiterally("!.value")
|
|
544
316
|
return nil
|
|
317
|
+
} else {
|
|
318
|
+
return c.WriteValueExpr(expr)
|
|
545
319
|
}
|
|
320
|
+
}
|
|
546
321
|
|
|
547
|
-
|
|
322
|
+
func (c *GoToTSCompiler) writeIteratorRange(exp *ast.RangeStmt, sig *types.Signature) error {
|
|
323
|
+
params := sig.Params()
|
|
324
|
+
yieldParam := params.At(0).Type()
|
|
325
|
+
yieldSig := yieldParam.Underlying().(*types.Signature)
|
|
326
|
+
yieldParams := yieldSig.Params()
|
|
327
|
+
|
|
328
|
+
c.tsw.WriteLiterally(";(() => {")
|
|
329
|
+
c.tsw.Indent(1)
|
|
330
|
+
c.tsw.WriteLine("")
|
|
331
|
+
c.tsw.WriteLiterally("let shouldContinue = true")
|
|
332
|
+
c.tsw.WriteLine("")
|
|
333
|
+
|
|
334
|
+
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
335
|
+
return fmt.Errorf("failed to write iterator expression: %w", err)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
switch yieldParams.Len() {
|
|
339
|
+
case 0:
|
|
340
|
+
c.tsw.WriteLiterally("!(() => {")
|
|
341
|
+
case 1:
|
|
342
|
+
c.tsw.WriteLiterally("!((")
|
|
343
|
+
c.writeIteratorParam(exp.Value, "v")
|
|
344
|
+
c.tsw.WriteLiterally(") => {")
|
|
345
|
+
case 2:
|
|
346
|
+
c.tsw.WriteLiterally("!((")
|
|
347
|
+
c.writeIteratorParam(exp.Key, "k")
|
|
348
|
+
c.tsw.WriteLiterally(", ")
|
|
349
|
+
c.writeIteratorParam(exp.Value, "v")
|
|
350
|
+
c.tsw.WriteLiterally(") => {")
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
c.tsw.Indent(1)
|
|
354
|
+
c.tsw.WriteLine("")
|
|
355
|
+
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
356
|
+
return fmt.Errorf("failed to write iterator body: %w", err)
|
|
357
|
+
}
|
|
358
|
+
c.tsw.WriteLiterally("return shouldContinue")
|
|
359
|
+
c.tsw.WriteLine("")
|
|
360
|
+
c.tsw.Indent(-1)
|
|
361
|
+
c.tsw.WriteLiterally("})")
|
|
362
|
+
c.tsw.WriteLine("")
|
|
363
|
+
c.tsw.Indent(-1)
|
|
364
|
+
c.tsw.WriteLine("})()")
|
|
365
|
+
return nil
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
func (c *GoToTSCompiler) writeIteratorParam(param ast.Expr, defaultName string) {
|
|
369
|
+
if param != nil {
|
|
370
|
+
if ident, ok := param.(*ast.Ident); ok && ident.Name != "_" {
|
|
371
|
+
c.WriteIdent(ident, false)
|
|
372
|
+
return
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
c.tsw.WriteLiterally(defaultName)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
func (c *GoToTSCompiler) writeInterfaceIteratorRange(exp *ast.RangeStmt) error {
|
|
379
|
+
c.tsw.WriteLiterally(";(() => {")
|
|
380
|
+
c.tsw.Indent(1)
|
|
381
|
+
c.tsw.WriteLine("")
|
|
382
|
+
c.tsw.WriteLiterally("let shouldContinue = true")
|
|
383
|
+
c.tsw.WriteLine("")
|
|
384
|
+
|
|
385
|
+
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
386
|
+
return fmt.Errorf("failed to write interface iterator expression: %w", err)
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if exp.Key != nil && exp.Value != nil {
|
|
390
|
+
c.tsw.WriteLiterally("!((")
|
|
391
|
+
c.writeIteratorParam(exp.Key, "k")
|
|
392
|
+
c.tsw.WriteLiterally(", ")
|
|
393
|
+
c.writeIteratorParam(exp.Value, "v")
|
|
394
|
+
c.tsw.WriteLiterally(") => {")
|
|
395
|
+
} else if exp.Value != nil {
|
|
396
|
+
c.tsw.WriteLiterally("!((")
|
|
397
|
+
c.writeIteratorParam(exp.Value, "v")
|
|
398
|
+
c.tsw.WriteLiterally(") => {")
|
|
399
|
+
} else if exp.Key != nil {
|
|
400
|
+
c.tsw.WriteLiterally("!((")
|
|
401
|
+
c.writeIteratorParam(exp.Key, "k")
|
|
402
|
+
c.tsw.WriteLiterally(") => {")
|
|
403
|
+
} else {
|
|
404
|
+
c.tsw.WriteLiterally("!(() => {")
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
c.tsw.Indent(1)
|
|
408
|
+
c.tsw.WriteLine("")
|
|
409
|
+
if err := c.WriteStmtBlock(exp.Body, false); err != nil {
|
|
410
|
+
return fmt.Errorf("failed to write interface iterator body: %w", err)
|
|
411
|
+
}
|
|
412
|
+
c.tsw.WriteLiterally("return shouldContinue")
|
|
413
|
+
c.tsw.WriteLine("")
|
|
414
|
+
c.tsw.Indent(-1)
|
|
415
|
+
c.tsw.WriteLiterally("})")
|
|
416
|
+
c.tsw.WriteLine("")
|
|
417
|
+
c.tsw.Indent(-1)
|
|
418
|
+
c.tsw.WriteLine("})()")
|
|
419
|
+
return nil
|
|
548
420
|
}
|