goscript 0.0.23 → 0.0.25
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 +2 -2
- package/cmd/goscript/cmd_compile.go +18 -2
- package/compiler/analysis.go +74 -132
- package/compiler/analysis_test.go +220 -0
- package/compiler/assignment.go +37 -43
- package/compiler/builtin_test.go +90 -0
- package/compiler/compiler.go +307 -22
- package/compiler/composite-lit.go +108 -43
- package/compiler/config.go +7 -3
- package/compiler/config_test.go +6 -33
- package/compiler/decl.go +7 -1
- package/compiler/expr-call.go +212 -2
- package/compiler/expr-selector.go +66 -41
- package/compiler/expr-star.go +57 -65
- package/compiler/expr-type.go +1 -1
- package/compiler/expr-value.go +1 -1
- package/compiler/expr.go +125 -20
- package/compiler/field.go +4 -4
- package/compiler/primitive.go +11 -10
- package/compiler/spec-struct.go +3 -3
- package/compiler/spec-value.go +75 -29
- package/compiler/spec.go +9 -3
- package/compiler/stmt-assign.go +36 -2
- package/compiler/stmt-for.go +11 -0
- package/compiler/stmt-range.go +314 -1
- package/compiler/stmt.go +52 -0
- package/compiler/type.go +83 -15
- package/dist/gs/builtin/builtin.d.ts +9 -0
- package/dist/gs/builtin/builtin.js +46 -0
- package/dist/gs/builtin/builtin.js.map +1 -0
- package/dist/gs/builtin/channel.d.ts +193 -0
- package/dist/gs/builtin/channel.js +471 -0
- package/dist/gs/builtin/channel.js.map +1 -0
- package/dist/gs/builtin/defer.d.ts +38 -0
- package/dist/gs/builtin/defer.js +54 -0
- package/dist/gs/builtin/defer.js.map +1 -0
- package/dist/gs/builtin/index.d.ts +1 -0
- package/dist/gs/builtin/index.js +2 -0
- package/dist/gs/builtin/index.js.map +1 -0
- package/dist/gs/builtin/io.d.ts +16 -0
- package/dist/gs/builtin/io.js +15 -0
- package/dist/gs/builtin/io.js.map +1 -0
- package/dist/gs/builtin/map.d.ts +33 -0
- package/dist/gs/builtin/map.js +44 -0
- package/dist/gs/builtin/map.js.map +1 -0
- package/dist/gs/builtin/slice.d.ts +173 -0
- package/dist/gs/builtin/slice.js +799 -0
- package/dist/gs/builtin/slice.js.map +1 -0
- package/dist/gs/builtin/type.d.ts +203 -0
- package/dist/gs/builtin/type.js +744 -0
- package/dist/gs/builtin/type.js.map +1 -0
- package/dist/gs/builtin/varRef.d.ts +14 -0
- package/dist/gs/builtin/varRef.js +14 -0
- package/dist/gs/builtin/varRef.js.map +1 -0
- package/dist/gs/cmp/index.d.ts +4 -0
- package/dist/gs/cmp/index.js +27 -0
- package/dist/gs/cmp/index.js.map +1 -0
- package/dist/gs/context/context.d.ts +26 -0
- package/dist/gs/context/context.js +305 -0
- package/dist/gs/context/context.js.map +1 -0
- package/dist/gs/context/index.d.ts +1 -0
- package/dist/gs/context/index.js +2 -0
- package/dist/gs/context/index.js.map +1 -0
- package/dist/gs/internal/goarch/index.d.ts +6 -0
- package/dist/gs/internal/goarch/index.js +14 -0
- package/dist/gs/internal/goarch/index.js.map +1 -0
- package/dist/gs/iter/index.d.ts +1 -0
- package/dist/gs/iter/index.js +2 -0
- package/dist/gs/iter/index.js.map +1 -0
- package/dist/gs/iter/iter.d.ts +4 -0
- package/dist/gs/iter/iter.js +91 -0
- package/dist/gs/iter/iter.js.map +1 -0
- package/dist/gs/math/bits/index.d.ts +47 -0
- package/dist/gs/math/bits/index.js +298 -0
- package/dist/gs/math/bits/index.js.map +1 -0
- package/dist/gs/runtime/index.d.ts +1 -0
- package/dist/gs/runtime/index.js +2 -0
- package/dist/gs/runtime/index.js.map +1 -0
- package/dist/gs/runtime/runtime.d.ts +41 -0
- package/dist/gs/runtime/runtime.js +158 -0
- package/dist/gs/runtime/runtime.js.map +1 -0
- package/dist/gs/slices/index.d.ts +1 -0
- package/dist/gs/slices/index.js +2 -0
- package/dist/gs/slices/index.js.map +1 -0
- package/dist/gs/slices/slices.d.ts +8 -0
- package/dist/gs/slices/slices.js +20 -0
- package/dist/gs/slices/slices.js.map +1 -0
- package/dist/gs/time/index.d.ts +1 -0
- package/dist/gs/time/index.js +2 -0
- package/dist/gs/time/index.js.map +1 -0
- package/dist/gs/time/time.d.ts +57 -0
- package/dist/gs/time/time.js +208 -0
- package/dist/gs/time/time.js.map +1 -0
- package/package.json +3 -2
package/compiler/assignment.go
CHANGED
|
@@ -21,7 +21,7 @@ import (
|
|
|
21
21
|
// to `$.mapSet(myMap_ts, key_ts, value_ts)`.
|
|
22
22
|
// - Other single-variable assignments (`variable = value`):
|
|
23
23
|
// - The LHS expression is written (caller typically ensures `.value` is appended
|
|
24
|
-
// if assigning to a
|
|
24
|
+
// if assigning to a VarRefed variable's content).
|
|
25
25
|
// - The Go assignment token (`tok`, e.g., `=`, `+=`) is translated to its
|
|
26
26
|
// TypeScript equivalent using `TokenToTs`.
|
|
27
27
|
// - The RHS expression(s) are written. If `shouldApplyClone` indicates the RHS
|
|
@@ -68,10 +68,10 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
68
68
|
return nil
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
// Special handling for
|
|
71
|
+
// Special handling for variable referenced variables in declarations
|
|
72
72
|
if addDeclaration && tok == token.DEFINE {
|
|
73
|
-
// Determine if LHS is
|
|
74
|
-
|
|
73
|
+
// Determine if LHS is variable referenced
|
|
74
|
+
isLHSVarRefed := false
|
|
75
75
|
var lhsIdent *ast.Ident
|
|
76
76
|
var lhsObj types.Object
|
|
77
77
|
|
|
@@ -84,30 +84,22 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
84
84
|
lhsObj = def
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
// Check if this variable needs to be
|
|
88
|
-
if lhsObj != nil && c.analysis.
|
|
89
|
-
|
|
87
|
+
// Check if this variable needs to be variable referenced
|
|
88
|
+
if lhsObj != nil && c.analysis.NeedsVarRef(lhsObj) {
|
|
89
|
+
isLHSVarRefed = true
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
// Special handling for short declaration of
|
|
94
|
-
if
|
|
93
|
+
// Special handling for short declaration of variable referenced variables
|
|
94
|
+
if isLHSVarRefed && lhsIdent != nil {
|
|
95
95
|
c.tsw.WriteLiterally("let ")
|
|
96
96
|
// Just write the identifier name without .value
|
|
97
97
|
c.tsw.WriteLiterally(lhsIdent.Name)
|
|
98
|
-
|
|
99
|
-
// Add type annotation for boxed variables in declarations
|
|
100
|
-
if lhsObj != nil {
|
|
101
|
-
c.tsw.WriteLiterally(": ")
|
|
102
|
-
c.tsw.WriteLiterally("$.Box<")
|
|
103
|
-
c.WriteGoType(lhsObj.Type(), GoTypeContextGeneral)
|
|
104
|
-
c.tsw.WriteLiterally(">")
|
|
105
|
-
}
|
|
106
|
-
|
|
98
|
+
// No type annotation, allow TypeScript to infer it from varRef.
|
|
107
99
|
c.tsw.WriteLiterally(" = ")
|
|
108
100
|
|
|
109
|
-
//
|
|
110
|
-
c.tsw.WriteLiterally("$.
|
|
101
|
+
// Create the variable reference for the initializer
|
|
102
|
+
c.tsw.WriteLiterally("$.varRef(")
|
|
111
103
|
if err := c.WriteValueExpr(rhs[0]); err != nil {
|
|
112
104
|
return err
|
|
113
105
|
}
|
|
@@ -226,12 +218,12 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
226
218
|
}
|
|
227
219
|
|
|
228
220
|
if !currentIsMapIndex {
|
|
229
|
-
// For single assignments, handle
|
|
221
|
+
// For single assignments, handle variable referenced variables specially
|
|
230
222
|
if len(lhs) == 1 && len(rhs) == 1 {
|
|
231
223
|
lhsExprIdent, lhsExprIsIdent := l.(*ast.Ident)
|
|
232
224
|
if lhsExprIsIdent {
|
|
233
|
-
// Determine if LHS is
|
|
234
|
-
|
|
225
|
+
// Determine if LHS is variable referenced
|
|
226
|
+
isLHSVarRefed := false
|
|
235
227
|
var lhsObj types.Object
|
|
236
228
|
|
|
237
229
|
// Get the types.Object from the identifier
|
|
@@ -241,13 +233,13 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
241
233
|
lhsObj = def
|
|
242
234
|
}
|
|
243
235
|
|
|
244
|
-
// Check if this variable needs to be
|
|
245
|
-
if lhsObj != nil && c.analysis.
|
|
246
|
-
|
|
236
|
+
// Check if this variable needs to be variable referenced
|
|
237
|
+
if lhsObj != nil && c.analysis.NeedsVarRef(lhsObj) {
|
|
238
|
+
isLHSVarRefed = true
|
|
247
239
|
}
|
|
248
240
|
|
|
249
|
-
// prevent writing .value unless lhs is
|
|
250
|
-
c.WriteIdent(lhsExprIdent,
|
|
241
|
+
// prevent writing .value unless lhs is variable referenced
|
|
242
|
+
c.WriteIdent(lhsExprIdent, isLHSVarRefed)
|
|
251
243
|
continue
|
|
252
244
|
}
|
|
253
245
|
}
|
|
@@ -279,15 +271,16 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
279
271
|
if i != 0 {
|
|
280
272
|
c.tsw.WriteLiterally(", ")
|
|
281
273
|
}
|
|
282
|
-
|
|
274
|
+
|
|
275
|
+
// Check if we need to access a variable referenced source value and apply clone
|
|
283
276
|
// For struct value assignments, we need to handle:
|
|
284
|
-
// 1.
|
|
285
|
-
// 2.
|
|
286
|
-
// 3.
|
|
287
|
-
// 4.
|
|
277
|
+
// 1. UnVarRefed source, unVarRefed target: source.clone()
|
|
278
|
+
// 2. Variable referenced source, unVarRefed target: source.value.clone()
|
|
279
|
+
// 3. UnVarRefed source, variable referenced target: $.varRef(source)
|
|
280
|
+
// 4. Variable referenced source, variable referenced target: source (straight assignment of the variable reference)
|
|
288
281
|
|
|
289
|
-
// Determine if RHS is a
|
|
290
|
-
|
|
282
|
+
// Determine if RHS is a variable referenced variable (could be a struct or other variable)
|
|
283
|
+
needsVarRefedAccessRHS := false
|
|
291
284
|
var rhsObj types.Object
|
|
292
285
|
|
|
293
286
|
// Check if RHS is an identifier (variable name)
|
|
@@ -298,17 +291,17 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
298
291
|
rhsObj = c.pkg.TypesInfo.Defs[rhsIdent]
|
|
299
292
|
}
|
|
300
293
|
|
|
301
|
-
// Important: For struct copying, we need to check if the variable itself is
|
|
302
|
-
// Important: For struct copying, we need to check if the variable needs
|
|
303
|
-
// This is more comprehensive than just checking if it's
|
|
294
|
+
// Important: For struct copying, we need to check if the variable itself is variable referenced
|
|
295
|
+
// Important: For struct copying, we need to check if the variable needs variable referenced access
|
|
296
|
+
// This is more comprehensive than just checking if it's variable referenced
|
|
304
297
|
if rhsObj != nil {
|
|
305
|
-
|
|
298
|
+
needsVarRefedAccessRHS = c.analysis.NeedsVarRefAccess(rhsObj)
|
|
306
299
|
}
|
|
307
300
|
}
|
|
308
301
|
|
|
309
302
|
// Handle different cases for struct cloning
|
|
310
303
|
if shouldApplyClone(c.pkg, r) {
|
|
311
|
-
// For other expressions, we need to handle
|
|
304
|
+
// For other expressions, we need to handle variable referenced access differently
|
|
312
305
|
if _, isIdent := r.(*ast.Ident); isIdent {
|
|
313
306
|
// For identifiers, WriteValueExpr already adds .value if needed
|
|
314
307
|
if err := c.WriteValueExpr(r); err != nil {
|
|
@@ -319,14 +312,15 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
319
312
|
if err := c.WriteValueExpr(r); err != nil {
|
|
320
313
|
return err
|
|
321
314
|
}
|
|
322
|
-
// Only add .value for non-identifiers that need
|
|
323
|
-
if
|
|
324
|
-
c.tsw.WriteLiterally(".value") // Access the
|
|
315
|
+
// Only add .value for non-identifiers that need variable referenced access
|
|
316
|
+
if needsVarRefedAccessRHS {
|
|
317
|
+
c.tsw.WriteLiterally(".value") // Access the variable referenced value
|
|
325
318
|
}
|
|
326
319
|
}
|
|
327
320
|
|
|
328
321
|
c.tsw.WriteLiterally(".clone()") // Always add clone for struct values
|
|
329
322
|
} else {
|
|
323
|
+
// Non-struct case: write RHS normally
|
|
330
324
|
if err := c.WriteValueExpr(r); err != nil { // RHS is a non-struct value
|
|
331
325
|
return err
|
|
332
326
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
package compiler
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"os"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"testing"
|
|
8
|
+
|
|
9
|
+
"github.com/sirupsen/logrus"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
func TestEmitBuiltinOption(t *testing.T) {
|
|
13
|
+
// Create a temporary directory for the test output
|
|
14
|
+
tempDir, err := os.MkdirTemp("", "goscript-test-emit-builtin")
|
|
15
|
+
if err != nil {
|
|
16
|
+
t.Fatalf("Failed to create temp dir: %v", err)
|
|
17
|
+
}
|
|
18
|
+
defer os.RemoveAll(tempDir)
|
|
19
|
+
|
|
20
|
+
// Setup logger
|
|
21
|
+
log := logrus.New()
|
|
22
|
+
log.SetLevel(logrus.DebugLevel)
|
|
23
|
+
le := logrus.NewEntry(log)
|
|
24
|
+
|
|
25
|
+
// Case 1: DisableEmitBuiltin = true (default behavior in compliance tests)
|
|
26
|
+
t.Run("DisableEmitBuiltin=true", func(t *testing.T) {
|
|
27
|
+
outputDir := filepath.Join(tempDir, "disabled")
|
|
28
|
+
config := &Config{
|
|
29
|
+
OutputPath: outputDir,
|
|
30
|
+
AllDependencies: true,
|
|
31
|
+
DisableEmitBuiltin: true,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
compiler, err := NewCompiler(config, le, nil)
|
|
35
|
+
if err != nil {
|
|
36
|
+
t.Fatalf("Failed to create compiler: %v", err)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Compile a package that depends on builtin (time)
|
|
40
|
+
_, err = compiler.CompilePackages(context.Background(), "time")
|
|
41
|
+
if err != nil {
|
|
42
|
+
t.Fatalf("Compilation failed: %v", err)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Check that the unsafe package wasn't emitted (we know it's handwritten)
|
|
46
|
+
unsafePath := filepath.Join(outputDir, "@goscript/unsafe")
|
|
47
|
+
if _, err := os.Stat(unsafePath); !os.IsNotExist(err) {
|
|
48
|
+
t.Errorf("unsafe package was emitted when DisableEmitBuiltin=true")
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Also check for runtime package
|
|
52
|
+
runtimePath := filepath.Join(outputDir, "@goscript/runtime")
|
|
53
|
+
if _, err := os.Stat(runtimePath); !os.IsNotExist(err) {
|
|
54
|
+
t.Errorf("runtime package was emitted when DisableEmitBuiltin=true")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// But time package should have been emitted
|
|
58
|
+
timePath := filepath.Join(outputDir, "@goscript/time")
|
|
59
|
+
if _, err := os.Stat(timePath); os.IsNotExist(err) {
|
|
60
|
+
t.Errorf("time package was not emitted")
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
// Case 2: DisableEmitBuiltin = false (new behavior for third-party projects)
|
|
65
|
+
t.Run("DisableEmitBuiltin=false", func(t *testing.T) {
|
|
66
|
+
outputDir := filepath.Join(tempDir, "enabled")
|
|
67
|
+
config := &Config{
|
|
68
|
+
OutputPath: outputDir,
|
|
69
|
+
AllDependencies: true,
|
|
70
|
+
DisableEmitBuiltin: false,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
compiler, err := NewCompiler(config, le, nil)
|
|
74
|
+
if err != nil {
|
|
75
|
+
t.Fatalf("Failed to create compiler: %v", err)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Compile a package that depends on builtin (time)
|
|
79
|
+
_, err = compiler.CompilePackages(context.Background(), "time")
|
|
80
|
+
if err != nil {
|
|
81
|
+
t.Fatalf("Compilation failed: %v", err)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Time package should also have been emitted
|
|
85
|
+
timePath := filepath.Join(outputDir, "@goscript/time")
|
|
86
|
+
if _, err := os.Stat(timePath); os.IsNotExist(err) {
|
|
87
|
+
t.Errorf("time package was not emitted")
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
}
|