goscript 0.0.2

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 (160) hide show
  1. package/.aider-prompt +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +427 -0
  4. package/builtin/builtin.ts +507 -0
  5. package/cmd/goscript/cmd_compile.go +59 -0
  6. package/cmd/goscript/main.go +23 -0
  7. package/compiler/compile.go +183 -0
  8. package/compiler/compile_comment.go +41 -0
  9. package/compiler/compile_decls.go +72 -0
  10. package/compiler/compile_expr.go +831 -0
  11. package/compiler/compile_field.go +89 -0
  12. package/compiler/compile_spec.go +256 -0
  13. package/compiler/compile_stmt.go +1509 -0
  14. package/compiler/compiler.go +81 -0
  15. package/compiler/config.go +32 -0
  16. package/compiler/context.go +9 -0
  17. package/compiler/file_compiler.go +80 -0
  18. package/compiler/output_path.go +31 -0
  19. package/compiler/pkg_compiler.go +73 -0
  20. package/compiler/writer.go +90 -0
  21. package/compliance/COMPLIANCE.md +133 -0
  22. package/compliance/compliance.go +313 -0
  23. package/compliance/compliance_test.go +57 -0
  24. package/compliance/tests/array_literal/array_literal.go +15 -0
  25. package/compliance/tests/array_literal/array_literal.gs.ts +19 -0
  26. package/compliance/tests/array_literal/expected.log +3 -0
  27. package/compliance/tests/async_basic/async_basic.go +26 -0
  28. package/compliance/tests/async_basic/async_basic.gs.ts +30 -0
  29. package/compliance/tests/async_basic/expected.log +1 -0
  30. package/compliance/tests/basic_arithmetic/basic_arithmetic.go +15 -0
  31. package/compliance/tests/basic_arithmetic/basic_arithmetic.gs.ts +19 -0
  32. package/compliance/tests/basic_arithmetic/expected.log +5 -0
  33. package/compliance/tests/boolean_logic/boolean_logic.go +13 -0
  34. package/compliance/tests/boolean_logic/boolean_logic.gs.ts +17 -0
  35. package/compliance/tests/boolean_logic/expected.log +3 -0
  36. package/compliance/tests/channel_basic/channel_basic.go +12 -0
  37. package/compliance/tests/channel_basic/channel_basic.gs.ts +18 -0
  38. package/compliance/tests/channel_basic/expected.log +1 -0
  39. package/compliance/tests/composite_literal_assignment/composite_literal_assignment.go +20 -0
  40. package/compliance/tests/composite_literal_assignment/composite_literal_assignment.gs.ts +27 -0
  41. package/compliance/tests/composite_literal_assignment/expected.log +2 -0
  42. package/compliance/tests/constants/constants.go +18 -0
  43. package/compliance/tests/constants/constants.gs.ts +22 -0
  44. package/compliance/tests/constants/expected.log +3 -0
  45. package/compliance/tests/copy_independence/copy_independence.go +29 -0
  46. package/compliance/tests/copy_independence/copy_independence.gs.ts +36 -0
  47. package/compliance/tests/copy_independence/expected.log +4 -0
  48. package/compliance/tests/float64/expected.log +6 -0
  49. package/compliance/tests/float64/float64.go +28 -0
  50. package/compliance/tests/float64/float64.gs.ts +32 -0
  51. package/compliance/tests/for_loop_basic/expected.log +5 -0
  52. package/compliance/tests/for_loop_basic/for_loop_basic.go +9 -0
  53. package/compliance/tests/for_loop_basic/for_loop_basic.gs.ts +13 -0
  54. package/compliance/tests/for_loop_condition_only/expected.log +5 -0
  55. package/compliance/tests/for_loop_condition_only/main.go +9 -0
  56. package/compliance/tests/for_loop_condition_only/main.gs.ts +13 -0
  57. package/compliance/tests/for_range/expected.log +9 -0
  58. package/compliance/tests/for_range/for_range.go +26 -0
  59. package/compliance/tests/for_range/for_range.gs.ts +45 -0
  60. package/compliance/tests/for_range_index_use/expected.log +6 -0
  61. package/compliance/tests/for_range_index_use/for_range_index_use.go +11 -0
  62. package/compliance/tests/for_range_index_use/for_range_index_use.gs.ts +18 -0
  63. package/compliance/tests/func_literal/expected.log +1 -0
  64. package/compliance/tests/func_literal/func_literal.go +10 -0
  65. package/compliance/tests/func_literal/func_literal.gs.ts +15 -0
  66. package/compliance/tests/function_call_result_assignment/expected.log +2 -0
  67. package/compliance/tests/function_call_result_assignment/function_call_result_assignment.go +24 -0
  68. package/compliance/tests/function_call_result_assignment/function_call_result_assignment.gs.ts +31 -0
  69. package/compliance/tests/if_statement/expected.log +1 -0
  70. package/compliance/tests/if_statement/if_statement.go +11 -0
  71. package/compliance/tests/if_statement/if_statement.gs.ts +15 -0
  72. package/compliance/tests/interface_to_interface_type_assertion/expected.log +1 -0
  73. package/compliance/tests/interface_to_interface_type_assertion/interface_to_interface_type_assertion.go +30 -0
  74. package/compliance/tests/interface_to_interface_type_assertion/interface_to_interface_type_assertion.gs.ts +41 -0
  75. package/compliance/tests/interface_type_assertion/expected.log +1 -0
  76. package/compliance/tests/interface_type_assertion/interface_type_assertion.go +26 -0
  77. package/compliance/tests/interface_type_assertion/interface_type_assertion.gs.ts +36 -0
  78. package/compliance/tests/map_support/expected.log +13 -0
  79. package/compliance/tests/map_support/map_support.go +89 -0
  80. package/compliance/tests/map_support/map_support.gs.ts +102 -0
  81. package/compliance/tests/method_call_on_pointer_receiver/expected.log +1 -0
  82. package/compliance/tests/method_call_on_pointer_receiver/method_call_on_pointer_receiver.go +19 -0
  83. package/compliance/tests/method_call_on_pointer_receiver/method_call_on_pointer_receiver.gs.ts +27 -0
  84. package/compliance/tests/method_call_on_pointer_via_value/expected.log +1 -0
  85. package/compliance/tests/method_call_on_pointer_via_value/method_call_on_pointer_via_value.go +29 -0
  86. package/compliance/tests/method_call_on_pointer_via_value/method_call_on_pointer_via_value.gs.ts +38 -0
  87. package/compliance/tests/method_call_on_value_receiver/expected.log +1 -0
  88. package/compliance/tests/method_call_on_value_receiver/method_call_on_value_receiver.go +16 -0
  89. package/compliance/tests/method_call_on_value_receiver/method_call_on_value_receiver.gs.ts +24 -0
  90. package/compliance/tests/method_call_on_value_via_pointer/expected.log +2 -0
  91. package/compliance/tests/method_call_on_value_via_pointer/method_call_on_value_via_pointer.go +30 -0
  92. package/compliance/tests/method_call_on_value_via_pointer/method_call_on_value_via_pointer.gs.ts +38 -0
  93. package/compliance/tests/multiple_return_values/expected.log +6 -0
  94. package/compliance/tests/multiple_return_values/multiple_return_values.go +19 -0
  95. package/compliance/tests/multiple_return_values/multiple_return_values.gs.ts +23 -0
  96. package/compliance/tests/pointer_assignment_no_copy/expected.log +2 -0
  97. package/compliance/tests/pointer_assignment_no_copy/pointer_assignment_no_copy.go +28 -0
  98. package/compliance/tests/pointer_assignment_no_copy/pointer_assignment_no_copy.gs.ts +35 -0
  99. package/compliance/tests/pointer_composite_literal_assignment/expected.log +3 -0
  100. package/compliance/tests/pointer_composite_literal_assignment/pointer_composite_literal_assignment.go +23 -0
  101. package/compliance/tests/pointer_composite_literal_assignment/pointer_composite_literal_assignment.gs.ts +30 -0
  102. package/compliance/tests/pointer_deref_multiassign/expected.log +0 -0
  103. package/compliance/tests/pointer_deref_multiassign/pointer_deref_multiassign.go +17 -0
  104. package/compliance/tests/pointer_deref_multiassign/pointer_deref_multiassign.gs.ts +27 -0
  105. package/compliance/tests/pointer_initialization/expected.log +1 -0
  106. package/compliance/tests/pointer_initialization/pointer_initialization.go +16 -0
  107. package/compliance/tests/pointer_initialization/pointer_initialization.gs.ts +22 -0
  108. package/compliance/tests/select_receive_on_closed_channel_no_default/expected.log +1 -0
  109. package/compliance/tests/select_receive_on_closed_channel_no_default/select_receive_on_closed_channel_no_default.go +15 -0
  110. package/compliance/tests/select_receive_on_closed_channel_no_default/select_receive_on_closed_channel_no_default.gs.ts +31 -0
  111. package/compliance/tests/select_send_on_full_buffered_channel_with_default/expected.log +1 -0
  112. package/compliance/tests/select_send_on_full_buffered_channel_with_default/select_send_on_full_buffered_channel_with_default.go +13 -0
  113. package/compliance/tests/select_send_on_full_buffered_channel_with_default/select_send_on_full_buffered_channel_with_default.gs.ts +35 -0
  114. package/compliance/tests/select_statement/expected.log +9 -0
  115. package/compliance/tests/select_statement/select_statement.go +109 -0
  116. package/compliance/tests/select_statement/select_statement.gs.ts +239 -0
  117. package/compliance/tests/simple/expected.log +1 -0
  118. package/compliance/tests/simple/simple.go +5 -0
  119. package/compliance/tests/simple/simple.gs.ts +9 -0
  120. package/compliance/tests/simple_deref_assignment/expected.log +2 -0
  121. package/compliance/tests/simple_deref_assignment/simple_deref_assignment.go +19 -0
  122. package/compliance/tests/simple_deref_assignment/simple_deref_assignment.gs.ts +26 -0
  123. package/compliance/tests/slices/expected.log +7 -0
  124. package/compliance/tests/slices/slices.go +22 -0
  125. package/compliance/tests/slices/slices.gs.ts +26 -0
  126. package/compliance/tests/string_rune_conversion/expected.log +3 -0
  127. package/compliance/tests/string_rune_conversion/string_rune_conversion.go +16 -0
  128. package/compliance/tests/string_rune_conversion/string_rune_conversion.gs.ts +22 -0
  129. package/compliance/tests/struct_field_access/expected.log +2 -0
  130. package/compliance/tests/struct_field_access/struct_field_access.go +13 -0
  131. package/compliance/tests/struct_field_access/struct_field_access.gs.ts +20 -0
  132. package/compliance/tests/struct_value_init_clone/expected.log +5 -0
  133. package/compliance/tests/struct_value_init_clone/struct_value_init_clone.go +28 -0
  134. package/compliance/tests/struct_value_init_clone/struct_value_init_clone.gs.ts +35 -0
  135. package/compliance/tests/switch_statement/expected.log +14 -0
  136. package/compliance/tests/switch_statement/switch_statement.go +59 -0
  137. package/compliance/tests/switch_statement/switch_statement.gs.ts +85 -0
  138. package/compliance/tests/value_type_copy_behavior/expected.log +3 -0
  139. package/compliance/tests/value_type_copy_behavior/value_type_copy_behavior.go +25 -0
  140. package/compliance/tests/value_type_copy_behavior/value_type_copy_behavior.gs.ts +34 -0
  141. package/design/DESIGN.md +599 -0
  142. package/example/simple/build.bash +10 -0
  143. package/example/simple/go.mod +23 -0
  144. package/example/simple/go.sum +39 -0
  145. package/example/simple/main.go +138 -0
  146. package/example/simple/main.gs.ts +133 -0
  147. package/example/simple/main.ts +3 -0
  148. package/example/simple/main_test.go +59 -0
  149. package/example/simple/main_tools.go +5 -0
  150. package/example/simple/package.json +7 -0
  151. package/example/simple/run.bash +6 -0
  152. package/example/simple/tsconfig.json +28 -0
  153. package/example/simple/yarn.lock +8 -0
  154. package/go.mod +22 -0
  155. package/go.sum +39 -0
  156. package/output/output.go +10 -0
  157. package/package.json +14 -0
  158. package/tsconfig.json +10 -0
  159. package/types/tokens.go +65 -0
  160. package/types/types.go +46 -0
