goscript 0.0.84 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +13 -1
  2. package/cmd/goscript/cmd_compile.go +70 -69
  3. package/cmd/goscript/cmd_compile_test.go +79 -0
  4. package/cmd/goscript/main.go +10 -5
  5. package/compiler/compile-request.go +218 -0
  6. package/compiler/compiler.go +16 -1336
  7. package/compiler/compliance_test.go +196 -0
  8. package/compiler/config.go +6 -13
  9. package/compiler/diagnostic.go +70 -0
  10. package/compiler/index.test.ts +28 -28
  11. package/compiler/index.ts +40 -72
  12. package/compiler/lowered-program.go +132 -0
  13. package/compiler/lowering.go +3576 -0
  14. package/compiler/override-registry.go +422 -0
  15. package/compiler/override-registry_test.go +207 -0
  16. package/compiler/package-graph.go +231 -0
  17. package/compiler/package-graph_test.go +281 -0
  18. package/compiler/result.go +13 -0
  19. package/compiler/runtime-contract.go +279 -0
  20. package/compiler/runtime-contract_test.go +90 -0
  21. package/compiler/semantic-model-types.go +110 -0
  22. package/compiler/semantic-model.go +922 -0
  23. package/compiler/semantic-model_test.go +416 -0
  24. package/compiler/service.go +133 -0
  25. package/compiler/skeleton_test.go +1145 -0
  26. package/compiler/typescript-emitter.go +663 -0
  27. package/compiler/wasm/compile.go +2 -3
  28. package/compiler/wasm/compile_test.go +29 -0
  29. package/compiler/wasm_api.go +10 -159
  30. package/dist/compiler/index.d.ts +1 -3
  31. package/dist/compiler/index.js +31 -55
  32. package/dist/compiler/index.js.map +1 -1
  33. package/dist/gs/builtin/builtin.d.ts +13 -0
  34. package/dist/gs/builtin/builtin.js +23 -0
  35. package/dist/gs/builtin/builtin.js.map +1 -1
  36. package/dist/gs/builtin/channel.d.ts +3 -3
  37. package/dist/gs/builtin/channel.js.map +1 -1
  38. package/dist/gs/builtin/hostio.d.ts +15 -1
  39. package/dist/gs/builtin/hostio.js +134 -49
  40. package/dist/gs/builtin/hostio.js.map +1 -1
  41. package/dist/gs/builtin/index.d.ts +1 -0
  42. package/dist/gs/builtin/index.js +1 -0
  43. package/dist/gs/builtin/index.js.map +1 -1
  44. package/dist/gs/builtin/slice.d.ts +1 -1
  45. package/dist/gs/builtin/slice.js.map +1 -1
  46. package/dist/gs/builtin/type.d.ts +11 -0
  47. package/dist/gs/builtin/type.js +55 -1
  48. package/dist/gs/builtin/type.js.map +1 -1
  49. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  50. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  51. package/dist/gs/bytes/reader.gs.js.map +1 -1
  52. package/dist/gs/context/context.js.map +1 -1
  53. package/dist/gs/crypto/rand/index.d.ts +5 -0
  54. package/dist/gs/crypto/rand/index.js +77 -0
  55. package/dist/gs/crypto/rand/index.js.map +1 -0
  56. package/dist/gs/encoding/json/index.d.ts +3 -0
  57. package/dist/gs/encoding/json/index.js +160 -0
  58. package/dist/gs/encoding/json/index.js.map +1 -0
  59. package/dist/gs/fmt/fmt.js.map +1 -1
  60. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -1
  61. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +1 -1
  62. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  63. package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
  64. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  65. package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
  66. package/dist/gs/go/scanner/index.d.ts +29 -0
  67. package/dist/gs/go/scanner/index.js +120 -0
  68. package/dist/gs/go/scanner/index.js.map +1 -0
  69. package/dist/gs/go/token/index.d.ts +31 -0
  70. package/dist/gs/go/token/index.js +82 -0
  71. package/dist/gs/go/token/index.js.map +1 -0
  72. package/dist/gs/internal/abi/index.js.map +1 -1
  73. package/dist/gs/io/fs/fs.js.map +1 -1
  74. package/dist/gs/io/fs/readdir.js.map +1 -1
  75. package/dist/gs/io/fs/readfile.js.map +1 -1
  76. package/dist/gs/io/fs/stat.js.map +1 -1
  77. package/dist/gs/io/fs/sub.js.map +1 -1
  78. package/dist/gs/io/io.js.map +1 -1
  79. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  80. package/dist/gs/os/error.gs.js +2 -4
  81. package/dist/gs/os/error.gs.js.map +1 -1
  82. package/dist/gs/os/exec.gs.js.map +1 -1
  83. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  84. package/dist/gs/os/rawconn_js.gs.js.map +1 -1
  85. package/dist/gs/os/root_js.gs.js.map +1 -1
  86. package/dist/gs/os/tempfile.gs.js +66 -9
  87. package/dist/gs/os/tempfile.gs.js.map +1 -1
  88. package/dist/gs/os/types.gs.js.map +1 -1
  89. package/dist/gs/os/types_js.gs.js +9 -9
  90. package/dist/gs/os/types_js.gs.js.map +1 -1
  91. package/dist/gs/os/types_unix.gs.js.map +1 -1
  92. package/dist/gs/path/filepath/match.js.map +1 -1
  93. package/dist/gs/path/match.js.map +1 -1
  94. package/dist/gs/path/path.js.map +1 -1
  95. package/dist/gs/reflect/index.d.ts +2 -2
  96. package/dist/gs/reflect/index.js +1 -1
  97. package/dist/gs/reflect/index.js.map +1 -1
  98. package/dist/gs/reflect/map.js.map +1 -1
  99. package/dist/gs/reflect/type.d.ts +2 -1
  100. package/dist/gs/reflect/type.js +85 -14
  101. package/dist/gs/reflect/type.js.map +1 -1
  102. package/dist/gs/reflect/types.js.map +1 -1
  103. package/dist/gs/reflect/visiblefields.js.map +1 -1
  104. package/dist/gs/runtime/runtime.js.map +1 -1
  105. package/dist/gs/sort/sort.gs.js.map +1 -1
  106. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  107. package/dist/gs/strconv/quote.gs.js.map +1 -1
  108. package/dist/gs/strings/builder.js.map +1 -1
  109. package/dist/gs/strings/reader.js.map +1 -1
  110. package/dist/gs/strings/replace.js.map +1 -1
  111. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  112. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  113. package/dist/gs/sync/sync.d.ts +1 -0
  114. package/dist/gs/sync/sync.js +12 -0
  115. package/dist/gs/sync/sync.js.map +1 -1
  116. package/dist/gs/time/time.js.map +1 -1
  117. package/dist/gs/unicode/unicode.js.map +1 -1
  118. package/go.mod +2 -2
  119. package/gs/builtin/builtin.ts +27 -0
  120. package/gs/builtin/hostio.test.ts +177 -0
  121. package/gs/builtin/hostio.ts +171 -56
  122. package/gs/builtin/index.ts +1 -0
  123. package/gs/builtin/runtime-contract.test.ts +230 -0
  124. package/gs/builtin/type.ts +84 -1
  125. package/gs/crypto/rand/index.test.ts +32 -0
  126. package/gs/crypto/rand/index.ts +90 -0
  127. package/gs/crypto/rand/meta.json +5 -0
  128. package/gs/encoding/json/index.test.ts +65 -0
  129. package/gs/encoding/json/index.ts +186 -0
  130. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +23 -0
  131. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +3 -1
  132. package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/meta.json +3 -1
  133. package/gs/go/scanner/index.test.ts +50 -0
  134. package/gs/go/scanner/index.ts +157 -0
  135. package/gs/go/token/index.test.ts +21 -0
  136. package/gs/go/token/index.ts +120 -0
  137. package/gs/os/file_unix_js.test.ts +50 -0
  138. package/gs/os/meta.json +1 -2
  139. package/gs/os/tempfile.gs.test.ts +85 -0
  140. package/gs/os/tempfile.gs.ts +71 -11
  141. package/gs/os/types_js.gs.ts +9 -9
  142. package/gs/reflect/index.ts +1 -1
  143. package/gs/reflect/type.ts +106 -17
  144. package/gs/reflect/typefor.test.ts +75 -0
  145. package/gs/sync/sync.test.ts +24 -0
  146. package/gs/sync/sync.ts +12 -0
  147. package/package.json +13 -13
  148. package/compiler/analysis.go +0 -3475
  149. package/compiler/analysis_test.go +0 -338
  150. package/compiler/assignment.go +0 -580
  151. package/compiler/builtin_test.go +0 -92
  152. package/compiler/code-writer.go +0 -115
  153. package/compiler/compiler_test.go +0 -149
  154. package/compiler/composite-lit.go +0 -779
  155. package/compiler/config_test.go +0 -62
  156. package/compiler/constraint.go +0 -86
  157. package/compiler/decl.go +0 -801
  158. package/compiler/expr-call-async.go +0 -188
  159. package/compiler/expr-call-builtins.go +0 -208
  160. package/compiler/expr-call-helpers.go +0 -382
  161. package/compiler/expr-call-make.go +0 -318
  162. package/compiler/expr-call-type-conversion.go +0 -520
  163. package/compiler/expr-call.go +0 -413
  164. package/compiler/expr-selector.go +0 -343
  165. package/compiler/expr-star.go +0 -82
  166. package/compiler/expr-type.go +0 -442
  167. package/compiler/expr-value.go +0 -89
  168. package/compiler/expr.go +0 -773
  169. package/compiler/field.go +0 -183
  170. package/compiler/gs_dependencies_test.go +0 -298
  171. package/compiler/lit.go +0 -322
  172. package/compiler/output.go +0 -72
  173. package/compiler/primitive.go +0 -149
  174. package/compiler/protobuf.go +0 -697
  175. package/compiler/sanitize.go +0 -100
  176. package/compiler/spec-struct.go +0 -995
  177. package/compiler/spec-value.go +0 -540
  178. package/compiler/spec.go +0 -725
  179. package/compiler/stmt-assign.go +0 -664
  180. package/compiler/stmt-for.go +0 -266
  181. package/compiler/stmt-range.go +0 -475
  182. package/compiler/stmt-select.go +0 -262
  183. package/compiler/stmt-type-switch.go +0 -147
  184. package/compiler/stmt.go +0 -1308
  185. package/compiler/type-assert.go +0 -386
  186. package/compiler/type-info.go +0 -156
  187. package/compiler/type-utils.go +0 -207
  188. package/compiler/type.go +0 -892
