goscript 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +41 -0
  2. package/builtin/builtin.ts +368 -348
  3. package/compiler/compile_expr.go +3 -37
  4. package/compiler/index.test.ts +29 -0
  5. package/compiler/index.ts +85 -0
  6. package/dist/builtin/builtin.d.ts +168 -0
  7. package/dist/builtin/builtin.js +372 -0
  8. package/dist/builtin/builtin.js.map +1 -0
  9. package/dist/compiler/index.d.ts +26 -0
  10. package/dist/compiler/index.js +64 -0
  11. package/dist/compiler/index.js.map +1 -0
  12. package/package.json +68 -3
  13. package/.aider-prompt +0 -11
  14. package/compliance/COMPLIANCE.md +0 -133
  15. package/compliance/compliance.go +0 -313
  16. package/compliance/compliance_test.go +0 -57
  17. package/compliance/tests/array_literal/array_literal.go +0 -15
  18. package/compliance/tests/array_literal/array_literal.gs.ts +0 -19
  19. package/compliance/tests/array_literal/expected.log +0 -3
  20. package/compliance/tests/async_basic/async_basic.go +0 -26
  21. package/compliance/tests/async_basic/async_basic.gs.ts +0 -30
  22. package/compliance/tests/async_basic/expected.log +0 -1
  23. package/compliance/tests/basic_arithmetic/basic_arithmetic.go +0 -15
  24. package/compliance/tests/basic_arithmetic/basic_arithmetic.gs.ts +0 -19
  25. package/compliance/tests/basic_arithmetic/expected.log +0 -5
  26. package/compliance/tests/boolean_logic/boolean_logic.go +0 -13
  27. package/compliance/tests/boolean_logic/boolean_logic.gs.ts +0 -17
  28. package/compliance/tests/boolean_logic/expected.log +0 -3
  29. package/compliance/tests/channel_basic/channel_basic.go +0 -12
  30. package/compliance/tests/channel_basic/channel_basic.gs.ts +0 -18
  31. package/compliance/tests/channel_basic/expected.log +0 -1
  32. package/compliance/tests/composite_literal_assignment/composite_literal_assignment.go +0 -20
  33. package/compliance/tests/composite_literal_assignment/composite_literal_assignment.gs.ts +0 -27
  34. package/compliance/tests/composite_literal_assignment/expected.log +0 -2
  35. package/compliance/tests/constants/constants.go +0 -18
  36. package/compliance/tests/constants/constants.gs.ts +0 -22
  37. package/compliance/tests/constants/expected.log +0 -3
  38. package/compliance/tests/copy_independence/copy_independence.go +0 -29
  39. package/compliance/tests/copy_independence/copy_independence.gs.ts +0 -36
  40. package/compliance/tests/copy_independence/expected.log +0 -4
  41. package/compliance/tests/float64/expected.log +0 -6
  42. package/compliance/tests/float64/float64.go +0 -28
  43. package/compliance/tests/float64/float64.gs.ts +0 -32
  44. package/compliance/tests/for_loop_basic/expected.log +0 -5
  45. package/compliance/tests/for_loop_basic/for_loop_basic.go +0 -9
  46. package/compliance/tests/for_loop_basic/for_loop_basic.gs.ts +0 -13
  47. package/compliance/tests/for_loop_condition_only/expected.log +0 -5
  48. package/compliance/tests/for_loop_condition_only/main.go +0 -9
  49. package/compliance/tests/for_loop_condition_only/main.gs.ts +0 -13
  50. package/compliance/tests/for_range/expected.log +0 -9
  51. package/compliance/tests/for_range/for_range.go +0 -26
  52. package/compliance/tests/for_range/for_range.gs.ts +0 -45
  53. package/compliance/tests/for_range_index_use/expected.log +0 -6
  54. package/compliance/tests/for_range_index_use/for_range_index_use.go +0 -11
  55. package/compliance/tests/for_range_index_use/for_range_index_use.gs.ts +0 -18
  56. package/compliance/tests/func_literal/expected.log +0 -1
  57. package/compliance/tests/func_literal/func_literal.go +0 -10
  58. package/compliance/tests/func_literal/func_literal.gs.ts +0 -15
  59. package/compliance/tests/function_call_result_assignment/expected.log +0 -2
  60. package/compliance/tests/function_call_result_assignment/function_call_result_assignment.go +0 -24
  61. package/compliance/tests/function_call_result_assignment/function_call_result_assignment.gs.ts +0 -31
  62. package/compliance/tests/if_statement/expected.log +0 -1
  63. package/compliance/tests/if_statement/if_statement.go +0 -11
  64. package/compliance/tests/if_statement/if_statement.gs.ts +0 -15
  65. package/compliance/tests/interface_to_interface_type_assertion/expected.log +0 -1
  66. package/compliance/tests/interface_to_interface_type_assertion/interface_to_interface_type_assertion.go +0 -30
  67. package/compliance/tests/interface_to_interface_type_assertion/interface_to_interface_type_assertion.gs.ts +0 -41
  68. package/compliance/tests/interface_type_assertion/expected.log +0 -1
  69. package/compliance/tests/interface_type_assertion/interface_type_assertion.go +0 -26
  70. package/compliance/tests/interface_type_assertion/interface_type_assertion.gs.ts +0 -36
  71. package/compliance/tests/map_support/expected.log +0 -13
  72. package/compliance/tests/map_support/map_support.go +0 -89
  73. package/compliance/tests/map_support/map_support.gs.ts +0 -102
  74. package/compliance/tests/method_call_on_pointer_receiver/expected.log +0 -1
  75. package/compliance/tests/method_call_on_pointer_receiver/method_call_on_pointer_receiver.go +0 -19
  76. package/compliance/tests/method_call_on_pointer_receiver/method_call_on_pointer_receiver.gs.ts +0 -27
  77. package/compliance/tests/method_call_on_pointer_via_value/expected.log +0 -1
  78. package/compliance/tests/method_call_on_pointer_via_value/method_call_on_pointer_via_value.go +0 -29
  79. package/compliance/tests/method_call_on_pointer_via_value/method_call_on_pointer_via_value.gs.ts +0 -38
  80. package/compliance/tests/method_call_on_value_receiver/expected.log +0 -1
  81. package/compliance/tests/method_call_on_value_receiver/method_call_on_value_receiver.go +0 -16
  82. package/compliance/tests/method_call_on_value_receiver/method_call_on_value_receiver.gs.ts +0 -24
  83. package/compliance/tests/method_call_on_value_via_pointer/expected.log +0 -2
  84. package/compliance/tests/method_call_on_value_via_pointer/method_call_on_value_via_pointer.go +0 -30
  85. package/compliance/tests/method_call_on_value_via_pointer/method_call_on_value_via_pointer.gs.ts +0 -38
  86. package/compliance/tests/multiple_return_values/expected.log +0 -6
  87. package/compliance/tests/multiple_return_values/multiple_return_values.go +0 -19
  88. package/compliance/tests/multiple_return_values/multiple_return_values.gs.ts +0 -23
  89. package/compliance/tests/pointer_assignment_no_copy/expected.log +0 -2
  90. package/compliance/tests/pointer_assignment_no_copy/pointer_assignment_no_copy.go +0 -28
  91. package/compliance/tests/pointer_assignment_no_copy/pointer_assignment_no_copy.gs.ts +0 -35
  92. package/compliance/tests/pointer_composite_literal_assignment/expected.log +0 -3
  93. package/compliance/tests/pointer_composite_literal_assignment/pointer_composite_literal_assignment.go +0 -23
  94. package/compliance/tests/pointer_composite_literal_assignment/pointer_composite_literal_assignment.gs.ts +0 -30
  95. package/compliance/tests/pointer_deref_multiassign/expected.log +0 -0
  96. package/compliance/tests/pointer_deref_multiassign/pointer_deref_multiassign.go +0 -17
  97. package/compliance/tests/pointer_deref_multiassign/pointer_deref_multiassign.gs.ts +0 -27
  98. package/compliance/tests/pointer_initialization/expected.log +0 -1
  99. package/compliance/tests/pointer_initialization/pointer_initialization.go +0 -16
  100. package/compliance/tests/pointer_initialization/pointer_initialization.gs.ts +0 -22
  101. package/compliance/tests/select_receive_on_closed_channel_no_default/expected.log +0 -1
  102. package/compliance/tests/select_receive_on_closed_channel_no_default/select_receive_on_closed_channel_no_default.go +0 -15
  103. package/compliance/tests/select_receive_on_closed_channel_no_default/select_receive_on_closed_channel_no_default.gs.ts +0 -31
  104. package/compliance/tests/select_send_on_full_buffered_channel_with_default/expected.log +0 -1
  105. package/compliance/tests/select_send_on_full_buffered_channel_with_default/select_send_on_full_buffered_channel_with_default.go +0 -13
  106. package/compliance/tests/select_send_on_full_buffered_channel_with_default/select_send_on_full_buffered_channel_with_default.gs.ts +0 -35
  107. package/compliance/tests/select_statement/expected.log +0 -9
  108. package/compliance/tests/select_statement/select_statement.go +0 -109
  109. package/compliance/tests/select_statement/select_statement.gs.ts +0 -239
  110. package/compliance/tests/simple/expected.log +0 -1
  111. package/compliance/tests/simple/simple.go +0 -5
  112. package/compliance/tests/simple/simple.gs.ts +0 -9
  113. package/compliance/tests/simple_deref_assignment/expected.log +0 -2
  114. package/compliance/tests/simple_deref_assignment/simple_deref_assignment.go +0 -19
  115. package/compliance/tests/simple_deref_assignment/simple_deref_assignment.gs.ts +0 -26
  116. package/compliance/tests/slices/expected.log +0 -7
  117. package/compliance/tests/slices/slices.go +0 -22
  118. package/compliance/tests/slices/slices.gs.ts +0 -26
  119. package/compliance/tests/string_rune_conversion/expected.log +0 -3
  120. package/compliance/tests/string_rune_conversion/string_rune_conversion.go +0 -16
  121. package/compliance/tests/string_rune_conversion/string_rune_conversion.gs.ts +0 -22
  122. package/compliance/tests/struct_field_access/expected.log +0 -2
  123. package/compliance/tests/struct_field_access/struct_field_access.go +0 -13
  124. package/compliance/tests/struct_field_access/struct_field_access.gs.ts +0 -20
  125. package/compliance/tests/struct_value_init_clone/expected.log +0 -5
  126. package/compliance/tests/struct_value_init_clone/struct_value_init_clone.go +0 -28
  127. package/compliance/tests/struct_value_init_clone/struct_value_init_clone.gs.ts +0 -35
  128. package/compliance/tests/switch_statement/expected.log +0 -14
  129. package/compliance/tests/switch_statement/switch_statement.go +0 -59
  130. package/compliance/tests/switch_statement/switch_statement.gs.ts +0 -85
  131. package/compliance/tests/value_type_copy_behavior/expected.log +0 -3
  132. package/compliance/tests/value_type_copy_behavior/value_type_copy_behavior.go +0 -25
  133. package/compliance/tests/value_type_copy_behavior/value_type_copy_behavior.gs.ts +0 -34
  134. package/design/DESIGN.md +0 -599
  135. package/example/simple/build.bash +0 -10
  136. package/example/simple/go.mod +0 -23
  137. package/example/simple/go.sum +0 -39
  138. package/example/simple/main.go +0 -138
  139. package/example/simple/main.gs.ts +0 -133
  140. package/example/simple/main.ts +0 -3
  141. package/example/simple/main_test.go +0 -59
  142. package/example/simple/main_tools.go +0 -5
  143. package/example/simple/package.json +0 -7
  144. package/example/simple/run.bash +0 -6
  145. package/example/simple/tsconfig.json +0 -28
  146. package/example/simple/yarn.lock +0 -8
  147. package/output/output.go +0 -10
  148. package/tsconfig.json +0 -10
  149. package/types/tokens.go +0 -65
  150. package/types/types.go +0 -46
