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
package/compiler/type-assert.go
DELETED
|
@@ -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
|
-
}
|
package/compiler/type-info.go
DELETED
|
@@ -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
|
-
}
|