@@ -1,475 +0,0 @@
1
- package compiler
2
-
3
- import (
4
- "fmt"
5
- "go/ast"
6
- "go/token"
7
- "go/types"
8
- "strings"
9
-
10
- "github.com/pkg/errors"
11
- )
12
-
13
- // WriteStmtRange translates a Go `for...range` statement (`ast.RangeStmt`)
14
- // into an equivalent TypeScript loop. The translation depends on the type of
15
- // the expression being ranged over (`exp.X`), determined using `go/types` info.
16
- //
17
- // - **Maps (`*types.Map`):**
18
- // `for k, v := range myMap` becomes `for (const [k_ts, v_ts] of myMap_ts.entries()) { const k = k_ts; const v = v_ts; ...body... }`.
19
- // If only `k` or `v` (or neither) is used, the corresponding TypeScript const declaration is adjusted.
20
- //
21
- // - **Strings (`*types.Basic` with `IsString` info):**
22
- // `for i, r := range myString` becomes:
23
- // `const _runes = $.stringToRunes(myString_ts);`
24
- // `for (let i_ts = 0; i_ts < _runes.length; i_ts++) { const r_ts = _runes[i_ts]; ...body... }`.
25
- // The index variable `i_ts` uses the Go key variable name if provided (and not `_`).
26
- // The rune variable `r_ts` uses the Go value variable name.
27
- //
28
- // - **Integers (`*types.Basic` with `IsInteger` info, Go 1.22+):**
29
- // `for i := range N` becomes `for (let i_ts = 0; i_ts < N_ts; i_ts++) { ...body... }`.
30
- // `for i, v := range N` becomes `for (let i_ts = 0; i_ts < N_ts; i_ts++) { const v_ts = i_ts; ...body... }`.
31
- //
32
- // - **Arrays (`*types.Array`) and Slices (`*types.Slice`):**
33
- // - If both key (index) and value are used (`for i, val := range arr`):
34
- // `for (let i_ts = 0; i_ts < arr_ts.length; i_ts++) { const val_ts = arr_ts[i_ts]; ...body... }`.
35
- // - If only the key (index) is used (`for i := range arr`):
36
- // `for (let i_ts = 0; i_ts < arr_ts.length; i_ts++) { ...body... }`.
37
- // - If only the value is used (`for _, val := range arr`):
38
- // `for (const v_ts of arr_ts) { const val_ts = v_ts; ...body... }`.
39
- // - If neither is used (e.g., `for range arr`), a simple index loop `for (let _i = 0; ...)` is generated.
40
- // The index variable `i_ts` uses the Go key variable name if provided.
41
- //
42
- // Loop variables (`exp.Key`, `exp.Value`) are declared as `const` inside the loop
43
- // body if they are not blank identifiers (`_`). The loop body (`exp.Body`) is
44
- // translated using `WriteStmtBlock` (or `WriteStmt` for array/slice with key and value).
45
- // If the ranged type is not supported, a comment is written, and an error is returned.
46
- func (c *GoToTSCompiler) WriteStmtRange(exp *ast.RangeStmt) error {
47
- // Get the type of the iterable expression
48
- iterType := c.pkg.TypesInfo.TypeOf(exp.X)
49
- underlying := iterType.Underlying()
50
-
51
- // Handle map types (both concrete maps and type parameters constrained to maps)
52
- if c.isMapType(iterType, underlying) {
53
- return c.writeMapRange(exp)
54
- }
55
-
56
- // Handle basic types (string, integer)
57
- if basic, ok := underlying.(*types.Basic); ok {
58
- if c.isStringType(iterType) {
59
- return c.writeStringRange(exp)
60
- } else if basic.Info()&types.IsInteger != 0 {
61
- return c.writeIntegerRange(exp)
62
- }
63
- }
64
-
65
- // Handle array and slice types
66
- if c.isArrayOrSlice(underlying) {
67
- return c.writeArraySliceRange(exp, false)
68
- }
69
-
70
- // Handle pointer to array/slice types
71
- if ptrType, ok := underlying.(*types.Pointer); ok {
72
- elem := ptrType.Elem().Underlying()
73
- if c.isArrayOrSlice(elem) {
74
- return c.writeArraySliceRange(exp, true)
75
- }
76
- }
77
-
78
- // Handle iterator function signatures
79
- if sig, ok := underlying.(*types.Signature); ok {
80
- if c.isIteratorSignature(sig) {
81
- return c.writeIteratorRange(exp, sig)
82
- }
83
- }
84
-
85
- // Handle interface types that may represent iterators
86
- if _, ok := underlying.(*types.Interface); ok {
87
- return c.writeInterfaceIteratorRange(exp)
88
- }
89
-
90
- if _, ok := underlying.(*types.Chan); ok {
91
- return c.writeChannelRange(exp)
92
- }
93
-
94
- return errors.Errorf("unsupported range loop type: %T for expression %v", underlying, exp)
95
- }
96
-
97
- // Helper functions
98
-
99
- func (c *GoToTSCompiler) isIteratorSignature(sig *types.Signature) bool {
100
- params := sig.Params()
101
- if params.Len() != 1 {
102
- return false
103
- }
104
- yieldParam := params.At(0).Type()
105
- if yieldSig, ok := yieldParam.Underlying().(*types.Signature); ok {
106
- yieldResults := yieldSig.Results()
107
- if yieldResults.Len() == 1 {
108
- if basic, ok := yieldResults.At(0).Type().Underlying().(*types.Basic); ok && basic.Kind() == types.Bool {
109
- return true
110
- }
111
- }
112
- }
113
- return false
114
- }
115
-
116
- func (c *GoToTSCompiler) getIndexVarName(exp *ast.RangeStmt, defaultName string) string {
117
- if exp.Key != nil {
118
- if keyIdent, ok := exp.Key.(*ast.Ident); ok && keyIdent.Name != "_" {
119
- return keyIdent.Name
120
- }
121
- }
122
- return defaultName
123
- }
124
-
125
- func (c *GoToTSCompiler) writeMapRange(exp *ast.RangeStmt) error {
126
- keyVarName := "_k"
127
- valueVarName := "_v"
128
-
129
- if exp.Key != nil {
130
- if ident, ok := exp.Key.(*ast.Ident); ok && ident.Name != "_" {
131
- keyVarName = ident.Name
132
- }
133
- }
134
- if exp.Value != nil {
135
- if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
136
- valueVarName = ident.Name
137
- }
138
- }
139
-
140
- c.tsw.WriteLiterallyf("for (const [%s, %s] of ", keyVarName, valueVarName)
141
- if err := c.WriteValueExpr(exp.X); err != nil {
142
- return fmt.Errorf("failed to write range loop map expression: %w", err)
143
- }
144
- c.tsw.WriteLiterally("?.entries() ?? []) {")
145
- c.tsw.Indent(1)
146
- c.tsw.WriteLine("")
147
-
148
- if err := c.WriteStmtBlock(exp.Body, false); err != nil {
149
- return fmt.Errorf("failed to write range loop map body: %w", err)
150
- }
151
- c.tsw.Indent(-1)
152
- c.tsw.WriteLine("}")
153
- return nil
154
- }
155
-
156
- func (c *GoToTSCompiler) writeStringRange(exp *ast.RangeStmt) error {
157
- c.tsw.WriteLine("{")
158
- c.tsw.Indent(1)
159
-
160
- c.tsw.WriteLiterally("const _runes = $.stringToRunes(")
161
- if err := c.WriteValueExpr(exp.X); err != nil {
162
- return fmt.Errorf("failed to write range loop string conversion expression: %w", err)
163
- }
164
- c.tsw.WriteLiterally(")")
165
- c.tsw.WriteLine("")
166
-
167
- indexVarName := c.getIndexVarName(exp, "i")
168
- c.tsw.WriteLiterallyf("for (let %s = 0; %s < _runes.length; %s++) {", indexVarName, indexVarName, indexVarName)
169
- c.tsw.Indent(1)
170
- c.tsw.WriteLine("")
171
-
172
- if exp.Value != nil {
173
- if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
174
- c.tsw.WriteLiterally("let ")
175
- c.WriteIdent(ident, false)
176
- c.tsw.WriteLiterally(" = _runes[")
177
- c.tsw.WriteLiterally(indexVarName)
178
- c.tsw.WriteLiterally("]")
179
- c.tsw.WriteLine("")
180
- }
181
- }
182
-
183
- if err := c.WriteStmtBlock(exp.Body, false); err != nil {
184
- return fmt.Errorf("failed to write range loop string body: %w", err)
185
- }
186
- c.tsw.Indent(-1)
187
- c.tsw.WriteLine("}")
188
- c.tsw.Indent(-1)
189
- c.tsw.WriteLine("}")
190
- return nil
191
- }
192
-
193
- func (c *GoToTSCompiler) writeIntegerRange(exp *ast.RangeStmt) error {
194
- if exp.Value != nil {
195
- return errors.Errorf("ranging over an integer supports key variable only (not value variable): %v", exp)
196
- }
197
-
198
- indexVarName := c.getIndexVarName(exp, "_i")
199
- c.tsw.WriteLiterallyf("for (let %s = 0; %s < ", indexVarName, indexVarName)
200
- if err := c.WriteValueExpr(exp.X); err != nil {
201
- return fmt.Errorf("failed to write range loop integer expression: %w", err)
202
- }
203
- c.tsw.WriteLiterallyf("; %s++) {", indexVarName)
204
-
205
- if err := c.WriteStmtBlock(exp.Body, false); err != nil {
206
- return fmt.Errorf("failed to write range loop integer body: %w", err)
207
- }
208
-
209
- c.tsw.Indent(-1)
210
- c.tsw.WriteLine("}")
211
- return nil
212
- }
213
-
214
- func (c *GoToTSCompiler) writeArraySliceRange(exp *ast.RangeStmt, isPointer bool) error {
215
- indexVarName := c.getIndexVarName(exp, "_i")
216
-
217
- // Handle the different cases
218
- if exp.Key != nil && exp.Value != nil {
219
- return c.writeArraySliceWithKeyValue(exp, indexVarName, isPointer)
220
- } else if exp.Key != nil && exp.Value == nil {
221
- return c.writeArraySliceKeyOnly(exp, indexVarName, isPointer)
222
- } else if exp.Key == nil && exp.Value != nil {
223
- return errors.Errorf("unexpected value without key in for range expression: %v", exp)
224
- } else {
225
- return c.writeArraySliceFallback(exp, isPointer)
226
- }
227
- }
228
-
229
- func (c *GoToTSCompiler) writeArraySliceWithKeyValue(exp *ast.RangeStmt, indexVarName string, isPointer bool) error {
230
- c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
231
- if err := c.writeArraySliceExpression(exp.X, isPointer); err != nil {
232
- return fmt.Errorf("failed to write range loop array/slice expression (key and value): %w", err)
233
- }
234
- c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
235
- c.tsw.Indent(1)
236
- c.tsw.WriteLine("")
237
-
238
- if ident, ok := exp.Value.(*ast.Ident); ok && ident.Name != "_" {
239
- c.tsw.WriteLiterally("let ")
240
- c.WriteIdent(ident, false)
241
- c.tsw.WriteLiterally(" = ")
242
- if err := c.writeArraySliceExpression(exp.X, isPointer); err != nil {
243
- return fmt.Errorf("failed to write range loop array/slice value expression: %w", err)
244
- }
245
- c.tsw.WriteLiterallyf("![%s]", indexVarName)
246
- c.tsw.WriteLine("")
247
- }
248
-
249
- if err := c.WriteStmt(exp.Body); err != nil {
250
- return fmt.Errorf("failed to write range loop array/slice body (key and value): %w", err)
251
- }
252
- c.tsw.Indent(-1)
253
- c.tsw.WriteLine("}")
254
- return nil
255
- }
256
-
257
- func (c *GoToTSCompiler) writeArraySliceKeyOnly(exp *ast.RangeStmt, indexVarName string, isPointer bool) error {
258
- c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
259
- if err := c.writeArraySliceExpression(exp.X, isPointer); err != nil {
260
- return fmt.Errorf("failed to write expression for the iterable: %w", err)
261
- }
262
- c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
263
- c.tsw.Indent(1)
264
- c.tsw.WriteLine("")
265
-
266
- if err := c.WriteStmtBlock(exp.Body, false); err != nil {
267
- return fmt.Errorf("failed to write range loop array/slice body (only key): %w", err)
268
- }
269
- c.tsw.Indent(-1)
270
- c.tsw.WriteLine("}")
271
- return nil
272
- }
273
-
274
- func (c *GoToTSCompiler) writeArraySliceFallback(exp *ast.RangeStmt, isPointer bool) error {
275
- indexVarName := "_i"
276
- c.tsw.WriteLiterallyf("for (let %s = 0; %s < $.len(", indexVarName, indexVarName)
277
- if err := c.writeArraySliceExpression(exp.X, isPointer); err != nil {
278
- return fmt.Errorf("failed to write range loop array/slice length expression (fallback): %w", err)
279
- }
280
- c.tsw.WriteLiterallyf("); %s++) {", indexVarName)
281
- c.tsw.Indent(1)
282
- c.tsw.WriteLine("")
283
-
284
- if err := c.WriteStmtBlock(exp.Body, false); err != nil {
285
- return fmt.Errorf("failed to write range loop array/slice body (fallback): %w", err)
286
- }
287
- c.tsw.Indent(-1)
288
- c.tsw.WriteLine("}")
289
- return nil
290
- }
291
-
292
- func (c *GoToTSCompiler) writeArraySliceExpression(expr ast.Expr, isPointer bool) error {
293
- if isPointer {
294
- if ident, ok := expr.(*ast.Ident); ok {
295
- c.WriteIdent(ident, false)
296
- } else {
297
- if err := c.WriteValueExpr(expr); err != nil {
298
- return err
299
- }
300
- }
301
- c.tsw.WriteLiterally("!.value")
302
- return nil
303
- } else {
304
- return c.WriteValueExpr(expr)
305
- }
306
- }
307
-
308
- func (c *GoToTSCompiler) writeIteratorRange(exp *ast.RangeStmt, sig *types.Signature) error {
309
- params := sig.Params()
310
- yieldParam := params.At(0).Type()
311
- yieldSig := yieldParam.Underlying().(*types.Signature)
312
- yieldParams := yieldSig.Params()
313
-
314
- c.tsw.WriteLiterally(";(() => {")
315
- c.tsw.Indent(1)
316
- c.tsw.WriteLine("")
317
- c.tsw.WriteLiterally("let shouldContinue = true")
318
- c.tsw.WriteLine("")
319
-
320
- if err := c.WriteValueExpr(exp.X); err != nil {
321
- return fmt.Errorf("failed to write iterator expression: %w", err)
322
- }
323
-
324
- switch yieldParams.Len() {
325
- case 0:
326
- c.tsw.WriteLiterally("!(() => {")
327
- case 1:
328
- c.tsw.WriteLiterally("!((")
329
- c.writeIteratorParam(exp.Value, "v")
330
- c.tsw.WriteLiterally(") => {")
331
- case 2:
332
- c.tsw.WriteLiterally("!((")
333
- c.writeIteratorParam(exp.Key, "k")
334
- c.tsw.WriteLiterally(", ")
335
- c.writeIteratorParam(exp.Value, "v")
336
- c.tsw.WriteLiterally(") => {")
337
- }
338
-
339
- c.tsw.Indent(1)
340
- c.tsw.WriteLine("")
341
- if err := c.WriteStmtBlock(exp.Body, false); err != nil {
342
- return fmt.Errorf("failed to write iterator body: %w", err)
343
- }
344
- c.tsw.WriteLiterally("return shouldContinue")
345
- c.tsw.WriteLine("")
346
- c.tsw.Indent(-1)
347
- c.tsw.WriteLiterally("})")
348
- c.tsw.WriteLine("")
349
- c.tsw.Indent(-1)
350
- c.tsw.WriteLine("})()")
351
- return nil
352
- }
353
-
354
- func (c *GoToTSCompiler) writeIteratorParam(param ast.Expr, defaultName string) {
355
- if param != nil {
356
- if ident, ok := param.(*ast.Ident); ok && ident.Name != "_" {
357
- c.WriteIdent(ident, false)
358
- return
359
- }
360
- }
361
- c.tsw.WriteLiterally(defaultName)
362
- }
363
-
364
- func (c *GoToTSCompiler) writeInterfaceIteratorRange(exp *ast.RangeStmt) error {
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
-
371
- if err := c.WriteValueExpr(exp.X); err != nil {
372
- return fmt.Errorf("failed to write interface iterator expression: %w", err)
373
- }
374
-
375
- if exp.Key != nil && exp.Value != nil {
376
- c.tsw.WriteLiterally("!((")
377
- c.writeIteratorParam(exp.Key, "k")
378
- c.tsw.WriteLiterally(", ")
379
- c.writeIteratorParam(exp.Value, "v")
380
- c.tsw.WriteLiterally(") => {")
381
- } else if exp.Value != nil {
382
- c.tsw.WriteLiterally("!((")
383
- c.writeIteratorParam(exp.Value, "v")
384
- c.tsw.WriteLiterally(") => {")
385
- } else if exp.Key != nil {
386
- c.tsw.WriteLiterally("!((")
387
- c.writeIteratorParam(exp.Key, "k")
388
- c.tsw.WriteLiterally(") => {")
389
- } else {
390
- c.tsw.WriteLiterally("!(() => {")
391
- }
392
-
393
- c.tsw.Indent(1)
394
- c.tsw.WriteLine("")
395
- if err := c.WriteStmtBlock(exp.Body, false); err != nil {
396
- return fmt.Errorf("failed to write interface iterator body: %w", err)
397
- }
398
- c.tsw.WriteLiterally("return shouldContinue")
399
- c.tsw.WriteLine("")
400
- c.tsw.Indent(-1)
401
- c.tsw.WriteLiterally("})")
402
- c.tsw.WriteLine("")
403
- c.tsw.Indent(-1)
404
- c.tsw.WriteLine("})()")
405
- return nil
406
- }
407
-
408
- func (c *GoToTSCompiler) writeChannelRange(exp *ast.RangeStmt) error {
409
- if exp.Value != nil {
410
- return fmt.Errorf("channel range does not support two iteration variables")
411
- }
412
-
413
- c.tsw.WriteLiterally("for (;;) {")
414
- c.tsw.Indent(1)
415
- c.tsw.WriteLine("")
416
-
417
- valueIsBlank := exp.Key == nil
418
- valueName := "_"
419
- if !valueIsBlank {
420
- if valIdent, ok := exp.Key.(*ast.Ident); ok {
421
- if valIdent.Name != "_" {
422
- valueName = valIdent.Name
423
- } else {
424
- valueIsBlank = true
425
- }
426
- } else {
427
- return fmt.Errorf("unsupported iteration variable in channel range: %T", exp.Key)
428
- }
429
- }
430
-
431
- keyword := "const "
432
- okVarName := "_ok"
433
- if exp.Tok != token.DEFINE {
434
- keyword = ""
435
- c.tsw.WriteLiterally("let ")
436
- c.tsw.WriteLiterally(okVarName)
437
- c.tsw.WriteLine("")
438
- }
439
-
440
- patternParts := []string{}
441
- if !valueIsBlank {
442
- patternParts = append(patternParts, fmt.Sprintf("value: %s", valueName))
443
- }
444
- patternParts = append(patternParts, fmt.Sprintf("ok: %s", okVarName))
445
- destructuringPattern := fmt.Sprintf("{ %s }", strings.Join(patternParts, ", "))
446
-
447
- c.tsw.WriteLiterally(keyword)
448
- if keyword == "" {
449
- c.tsw.WriteLiterally(";(")
450
- }
451
- c.tsw.WriteLiterally(destructuringPattern)
452
- c.tsw.WriteLiterally(" = await $.chanRecvWithOk(")
453
- if err := c.WriteValueExpr(exp.X); err != nil {
454
- return err
455
- }
456
- c.tsw.WriteLiterally(")")
457
- if keyword == "" {
458
- c.tsw.WriteLiterally(")")
459
- }
460
- c.tsw.WriteLine("")
461
-
462
- c.tsw.WriteLiterally("if (!")
463
- c.tsw.WriteLiterally(okVarName)
464
- c.tsw.WriteLiterally(") break")
465
- c.tsw.WriteLine("")
466
-
467
- if err := c.WriteStmtBlock(exp.Body, false); err != nil {
468
- return err
469
- }
470
-
471
- c.tsw.Indent(-1)
472
- c.tsw.WriteLine("}")
473
-
474
- return nil
475
- }