goscript 0.0.83 → 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 (197) 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 +27 -7
  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 +86 -0
  39. package/dist/gs/builtin/hostio.js +266 -0
  40. package/dist/gs/builtin/hostio.js.map +1 -0
  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/print.d.ts +8 -0
  45. package/dist/gs/builtin/print.js +111 -0
  46. package/dist/gs/builtin/print.js.map +1 -0
  47. package/dist/gs/builtin/slice.d.ts +1 -1
  48. package/dist/gs/builtin/slice.js.map +1 -1
  49. package/dist/gs/builtin/type.d.ts +11 -0
  50. package/dist/gs/builtin/type.js +55 -1
  51. package/dist/gs/builtin/type.js.map +1 -1
  52. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  53. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  54. package/dist/gs/bytes/reader.gs.js.map +1 -1
  55. package/dist/gs/context/context.js.map +1 -1
  56. package/dist/gs/crypto/rand/index.d.ts +5 -0
  57. package/dist/gs/crypto/rand/index.js +77 -0
  58. package/dist/gs/crypto/rand/index.js.map +1 -0
  59. package/dist/gs/encoding/json/index.d.ts +3 -0
  60. package/dist/gs/encoding/json/index.js +160 -0
  61. package/dist/gs/encoding/json/index.js.map +1 -0
  62. package/dist/gs/fmt/fmt.js +2 -22
  63. package/dist/gs/fmt/fmt.js.map +1 -1
  64. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -1
  65. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +1 -1
  66. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  67. package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
  68. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  69. package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
  70. package/dist/gs/go/scanner/index.d.ts +29 -0
  71. package/dist/gs/go/scanner/index.js +120 -0
  72. package/dist/gs/go/scanner/index.js.map +1 -0
  73. package/dist/gs/go/token/index.d.ts +31 -0
  74. package/dist/gs/go/token/index.js +82 -0
  75. package/dist/gs/go/token/index.js.map +1 -0
  76. package/dist/gs/internal/abi/index.js.map +1 -1
  77. package/dist/gs/io/fs/fs.js.map +1 -1
  78. package/dist/gs/io/fs/readdir.js.map +1 -1
  79. package/dist/gs/io/fs/readfile.js.map +1 -1
  80. package/dist/gs/io/fs/stat.js.map +1 -1
  81. package/dist/gs/io/fs/sub.js.map +1 -1
  82. package/dist/gs/io/io.js.map +1 -1
  83. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  84. package/dist/gs/os/error.gs.js +2 -4
  85. package/dist/gs/os/error.gs.js.map +1 -1
  86. package/dist/gs/os/exec.gs.js.map +1 -1
  87. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  88. package/dist/gs/os/rawconn_js.gs.js.map +1 -1
  89. package/dist/gs/os/root_js.gs.js.map +1 -1
  90. package/dist/gs/os/tempfile.gs.js +66 -9
  91. package/dist/gs/os/tempfile.gs.js.map +1 -1
  92. package/dist/gs/os/types.gs.js.map +1 -1
  93. package/dist/gs/os/types_js.gs.d.ts +2 -51
  94. package/dist/gs/os/types_js.gs.js +67 -105
  95. package/dist/gs/os/types_js.gs.js.map +1 -1
  96. package/dist/gs/os/types_unix.gs.js.map +1 -1
  97. package/dist/gs/path/filepath/match.js.map +1 -1
  98. package/dist/gs/path/match.js.map +1 -1
  99. package/dist/gs/path/path.js.map +1 -1
  100. package/dist/gs/reflect/index.d.ts +2 -2
  101. package/dist/gs/reflect/index.js +1 -1
  102. package/dist/gs/reflect/index.js.map +1 -1
  103. package/dist/gs/reflect/map.js.map +1 -1
  104. package/dist/gs/reflect/type.d.ts +2 -1
  105. package/dist/gs/reflect/type.js +85 -14
  106. package/dist/gs/reflect/type.js.map +1 -1
  107. package/dist/gs/reflect/types.js.map +1 -1
  108. package/dist/gs/reflect/visiblefields.js.map +1 -1
  109. package/dist/gs/runtime/runtime.js.map +1 -1
  110. package/dist/gs/sort/sort.gs.js.map +1 -1
  111. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  112. package/dist/gs/strconv/quote.gs.js.map +1 -1
  113. package/dist/gs/strings/builder.js.map +1 -1
  114. package/dist/gs/strings/reader.js.map +1 -1
  115. package/dist/gs/strings/replace.js.map +1 -1
  116. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  117. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  118. package/dist/gs/sync/sync.d.ts +1 -0
  119. package/dist/gs/sync/sync.js +12 -0
  120. package/dist/gs/sync/sync.js.map +1 -1
  121. package/dist/gs/time/time.js.map +1 -1
  122. package/dist/gs/unicode/unicode.js.map +1 -1
  123. package/go.mod +2 -2
  124. package/gs/builtin/builtin.ts +31 -6
  125. package/gs/builtin/hostio.test.ts +246 -0
  126. package/gs/builtin/hostio.ts +413 -0
  127. package/gs/builtin/index.ts +1 -0
  128. package/gs/builtin/print.test.ts +48 -0
  129. package/gs/builtin/print.ts +154 -0
  130. package/gs/builtin/runtime-contract.test.ts +230 -0
  131. package/gs/builtin/type.ts +84 -1
  132. package/gs/crypto/rand/index.test.ts +32 -0
  133. package/gs/crypto/rand/index.ts +90 -0
  134. package/gs/crypto/rand/meta.json +5 -0
  135. package/gs/encoding/json/index.test.ts +65 -0
  136. package/gs/encoding/json/index.ts +186 -0
  137. package/gs/fmt/fmt.test.ts +41 -30
  138. package/gs/fmt/fmt.ts +2 -22
  139. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +23 -0
  140. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +3 -1
  141. package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/meta.json +3 -1
  142. package/gs/go/scanner/index.test.ts +50 -0
  143. package/gs/go/scanner/index.ts +157 -0
  144. package/gs/go/token/index.test.ts +21 -0
  145. package/gs/go/token/index.ts +120 -0
  146. package/gs/os/file_unix_js.test.ts +103 -0
  147. package/gs/os/meta.json +1 -2
  148. package/gs/os/tempfile.gs.test.ts +85 -0
  149. package/gs/os/tempfile.gs.ts +71 -11
  150. package/gs/os/types_js.gs.ts +74 -153
  151. package/gs/reflect/index.ts +1 -1
  152. package/gs/reflect/type.ts +106 -17
  153. package/gs/reflect/typefor.test.ts +75 -0
  154. package/gs/sync/sync.test.ts +24 -0
  155. package/gs/sync/sync.ts +12 -0
  156. package/package.json +13 -13
  157. package/compiler/analysis.go +0 -3475
  158. package/compiler/analysis_test.go +0 -338
  159. package/compiler/assignment.go +0 -580
  160. package/compiler/builtin_test.go +0 -92
  161. package/compiler/code-writer.go +0 -115
  162. package/compiler/compiler_test.go +0 -149
  163. package/compiler/composite-lit.go +0 -779
  164. package/compiler/config_test.go +0 -62
  165. package/compiler/constraint.go +0 -86
  166. package/compiler/decl.go +0 -801
  167. package/compiler/expr-call-async.go +0 -188
  168. package/compiler/expr-call-builtins.go +0 -208
  169. package/compiler/expr-call-helpers.go +0 -382
  170. package/compiler/expr-call-make.go +0 -318
  171. package/compiler/expr-call-type-conversion.go +0 -520
  172. package/compiler/expr-call.go +0 -413
  173. package/compiler/expr-selector.go +0 -343
  174. package/compiler/expr-star.go +0 -82
  175. package/compiler/expr-type.go +0 -442
  176. package/compiler/expr-value.go +0 -89
  177. package/compiler/expr.go +0 -773
  178. package/compiler/field.go +0 -183
  179. package/compiler/gs_dependencies_test.go +0 -298
  180. package/compiler/lit.go +0 -322
  181. package/compiler/output.go +0 -72
  182. package/compiler/primitive.go +0 -149
  183. package/compiler/protobuf.go +0 -697
  184. package/compiler/sanitize.go +0 -100
  185. package/compiler/spec-struct.go +0 -995
  186. package/compiler/spec-value.go +0 -540
  187. package/compiler/spec.go +0 -725
  188. package/compiler/stmt-assign.go +0 -664
  189. package/compiler/stmt-for.go +0 -266
  190. package/compiler/stmt-range.go +0 -475
  191. package/compiler/stmt-select.go +0 -262
  192. package/compiler/stmt-type-switch.go +0 -147
  193. package/compiler/stmt.go +0 -1308
  194. package/compiler/type-assert.go +0 -386
  195. package/compiler/type-info.go +0 -156
  196. package/compiler/type-utils.go +0 -207
  197. package/compiler/type.go +0 -892
