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.
- 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 +27 -7
- 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 +86 -0
- package/dist/gs/builtin/hostio.js +266 -0
- package/dist/gs/builtin/hostio.js.map +1 -0
- 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/print.d.ts +8 -0
- package/dist/gs/builtin/print.js +111 -0
- package/dist/gs/builtin/print.js.map +1 -0
- 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 +2 -22
- 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.d.ts +2 -51
- package/dist/gs/os/types_js.gs.js +67 -105
- 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 +31 -6
- package/gs/builtin/hostio.test.ts +246 -0
- package/gs/builtin/hostio.ts +413 -0
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/print.test.ts +48 -0
- package/gs/builtin/print.ts +154 -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/fmt/fmt.test.ts +41 -30
- package/gs/fmt/fmt.ts +2 -22
- 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 +103 -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 +74 -153
- 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/lit.go
DELETED
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
package compiler
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
"go/ast"
|
|
6
|
-
"go/token"
|
|
7
|
-
"regexp"
|
|
8
|
-
"strconv"
|
|
9
|
-
"strings"
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
// WriteBasicLit translates a Go basic literal (`ast.BasicLit`) into its
|
|
13
|
-
// TypeScript equivalent.
|
|
14
|
-
// - Character literals (e.g., `'a'`, `'\n'`) are translated to their numeric
|
|
15
|
-
// Unicode code point (e.g., `97`, `10`). Escape sequences are handled.
|
|
16
|
-
// - Integer, float, imaginary, and string literals are written directly as their
|
|
17
|
-
// `exp.Value` string, which typically corresponds to valid TypeScript syntax
|
|
18
|
-
// (e.g., `123`, `3.14`, `"hello"`). Imaginary literals might need special
|
|
19
|
-
// handling if they are to be fully supported beyond direct string output.
|
|
20
|
-
// - Legacy octal literals (e.g., `0777`) are converted to modern TypeScript
|
|
21
|
-
// octal syntax (e.g., `0o777`) to avoid ES module compatibility issues.
|
|
22
|
-
func (c *GoToTSCompiler) WriteBasicLit(exp *ast.BasicLit) {
|
|
23
|
-
if exp.Kind == token.CHAR {
|
|
24
|
-
// Go char literal 'x' is a rune (int32). Translate to its numeric code point.
|
|
25
|
-
// Use strconv.UnquoteChar to handle escape sequences correctly.
|
|
26
|
-
val, _, _, err := strconv.UnquoteChar(exp.Value[1:len(exp.Value)-1], '\'')
|
|
27
|
-
if err != nil {
|
|
28
|
-
c.tsw.WriteCommentInlinef("error parsing char literal %s: %v", exp.Value, err)
|
|
29
|
-
c.tsw.WriteLiterally("0") // Default to 0 on error
|
|
30
|
-
} else {
|
|
31
|
-
c.tsw.WriteLiterallyf("%d", val)
|
|
32
|
-
}
|
|
33
|
-
} else if exp.Kind == token.INT {
|
|
34
|
-
// Handle integer literals, including legacy octal conversion
|
|
35
|
-
value := exp.Value
|
|
36
|
-
|
|
37
|
-
// Check for legacy octal literals (starts with 0, followed by octal digits, but not 0x, 0b, or 0o)
|
|
38
|
-
if len(value) > 1 && value[0] == '0' && value != "0" {
|
|
39
|
-
// Check if it's already modern syntax (0x, 0b, 0o) or just legacy octal
|
|
40
|
-
if len(value) > 2 && (value[1] == 'x' || value[1] == 'X' ||
|
|
41
|
-
value[1] == 'b' || value[1] == 'B' ||
|
|
42
|
-
value[1] == 'o' || value[1] == 'O') {
|
|
43
|
-
// Already modern syntax (hex, binary, or modern octal), write as-is
|
|
44
|
-
c.tsw.WriteLiterally(value)
|
|
45
|
-
} else {
|
|
46
|
-
// Check if all remaining characters are valid octal digits (0-7)
|
|
47
|
-
isLegacyOctal := true
|
|
48
|
-
for i := 1; i < len(value); i++ {
|
|
49
|
-
if value[i] < '0' || value[i] > '7' {
|
|
50
|
-
isLegacyOctal = false
|
|
51
|
-
break
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if isLegacyOctal {
|
|
56
|
-
// Convert legacy octal 0777 to modern octal 0o777
|
|
57
|
-
c.tsw.WriteLiterallyf("0o%s", value[1:])
|
|
58
|
-
} else {
|
|
59
|
-
// Not a valid octal, write as-is (might be decimal with leading zero)
|
|
60
|
-
c.tsw.WriteLiterally(value)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
} else {
|
|
64
|
-
// Regular decimal integer or single zero, write as-is
|
|
65
|
-
c.tsw.WriteLiterally(value)
|
|
66
|
-
}
|
|
67
|
-
} else if exp.Kind == token.STRING {
|
|
68
|
-
// Handle string literals, with special processing for raw strings
|
|
69
|
-
value := exp.Value
|
|
70
|
-
|
|
71
|
-
// Check if this is a raw string literal (starts and ends with backticks)
|
|
72
|
-
if len(value) >= 2 && value[0] == '`' && value[len(value)-1] == '`' {
|
|
73
|
-
// This is a Go raw string
|
|
74
|
-
content := value[1 : len(value)-1] // Remove surrounding backticks
|
|
75
|
-
|
|
76
|
-
// Check if the raw string contains backslashes that would be problematic in template literals
|
|
77
|
-
if strings.Contains(content, `\`) {
|
|
78
|
-
// Convert to a regular string literal with proper escaping
|
|
79
|
-
c.tsw.WriteLiterallyf("%q", content)
|
|
80
|
-
} else {
|
|
81
|
-
// No backslashes, safe to use template literal
|
|
82
|
-
// Escape invalid \x, \u, and \U sequences that would cause TS1125 errors
|
|
83
|
-
content = c.escapeInvalidEscapeSequences(content)
|
|
84
|
-
// Write as template literal with corrected content
|
|
85
|
-
c.tsw.WriteLiterallyf("`%s`", content)
|
|
86
|
-
}
|
|
87
|
-
} else {
|
|
88
|
-
// Regular string literal (double quotes) - write as-is
|
|
89
|
-
c.tsw.WriteLiterally(value)
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
// Other literals (FLOAT, IMAG)
|
|
93
|
-
c.tsw.WriteLiterally(exp.Value)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// WriteFuncLitValue translates a Go function literal (`ast.FuncLit`) into a
|
|
98
|
-
// TypeScript arrow function.
|
|
99
|
-
// The translation results in: `[async] (param1: type1, ...) : returnType => { ...body... }`.
|
|
100
|
-
// - The `async` keyword is prepended if `c.analysis.IsFuncLitAsync(exp)`
|
|
101
|
-
// indicates the function literal contains asynchronous operations.
|
|
102
|
-
// - Parameters are translated using `WriteFieldList`.
|
|
103
|
-
// - The return type is determined similarly to `WriteFuncType`:
|
|
104
|
-
// - `void` for no results.
|
|
105
|
-
// - `resultType` for a single unnamed result.
|
|
106
|
-
// - `[typeA, typeB]` for multiple or named results.
|
|
107
|
-
// - Wrapped in `Promise<>` if `async`.
|
|
108
|
-
// - The function body (`exp.Body`) is translated using `WriteStmt`.
|
|
109
|
-
func (c *GoToTSCompiler) WriteFuncLitValue(exp *ast.FuncLit) error {
|
|
110
|
-
// Check if this function needs reflection metadata
|
|
111
|
-
needsReflection := c.analysis.NeedsReflectionMetadata(exp)
|
|
112
|
-
|
|
113
|
-
if needsReflection {
|
|
114
|
-
// Start IIFE to attach metadata
|
|
115
|
-
c.tsw.WriteLiterally("(() => {")
|
|
116
|
-
c.tsw.Indent(1)
|
|
117
|
-
c.tsw.WriteLine("")
|
|
118
|
-
c.tsw.WriteLiterally("const fn = ")
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Determine if the function literal should be async
|
|
122
|
-
isAsync := c.analysis.IsFuncLitAsync(exp)
|
|
123
|
-
|
|
124
|
-
if isAsync {
|
|
125
|
-
c.tsw.WriteLiterally("async ")
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Write arrow function: (params) => { body }
|
|
129
|
-
c.tsw.WriteLiterally("(")
|
|
130
|
-
|
|
131
|
-
// Use WriteFieldList which now handles variadic parameters
|
|
132
|
-
c.WriteFieldList(exp.Type.Params, true) // true = arguments
|
|
133
|
-
|
|
134
|
-
c.tsw.WriteLiterally(")")
|
|
135
|
-
|
|
136
|
-
// Handle return type for function literals
|
|
137
|
-
if exp.Type.Results != nil && len(exp.Type.Results.List) > 0 {
|
|
138
|
-
c.tsw.WriteLiterally(": ")
|
|
139
|
-
if isAsync {
|
|
140
|
-
c.tsw.WriteLiterally("Promise<")
|
|
141
|
-
}
|
|
142
|
-
if len(exp.Type.Results.List) == 1 && len(exp.Type.Results.List[0].Names) == 0 {
|
|
143
|
-
c.WriteTypeExpr(exp.Type.Results.List[0].Type)
|
|
144
|
-
} else {
|
|
145
|
-
c.tsw.WriteLiterally("[")
|
|
146
|
-
first := true
|
|
147
|
-
for _, field := range exp.Type.Results.List {
|
|
148
|
-
// Each field may represent multiple return values (e.g., "a, b int")
|
|
149
|
-
count := len(field.Names)
|
|
150
|
-
if count == 0 {
|
|
151
|
-
count = 1 // Unnamed return value
|
|
152
|
-
}
|
|
153
|
-
for j := 0; j < count; j++ {
|
|
154
|
-
if !first {
|
|
155
|
-
c.tsw.WriteLiterally(", ")
|
|
156
|
-
}
|
|
157
|
-
first = false
|
|
158
|
-
c.WriteTypeExpr(field.Type)
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
c.tsw.WriteLiterally("]")
|
|
162
|
-
}
|
|
163
|
-
if isAsync {
|
|
164
|
-
c.tsw.WriteLiterally(">")
|
|
165
|
-
}
|
|
166
|
-
} else {
|
|
167
|
-
if isAsync {
|
|
168
|
-
c.tsw.WriteLiterally(": Promise<void>")
|
|
169
|
-
} else {
|
|
170
|
-
c.tsw.WriteLiterally(": void")
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
c.tsw.WriteLiterally(" => ")
|
|
175
|
-
|
|
176
|
-
if c.hasNamedReturns(exp.Type.Results) {
|
|
177
|
-
c.tsw.WriteLine("{")
|
|
178
|
-
c.tsw.Indent(1)
|
|
179
|
-
|
|
180
|
-
// Declare named return variables and initialize them to their zero values
|
|
181
|
-
if err := c.writeNamedReturnDeclarations(exp.Type.Results); err != nil {
|
|
182
|
-
return fmt.Errorf("failed to write named return declarations: %w", err)
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Write function body
|
|
187
|
-
if err := c.WriteStmtBlock(exp.Body, true); err != nil {
|
|
188
|
-
return fmt.Errorf("failed to write block statement: %w", err)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if c.hasNamedReturns(exp.Type.Results) {
|
|
192
|
-
c.tsw.Indent(-1)
|
|
193
|
-
c.tsw.WriteLiterally("}")
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Add reflection metadata if needed
|
|
197
|
-
if needsReflection {
|
|
198
|
-
c.tsw.WriteLine("")
|
|
199
|
-
|
|
200
|
-
// Attach type metadata to the function
|
|
201
|
-
if err := c.writeReflectionMetadata(exp); err != nil {
|
|
202
|
-
return fmt.Errorf("failed to write reflection metadata: %w", err)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
c.tsw.WriteLine("return fn")
|
|
206
|
-
c.tsw.Indent(-1)
|
|
207
|
-
c.tsw.WriteLiterally("})()")
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return nil
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// writeReflectionMetadata attaches function type information to a function for reflection support
|
|
214
|
-
func (c *GoToTSCompiler) writeReflectionMetadata(exp *ast.FuncLit) error {
|
|
215
|
-
// Get the reflection info for this function
|
|
216
|
-
reflectInfo := c.analysis.GetFunctionTypeInfo(exp)
|
|
217
|
-
if reflectInfo == nil || reflectInfo.FuncType == nil {
|
|
218
|
-
return nil // No reflection info available
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
funcType := reflectInfo.FuncType
|
|
222
|
-
|
|
223
|
-
// Build FunctionTypeInfo metadata
|
|
224
|
-
c.tsw.WriteLiterally("fn.__typeInfo = {")
|
|
225
|
-
c.tsw.Indent(1)
|
|
226
|
-
c.tsw.WriteLine("")
|
|
227
|
-
c.tsw.WriteLiterally("kind: $.TypeKind.Function,")
|
|
228
|
-
c.tsw.WriteLine("")
|
|
229
|
-
|
|
230
|
-
// Add parameters
|
|
231
|
-
if funcType.Params() != nil && funcType.Params().Len() > 0 {
|
|
232
|
-
c.tsw.WriteLiterally("params: [")
|
|
233
|
-
for i := 0; i < funcType.Params().Len(); i++ {
|
|
234
|
-
if i > 0 {
|
|
235
|
-
c.tsw.WriteLiterally(", ")
|
|
236
|
-
}
|
|
237
|
-
param := funcType.Params().At(i)
|
|
238
|
-
c.tsw.WriteLiterallyf("'%s'", param.Type().String())
|
|
239
|
-
}
|
|
240
|
-
c.tsw.WriteLiterally("],")
|
|
241
|
-
c.tsw.WriteLine("")
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Add results
|
|
245
|
-
if funcType.Results() != nil && funcType.Results().Len() > 0 {
|
|
246
|
-
c.tsw.WriteLiterally("results: [")
|
|
247
|
-
for i := 0; i < funcType.Results().Len(); i++ {
|
|
248
|
-
if i > 0 {
|
|
249
|
-
c.tsw.WriteLiterally(", ")
|
|
250
|
-
}
|
|
251
|
-
result := funcType.Results().At(i)
|
|
252
|
-
c.tsw.WriteLiterallyf("'%s'", result.Type().String())
|
|
253
|
-
}
|
|
254
|
-
c.tsw.WriteLiterally("],")
|
|
255
|
-
c.tsw.WriteLine("")
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Add variadic flag
|
|
259
|
-
if funcType.Variadic() {
|
|
260
|
-
c.tsw.WriteLiterally("isVariadic: true,")
|
|
261
|
-
c.tsw.WriteLine("")
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
c.tsw.Indent(-1)
|
|
265
|
-
c.tsw.WriteLiterally("}")
|
|
266
|
-
c.tsw.WriteLine("")
|
|
267
|
-
|
|
268
|
-
return nil
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// escapeInvalidEscapeSequences escapes \x, \u, and \U sequences in raw strings that would be invalid in JavaScript template literals.
|
|
272
|
-
// JavaScript template literals expect:
|
|
273
|
-
// - \x to be followed by exactly 2 hexadecimal digits
|
|
274
|
-
// - \u to be followed by exactly 4 hexadecimal digits
|
|
275
|
-
// - \U to be followed by exactly 8 hexadecimal digits
|
|
276
|
-
// This function escapes sequences that don't meet these requirements.
|
|
277
|
-
func (c *GoToTSCompiler) escapeInvalidEscapeSequences(content string) string {
|
|
278
|
-
// Use regex to find all \x, \u, and \U sequences
|
|
279
|
-
re := regexp.MustCompile(`\\([xuU])([0-9a-fA-F]*)`)
|
|
280
|
-
|
|
281
|
-
return re.ReplaceAllStringFunc(content, func(match string) string {
|
|
282
|
-
if len(match) < 2 {
|
|
283
|
-
return match
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
escapeType := match[1] // x, u, or U
|
|
287
|
-
suffix := match[2:] // The hex digits that follow
|
|
288
|
-
|
|
289
|
-
var expectedLength int
|
|
290
|
-
switch escapeType {
|
|
291
|
-
case 'x':
|
|
292
|
-
expectedLength = 2
|
|
293
|
-
case 'u':
|
|
294
|
-
expectedLength = 4
|
|
295
|
-
case 'U':
|
|
296
|
-
expectedLength = 8
|
|
297
|
-
default:
|
|
298
|
-
return match
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Check if it has exactly the expected number of hex digits
|
|
302
|
-
if len(suffix) == expectedLength {
|
|
303
|
-
// Check if all characters are hex digits
|
|
304
|
-
isValidHex := true
|
|
305
|
-
for _, char := range suffix {
|
|
306
|
-
if !((char >= '0' && char <= '9') ||
|
|
307
|
-
(char >= 'a' && char <= 'f') ||
|
|
308
|
-
(char >= 'A' && char <= 'F')) {
|
|
309
|
-
isValidHex = false
|
|
310
|
-
break
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
if isValidHex {
|
|
314
|
-
// Valid escape sequence, keep as-is
|
|
315
|
-
return match
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Invalid escape sequence, escape the backslash
|
|
320
|
-
return strings.Replace(match, `\`, `\\`, 1)
|
|
321
|
-
})
|
|
322
|
-
}
|
package/compiler/output.go
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
package compiler
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
"path/filepath"
|
|
6
|
-
"strings"
|
|
7
|
-
|
|
8
|
-
"golang.org/x/tools/go/packages"
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
// ComputeModulePath computes the root of the output typescript module.
|
|
12
|
-
func ComputeModulePath(outputRoot, goPkg string) string {
|
|
13
|
-
return filepath.Join(outputRoot, translateGoPathToTypescriptPath(goPkg))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
var typeScriptGoStubPrefix = "@ts/"
|
|
17
|
-
|
|
18
|
-
const builtinGoImportPath = "github.com/aperturerobotics/goscript/builtin"
|
|
19
|
-
|
|
20
|
-
// translateGoPathToTypescriptPath translates a go package import path to a typescript import path.
|
|
21
|
-
func translateGoPathToTypescriptPath(goImportPath string) string {
|
|
22
|
-
if strings.HasPrefix(goImportPath, typeScriptGoStubPrefix) {
|
|
23
|
-
return goImportPath[len(typeScriptGoStubPrefix):]
|
|
24
|
-
}
|
|
25
|
-
return fmt.Sprintf("@goscript/%s", goImportPath)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// translateGoImportPathToTypescriptModulePath maps a Go import path to a TypeScript module path.
|
|
29
|
-
func translateGoImportPathToTypescriptModulePath(goImportPath string) string {
|
|
30
|
-
if goImportPath == builtinGoImportPath {
|
|
31
|
-
return "@goscript/builtin"
|
|
32
|
-
}
|
|
33
|
-
return translateGoPathToTypescriptPath(goImportPath)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// translateTypescriptModulePathToIndexImportPath maps a TypeScript module path to its index.ts import path.
|
|
37
|
-
func translateTypescriptModulePathToIndexImportPath(modulePath string) string {
|
|
38
|
-
return modulePath + "/index.ts"
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// translateGeneratedFileToImportPath maps a generated file stem to its .ts import path.
|
|
42
|
-
func translateGeneratedFileToImportPath(fileName string) string {
|
|
43
|
-
return fmt.Sprintf("./%s.ts", fileName)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// translateGeneratedGoFileToImportPath maps a generated Go file stem to its .gs.ts import path.
|
|
47
|
-
func translateGeneratedGoFileToImportPath(fileName string) string {
|
|
48
|
-
return fmt.Sprintf("./%s.gs.ts", fileName)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// translateGeneratedProtobufFileToImportPath maps a protobuf file stem to its .pb.ts import path.
|
|
52
|
-
func translateGeneratedProtobufFileToImportPath(fileName string) string {
|
|
53
|
-
return fmt.Sprintf("./%s.pb.ts", fileName)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// getActualPackageName returns the actual Go package name from package information.
|
|
57
|
-
// If the package is not found in the imports map, returns an error instead of falling back.
|
|
58
|
-
// This handles cases where the package name differs from the last segment of the import path.
|
|
59
|
-
func getActualPackageName(importPath string, importsMap map[string]*packages.Package) (string, error) {
|
|
60
|
-
if pkg, exists := importsMap[importPath]; exists && pkg.Name != "" {
|
|
61
|
-
return pkg.Name, nil
|
|
62
|
-
}
|
|
63
|
-
return "", fmt.Errorf("package %s not found in imports map", importPath)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// TranslateGoFilePathToTypescriptFilePath converts the go package path and typescript filename to output path within the typescript output dir
|
|
67
|
-
func TranslateGoFilePathToTypescriptFilePath(goPkgPath, goCodeFilename string) string {
|
|
68
|
-
op := translateGoPathToTypescriptPath(goPkgPath)
|
|
69
|
-
baseFilename := goCodeFilename[:len(goCodeFilename)-3]
|
|
70
|
-
baseFilename = fmt.Sprintf("%s.gs.ts", baseFilename)
|
|
71
|
-
return filepath.Join(op, baseFilename)
|
|
72
|
-
}
|
package/compiler/primitive.go
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
package compiler
|
|
2
|
-
|
|
3
|
-
import "go/token"
|
|
4
|
-
|
|
5
|
-
// goToTypescriptPrimitives maps Go built-in primitive type names (as strings)
|
|
6
|
-
// to their corresponding TypeScript type names. This map is used by
|
|
7
|
-
// `GoBuiltinToTypescript` for direct type name translation.
|
|
8
|
-
//
|
|
9
|
-
// Key mappings include:
|
|
10
|
-
// - `bool` -> `boolean`
|
|
11
|
-
// - `string` -> `string`
|
|
12
|
-
// - `int`, `int8`, `int16`, `int32`, `rune` (alias for int32) -> `number`
|
|
13
|
-
// - `uint`, `uint8` (`byte`), `uint16`, `uint32` -> `number`
|
|
14
|
-
// - `int64`, `uint64` -> `bigint` (requires ES2020+ TypeScript target)
|
|
15
|
-
// - `float32`, `float64` -> `number`
|
|
16
|
-
//
|
|
17
|
-
// This mapping assumes a target environment similar to GOOS=js, GOARCH=wasm,
|
|
18
|
-
// where Go's `int` and `uint` are 32-bit and fit within TypeScript's `number`.
|
|
19
|
-
var goToTypescriptPrimitives = map[string]string{
|
|
20
|
-
// Boolean
|
|
21
|
-
"bool": "boolean",
|
|
22
|
-
|
|
23
|
-
// Strings
|
|
24
|
-
"string": "string",
|
|
25
|
-
|
|
26
|
-
// Signed Integers
|
|
27
|
-
"int": "number",
|
|
28
|
-
"int8": "number",
|
|
29
|
-
"int16": "number",
|
|
30
|
-
"int32": "number",
|
|
31
|
-
"rune": "number", // alias for int32
|
|
32
|
-
|
|
33
|
-
// TODO: add bigint support
|
|
34
|
-
// "int64": "bigint", // Requires TypeScript target >= ES2020
|
|
35
|
-
"int64": "number",
|
|
36
|
-
|
|
37
|
-
// Unsigned Integers
|
|
38
|
-
"uint": "number",
|
|
39
|
-
"uint8": "number", // byte is an alias for uint8
|
|
40
|
-
"byte": "number",
|
|
41
|
-
"uint16": "number",
|
|
42
|
-
"uint32": "number",
|
|
43
|
-
|
|
44
|
-
// TODO: add bigint support
|
|
45
|
-
// "uint64": "bigint", // Requires TypeScript target >= ES2020
|
|
46
|
-
"uint64": "number",
|
|
47
|
-
|
|
48
|
-
// Floating Point Numbers
|
|
49
|
-
"float32": "number",
|
|
50
|
-
"float64": "number",
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
func isPrimitiveType(name string) bool {
|
|
54
|
-
_, ok := goToTypescriptPrimitives[name]
|
|
55
|
-
return ok
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// GoBuiltinToTypescript translates a Go built-in primitive type name (string)
|
|
59
|
-
// to its TypeScript equivalent. It uses the `goToTypescriptPrimitives` map
|
|
60
|
-
// for the conversion.
|
|
61
|
-
// It returns the TypeScript type name and `true` if the Go type name is found
|
|
62
|
-
// in the map. Otherwise, it returns an empty string and `false`.
|
|
63
|
-
// This function only handles primitive types listed in the map; composite types
|
|
64
|
-
// or custom types are not processed here.
|
|
65
|
-
func GoBuiltinToTypescript(typeName string) (string, bool) {
|
|
66
|
-
val, ok := goToTypescriptPrimitives[typeName]
|
|
67
|
-
return val, ok
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// tokenMap provides a mapping from Go `token.Token` types (representing operators
|
|
71
|
-
// and punctuation) to their corresponding string representations in TypeScript.
|
|
72
|
-
// This map is used by `TokenToTs` to translate Go operators during expression
|
|
73
|
-
// and statement compilation.
|
|
74
|
-
//
|
|
75
|
-
// Examples:
|
|
76
|
-
// - `token.ADD` (Go `+`) -> `"+"` (TypeScript `+`)
|
|
77
|
-
// - `token.LAND` (Go `&&`) -> `"&&"` (TypeScript `&&`)
|
|
78
|
-
// - `token.ASSIGN` (Go `=`) -> `"="` (TypeScript `=`)
|
|
79
|
-
// - `token.DEFINE` (Go `:=`) -> `"="` (TypeScript `=`, as `let` is handled separately)
|
|
80
|
-
//
|
|
81
|
-
// Some tokens like `token.ARROW` (channel send/receive) are handled specially
|
|
82
|
-
// in their respective expression/statement writers and might not be directly mapped here.
|
|
83
|
-
// Bitwise AND NOT (`&^=`) is also mapped but may require specific runtime support if not directly translatable.
|
|
84
|
-
var tokenMap = map[token.Token]string{
|
|
85
|
-
token.ADD: "+",
|
|
86
|
-
token.SUB: "-",
|
|
87
|
-
token.MUL: "*",
|
|
88
|
-
token.QUO: "/",
|
|
89
|
-
token.REM: "%",
|
|
90
|
-
token.AND: "&",
|
|
91
|
-
token.OR: "|",
|
|
92
|
-
token.XOR: "^",
|
|
93
|
-
token.SHL: "<<",
|
|
94
|
-
token.SHR: ">>",
|
|
95
|
-
token.AND_NOT: "& ~", // &^ operator: bitwise AND NOT
|
|
96
|
-
|
|
97
|
-
token.ADD_ASSIGN: "+=",
|
|
98
|
-
token.SUB_ASSIGN: "-=",
|
|
99
|
-
token.MUL_ASSIGN: "*=",
|
|
100
|
-
token.QUO_ASSIGN: "/=",
|
|
101
|
-
token.REM_ASSIGN: "%=",
|
|
102
|
-
|
|
103
|
-
token.AND_ASSIGN: "&=",
|
|
104
|
-
token.OR_ASSIGN: "|=",
|
|
105
|
-
token.XOR_ASSIGN: "^=", // TODO: check if this works
|
|
106
|
-
token.SHL_ASSIGN: "<<=",
|
|
107
|
-
token.SHR_ASSIGN: ">>=",
|
|
108
|
-
// token.AND_NOT_ASSIGN: "&^=", // Handled specially in assignment logic
|
|
109
|
-
|
|
110
|
-
token.LAND: "&&",
|
|
111
|
-
token.LOR: "||",
|
|
112
|
-
// token.ARROW: ""
|
|
113
|
-
token.INC: "++",
|
|
114
|
-
token.DEC: "--",
|
|
115
|
-
token.EQL: "==",
|
|
116
|
-
token.LSS: "<",
|
|
117
|
-
token.GTR: ">",
|
|
118
|
-
token.ASSIGN: "=",
|
|
119
|
-
token.NOT: "!",
|
|
120
|
-
|
|
121
|
-
token.NEQ: "!=",
|
|
122
|
-
token.LEQ: "<=",
|
|
123
|
-
token.GEQ: ">=",
|
|
124
|
-
token.DEFINE: "=", // :=
|
|
125
|
-
token.ELLIPSIS: "...", // TODO
|
|
126
|
-
|
|
127
|
-
token.LPAREN: "(",
|
|
128
|
-
token.LBRACK: "[",
|
|
129
|
-
token.LBRACE: "{",
|
|
130
|
-
token.COMMA: ",",
|
|
131
|
-
token.PERIOD: ".",
|
|
132
|
-
|
|
133
|
-
token.RPAREN: ")",
|
|
134
|
-
token.RBRACK: "]",
|
|
135
|
-
token.RBRACE: "}",
|
|
136
|
-
token.SEMICOLON: ";",
|
|
137
|
-
token.COLON: ":",
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// TokenToTs converts a Go `token.Token` (representing an operator or punctuation)
|
|
141
|
-
// into its corresponding TypeScript string representation using the `tokenMap`.
|
|
142
|
-
// It returns the TypeScript string and `true` if the token is found in the map.
|
|
143
|
-
// Otherwise, it returns an empty string and `false`. This function is essential
|
|
144
|
-
// for translating expressions involving operators (e.g., arithmetic, logical,
|
|
145
|
-
// assignment operators).
|
|
146
|
-
func TokenToTs(tok token.Token) (string, bool) {
|
|
147
|
-
t, ok := tokenMap[tok]
|
|
148
|
-
return t, ok
|
|
149
|
-
}
|