@@ -1,133 +0,0 @@
1
- # GoScript Compliance Tests
2
-
3
- This document outlines the compliance tests for the GoScript compiler, verifying its ability to correctly translate various Go language features into TypeScript.
4
-
5
- ## Existing Compliance Tests
6
-
7
- The following tests are currently implemented in the `/compliance/tests` directory:
8
-
9
- * **`basic_arithmetic/`**: Verifies basic arithmetic operations (`+`, `-`, `*`, `/`, `%`).
10
- * **`boolean_logic/`**: Tests boolean logic operators (`&&`, `||`, `!`) and comparisons (`==`, `!=`, `<`, `>`, `<=`, `>=`).
11
- * **`composite_literal_assignment/`**: Checks the assignment of struct values created using composite literals, ensuring correct value copying.
12
- * **`copy_independence/`**: Verifies that copies of struct values are independent and modifications to one do not affect others.
13
- * **`function_call_result_assignment/`**: Tests assigning the result of a function returning a struct, ensuring proper value semantics (copying).
14
- * **`if_statement/`**: Covers basic `if`/`else` conditional statements, including correct `} else {` formatting.
15
- * **`switch_statement/`**: Verifies basic `switch` statements with integer and string tags and default cases.
16
- * **`for_loop_basic/`**: Verifies basic counter-based `for` loops (`for init; cond; post {}`).
17
- * **`map_support/`**: Covers map creation (`make`, literal), access, assignment, deletion, length, and iteration (`range`).
18
- * **`method_call_on_pointer_receiver/`**: Verifies calling methods with pointer receivers (`*T`) on pointer variables.
19
- * **`method_call_on_value_receiver/`**: Verifies calling methods with value receivers (`T`) on value variables. (Note: Go often implicitly takes the address for pointer receivers, this tests the explicit value receiver case).
20
- * **`pointer_deref_multiassign/`**: Tests dereferencing a pointer during a multi-variable assignment (`:=` or `=`), including the use of the blank identifier (`_`).
21
- * **`pointer_initialization/`**: Checks the initialization of pointer variables using the address-of operator (`&`) or `new()`.
22
- * **`simple/`**: A basic test covering simple struct definition, field access, method calls, and `println`. (Likely overlaps with others, could be a general integration test).
23
- * **`simple_deref_assignment/`**: Tests simple assignment involving pointer dereferencing (`*ptr`), ensuring value copying.
24
- * **`struct_field_access/`**: Verifies accessing fields of struct values and struct pointers.
25
- * **`struct_value_init_clone/`**: Checks struct initialization via composite literal (`T{...}`) (omitting `.clone()` for direct assignment) and subsequent assignment from variables (ensuring `.clone()` is used for value semantics).
26
- * **`value_type_copy_behavior/`**: Focuses specifically on demonstrating that assigning struct values creates independent copies (value semantics).
27
-
28
- Each test should have only three files:
29
-
30
- 1. test_name.go - the Go code to convert to TypeScript
31
- 2. test_name.gs.ts - the generated TypeScript code, created automatically on test run
32
- 3. expected.log - the expected output from running the .gs.ts
33
-
34
- ## Covered Go Language Constructs
35
-
36
- Based on the existing tests, GoScript aims to support the following Go features:
37
-
38
- * **Basic Types:** `int`, `string`, `bool`, `float64` (implicitly tested).
39
- * **Type Conversions:** `string(rune)`
40
- * **Operators:**
41
- * Arithmetic: `+`, `-`, `*`, `/`, `%`
42
- * Comparison: `==`, `!=`, `<`, `>`, `<=`, `>=`
43
- * Logical: `&&`, `||`, `!`
44
- * **Control Flow:**
45
- * `if`/`else` statements.
46
- * `switch` statements.
47
- * `select` statement.
48
- * `for` loops (condition-only, basic counter-based, `range` over arrays/slices/strings).
49
- * **Data Structures:**
50
- * Arrays (`[N]T`) - Including array literals and indexing.
51
- * Slices (`[]T`) - Creation using `make([]T, len)` and `make([]T, len, cap)`.
52
- * Maps (`map[K]V`) - Creation using `make`, literals, access, assignment, `delete`, `len`, `range`.
53
- * `struct` definitions (including exported/unexported fields).
54
- * Composite Literals for structs (`MyStruct{...}`).
55
- * **Functions & Methods:**
56
- * Function definition (`func`).
57
- * Function Literals (`func() { ... }`)
58
- * Method definition with value receivers (`func (v T) Method()`).
59
- * Method definition with pointer receivers (`func (p *T) Method()`).
60
- * Function calls.
61
- * Method calls (on values and pointers).
62
- * `println` built-in (mapped to `console.log`).
63
- * Multiple return values (including assignment and usage with blank identifier).
64
- * Asynchronous Functions (`async`/`await` based on channel operations)
65
- * **Variables & Assignment:**
66
- * Variable declaration (`var`, implicitly via `:=`).
67
- * Short variable declaration (`:=`).
68
- * Assignment (`=`).
69
- * Multi-variable assignment.
70
- * Blank identifier (`_`) in assignment.
71
- * **Pointers:**
72
- * Pointer types (`*T`).
73
- * Address-of operator (`&`).
74
- * Dereference operator (`*`).
75
- * **Value Semantics:** Emulation of Go's struct copy-on-assignment behavior.
76
- * **Concurrency:**
77
- * Goroutines (`go func()`)
78
- * Channels (`chan T`, `make`, send `<-`, receive `<-`, buffered/unbuffered, closing)
79
-
80
- ## Uncovered Go Language Constructs (Based on Go By Example)
81
-
82
- The following Go constructs, present in the "Go By Example" guide, do not appear to have dedicated compliance tests yet. This list is not exhaustive but provides a starting point for future test development.
83
-
84
- * Interfaces (`interface{}`) - Definition tested, and type assertions (`v.(T)`) are now compliant, including interface-to-interface type assertions.
85
- * **Control Flow:**
86
- * `for` loops (condition-only, infinite still uncovered)
87
- * `switch` statements (with/without expression, type switches)
88
- * `select` statement (for channel operations)
89
- * `defer` statement
90
- * `panic` / `recover`
91
- * **Data Structures:**
92
- * Struct Embedding
93
- * **Functions:**
94
- * Variadic functions (`...T`)
95
- * Closures
96
- * Recursion
97
- * **Basic Types & Values:**
98
- * `iota` consts
99
- * **Concurrency:**
100
- * Mutexes (`sync.Mutex`)
101
- * **Error Handling:**
102
- * `error` interface usage
103
- * **Packages & Imports:**
104
- * Import aliasing (`import alias "path"`)
105
-
106
- This list helps identify areas where GoScript's feature coverage can be expanded and verified through new compliance tests.
107
-
108
- ## Ignored or Not-planned Go Language Constructs
109
-
110
- These are the not-planned features that we should NOT waste time adding yet:
111
-
112
- * complex number support (complex64, etc.)
113
- * **Reflection:** (`reflect` package) - Likely out of scope for direct translation.
114
- * **Testing:** (`testing` package) - Test files themselves are usually not translated.
115
- * Constants (`const`) - handling of large integer constants (exceeding standard JavaScript number limits) is currently not fully compliant.
116
- * Generics (Type parameters, constraints)
117
- * `goto` (less common, but part of the language)
118
- * **Directives:**
119
- * `//go:embed`
120
- * Dot imports (`import . "path"`) - Generally discouraged.
121
- * Handling standard library packages (e.g., `fmt`, `math`, `time`, `os`, `net/http`, `encoding/json`, `regexp`, etc.) - Requires runtime shims or direct translation.
122
- * **Input/Output & System:**
123
- * File I/O (`os.ReadFile`, `os.WriteFile`, etc.)
124
- * Command-line arguments/flags (`os.Args`, `flag` package)
125
- * Environment variables (`os.Getenv`)
126
- * Executing processes (`os/exec`)
127
- * Signals (`os/signal`)
128
- * Context (`context`)
129
- * WaitGroups (`sync.WaitGroup`)
130
- * Atomic Counters (`sync/atomic`)
131
- * Rate Limiting concepts
132
- * Worker Pools
133
- * Stateful Goroutines
@@ -1,313 +0,0 @@
1
- package compliance
2
-
3
- import (
4
- "bytes"
5
- "context"
6
- "fmt" // Added for Sprintf
7
- "io"
8
- "os"
9
- "os/exec"
10
- "path/filepath"
11
- "strings"
12
- "testing"
13
-
14
- "github.com/paralin/goscript/compiler"
15
- "github.com/sirupsen/logrus"
16
- )
17
-
18
- // TestCase defines a single Go-to-TypeScript compliance test.
19
- type TestCase struct {
20
- Name string
21
- GoSource string
22
- ExpectedOutput string
23
- }
24
-
25
- // PrepareTempTestDir creates a temp dir, copies .go files, and writes go.mod. Returns tempDir path.
26
- func PrepareTempTestDir(t *testing.T, testDir string) string {
27
- t.Helper()
28
- tempDir, err := os.MkdirTemp("", "goscript-test-")
29
- if err != nil {
30
- t.Fatalf("failed to create temp dir: %v", err)
31
- }
32
-
33
- goModPath := filepath.Join(tempDir, "go.mod")
34
- goModContent := []byte("module tempmod\n\ngo 1.24\n")
35
- if err := os.WriteFile(goModPath, goModContent, 0o644); err != nil {
36
- os.RemoveAll(tempDir) //nolint:errcheck
37
- t.Fatalf("failed to write go.mod: %v", err)
38
- }
39
-
40
- goFiles, err := filepath.Glob(filepath.Join(testDir, "*.go"))
41
- if err != nil || len(goFiles) == 0 {
42
- os.RemoveAll(tempDir) //nolint:errcheck
43
- t.Fatalf("no .go files found in %s", testDir)
44
- }
45
- for _, src := range goFiles {
46
- base := filepath.Base(src)
47
- dst := filepath.Join(tempDir, base)
48
- data, err := os.ReadFile(src)
49
- if err != nil {
50
- os.RemoveAll(tempDir) //nolint:errcheck
51
- t.Fatalf("failed to read %s: %v", src, err)
52
- }
53
- if err := os.WriteFile(dst, data, 0o644); err != nil {
54
- os.RemoveAll(tempDir) //nolint:errcheck
55
- t.Fatalf("failed to write %s: %v", dst, err)
56
- }
57
- }
58
- return tempDir
59
- }
60
-
61
- // ReadExpectedLog reads expected.log from testDir.
62
- func ReadExpectedLog(t *testing.T, testDir string) string {
63
- t.Helper()
64
- expectedLogPath := filepath.Join(testDir, "expected.log")
65
- expected, err := os.ReadFile(expectedLogPath)
66
- if err != nil {
67
- t.Fatalf("failed to read expected.log in %s: %v", testDir, err)
68
- }
69
- return string(expected)
70
- }
71
-
72
- func CompileGoToTypeScript(t *testing.T, testDir, tempDir, outputDir string, le *logrus.Entry) {
73
- t.Helper()
74
- conf := &compiler.Config{
75
- Dir: tempDir,
76
- OutputPathRoot: outputDir,
77
- }
78
- if err := conf.Validate(); err != nil {
79
- t.Fatalf("invalid compiler config: %v", err)
80
- }
81
-
82
- // Log each .go file and its mapped .gs.ts output file and contents
83
- goFiles, err := filepath.Glob(filepath.Join(tempDir, "*.go"))
84
- if err != nil || len(goFiles) == 0 {
85
- t.Fatalf("no .go files found in %s: %v", tempDir, err)
86
- }
87
- for _, src := range goFiles {
88
- base := filepath.Base(src)
89
- out := filepath.Join(outputDir, compiler.TranslateGoFilePathToTypescriptFilePath("tempmod", base))
90
- t.Logf("Compiling Go file: %s => %s", src, out)
91
- if data, err := os.ReadFile(src); err == nil {
92
- t.Logf("Source %s:\n%s", src, string(data))
93
- } else {
94
- t.Logf("could not read source %s: %v", src, err)
95
- }
96
- }
97
-
98
- comp, err := compiler.NewCompiler(conf, le, nil)
99
- if err != nil {
100
- t.Fatalf("failed to create compiler: %v", err)
101
- }
102
- cmpErr := comp.CompilePackages(context.Background(), ".")
103
- if cmpErr != nil {
104
- t.Errorf("compilation failed: %v", err)
105
- }
106
-
107
- // Log generated TypeScript files and copy them back to testDir
108
- if err := filepath.WalkDir(outputDir, func(path string, d os.DirEntry, err error) error {
109
- if err != nil {
110
- t.Logf("error walking path %s: %v", path, err)
111
- return nil
112
- }
113
- if strings.HasSuffix(path, ".gs.ts") { // Look specifically for .gs.ts files
114
- // Determine the destination path in the original testDir
115
- relPath, err := filepath.Rel(outputDir, path)
116
- if err != nil {
117
- t.Logf("failed to get relative path for %s: %v", path, err)
118
- return nil // Continue walking
119
- }
120
- // relPath is like "@go/tempmod/file.gs.ts", so extract the base file name
121
- parts := strings.Split(relPath, string(filepath.Separator))
122
- if len(parts) < 3 {
123
- t.Logf("unexpected path structure for %s", path)
124
- return nil // Continue walking
125
- }
126
- fileName := parts[len(parts)-1]
127
- destPath := filepath.Join(testDir, fileName)
128
-
129
- // Read the generated content
130
- generatedContent, err := os.ReadFile(path)
131
- if err != nil {
132
- t.Logf("could not read generated file %s: %v", path, err)
133
- return nil // Continue walking
134
- }
135
-
136
- // Determine the original Go file name
137
- goFileName := strings.TrimSuffix(fileName, ".gs.ts") + ".go"
138
-
139
- // Construct the comment
140
- comment := fmt.Sprintf("// Generated file based on %s\n// Updated when compliance tests are re-run, DO NOT EDIT!\n\n", goFileName)
141
-
142
- // Prepend the comment to the generated content
143
- finalContent := append([]byte(comment), generatedContent...)
144
-
145
- if err := os.WriteFile(destPath, finalContent, 0o644); err != nil {
146
- t.Logf("failed to write file %s: %v", destPath, err)
147
- return err
148
- }
149
-
150
- t.Logf("generated content written to %s:\n%s", destPath, string(finalContent))
151
- }
152
- return nil
153
- }); err != nil {
154
- t.Fatalf("error while walking: %v", err.Error())
155
- }
156
-
157
- if cmpErr != nil {
158
- t.Fatalf("compilation failed: %v", cmpErr)
159
- }
160
- }
161
-
162
- // WriteTypeScriptRunner writes a runner.ts file to tempDir.
163
- func WriteTypeScriptRunner(t *testing.T, tempDir string) string {
164
- t.Helper()
165
-
166
- // Find the Go source file in the temp directory
167
- goFiles, err := filepath.Glob(filepath.Join(tempDir, "*.go"))
168
- if err != nil || len(goFiles) == 0 {
169
- t.Fatalf("could not find Go source file in temp dir %s: %v", tempDir, err)
170
- }
171
- if len(goFiles) > 1 {
172
- // For simplicity, assume only one relevant Go file per test case for now.
173
- t.Logf("warning: found multiple Go files in %s, using the first one: %s", tempDir, goFiles[0])
174
- }
175
- goSourceBase := filepath.Base(goFiles[0])
176
- tsFileName := strings.TrimSuffix(goSourceBase, ".go") + ".gs.ts"
177
- tsImportPath := fmt.Sprintf("./output/@go/tempmod/%s", tsFileName)
178
-
179
- tsRunner := filepath.Join(tempDir, "runner.ts")
180
- // Import the goscript runtime and the main function from the compiled code
181
- runnerContent := fmt.Sprintf("import { goscript } from \"./goscript\";\nimport { main } from %q;\nmain();\n", tsImportPath) // Use dynamic path
182
- if err := os.WriteFile(tsRunner, []byte(runnerContent), 0o644); err != nil {
183
- t.Fatalf("failed to write runner: %v", err)
184
- }
185
- return tsRunner
186
- }
187
-
188
- // RunTypeScriptRunner runs the runner.ts file using tsx and returns its stdout.
189
- func RunTypeScriptRunner(t *testing.T, workspaceDir, tempDir, tsRunner string) string {
190
- t.Helper()
191
- cmd := exec.Command("tsx", tsRunner)
192
- cmd.Dir = tempDir
193
-
194
- // Prepend node_modules/.bin to PATH
195
- nodeBinDir := filepath.Join(workspaceDir, "node_modules", ".bin")
196
- currentPath := os.Getenv("PATH")
197
- newPath := fmt.Sprintf("%s%c%s", nodeBinDir, os.PathListSeparator, currentPath)
198
- cmd.Env = append(os.Environ(), "PATH="+newPath) // Set the modified PATH
199
-
200
- var outBuf, errBuf bytes.Buffer
201
- cmd.Stdout = io.MultiWriter(&outBuf, os.Stderr)
202
- cmd.Stderr = os.Stderr // Keep stderr going to the test output for debugging
203
- if err := cmd.Run(); err != nil {
204
- t.Fatalf("run failed: %v\nstderr: %s", err, errBuf.String())
205
- }
206
- return outBuf.String()
207
- }
208
-
209
- // copyFile copies a file from src to dst.
210
- func copyFile(src, dst string) error {
211
- sourceFile, err := os.Open(src)
212
- if err != nil {
213
- return fmt.Errorf("failed to open source file %s: %w", src, err)
214
- }
215
- defer sourceFile.Close() //nolint:errcheck
216
-
217
- // Ensure destination directory exists
218
- destDir := filepath.Dir(dst)
219
- if err := os.MkdirAll(destDir, 0o755); err != nil {
220
- return fmt.Errorf("failed to create destination directory %s: %w", destDir, err)
221
- }
222
-
223
- destFile, err := os.Create(dst)
224
- if err != nil {
225
- return fmt.Errorf("failed to create destination file %s: %w", dst, err)
226
- }
227
- defer destFile.Close() //nolint:errcheck
228
-
229
- if _, err := io.Copy(destFile, sourceFile); err != nil {
230
- return fmt.Errorf("failed to copy file content from %s to %s: %w", src, dst, err)
231
- }
232
-
233
- // Ensure data is synced to disk
234
- if err := destFile.Sync(); err != nil {
235
- return fmt.Errorf("failed to sync destination file %s: %w", dst, err)
236
- }
237
-
238
- return nil
239
- }
240
-
241
- // RunGoScriptTestDir compiles all .go files in testDir, runs the generated TypeScript, and compares output to expected.log.
242
- func RunGoScriptTestDir(t *testing.T, workspaceDir, testDir string) {
243
- t.Helper()
244
-
245
- // Check for expect-fail file
246
- expectFailPath := filepath.Join(testDir, "expect-fail")
247
- if _, err := os.Stat(expectFailPath); err == nil {
248
- t.Skipf("Skipping test %s: expect-fail file found", filepath.Base(testDir))
249
- return // Skip the test
250
- } else if !os.IsNotExist(err) {
251
- // If there was an error other than "not exists", fail the test
252
- t.Fatalf("failed to check for expect-fail file in %s: %v", testDir, err)
253
- }
254
-
255
- log := logrus.New()
256
- log.SetLevel(logrus.DebugLevel)
257
- le := logrus.NewEntry(log)
258
-
259
- tempDir := PrepareTempTestDir(t, testDir)
260
- defer os.RemoveAll(tempDir)
261
-
262
- // Create tsconfig.json in the temporary directory for path aliases
263
- builtinTsPath := filepath.Join(workspaceDir, "builtin", "builtin.ts") // Use passed workspaceDir
264
- // Ensure the path uses forward slashes for JSON compatibility, even on Windows
265
- builtinTsPathForJSON := filepath.ToSlash(builtinTsPath)
266
- tsconfigContent := fmt.Sprintf(`{
267
- "compilerOptions": {
268
- "baseUrl": ".",
269
- "paths": {
270
- "@go/builtin": ["%s"]
271
- }
272
- }
273
- }`, builtinTsPathForJSON) // Use dynamic path
274
- tsconfigPath := filepath.Join(tempDir, "tsconfig.json")
275
- if err := os.WriteFile(tsconfigPath, []byte(tsconfigContent), 0o644); err != nil {
276
- t.Fatalf("failed to write tsconfig.json to temp dir: %v", err)
277
- }
278
-
279
- outputDir := filepath.Join(tempDir, "output")
280
- CompileGoToTypeScript(t, testDir, tempDir, outputDir, le) // Pass testDir to enable copying output files back to the test directory
281
-
282
- // Copy the goscript runtime file to the temp directory
283
- // Use absolute path to avoid issues with changing working directories
284
- runtimeSrc := filepath.Join(workspaceDir, "builtin", "builtin.ts") // Use passed workspaceDir
285
- runtimeDst := filepath.Join(tempDir, "builtin.ts") // Rename to builtin.ts in temp dir
286
- if err := copyFile(runtimeSrc, runtimeDst); err != nil {
287
- t.Fatalf("failed to copy goscript runtime file: %v", err)
288
- }
289
-
290
- tsRunner := WriteTypeScriptRunner(t, tempDir)
291
- actual := strings.TrimSpace(RunTypeScriptRunner(t, workspaceDir, tempDir, tsRunner)) // Pass workspaceDir
292
-
293
- expectedLogPath := filepath.Join(testDir, "expected.log")
294
- expected, err := os.ReadFile(expectedLogPath)
295
- if os.IsNotExist(err) {
296
- // If expected.log doesn't exist, write the actual output to it
297
- t.Logf("expected.log not found, writing actual output to %s", expectedLogPath)
298
- if writeErr := os.WriteFile(expectedLogPath, []byte(actual), 0o644); writeErr != nil {
299
- t.Fatalf("failed to write expected.log: %v", writeErr)
300
- }
301
- // Test passes on the first run if expected.log is generated
302
- t.Logf("Generated expected.log for %s", filepath.Base(testDir))
303
- } else if err != nil {
304
- // If there was another error reading expected.log, fail the test
305
- t.Fatalf("failed to read expected.log in %s: %v", testDir, err)
306
- } else {
307
- // If expected.log exists, compare actual output to expected
308
- exp := strings.TrimSpace(string(expected))
309
- if actual != exp {
310
- t.Fatalf("output mismatch\nExpected:\n%s\nActual:\n%s", exp, actual)
311
- }
312
- }
313
- }
@@ -1,57 +0,0 @@
1
- package compliance
2
-
3
- import (
4
- "os"
5
- "path/filepath"
6
- "sync"
7
- "testing"
8
- )
9
-
10
- func TestCompliance(t *testing.T) {
11
- testsDir := "./tests"
12
- dirs, err := os.ReadDir(testsDir)
13
- if err != nil {
14
- t.Fatalf("failed to read tests dir: %v", err)
15
- }
16
-
17
- // Get workspace directory (project root)
18
- workspaceDir, err := os.Getwd()
19
- if err != nil {
20
- t.Fatalf("failed to get working directory: %v", err)
21
- }
22
- workspaceDir = filepath.Join(workspaceDir, "..")
23
-
24
- // First collect all test paths
25
- var testPaths []string
26
- for _, dir := range dirs {
27
- if !dir.IsDir() {
28
- continue
29
- }
30
- testPath := filepath.Join(testsDir, dir.Name())
31
- // expectedLogPath := filepath.Join(testPath, "expected.log")
32
- // if _, err := os.Stat(expectedLogPath); err != nil {
33
- // continue // skip if no expected.log
34
- //}
35
- goFiles, err := filepath.Glob(filepath.Join(testPath, "*.go"))
36
- if err != nil || len(goFiles) == 0 {
37
- t.Errorf("no .go files found in %s", testPath)
38
- continue
39
- }
40
- testPaths = append(testPaths, testPath)
41
- }
42
-
43
- // Now run tests in parallel with goroutines
44
- var wg sync.WaitGroup
45
- for _, testPath := range testPaths {
46
- wg.Add(1)
47
- go func(path string) {
48
- defer wg.Done()
49
- t.Run(filepath.Base(path), func(t *testing.T) {
50
- RunGoScriptTestDir(t, workspaceDir, path) // Pass workspaceDir
51
- })
52
- }(testPath)
53
- }
54
-
55
- // Wait for all tests to complete
56
- wg.Wait()
57
- }
@@ -1,15 +0,0 @@
1
- package main
2
-
3
- func main() {
4
- // Test basic array literal
5
- var a [3]int = [3]int{1, 2, 3}
6
- println(a[0], a[1], a[2])
7
-
8
- // Test array literal with inferred length
9
- b := [...]string{"hello", "world"}
10
- println(b[0], b[1])
11
-
12
- // Test array literal with specific element initialization
13
- c := [5]int{1: 10, 3: 30}
14
- println(c[0], c[1], c[2], c[3], c[4])
15
- }
@@ -1,19 +0,0 @@
1
- // Generated file based on array_literal.go
2
- // Updated when compliance tests are re-run, DO NOT EDIT!
3
-
4
- import * as goscript from "@go/builtin";
5
-
6
- export async function main(): Promise<void> {
7
- // Test basic array literal
8
- let a: number[] = [1, 2, 3];
9
- console.log(a[0], a[1], a[2])
10
-
11
- // Test array literal with inferred length
12
- let b = ["hello", "world"]
13
- console.log(b[0], b[1])
14
-
15
- // Test array literal with specific element initialization
16
- let c = [0, 10, 0, 30, 0]
17
- console.log(c[0], c[1], c[2], c[3], c[4])
18
- }
19
-
@@ -1,3 +0,0 @@
1
- 1 2 3
2
- hello world
3
- 0 10 0 30 0
@@ -1,26 +0,0 @@
1
- package main
2
-
3
- // This function receives from a channel, making it async.
4
- func receiveFromChan(ch chan int) int {
5
- val := <-ch // This operation makes the function async
6
- return val
7
- }
8
-
9
- // This function calls an async function, making it async too.
10
- func caller(ch chan int) int {
11
- // We expect this call to be awaited in TypeScript
12
- result := receiveFromChan(ch)
13
- return result + 1
14
- }
15
-
16
- func main() {
17
- // Create a buffered channel
18
- myChan := make(chan int, 1)
19
- myChan <- 10 // Send a value
20
-
21
- // Call the async caller function
22
- finalResult := caller(myChan)
23
- println(finalResult) // Expected output: 11
24
-
25
- close(myChan)
26
- }
@@ -1,30 +0,0 @@
1
- // Generated file based on async_basic.go
2
- // Updated when compliance tests are re-run, DO NOT EDIT!
3
-
4
- import * as goscript from "@go/builtin";
5
-
6
- // This function receives from a channel, making it async.
7
- async function receiveFromChan(ch: goscript.Channel<number>): Promise<number> {
8
- let val = await ch.receive() // This operation makes the function async
9
- return val
10
- }
11
-
12
- // This function calls an async function, making it async too.
13
- async function caller(ch: goscript.Channel<number>): Promise<number> {
14
- // We expect this call to be awaited in TypeScript
15
- let result = await receiveFromChan(ch)
16
- return result + 1
17
- }
18
-
19
- export async function main(): Promise<void> {
20
- // Create a buffered channel
21
- let myChan = goscript.makeChannel<number>(1)
22
- await myChan.send(10)
23
-
24
- // Call the async caller function
25
- let finalResult = await caller(myChan)
26
- console.log(finalResult) // Expected output: 11
27
-
28
- myChan.close()
29
- }
30
-
@@ -1 +0,0 @@
1
- 11
@@ -1,15 +0,0 @@
1
- package main
2
-
3
- func main() {
4
- // === Basic Arithmetic ===
5
- add := 2 + 3
6
- sub := 10 - 4
7
- mul := 6 * 7
8
- div := 20 / 5
9
- mod := 17 % 3
10
- println("Addition: Expected: 5, Actual:", add)
11
- println("Subtraction: Expected: 6, Actual:", sub)
12
- println("Multiplication: Expected: 42, Actual:", mul)
13
- println("Division: Expected: 4, Actual:", div)
14
- println("Modulus: Expected: 2, Actual:", mod)
15
- }
@@ -1,19 +0,0 @@
1
- // Generated file based on basic_arithmetic.go
2
- // Updated when compliance tests are re-run, DO NOT EDIT!
3
-
4
- import * as goscript from "@go/builtin";
5
-
6
- export async function main(): Promise<void> {
7
- // === Basic Arithmetic ===
8
- let add = 2 + 3
9
- let sub = 10 - 4
10
- let mul = 6 * 7
11
- let div = 20 / 5
12
- let mod = 17 % 3
13
- console.log("Addition: Expected: 5, Actual:", add)
14
- console.log("Subtraction: Expected: 6, Actual:", sub)
15
- console.log("Multiplication: Expected: 42, Actual:", mul)
16
- console.log("Division: Expected: 4, Actual:", div)
17
- console.log("Modulus: Expected: 2, Actual:", mod)
18
- }
19
-
@@ -1,5 +0,0 @@
1
- Addition: Expected: 5, Actual: 5
2
- Subtraction: Expected: 6, Actual: 6
3
- Multiplication: Expected: 42, Actual: 42
4
- Division: Expected: 4, Actual: 4
5
- Modulus: Expected: 2, Actual: 2
@@ -1,13 +0,0 @@
1
- package main
2
-
3
- func main() {
4
- // === Boolean Logic ===
5
- a := true
6
- b := false
7
- and := a && b
8
- or := a || b
9
- notA := !a
10
- println("AND: Expected: false, Actual:", and)
11
- println("OR: Expected: true, Actual:", or)
12
- println("NOT: Expected: false, Actual:", notA)
13
- }
@@ -1,17 +0,0 @@
1
- // Generated file based on boolean_logic.go
2
- // Updated when compliance tests are re-run, DO NOT EDIT!
3
-
4
- import * as goscript from "@go/builtin";
5
-
6
- export async function main(): Promise<void> {
7
- // === Boolean Logic ===
8
- let a = true
9
- let b = false
10
- let and = a && b
11
- let or = a || b
12
- let notA = !a
13
- console.log("AND: Expected: false, Actual:", and)
14
- console.log("OR: Expected: true, Actual:", or)
15
- console.log("NOT: Expected: false, Actual:", notA)
16
- }
17
-