@@ -1,343 +0,0 @@
1
- package compiler
2
-
3
- import (
4
- "fmt"
5
- "go/ast"
6
- "go/types"
7
- )
8
-
9
- // WriteSelectorExpr translates a Go selector expression (`ast.SelectorExpr`)
10
- // used as a value (e.g., `obj.Field`, `pkg.Variable`, `structVar.Method()`)
11
- // into its TypeScript equivalent.
12
- // It distinguishes between package selectors (e.g., `time.Now`) and field/method
13
- // access on an object or struct.
14
- // - For package selectors, it writes `PackageName.IdentifierName`. The `IdentifierName`
15
- // is written using `WriteIdent` which handles potential `.value` access if the
16
- // package-level variable is varrefed.
17
- // - For field or method access on an object (`exp.X`), it first writes the base
18
- // expression (`exp.X`) using `WriteValueExpr` (which handles its own varRefing).
19
- // Then, it writes a dot (`.`) followed by the selected identifier (`exp.Sel`)
20
- // using `WriteIdent`, which appends `.value` if the field itself is varrefed
21
- // (e.g., accessing a field of primitive type through a pointer to a struct
22
- // where the field's address might have been taken).
23
- //
24
- // This function aims to correctly navigate Go's automatic dereferencing and
25
- // TypeScript's explicit varRefing model.
26
- func (c *GoToTSCompiler) WriteSelectorExpr(exp *ast.SelectorExpr) error {
27
- // Check if this is a package selector (e.g., time.Now)
28
- if pkgIdent, isPkgIdent := exp.X.(*ast.Ident); isPkgIdent {
29
- if obj := c.pkg.TypesInfo.ObjectOf(pkgIdent); obj != nil {
30
- if pkgName, isPkg := obj.(*types.PkgName); isPkg {
31
- // Package selectors should never use .value on the package name
32
- c.tsw.WriteLiterally(pkgIdent.Name)
33
- c.tsw.WriteLiterally(".")
34
-
35
- // Special case: reflect.Pointer should be translated to reflect.Ptr
36
- // (Go has both names for the same Kind constant)
37
- if pkgName.Imported().Path() == "reflect" && exp.Sel.Name == "Pointer" {
38
- c.tsw.WriteLiterally("Ptr")
39
- return nil
40
- }
41
-
42
- // Write the selected identifier, allowing .value if it's a varrefed package variable
43
- c.WriteIdent(exp.Sel, true)
44
- return nil
45
- }
46
- }
47
- }
48
-
49
- // Check if this is a method value (method being used as a value, not called immediately)
50
- if c.analysis.IsMethodValue(exp) {
51
- // This is a method value - we need to bind it properly
52
- if selection := c.pkg.TypesInfo.Selections[exp]; selection != nil {
53
- return c.writeMethodValue(exp, selection)
54
- }
55
- }
56
-
57
- // --- Special case for dereferenced pointer to struct with field access: (*p).field or (**p).field etc ---
58
- var baseExpr ast.Expr = exp.X
59
- // Look inside parentheses if present
60
- if parenExpr, isParen := exp.X.(*ast.ParenExpr); isParen {
61
- baseExpr = parenExpr.X
62
- }
63
-
64
- // Check if we have one or more star expressions (dereferences)
65
- if starExpr, isStarExpr := baseExpr.(*ast.StarExpr); isStarExpr {
66
- // Count the levels of dereference and find the innermost expression
67
- dereferenceCount := 0
68
- currentExpr := baseExpr
69
- for {
70
- if star, ok := currentExpr.(*ast.StarExpr); ok {
71
- dereferenceCount++
72
- currentExpr = star.X
73
- } else {
74
- break
75
- }
76
- }
77
-
78
- // Get the type of the innermost expression (the pointer variable)
79
- innerType := c.pkg.TypesInfo.TypeOf(currentExpr)
80
- if innerType != nil {
81
- // Check if after all dereferences we end up with a struct
82
- finalType := innerType
83
- for i := 0; i < dereferenceCount; i++ {
84
- if ptrType, ok := finalType.(*types.Pointer); ok {
85
- finalType = ptrType.Elem()
86
- } else {
87
- break
88
- }
89
- }
90
-
91
- // If the final type is a struct, handle field access specially
92
- if _, isStruct := finalType.Underlying().(*types.Struct); isStruct {
93
- // Write the fully dereferenced expression
94
- if err := c.WriteValueExpr(starExpr); err != nil {
95
- return fmt.Errorf("failed to write dereferenced expression for field access: %w", err)
96
- }
97
-
98
- // Check if we need an extra .value for varrefed struct access
99
- // This happens when the struct being pointed to is varrefed
100
- needsExtraValue := false
101
- if ident, ok := currentExpr.(*ast.Ident); ok {
102
- if obj := c.pkg.TypesInfo.ObjectOf(ident); obj != nil {
103
- // Check if after dereferencing, we get a varrefed struct
104
- ptrType := obj.Type()
105
- for i := 0; i < dereferenceCount; i++ {
106
- if ptr, ok := ptrType.(*types.Pointer); ok {
107
- ptrType = ptr.Elem()
108
- }
109
- }
110
- // If the final pointed-to type suggests the struct is varrefed
111
- // (i.e., the dereference operation results in VarRef<Struct>)
112
- if c.analysis.NeedsVarRefAccess(obj) {
113
- needsExtraValue = true
114
- }
115
- }
116
- }
117
-
118
- if needsExtraValue {
119
- c.tsw.WriteLiterally("!.value")
120
- }
121
-
122
- // Add .field
123
- c.tsw.WriteLiterally(".")
124
- c.WriteIdent(exp.Sel, false) // Don't add .value to the field itself
125
- return nil
126
- }
127
- }
128
- }
129
- // --- End Special Case ---
130
-
131
- // Fallback / Normal Case (e.g., obj.Field, pkg.Var, method calls)
132
- // WriteValueExpr handles adding .value for the base variable itself if it's varrefed.
133
-
134
- // Check if the base expression is an async call - if so, we need to wrap it in parentheses
135
- // so that await binds correctly: (await asyncFn()).method instead of await asyncFn().method
136
- needsParensForAsync := false
137
- if callExpr, isCall := exp.X.(*ast.CallExpr); isCall && c.isCallExprAsync(callExpr) {
138
- needsParensForAsync = true
139
- c.tsw.WriteLiterally("(")
140
- }
141
-
142
- if err := c.WriteValueExpr(exp.X); err != nil {
143
- return fmt.Errorf("failed to write selector base expression: %w", err)
144
- }
145
-
146
- if needsParensForAsync {
147
- c.tsw.WriteLiterally(")")
148
- }
149
-
150
- // Add null assertion for selector expressions when accessing fields/methods on nullable types
151
- // In Go, accessing fields or calling methods on nil pointers/interfaces panics, so we should throw in TypeScript
152
- baseType := c.pkg.TypesInfo.TypeOf(exp.X)
153
-
154
- // Check if this is a method receiver alias (e.g., `c` in `const c = this`)
155
- // Use proper AST/types analysis instead of heuristics
156
- isMethodReceiverAlias := c.isReceiverAlias(exp.X)
157
-
158
- if baseType != nil && !isMethodReceiverAlias {
159
- // Check if the base is a pointer type
160
- if _, isPtr := baseType.(*types.Pointer); isPtr {
161
- c.tsw.WriteLiterally("!.")
162
- } else if _, isInterface := baseType.Underlying().(*types.Interface); isInterface {
163
- // For interface types, add null assertion since interfaces can be nil
164
- c.tsw.WriteLiterally("!.")
165
- } else if callExpr, isCall := exp.X.(*ast.CallExpr); isCall {
166
- // For function calls that return nullable types, add null assertion
167
- _ = callExpr // Use the variable to avoid unused error
168
- c.tsw.WriteLiterally("!.")
169
- } else {
170
- // Add .
171
- c.tsw.WriteLiterally(".")
172
- }
173
- } else {
174
- // Add . (either baseType is nil or this is a method receiver alias)
175
- c.tsw.WriteLiterally(".")
176
- }
177
-
178
- // Write the field/method name.
179
- // Pass 'false' to WriteIdent to NOT add '.value' for struct fields.
180
- // Struct fields use getters/setters, so we don't want to add .value here.
181
- // The setter will handle the internal .value access.
182
- c.WriteIdent(exp.Sel, false)
183
- return nil
184
- }
185
-
186
- // writeMethodValue handles method values (methods used as values, not called immediately)
187
- // and generates proper binding code to maintain the 'this' context.
188
- func (c *GoToTSCompiler) writeMethodValue(exp *ast.SelectorExpr, selection *types.Selection) error {
189
- // Get the method signature to understand the receiver type
190
- methodObj := selection.Obj().(*types.Func)
191
- sig := methodObj.Type().(*types.Signature)
192
- recv := sig.Recv()
193
-
194
- if recv == nil {
195
- // This shouldn't happen for method values, but handle gracefully
196
- return fmt.Errorf("method value has no receiver: %s", methodObj.Name())
197
- }
198
-
199
- // Determine if this is a pointer receiver or value receiver
200
- recvType := recv.Type()
201
- isPointerReceiver := false
202
- if _, ok := recvType.(*types.Pointer); ok {
203
- isPointerReceiver = true
204
- }
205
-
206
- // Get the base expression type to understand what we're working with
207
- baseType := c.pkg.TypesInfo.TypeOf(exp.X)
208
- baseIsPointer := false
209
- if _, ok := baseType.(*types.Pointer); ok {
210
- baseIsPointer = true
211
- }
212
-
213
- // Check if the receiver is a primitive/wrapper type
214
- underlyingRecvType := recvType
215
- if ptr, ok := recvType.(*types.Pointer); ok {
216
- underlyingRecvType = ptr.Elem()
217
- }
218
- isPrimitiveReceiver := c.isWrapperType(underlyingRecvType)
219
-
220
- // For primitive types, generate a closure that captures the receiver and calls the free function
221
- if isPrimitiveReceiver {
222
- // Get the type name for the free function
223
- typeName := c.getQualifiedTypeName(underlyingRecvType)
224
- if typeName == "" {
225
- return fmt.Errorf("failed to get qualified type name for primitive receiver")
226
- }
227
-
228
- // Get the method parameters to forward them
229
- params := sig.Params()
230
- paramNames := make([]string, params.Len())
231
- for i := 0; i < params.Len(); i++ {
232
- paramNames[i] = fmt.Sprintf("_p%d", i)
233
- }
234
-
235
- // Generate: ((_p0: type0, _p1: type1, ...) => TypeName_MethodName(receiverValue, _p0, _p1, ...))
236
- c.tsw.WriteLiterally("((")
237
- for i, name := range paramNames {
238
- if i > 0 {
239
- c.tsw.WriteLiterally(", ")
240
- }
241
- c.tsw.WriteLiterally(name)
242
- c.tsw.WriteLiterally(": ")
243
- c.WriteGoType(params.At(i).Type(), GoTypeContextGeneral)
244
- }
245
- c.tsw.WriteLiterally(") => ")
246
- c.tsw.WriteLiterally(typeName)
247
- c.tsw.WriteLiterally("_")
248
- c.tsw.WriteLiterally(exp.Sel.Name)
249
- c.tsw.WriteLiterally("(")
250
- if err := c.WriteValueExpr(exp.X); err != nil {
251
- return fmt.Errorf("failed to write method value receiver: %w", err)
252
- }
253
- for _, name := range paramNames {
254
- c.tsw.WriteLiterally(", ")
255
- c.tsw.WriteLiterally(name)
256
- }
257
- c.tsw.WriteLiterally("))")
258
-
259
- return nil
260
- }
261
-
262
- // Write the receiver expression
263
- if err := c.WriteValueExpr(exp.X); err != nil {
264
- return fmt.Errorf("failed to write method value receiver: %w", err)
265
- }
266
-
267
- // Add null assertion if needed
268
- if baseIsPointer {
269
- c.tsw.WriteLiterally("!")
270
- }
271
-
272
- // Handle different receiver type combinations according to Go semantics
273
- if isPointerReceiver && !baseIsPointer {
274
- // Pointer receiver method on value type: t.Mp equivalent to (&t).Mp
275
- // The receiver should be the address of the value
276
- c.tsw.WriteLiterally(".")
277
- c.WriteIdent(exp.Sel, false)
278
- c.tsw.WriteLiterally(".bind(")
279
- if err := c.WriteValueExpr(exp.X); err != nil {
280
- return fmt.Errorf("failed to write method value receiver for binding: %w", err)
281
- }
282
- if baseIsPointer {
283
- c.tsw.WriteLiterally("!")
284
- }
285
- c.tsw.WriteLiterally(")")
286
- } else if !isPointerReceiver && baseIsPointer {
287
- // Value receiver method on pointer type: pt.Mv equivalent to (*pt).Mv
288
- // The receiver should be a copy of the dereferenced value
289
- c.tsw.WriteLiterally(".value.")
290
- c.WriteIdent(exp.Sel, false)
291
- c.tsw.WriteLiterally(".bind($.markAsStructValue(")
292
- if err := c.WriteValueExpr(exp.X); err != nil {
293
- return fmt.Errorf("failed to write method value receiver for binding: %w", err)
294
- }
295
- c.tsw.WriteLiterally("!.value.clone()))")
296
- } else if !isPointerReceiver && !baseIsPointer {
297
- // Value receiver method on value type: t.Mv
298
- // The receiver should be a copy of the value
299
- c.tsw.WriteLiterally(".")
300
- c.WriteIdent(exp.Sel, false)
301
- c.tsw.WriteLiterally(".bind($.markAsStructValue(")
302
- if err := c.WriteValueExpr(exp.X); err != nil {
303
- return fmt.Errorf("failed to write method value receiver for binding: %w", err)
304
- }
305
- if baseIsPointer {
306
- c.tsw.WriteLiterally("!")
307
- }
308
- c.tsw.WriteLiterally(".clone()))")
309
- } else {
310
- // Pointer receiver method on pointer type: pt.Mp
311
- // The receiver should be the pointer itself
312
- c.tsw.WriteLiterally(".")
313
- c.WriteIdent(exp.Sel, false)
314
- c.tsw.WriteLiterally(".bind(")
315
- if err := c.WriteValueExpr(exp.X); err != nil {
316
- return fmt.Errorf("failed to write method value receiver for binding: %w", err)
317
- }
318
- if baseIsPointer {
319
- c.tsw.WriteLiterally("!")
320
- }
321
- c.tsw.WriteLiterally(")")
322
- }
323
-
324
- return nil
325
- }
326
-
327
- // isReceiverAlias detects if a variable is likely a receiver alias (e.g., const c = this)
328
- // These variables are guaranteed to be non-null and don't need null assertions
329
- func (c *GoToTSCompiler) isReceiverAlias(expr ast.Expr) bool {
330
- // Only check identifiers - receiver aliases are always identifiers
331
- ident, ok := expr.(*ast.Ident)
332
- if !ok {
333
- return false
334
- }
335
-
336
- // If analysis marked this identifier with a mapping, treat it as a receiver alias
337
- if mapped := c.analysis.GetIdentifierMapping(ident); mapped != "" {
338
- return true
339
- }
340
-
341
- // Fallback conservative behavior
342
- return false
343
- }
@@ -1,82 +0,0 @@
1
- package compiler
2
-
3
- import (
4
- "go/ast"
5
- "go/types"
6
- )
7
-
8
- // WriteStarExpr translates a Go pointer dereference expression (`ast.StarExpr`, e.g., `*p`)
9
- // into its TypeScript equivalent. This involves careful handling of Go's pointers
10
- // and TypeScript's varRefing mechanism for emulating pointer semantics.
11
- //
12
- // The translation depends on whether the pointer variable `p` itself is varrefed and
13
- // what type of value it points to:
14
- // 1. If `p` is not varrefed and points to a primitive or another pointer: `*p` -> `p!.value`.
15
- // (`p` holds a varRef, so dereference accesses its `value` field).
16
- // 2. If `p` is not varrefed and points to a struct: `*p` -> `p!`.
17
- // (`p` holds the struct instance directly; structs are reference types in TS).
18
- // 3. If `p` is variable referenced (i.e., `p` is `$.VarRef<PointerType>`) and points to a primitive/pointer:
19
- // `p.value!.value` (access the variable reference, then dereference the pointer)
20
- // 4. If `p` is varrefed and points to a struct: `p.value!`.
21
- // (First `.value` unvarRefes `p` to get the struct instance).
22
- //
23
- // `WriteValueExpr(operand)` handles the initial unvarRefing of `p` if `p` itself is a varrefed variable.
24
- // A non-null assertion `!` is always added as pointers can be nil.
25
- // The function determines if `.value` access is needed by checking what the Go pointer operand points to.
26
- //
27
- // For multi-level dereferences like `***p`, this function is called recursively, with each level
28
- // adding the appropriate `!.value` suffix.
29
- //
30
- // Examples:
31
- // - Simple pointer to primitive: `p!.value` (where p is *int)
32
- // - Variable referenced pointer to primitive: `p.value!.value` (where p is VarRef<*int>)
33
- // Example: let p = $.varRef(x) (where x is another variable reference) => p.value!.value
34
- // - Pointer to struct: `p!` (where p is *MyStruct)
35
- // Example: let p = $.varRef(new MyStruct()) => p.value!
36
- // - Variable referenced pointer to struct: `p.value!` (where p is VarRef<*MyStruct>)
37
- // - Triple pointer: `p3!.value!.value!.value` (where p3 is VarRef<VarRef<VarRef<number> | null> | null> | null)
38
- func (c *GoToTSCompiler) WriteStarExpr(exp *ast.StarExpr) error {
39
- // Check if the operand is an identifier that is varrefed
40
- isVarrefedIdent := false
41
- if ident, ok := exp.X.(*ast.Ident); ok {
42
- if obj := c.pkg.TypesInfo.ObjectOf(ident); obj != nil {
43
- isVarrefedIdent = c.analysis.NeedsVarRef(obj)
44
- }
45
- }
46
-
47
- // Write the operand
48
- if isVarrefedIdent {
49
- // For varrefed identifiers, we need to access the value first
50
- if err := c.WriteValueExpr(exp.X); err != nil {
51
- return err
52
- }
53
- } else {
54
- // For non-varrefed identifiers and other expressions
55
- switch operand := exp.X.(type) {
56
- case *ast.Ident:
57
- // Write identifier without .value access
58
- c.WriteIdent(operand, false)
59
- default:
60
- // For other expressions (like nested star expressions), use WriteValueExpr
61
- if err := c.WriteValueExpr(exp.X); err != nil {
62
- return err
63
- }
64
- }
65
- }
66
-
67
- // Add non-null assertion for pointer safety
68
- c.tsw.WriteLiterally("!")
69
-
70
- // Check what the operand points to (not what the result is)
71
- operandType := c.pkg.TypesInfo.TypeOf(exp.X)
72
- if ptrType, isPtr := operandType.(*types.Pointer); isPtr {
73
- elemType := ptrType.Elem()
74
- // Only add .value if NOT pointing to a struct
75
- if _, isStruct := elemType.Underlying().(*types.Struct); !isStruct {
76
- c.tsw.WriteLiterally(".value")
77
- }
78
- // If pointing to a struct, don't add .value (structs are reference types in TS)
79
- }
80
-
81
- return nil
82
- }