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.
- package/README.md +13 -1
- package/cmd/goscript/cmd_compile.go +70 -69
- package/cmd/goscript/cmd_compile_test.go +79 -0
- package/cmd/goscript/main.go +10 -5
- package/compiler/compile-request.go +218 -0
- package/compiler/compiler.go +16 -1336
- package/compiler/compliance_test.go +196 -0
- package/compiler/config.go +6 -13
- package/compiler/diagnostic.go +70 -0
- package/compiler/index.test.ts +28 -28
- package/compiler/index.ts +40 -72
- package/compiler/lowered-program.go +132 -0
- package/compiler/lowering.go +3576 -0
- package/compiler/override-registry.go +422 -0
- package/compiler/override-registry_test.go +207 -0
- package/compiler/package-graph.go +231 -0
- package/compiler/package-graph_test.go +281 -0
- package/compiler/result.go +13 -0
- package/compiler/runtime-contract.go +279 -0
- package/compiler/runtime-contract_test.go +90 -0
- package/compiler/semantic-model-types.go +110 -0
- package/compiler/semantic-model.go +922 -0
- package/compiler/semantic-model_test.go +416 -0
- package/compiler/service.go +133 -0
- package/compiler/skeleton_test.go +1145 -0
- package/compiler/typescript-emitter.go +663 -0
- package/compiler/wasm/compile.go +2 -3
- package/compiler/wasm/compile_test.go +29 -0
- package/compiler/wasm_api.go +10 -159
- package/dist/compiler/index.d.ts +1 -3
- package/dist/compiler/index.js +31 -55
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/builtin/builtin.d.ts +13 -0
- package/dist/gs/builtin/builtin.js +23 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.d.ts +3 -3
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +15 -1
- package/dist/gs/builtin/hostio.js +134 -49
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/index.d.ts +1 -0
- package/dist/gs/builtin/index.js +1 -0
- package/dist/gs/builtin/index.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +1 -1
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +11 -0
- package/dist/gs/builtin/type.js +55 -1
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/crypto/rand/index.d.ts +5 -0
- package/dist/gs/crypto/rand/index.js +77 -0
- package/dist/gs/crypto/rand/index.js.map +1 -0
- package/dist/gs/encoding/json/index.d.ts +3 -0
- package/dist/gs/encoding/json/index.js +160 -0
- package/dist/gs/encoding/json/index.js.map +1 -0
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
- package/dist/gs/go/scanner/index.d.ts +29 -0
- package/dist/gs/go/scanner/index.js +120 -0
- package/dist/gs/go/scanner/index.js.map +1 -0
- package/dist/gs/go/token/index.d.ts +31 -0
- package/dist/gs/go/token/index.js +82 -0
- package/dist/gs/go/token/index.js.map +1 -0
- package/dist/gs/internal/abi/index.js.map +1 -1
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/readfile.js.map +1 -1
- package/dist/gs/io/fs/stat.js.map +1 -1
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/error.gs.js +2 -4
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/rawconn_js.gs.js.map +1 -1
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/tempfile.gs.js +66 -9
- package/dist/gs/os/tempfile.gs.js.map +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.js +9 -9
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/match.js.map +1 -1
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +2 -2
- package/dist/gs/reflect/index.js +1 -1
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +2 -1
- package/dist/gs/reflect/type.js +85 -14
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/sort/sort.gs.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/quote.gs.js.map +1 -1
- package/dist/gs/strings/builder.js.map +1 -1
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/atomic/value.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +1 -0
- package/dist/gs/sync/sync.js +12 -0
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/go.mod +2 -2
- package/gs/builtin/builtin.ts +27 -0
- package/gs/builtin/hostio.test.ts +177 -0
- package/gs/builtin/hostio.ts +171 -56
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/runtime-contract.test.ts +230 -0
- package/gs/builtin/type.ts +84 -1
- package/gs/crypto/rand/index.test.ts +32 -0
- package/gs/crypto/rand/index.ts +90 -0
- package/gs/crypto/rand/meta.json +5 -0
- package/gs/encoding/json/index.test.ts +65 -0
- package/gs/encoding/json/index.ts +186 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +23 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +3 -1
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/meta.json +3 -1
- package/gs/go/scanner/index.test.ts +50 -0
- package/gs/go/scanner/index.ts +157 -0
- package/gs/go/token/index.test.ts +21 -0
- package/gs/go/token/index.ts +120 -0
- package/gs/os/file_unix_js.test.ts +50 -0
- package/gs/os/meta.json +1 -2
- package/gs/os/tempfile.gs.test.ts +85 -0
- package/gs/os/tempfile.gs.ts +71 -11
- package/gs/os/types_js.gs.ts +9 -9
- package/gs/reflect/index.ts +1 -1
- package/gs/reflect/type.ts +106 -17
- package/gs/reflect/typefor.test.ts +75 -0
- package/gs/sync/sync.test.ts +24 -0
- package/gs/sync/sync.ts +12 -0
- package/package.json +13 -13
- package/compiler/analysis.go +0 -3475
- package/compiler/analysis_test.go +0 -338
- package/compiler/assignment.go +0 -580
- package/compiler/builtin_test.go +0 -92
- package/compiler/code-writer.go +0 -115
- package/compiler/compiler_test.go +0 -149
- package/compiler/composite-lit.go +0 -779
- package/compiler/config_test.go +0 -62
- package/compiler/constraint.go +0 -86
- package/compiler/decl.go +0 -801
- package/compiler/expr-call-async.go +0 -188
- package/compiler/expr-call-builtins.go +0 -208
- package/compiler/expr-call-helpers.go +0 -382
- package/compiler/expr-call-make.go +0 -318
- package/compiler/expr-call-type-conversion.go +0 -520
- package/compiler/expr-call.go +0 -413
- package/compiler/expr-selector.go +0 -343
- package/compiler/expr-star.go +0 -82
- package/compiler/expr-type.go +0 -442
- package/compiler/expr-value.go +0 -89
- package/compiler/expr.go +0 -773
- package/compiler/field.go +0 -183
- package/compiler/gs_dependencies_test.go +0 -298
- package/compiler/lit.go +0 -322
- package/compiler/output.go +0 -72
- package/compiler/primitive.go +0 -149
- package/compiler/protobuf.go +0 -697
- package/compiler/sanitize.go +0 -100
- package/compiler/spec-struct.go +0 -995
- package/compiler/spec-value.go +0 -540
- package/compiler/spec.go +0 -725
- package/compiler/stmt-assign.go +0 -664
- package/compiler/stmt-for.go +0 -266
- package/compiler/stmt-range.go +0 -475
- package/compiler/stmt-select.go +0 -262
- package/compiler/stmt-type-switch.go +0 -147
- package/compiler/stmt.go +0 -1308
- package/compiler/type-assert.go +0 -386
- package/compiler/type-info.go +0 -156
- package/compiler/type-utils.go +0 -207
- 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
|
-
}
|
package/compiler/expr-star.go
DELETED
|
@@ -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
|
-
}
|