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,386 +0,0 @@
1
- package compiler
2
-
3
- import (
4
- "fmt"
5
- "go/ast"
6
- "go/token"
7
- "go/types"
8
- "strings"
9
- )
10
-
11
- // writeTypeAssert handles the Go type assertion with comma-ok idiom in an
12
- // assignment context: `value, ok := interfaceExpr.(AssertedType)` (or with `=`).
13
- // It translates this to a TypeScript destructuring assignment (or declaration if `tok`
14
- // is `token.DEFINE` for `:=`) using the `$.typeAssert` runtime helper.
15
- //
16
- // The generated TypeScript is:
17
- // `[let] { value: valueName, ok: okName } = $.typeAssert<AssertedType_ts>(interfaceExpr_ts, 'AssertedTypeName');`
18
- //
19
- // - `AssertedType_ts` is the TypeScript translation of `AssertedType`.
20
- // - `interfaceExpr_ts` is the TypeScript translation of `interfaceExpr`.
21
- // - `'AssertedTypeName'` is a string representation of the asserted type name,
22
- // obtained via `getTypeNameString`, used for runtime error messages.
23
- // - `valueName` and `okName` are the Go variable names from the LHS.
24
- // - Blank identifiers (`_`) on the LHS are handled by omitting the corresponding
25
- // property in the destructuring pattern (e.g., `{ ok: okName } = ...` if `value` is blank).
26
- // - If `tok` is not `token.DEFINE` (i.e., for regular assignment `=`), the entire
27
- // destructuring assignment is wrapped in parentheses `(...)` to make it a valid
28
- // expression if needed, though typically assignments are statements.
29
- //
30
- // The statement is terminated with a newline.
31
- func (c *GoToTSCompiler) writeTypeAssert(lhs []ast.Expr, typeAssertExpr *ast.TypeAssertExpr, tok token.Token) error {
32
- interfaceExpr := typeAssertExpr.X
33
- assertedType := typeAssertExpr.Type
34
-
35
- // Unwrap parenthesized expressions to handle cases like r.((<-chan T))
36
- for {
37
- if parenExpr, ok := assertedType.(*ast.ParenExpr); ok {
38
- assertedType = parenExpr.X
39
- } else {
40
- break
41
- }
42
- }
43
-
44
- // Ensure LHS has exactly two expressions (value and ok)
45
- if len(lhs) != 2 {
46
- return fmt.Errorf("type assertion assignment requires exactly 2 variables on LHS, got %d", len(lhs))
47
- }
48
-
49
- var okIsBlank bool
50
- var okIsSelectorExpr bool
51
- var okIdent *ast.Ident
52
- var okSelectorExpr *ast.SelectorExpr
53
-
54
- okExpr := lhs[1]
55
-
56
- // Handle different types of ok expressions
57
- switch okE := okExpr.(type) {
58
- case *ast.Ident:
59
- okIdent = okE
60
- okIsBlank = okIdent.Name == "_"
61
- case *ast.SelectorExpr:
62
- okSelectorExpr = okE
63
- okIsSelectorExpr = true
64
- okIsBlank = false // Selector expressions can't be blank
65
- default:
66
- return fmt.Errorf("ok expression must be an identifier or selector expression, got: %T", okExpr)
67
- }
68
-
69
- valueExpr := lhs[0]
70
-
71
- // Determine if 'ok' variable is new in 'tok == token.DEFINE' context.
72
- // This uses types.Info.Defs to see if the identifier is defined by this statement.
73
- var okIsNewInDefine bool
74
- if tok == token.DEFINE && !okIsBlank && !okIsSelectorExpr {
75
- // Only applies to identifiers, not selector expressions
76
- if c.pkg.TypesInfo.Defs[okIdent] != nil {
77
- okIsNewInDefine = true
78
- }
79
- }
80
-
81
- switch vLHS := valueExpr.(type) {
82
- case *ast.Ident:
83
- var valueIsBlank bool
84
- var valueName string
85
- valueIdent := vLHS
86
- valueIsBlank = (valueIdent.Name == "_")
87
- valueName = valueIdent.Name
88
-
89
- var valueIsNewInDefine bool
90
- if tok == token.DEFINE && !valueIsBlank {
91
- if c.pkg.TypesInfo.Defs[valueIdent] != nil { // valueIdent is defined by this statement
92
- valueIsNewInDefine = true
93
- }
94
- }
95
-
96
- // For selector expressions as ok, we need to use temporary variables approach
97
- if okIsSelectorExpr {
98
- // Use temporary variables approach similar to SelectorExpr case
99
- tempValName := fmt.Sprintf("_gs_ta_val_%s", c.getDeterministicID(typeAssertExpr.Pos())) // Unique name based on deterministic position
100
- tempOkName := fmt.Sprintf("_gs_ta_ok_%s", c.getDeterministicID(typeAssertExpr.Pos())) // Unique name based on deterministic position
101
-
102
- // Declare temporary variables:
103
- // let _gs_ta_val_: AssertedTypeTS;
104
- c.tsw.WriteLiterally("let ")
105
- c.tsw.WriteLiterally(tempValName)
106
- c.tsw.WriteLiterally(": ")
107
- c.WriteTypeExpr(assertedType) // TypeScript type for assertedType
108
- c.tsw.WriteLine("")
109
-
110
- // let _gs_ta_ok_: boolean;
111
- c.tsw.WriteLiterally("let ")
112
- c.tsw.WriteLiterally(tempOkName)
113
- c.tsw.WriteLiterally(": boolean")
114
- c.tsw.WriteLine("")
115
-
116
- // Perform type assertion into temporary variables:
117
- // ({ value: _gs_ta_val_, ok: _gs_ta_ok_ } = $.typeAssert<AssertedTypeTS>(expr, "GoTypeStr"));
118
- c.tsw.WriteLiterally("({ value: ")
119
- c.tsw.WriteLiterally(tempValName)
120
- c.tsw.WriteLiterally(", ok: ")
121
- c.tsw.WriteLiterally(tempOkName)
122
- c.tsw.WriteLiterally(" } = $.typeAssert<")
123
- c.WriteTypeExpr(assertedType) // Generic: <AssertedTypeTS>
124
- c.tsw.WriteLiterally(">(")
125
- if err := c.WriteValueExpr(interfaceExpr); err != nil { // Arg1: interfaceExpr
126
- return fmt.Errorf("failed to write interface expression in type assertion call: %w", err)
127
- }
128
- c.tsw.WriteLiterally(", ")
129
- c.writeTypeDescription(assertedType) // Arg2: type info for runtime
130
- c.tsw.WriteLine("))")
131
-
132
- // Assign temporary value to the value variable:
133
- if !valueIsBlank {
134
- if valueIsNewInDefine {
135
- c.tsw.WriteLiterally("let ")
136
- }
137
- c.tsw.WriteLiterally(valueName)
138
- c.tsw.WriteLiterally(" = ")
139
- c.tsw.WriteLiterally(tempValName)
140
- c.tsw.WriteLine("")
141
- }
142
-
143
- // Assign temporary ok to the selector expression:
144
- if err := c.WriteValueExpr(okSelectorExpr); err != nil {
145
- return fmt.Errorf("failed to write ok selector expression in type assertion: %w", err)
146
- }
147
- c.tsw.WriteLiterally(" = ")
148
- c.tsw.WriteLiterally(tempOkName)
149
- c.tsw.WriteLine("")
150
-
151
- return nil
152
- }
153
-
154
- writeEndParen := false // For wrapping assignment in parens to make it an expression
155
- letDestructure := false // True if 'let { value: v, ok: o } = ...' is appropriate
156
-
157
- if tok == token.DEFINE {
158
- anyNewVars := (valueIsNewInDefine && !valueIsBlank) || (okIsNewInDefine && !okIsBlank)
159
- // allVarsNewOrBlank means suitable for a single `let {v,o} = ...` destructuring
160
- allVarsNewOrBlank := (valueIsBlank || valueIsNewInDefine) && (okIsBlank || okIsNewInDefine)
161
-
162
- if allVarsNewOrBlank && anyNewVars {
163
- letDestructure = true
164
- } else if anyNewVars { // Mixed: some new, some existing. Declare new ones separately.
165
- if !valueIsBlank && valueIsNewInDefine {
166
- c.tsw.WriteLiterally("let ")
167
- c.tsw.WriteLiterally(valueName)
168
- c.tsw.WriteLiterally(": ")
169
- c.WriteTypeExpr(assertedType) // Use WriteTypeExpr for TS type annotation
170
- c.tsw.WriteLine("")
171
- }
172
- if !okIsBlank && okIsNewInDefine {
173
- c.tsw.WriteLiterally("let ")
174
- c.tsw.WriteLiterally(okIdent.Name)
175
- c.tsw.WriteLiterally(": boolean")
176
- c.tsw.WriteLine("")
177
- }
178
- c.tsw.WriteLiterally("(") // Parenthesize the assignment part
179
- writeEndParen = true
180
- } else { // All variables exist
181
- c.tsw.WriteLiterally("(")
182
- writeEndParen = true
183
- }
184
- } else { // tok == token.ASSIGN
185
- c.tsw.WriteLiterally("(")
186
- writeEndParen = true
187
- }
188
-
189
- if letDestructure {
190
- c.tsw.WriteLiterally("let ")
191
- }
192
-
193
- // Write the destructuring part: { value: v, ok: o }
194
- c.tsw.WriteLiterally("{ ")
195
- parts := []string{}
196
- if !valueIsBlank {
197
- parts = append(parts, fmt.Sprintf("value: %s", valueName))
198
- }
199
- if !okIsBlank {
200
- parts = append(parts, fmt.Sprintf("ok: %s", okIdent.Name))
201
- }
202
- c.tsw.WriteLiterally(strings.Join(parts, ", "))
203
- c.tsw.WriteLiterally(" } = $.typeAssert<")
204
- c.WriteTypeExpr(assertedType) // Generic: <AssertedTypeTS>
205
- c.tsw.WriteLiterally(">(")
206
- if err := c.WriteValueExpr(interfaceExpr); err != nil { // Arg1: interfaceExpr
207
- return fmt.Errorf("failed to write interface expression in type assertion call: %w", err)
208
- }
209
- c.tsw.WriteLiterally(", ")
210
- c.writeTypeDescription(assertedType) // Arg2: type info for runtime
211
- c.tsw.WriteLiterally(")")
212
-
213
- if writeEndParen {
214
- c.tsw.WriteLiterally(")")
215
- }
216
- c.tsw.WriteLine("")
217
-
218
- case *ast.SelectorExpr:
219
- // Handle s.field, ok := expr.(Type)
220
- tempValName := fmt.Sprintf("_gs_ta_val_%s", c.getDeterministicID(typeAssertExpr.Pos())) // Unique name based on deterministic position
221
- tempOkName := fmt.Sprintf("_gs_ta_ok_%s", c.getDeterministicID(typeAssertExpr.Pos())) // Unique name based on deterministic position
222
-
223
- // Declare temporary variables:
224
- // let _gs_ta_val_: AssertedTypeTS;
225
- c.tsw.WriteLiterally("let ")
226
- c.tsw.WriteLiterally(tempValName)
227
- c.tsw.WriteLiterally(": ")
228
- c.WriteTypeExpr(assertedType) // TypeScript type for assertedType
229
- c.tsw.WriteLine("")
230
-
231
- // let _gs_ta_ok_: boolean;
232
- c.tsw.WriteLiterally("let ")
233
- c.tsw.WriteLiterally(tempOkName)
234
- c.tsw.WriteLiterally(": boolean")
235
- c.tsw.WriteLine("")
236
-
237
- // Perform type assertion into temporary variables:
238
- // ({ value: _gs_ta_val_, ok: _gs_ta_ok_ } = $.typeAssert<AssertedTypeTS>(expr, "GoTypeStr"));
239
- c.tsw.WriteLiterally("({ value: ")
240
- c.tsw.WriteLiterally(tempValName)
241
- c.tsw.WriteLiterally(", ok: ")
242
- c.tsw.WriteLiterally(tempOkName)
243
- c.tsw.WriteLiterally(" } = $.typeAssert<")
244
- c.WriteTypeExpr(assertedType) // Generic: <AssertedTypeTS>
245
- c.tsw.WriteLiterally(">(")
246
- if err := c.WriteValueExpr(interfaceExpr); err != nil { // Arg1: interfaceExpr
247
- return fmt.Errorf("failed to write interface expression in type assertion call: %w", err)
248
- }
249
- c.tsw.WriteLiterally(", ")
250
- c.writeTypeDescription(assertedType) // Arg2: type info for runtime
251
- c.tsw.WriteLine("))")
252
-
253
- // Assign temporary value to the selector expression:
254
- // s.f = _gs_ta_val_;
255
- if err := c.WriteValueExpr(vLHS); err != nil { // Writes selector expression (e.g., "s.f")
256
- return fmt.Errorf("failed to write LHS selector expression in type assertion: %w", err)
257
- }
258
- c.tsw.WriteLiterally(" = ")
259
- c.tsw.WriteLiterally(tempValName)
260
- c.tsw.WriteLine("")
261
-
262
- // Assign temporary ok to the ok variable (e.g., okName = _gs_ta_ok_; or let okName = ...)
263
- if !okIsBlank {
264
- if okIsSelectorExpr {
265
- // Assign to selector expression
266
- if err := c.WriteValueExpr(okSelectorExpr); err != nil {
267
- return fmt.Errorf("failed to write ok selector expression in type assertion: %w", err)
268
- }
269
- c.tsw.WriteLiterally(" = ")
270
- c.tsw.WriteLiterally(tempOkName)
271
- c.tsw.WriteLine("")
272
- } else {
273
- // Assign to identifier
274
- if okIsNewInDefine { // okIsNewInDefine was determined earlier based on tok == token.DEFINE and Defs check
275
- c.tsw.WriteLiterally("let ")
276
- }
277
- c.tsw.WriteLiterally(okIdent.Name)
278
- c.tsw.WriteLiterally(" = ")
279
- c.tsw.WriteLiterally(tempOkName)
280
- c.tsw.WriteLine("")
281
- }
282
- }
283
-
284
- case *ast.IndexExpr:
285
- // Handle slice[index], ok := expr.(Type) or map[key], ok := expr.(Type)
286
- // Use unique temporary variable names to avoid redeclaration
287
- tempValName := fmt.Sprintf("_gs_ta_val_%s", c.getDeterministicID(vLHS.Pos())) // Unique name based on deterministic position
288
- tempOkName := fmt.Sprintf("_gs_ta_ok_%s", c.getDeterministicID(vLHS.Pos())) // Unique name based on deterministic position
289
-
290
- // Declare temporary variables:
291
- // let _gs_ta_val_N_: AssertedTypeTS;
292
- c.tsw.WriteLiterally("let ")
293
- c.tsw.WriteLiterally(tempValName)
294
- c.tsw.WriteLiterally(": ")
295
- c.WriteTypeExpr(assertedType) // TypeScript type for assertedType
296
- c.tsw.WriteLine("")
297
-
298
- // let _gs_ta_ok_N_: boolean;
299
- c.tsw.WriteLiterally("let ")
300
- c.tsw.WriteLiterally(tempOkName)
301
- c.tsw.WriteLiterally(": boolean")
302
- c.tsw.WriteLine("")
303
-
304
- // Perform type assertion into temporary variables:
305
- // ({ value: _gs_ta_val_N_, ok: _gs_ta_ok_N_ } = $.typeAssert<AssertedTypeTS>(expr, "GoTypeStr"));
306
- c.tsw.WriteLiterally("({ value: ")
307
- c.tsw.WriteLiterally(tempValName)
308
- c.tsw.WriteLiterally(", ok: ")
309
- c.tsw.WriteLiterally(tempOkName)
310
- c.tsw.WriteLiterally(" } = $.typeAssert<")
311
- c.WriteTypeExpr(assertedType) // Generic: <AssertedTypeTS>
312
- c.tsw.WriteLiterally(">(")
313
- if err := c.WriteValueExpr(interfaceExpr); err != nil { // Arg1: interfaceExpr
314
- return fmt.Errorf("failed to write interface expression in type assertion call: %w", err)
315
- }
316
- c.tsw.WriteLiterally(", ")
317
- c.writeTypeDescription(assertedType) // Arg2: type info for runtime
318
- c.tsw.WriteLine("))")
319
-
320
- // Check if this is a map assignment and handle it specially
321
- if tv, ok := c.pkg.TypesInfo.Types[vLHS.X]; ok {
322
- if _, isMap := tv.Type.Underlying().(*types.Map); isMap {
323
- // Map assignment: use $.mapSet(map, key, value)
324
- c.tsw.WriteLiterally("$.mapSet(")
325
- if err := c.WriteValueExpr(vLHS.X); err != nil { // Map
326
- return fmt.Errorf("failed to write map expression in type assertion: %w", err)
327
- }
328
- c.tsw.WriteLiterally(", ")
329
- if err := c.WriteValueExpr(vLHS.Index); err != nil { // Key
330
- return fmt.Errorf("failed to write map key expression in type assertion: %w", err)
331
- }
332
- c.tsw.WriteLiterally(", ")
333
- c.tsw.WriteLiterally(tempValName) // Value
334
- c.tsw.WriteLine(")")
335
- } else {
336
- // Array/slice assignment: use direct assignment
337
- // slice[index] = _gs_ta_val_N_;
338
- if err := c.WriteValueExpr(vLHS.X); err != nil { // Array/slice
339
- return fmt.Errorf("failed to write array/slice expression in type assertion: %w", err)
340
- }
341
- c.tsw.WriteLiterally("![") // Non-null assertion
342
- if err := c.WriteValueExpr(vLHS.Index); err != nil { // Index
343
- return fmt.Errorf("failed to write array/slice index expression in type assertion: %w", err)
344
- }
345
- c.tsw.WriteLiterally("] = ")
346
- c.tsw.WriteLiterally(tempValName)
347
- c.tsw.WriteLine("")
348
- }
349
- } else {
350
- // Fallback: try direct assignment (might fail for maps)
351
- if err := c.WriteValueExpr(vLHS); err != nil { // Writes indexed expression
352
- return fmt.Errorf("failed to write LHS indexed expression in type assertion: %w", err)
353
- }
354
- c.tsw.WriteLiterally(" = ")
355
- c.tsw.WriteLiterally(tempValName)
356
- c.tsw.WriteLine("")
357
- }
358
-
359
- // Assign temporary ok to the ok variable (e.g., okName = _gs_ta_ok_N_; or let okName = ...)
360
- if !okIsBlank {
361
- if okIsSelectorExpr {
362
- // Assign to selector expression
363
- if err := c.WriteValueExpr(okSelectorExpr); err != nil {
364
- return fmt.Errorf("failed to write ok selector expression in type assertion: %w", err)
365
- }
366
- c.tsw.WriteLiterally(" = ")
367
- c.tsw.WriteLiterally(tempOkName)
368
- c.tsw.WriteLine("")
369
- } else {
370
- // Assign to identifier
371
- if okIsNewInDefine { // okIsNewInDefine was determined earlier based on tok == token.DEFINE and Defs check
372
- c.tsw.WriteLiterally("let ")
373
- }
374
- c.tsw.WriteLiterally(okIdent.Name)
375
- c.tsw.WriteLiterally(" = ")
376
- c.tsw.WriteLiterally(tempOkName)
377
- c.tsw.WriteLine("")
378
- }
379
- }
380
-
381
- default:
382
- return fmt.Errorf("unhandled LHS expression type for value in type assertion: %T", valueExpr)
383
- }
384
-
385
- return nil
386
- }
@@ -1,156 +0,0 @@
1
- package compiler
2
-
3
- import "go/types"
4
-
5
- func qualifiedTypeName(namedType *types.Named) string {
6
- if namedType == nil || namedType.Obj() == nil {
7
- return ""
8
- }
9
-
10
- typeName := namedType.Obj().Name()
11
- if pkg := namedType.Obj().Pkg(); pkg != nil {
12
- switch {
13
- case pkg.Name() == "main":
14
- typeName = "main." + typeName
15
- case pkg.Path() != "":
16
- typeName = pkg.Path() + "." + typeName
17
- }
18
- }
19
- return typeName
20
- }
21
-
22
- // writeTypeInfoObject writes a TypeScript TypeInfo object literal for a given Go type.
23
- func (c *GoToTSCompiler) writeTypeInfoObject(typ types.Type) {
24
- if typ == nil {
25
- c.tsw.WriteLiterally("{ kind: $.TypeKind.Basic, name: 'any' }") // Or handle as error
26
- return
27
- }
28
-
29
- // If typ is a *types.Named, handle it by reference to break recursion.
30
- if namedType, ok := typ.(*types.Named); ok {
31
- if namedType.Obj().Name() == "error" && namedType.Obj().Pkg() == nil { // Check for builtin error
32
- c.tsw.WriteLiterally("{ kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] }")
33
- } else {
34
- // For all other named types, output their name as a string literal.
35
- // This relies on the type being registered elsewhere (e.g., via registerStructType or registerInterfaceType)
36
- // so the TypeScript runtime can resolve the reference.
37
- c.tsw.WriteLiterallyf("%q", qualifiedTypeName(namedType))
38
- }
39
- return // Return after handling the named type by reference.
40
- }
41
-
42
- // If typ is not *types.Named, process its underlying structure.
43
- underlying := typ.Underlying()
44
- switch t := underlying.(type) {
45
- case *types.Basic:
46
- // Use Go type name (e.g., "int") not TypeScript type name (e.g., "number")
47
- // The reflect system needs Go type names to correctly determine Kind()
48
- c.tsw.WriteLiterallyf("{ kind: $.TypeKind.Basic, name: %q }", t.Name())
49
- // Note: The original 'case *types.Named:' here for 'underlying' is intentionally omitted.
50
- // If typ.Underlying() is *types.Named (e.g. type T1 MyInt; type T2 T1;),
51
- // then writeTypeInfoObject(typ.Underlying()) would be called in some contexts,
52
- // and that call would handle it via the top-level *types.Named check.
53
- case *types.Pointer:
54
- c.tsw.WriteLiterally("{ kind: $.TypeKind.Pointer, elemType: ")
55
- c.writeTypeInfoObject(t.Elem()) // Recursive call
56
- c.tsw.WriteLiterally(" }")
57
- case *types.Slice:
58
- c.tsw.WriteLiterally("{ kind: $.TypeKind.Slice, elemType: ")
59
- c.writeTypeInfoObject(t.Elem()) // Recursive call
60
- c.tsw.WriteLiterally(" }")
61
- case *types.Array:
62
- c.tsw.WriteLiterallyf("{ kind: $.TypeKind.Array, length: %d, elemType: ", t.Len())
63
- c.writeTypeInfoObject(t.Elem()) // Recursive call
64
- c.tsw.WriteLiterally(" }")
65
- case *types.Map:
66
- c.tsw.WriteLiterally("{ kind: $.TypeKind.Map, keyType: ")
67
- c.writeTypeInfoObject(t.Key()) // Recursive call
68
- c.tsw.WriteLiterally(", elemType: ")
69
- c.writeTypeInfoObject(t.Elem()) // Recursive call
70
- c.tsw.WriteLiterally(" }")
71
- case *types.Chan:
72
- dir := "both"
73
- if t.Dir() == types.SendOnly {
74
- dir = "send"
75
- } else if t.Dir() == types.RecvOnly {
76
- dir = "receive"
77
- }
78
- c.tsw.WriteLiterallyf("{ kind: $.TypeKind.Channel, direction: %q, elemType: ", dir)
79
- c.writeTypeInfoObject(t.Elem()) // Recursive call
80
- c.tsw.WriteLiterally(" }")
81
- case *types.Interface: // Anonymous interface or underlying of a non-named type alias
82
- c.tsw.WriteLiterally("{ kind: $.TypeKind.Interface, methods: [")
83
- var methods []*types.Func
84
- for method := range t.ExplicitMethods() {
85
- methods = append(methods, method)
86
- }
87
- // TODO: Handle embedded methods for anonymous interfaces if needed.
88
- c.writeMethodSignatures(methods) // Calls writeMethodSignatures -> writeTypeInfoObject
89
- c.tsw.WriteLiterally("] }")
90
- case *types.Signature: // Anonymous func type or underlying of a non-named type alias
91
- c.tsw.WriteLiterally("{ kind: $.TypeKind.Function, params: [")
92
- for i := 0; i < t.Params().Len(); i++ {
93
- if i > 0 {
94
- c.tsw.WriteLiterally(", ")
95
- }
96
- c.writeTypeInfoObject(t.Params().At(i).Type()) // Recursive call
97
- }
98
- c.tsw.WriteLiterally("], results: [")
99
- for i := 0; i < t.Results().Len(); i++ {
100
- if i > 0 {
101
- c.tsw.WriteLiterally(", ")
102
- }
103
- c.writeTypeInfoObject(t.Results().At(i).Type()) // Recursive call
104
- }
105
- c.tsw.WriteLiterally("] }")
106
- case *types.Struct: // Anonymous struct or underlying of a non-named type alias
107
- c.tsw.WriteLiterally("{ kind: $.TypeKind.Struct, fields: {")
108
- for i := 0; i < t.NumFields(); i++ {
109
- if i > 0 {
110
- c.tsw.WriteLiterally(", ")
111
- }
112
- field := t.Field(i)
113
- c.tsw.WriteLiterallyf("%q: ", field.Name())
114
- c.writeTypeInfoObject(field.Type()) // Recursive call
115
- }
116
- c.tsw.WriteLiterally("}, methods: [] }") // Anonymous structs don't have methods in this context
117
- default:
118
- // Fallback, e.g. for types whose underlying isn't one of the above like *types.Tuple or other complex cases.
119
- c.tsw.WriteLiterallyf("{ kind: $.TypeKind.Basic, name: %q }", typ.String()) // Fallback using the type's string representation
120
- }
121
- }
122
-
123
- // writeMethodSignatures writes an array of TypeScript MethodSignature objects.
124
- func (c *GoToTSCompiler) writeMethodSignatures(methods []*types.Func) {
125
- firstMethod := true
126
- for _, method := range methods {
127
- if !firstMethod {
128
- c.tsw.WriteLiterally(", ")
129
- }
130
- firstMethod = false
131
-
132
- sig := method.Type().(*types.Signature)
133
- c.tsw.WriteLiterallyf("{ name: %q, args: [", method.Name())
134
- for i := 0; i < sig.Params().Len(); i++ {
135
- if i > 0 {
136
- c.tsw.WriteLiterally(", ")
137
- }
138
- param := sig.Params().At(i)
139
- c.tsw.WriteLiterallyf("{ name: %q, type: ", param.Name())
140
- c.writeTypeInfoObject(param.Type())
141
- c.tsw.WriteLiterally(" }")
142
- }
143
- c.tsw.WriteLiterally("], returns: [")
144
- for i := 0; i < sig.Results().Len(); i++ {
145
- if i > 0 {
146
- c.tsw.WriteLiterally(", ")
147
- }
148
- result := sig.Results().At(i)
149
- // Return parameters in Go often don't have names that are relevant for TS signature matching
150
- c.tsw.WriteLiterally("{ type: ")
151
- c.writeTypeInfoObject(result.Type())
152
- c.tsw.WriteLiterally(" }")
153
- }
154
- c.tsw.WriteLiterally("] }")
155
- }
156
- }