@@ -0,0 +1,81 @@
1
+ package compiler
2
+
3
+ import (
4
+ "context"
5
+ "os"
6
+
7
+ "github.com/sirupsen/logrus"
8
+ "golang.org/x/tools/go/packages"
9
+ )
10
+
11
+ // Compiler is the root compiler for a project.
12
+ type Compiler struct {
13
+ le *logrus.Entry
14
+ config Config
15
+ opts packages.Config
16
+ }
17
+
18
+ // NewCompiler builds a new Compiler
19
+ // opts can be nil
20
+ func NewCompiler(conf *Config, le *logrus.Entry, opts *packages.Config) (*Compiler, error) {
21
+ if err := conf.Validate(); err != nil {
22
+ return nil, err
23
+ }
24
+
25
+ if opts == nil {
26
+ opts = &packages.Config{Env: os.Environ()}
27
+ }
28
+ // opts.Logf = c.le.Debugf
29
+ opts.Tests = false
30
+ opts.Env = append(opts.Env, "GOOS=js", "GOARCH=wasm")
31
+ opts.Dir = conf.Dir
32
+
33
+ // NeedName adds Name and PkgPath.
34
+ // NeedFiles adds GoFiles and OtherFiles.
35
+ // NeedCompiledGoFiles adds CompiledGoFiles.
36
+ // NeedImports adds Imports. If NeedDeps is not set, the Imports field will contain
37
+ // "placeholder" Packages with only the ID set.
38
+ // NeedDeps adds the fields requested by the LoadMode in the packages in Imports.
39
+ // NeedExportsFile adds ExportsFile.
40
+ // NeedTypes adds Types, Fset, and IllTyped.
41
+ // NeedSyntax adds Syntax.
42
+ // NeedTypesInfo adds TypesInfo.
43
+ // NeedTypesSizes adds TypesSizes.
44
+ // TODO: disable these if not needed
45
+ opts.Mode |= packages.NeedName |
46
+ packages.NeedFiles |
47
+ packages.NeedCompiledGoFiles |
48
+ packages.NeedImports |
49
+ packages.NeedDeps |
50
+ packages.NeedExportFile |
51
+ packages.NeedTypes |
52
+ packages.NeedSyntax |
53
+ packages.NeedTypesInfo |
54
+ packages.NeedTypesSizes
55
+
56
+ return &Compiler{config: *conf, le: le, opts: *opts}, nil
57
+ }
58
+
59
+ // CompilePackages attempts to build packages.
60
+ func (c *Compiler) CompilePackages(ctx context.Context, patterns ...string) error {
61
+ opts := c.opts
62
+ opts.Context = ctx
63
+
64
+ pkgs, err := packages.Load(&opts, patterns...)
65
+ if err != nil {
66
+ return err
67
+ }
68
+
69
+ for _, pkg := range pkgs {
70
+ pkgCompiler, err := NewPackageCompiler(c.le, &c.config, pkg)
71
+ if err != nil {
72
+ return err
73
+ }
74
+
75
+ if err := pkgCompiler.Compile(ctx); err != nil {
76
+ return err
77
+ }
78
+ }
79
+
80
+ return nil
81
+ }
@@ -0,0 +1,32 @@
1
+ package compiler
2
+
3
+ import (
4
+ "go/token"
5
+
6
+ "github.com/pkg/errors"
7
+ )
8
+
9
+ // Config is the configuration for the compiler
10
+ // Dir is the working directory for the compiler. If empty, uses the current working directory.
11
+ type Config struct {
12
+ fset *token.FileSet
13
+
14
+ // Dir is the working directory for the compiler. If empty, uses the current working directory.
15
+ Dir string
16
+ // OutputPathRoot is the output path root.
17
+ OutputPathRoot string
18
+ }
19
+
20
+ // Validate checks the config.
21
+ func (c *Config) Validate() error {
22
+ if c.fset == nil {
23
+ c.fset = token.NewFileSet()
24
+ }
25
+ if c == nil {
26
+ return errors.New("config cannot be nil")
27
+ }
28
+ if c.OutputPathRoot == "" {
29
+ return errors.New("output path root must be specified")
30
+ }
31
+ return nil
32
+ }
@@ -0,0 +1,9 @@
1
+ package compiler
2
+
3
+ // CompilerContext is the context for the compiler.
4
+ type CompilerContext struct {
5
+ // GoPackage is the name of the go package to compile
6
+ GoPackage string
7
+ // ComputedTsPackage is the path to the typescript package for this Go package.
8
+ ComputedTsPackage string
9
+ }
@@ -0,0 +1,80 @@
1
+ package compiler
2
+
3
+ import (
4
+ "context"
5
+ "fmt"
6
+ "go/ast"
7
+ "os"
8
+ "path/filepath"
9
+
10
+ "golang.org/x/tools/go/packages"
11
+ )
12
+
13
+ // fileImport is an import in a file.
14
+ type fileImport struct {
15
+ importPath string
16
+ importVars map[string]struct{}
17
+ }
18
+
19
+ // FileCompiler is the root compiler for a file.
20
+ type FileCompiler struct {
21
+ compilerConfig *Config
22
+ codeWriter *TSCodeWriter
23
+ pkg *packages.Package
24
+ ast *ast.File
25
+ fullPath string
26
+
27
+ imports map[string]fileImport
28
+ }
29
+
30
+ // NewFileCompiler builds a new FileCompiler
31
+ func NewFileCompiler(
32
+ compilerConf *Config,
33
+ pkg *packages.Package,
34
+ astFile *ast.File,
35
+ fullPath string,
36
+ ) (*FileCompiler, error) {
37
+ return &FileCompiler{
38
+ compilerConfig: compilerConf,
39
+ pkg: pkg,
40
+ ast: astFile,
41
+ fullPath: fullPath,
42
+
43
+ imports: make(map[string]fileImport),
44
+ }, nil
45
+ }
46
+
47
+ // Compile compiles a file.
48
+ func (c *FileCompiler) Compile(ctx context.Context) error {
49
+ f := c.ast
50
+
51
+ pkgPath := c.pkg.PkgPath
52
+ outputFilePath := TranslateGoFilePathToTypescriptFilePath(pkgPath, filepath.Base(c.fullPath))
53
+ outputFilePathAbs := filepath.Join(c.compilerConfig.OutputPathRoot, outputFilePath)
54
+
55
+ if err := os.MkdirAll(filepath.Dir(outputFilePathAbs), 0o755); err != nil {
56
+ return err
57
+ }
58
+
59
+ of, err := os.OpenFile(outputFilePathAbs, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o644)
60
+ if err != nil {
61
+ return err
62
+ }
63
+ defer of.Close() //nolint:errcheck
64
+
65
+ c.codeWriter = NewTSCodeWriter(of)
66
+ // Create comment map
67
+ cmap := ast.NewCommentMap(c.pkg.Fset, f, f.Comments)
68
+ // Pass comment map to compiler
69
+ goWriter := NewGoToTSCompiler(c.codeWriter, c.pkg, cmap)
70
+
71
+ // Add import for the goscript runtime using namespace import and alias
72
+ c.codeWriter.WriteLine("import * as goscript from \"@go/builtin\";")
73
+ c.codeWriter.WriteLine("") // Add a newline after the import
74
+
75
+ if err := goWriter.WriteDecls(f.Decls); err != nil {
76
+ return fmt.Errorf("failed to write declarations: %w", err)
77
+ }
78
+
79
+ return nil
80
+ }
@@ -0,0 +1,31 @@
1
+ package compiler
2
+
3
+ import (
4
+ "fmt"
5
+ "path/filepath"
6
+ "strings"
7
+ )
8
+
9
+ var typeScriptGoStubPrefix = "@ts/"
10
+
11
+ // translateGoPathToTypescriptPath translates a go package import path to a typescript import path.
12
+ func translateGoPathToTypescriptPath(goImportPath string) string {
13
+ if strings.HasPrefix(goImportPath, typeScriptGoStubPrefix) {
14
+ return goImportPath[len(typeScriptGoStubPrefix):]
15
+ }
16
+ return fmt.Sprintf("@go/%s", goImportPath)
17
+ }
18
+
19
+ // packageNameFromGoPath attempts to determine the package name from the last segment of the go path.
20
+ func packageNameFromGoPath(goPkgPath string) string {
21
+ pts := strings.Split(goPkgPath, "/")
22
+ return pts[len(pts)-1]
23
+ }
24
+
25
+ // TranslateGoFilePathToTypescriptFilePath converts the go package path and typescript filename to output path within the typescript output dir
26
+ func TranslateGoFilePathToTypescriptFilePath(goPkgPath, goCodeFilename string) string {
27
+ op := translateGoPathToTypescriptPath(goPkgPath)
28
+ baseFilename := goCodeFilename[:len(goCodeFilename)-3]
29
+ baseFilename = fmt.Sprintf("%s.gs.ts", baseFilename)
30
+ return filepath.Join(op, baseFilename)
31
+ }
@@ -0,0 +1,73 @@
1
+ package compiler
2
+
3
+ import (
4
+ "context"
5
+ "go/ast"
6
+ "os"
7
+ "path/filepath"
8
+
9
+ "github.com/paralin/goscript/output"
10
+ "github.com/sirupsen/logrus"
11
+ "golang.org/x/tools/go/packages"
12
+ )
13
+
14
+ // PackageCompiler compiles an entire package.
15
+ type PackageCompiler struct {
16
+ le *logrus.Entry
17
+ compilerConf *Config
18
+ outputPath string
19
+ pkg *packages.Package
20
+ }
21
+
22
+ // NewPackageCompiler builds a new PackageCompiler.
23
+ func NewPackageCompiler(
24
+ le *logrus.Entry,
25
+ compilerConf *Config,
26
+ pkg *packages.Package,
27
+ ) (*PackageCompiler, error) {
28
+ res := &PackageCompiler{
29
+ le: le,
30
+ pkg: pkg,
31
+ compilerConf: compilerConf,
32
+ outputPath: output.ComputeModulePath(compilerConf.OutputPathRoot, pkg.PkgPath),
33
+ }
34
+
35
+ return res, nil
36
+ }
37
+
38
+ // Compile compiles the package.
39
+ func (c *PackageCompiler) Compile(ctx context.Context) error {
40
+ wd := c.compilerConf.Dir
41
+ if wd == "" {
42
+ var err error
43
+ wd, err = os.Getwd()
44
+ if err != nil {
45
+ return err
46
+ }
47
+ }
48
+
49
+ // Compile the files in the package one at a time
50
+ for i, f := range c.pkg.Syntax {
51
+ fileName := c.pkg.CompiledGoFiles[i]
52
+ relWdFileName, err := filepath.Rel(wd, fileName)
53
+ if err != nil {
54
+ return err
55
+ }
56
+
57
+ c.le.WithField("file", relWdFileName).Debug("compiling file")
58
+ if err := c.CompileFile(ctx, fileName, f); err != nil {
59
+ return err
60
+ }
61
+ }
62
+
63
+ return nil
64
+ }
65
+
66
+ // CompileFile compiles a file.
67
+ func (p *PackageCompiler) CompileFile(ctx context.Context, name string, syntax *ast.File) error {
68
+ fileCompiler, err := NewFileCompiler(p.compilerConf, p.pkg, syntax, name)
69
+ if err != nil {
70
+ return err
71
+ }
72
+ return fileCompiler.Compile(ctx)
73
+ }
@@ -0,0 +1,90 @@
1
+ package compiler
2
+
3
+ import (
4
+ "fmt"
5
+ "io"
6
+ "strings"
7
+ )
8
+
9
+ // TSCodeWriter writes TypeScript code.
10
+ type TSCodeWriter struct {
11
+ w io.Writer
12
+ indentLevel int
13
+ sectionWrittenFlag bool
14
+ lineWritten bool
15
+ }
16
+
17
+ // NewTSCodeWriter builds a new TypeScript code writer.
18
+ func NewTSCodeWriter(w io.Writer) *TSCodeWriter {
19
+ return &TSCodeWriter{w: w}
20
+ }
21
+
22
+ // WriteLinePreamble writes the indentation.
23
+ func (w *TSCodeWriter) WriteLinePreamble() {
24
+ w.sectionWrittenFlag = true
25
+ w.lineWritten = false
26
+ for range w.indentLevel {
27
+ w.w.Write([]byte{byte('\t')}) //nolint:errcheck
28
+ }
29
+ }
30
+
31
+ // WriteLine writes a line of code to the output.
32
+ func (w *TSCodeWriter) WriteLine(line string) {
33
+ if w.lineWritten {
34
+ w.WriteLinePreamble()
35
+ }
36
+ w.w.Write([]byte(line)) //nolint:errcheck
37
+ w.w.Write([]byte{byte('\n')}) //nolint:errcheck
38
+ w.lineWritten = true
39
+ }
40
+
41
+ // WriteLinef writes a formatted line of code to the output.
42
+ func (w *TSCodeWriter) WriteLinef(line string, args ...any) {
43
+ l := fmt.Sprintf(line, args...)
44
+ w.WriteLine(l)
45
+ }
46
+
47
+ // Indent changes the indentation level by a delta.
48
+ func (w *TSCodeWriter) Indent(count int) {
49
+ w.indentLevel += count
50
+ if w.indentLevel < 0 {
51
+ w.indentLevel = 0
52
+ }
53
+ }
54
+
55
+ // WriteImport writes a TypeScript import.
56
+ func (w *TSCodeWriter) WriteImport(symbolName, importPath string) {
57
+ w.WriteLinef("import * as %s from %q;", symbolName, importPath)
58
+ }
59
+
60
+ // WriteCommentLine writes a comment as a // line.
61
+ func (w *TSCodeWriter) WriteCommentLine(commentText string) {
62
+ lines := strings.Split(commentText, "\n")
63
+ for _, line := range lines {
64
+ w.WriteLinef("// %s", line)
65
+ }
66
+ }
67
+
68
+ // WriteCommentInline write a comment within /* */.
69
+ func (w *TSCodeWriter) WriteCommentInline(commentText string) {
70
+ w.w.Write([]byte("/* ")) //nolint:errcheck
71
+ w.w.Write([]byte(commentText)) //nolint:errcheck
72
+ w.w.Write([]byte(" */")) //nolint:errcheck
73
+ }
74
+
75
+ // WriteLiterally writes something to the output without processing
76
+ func (w *TSCodeWriter) WriteLiterally(literal string) {
77
+ w.sectionWrittenFlag = true
78
+ if w.lineWritten {
79
+ w.WriteLinePreamble()
80
+ }
81
+ w.w.Write([]byte(literal))
82
+ }
83
+
84
+ // WriteSectionTail writes the end of a section.
85
+ func (w *TSCodeWriter) WriteSectionTail() {
86
+ if w.sectionWrittenFlag {
87
+ w.WriteLine("")
88
+ w.sectionWrittenFlag = false
89
+ }
90
+ }
@@ -0,0 +1,133 @@
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