goscript 0.0.40 → 0.0.42
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/compiler/analysis.go +173 -2
- package/compiler/compiler.go +14 -4
- package/compiler/expr-type.go +25 -0
- package/compiler/field.go +4 -4
- package/compiler/spec.go +1 -1
- package/compiler/stmt.go +118 -17
- package/compiler/type.go +19 -4
- package/dist/gs/builtin/builtin.d.ts +10 -8
- package/dist/gs/builtin/builtin.js +14 -53
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/errors.d.ts +8 -0
- package/dist/gs/builtin/errors.js +18 -0
- package/dist/gs/builtin/errors.js.map +1 -0
- package/dist/gs/builtin/index.d.ts +7 -0
- package/dist/gs/builtin/index.js +7 -0
- package/dist/gs/builtin/index.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +5 -2
- package/dist/gs/builtin/slice.js +110 -77
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.d.ts +1 -1
- package/dist/gs/bytes/buffer.gs.js +1 -1
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.d.ts +1 -1
- package/dist/gs/bytes/bytes.gs.js +1 -1
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/bytes/iter.gs.d.ts +1 -1
- package/dist/gs/bytes/iter.gs.js +1 -1
- package/dist/gs/bytes/iter.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.d.ts +1 -1
- package/dist/gs/bytes/reader.gs.js +1 -1
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/context/context.d.ts +1 -1
- package/dist/gs/context/context.js +1 -1
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/errors/errors.d.ts +1 -1
- package/dist/gs/errors/errors.js +3 -15
- package/dist/gs/errors/errors.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/errors.d.ts +1 -1
- package/dist/gs/github.com/pkg/errors/errors.js +1 -1
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/go113.d.ts +1 -1
- package/dist/gs/github.com/pkg/errors/go113.js +1 -1
- package/dist/gs/github.com/pkg/errors/go113.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/stack.d.ts +1 -1
- package/dist/gs/github.com/pkg/errors/stack.js +1 -1
- package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
- package/dist/gs/internal/byteorder/index.d.ts +1 -1
- package/dist/gs/internal/byteorder/index.js +1 -1
- package/dist/gs/internal/byteorder/index.js.map +1 -1
- package/dist/gs/internal/oserror/errors.d.ts +1 -1
- package/dist/gs/io/fs/format.js +1 -1
- package/dist/gs/io/fs/format.js.map +1 -1
- package/dist/gs/io/fs/fs.d.ts +1 -1
- package/dist/gs/io/fs/fs.js +1 -1
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/fs/glob.d.ts +1 -1
- package/dist/gs/io/fs/glob.js +1 -1
- package/dist/gs/io/fs/glob.js.map +1 -1
- package/dist/gs/io/fs/readdir.d.ts +1 -1
- package/dist/gs/io/fs/readdir.js +1 -1
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/readfile.d.ts +1 -1
- package/dist/gs/io/fs/readfile.js +1 -1
- package/dist/gs/io/fs/readfile.js.map +1 -1
- package/dist/gs/io/fs/stat.d.ts +1 -1
- package/dist/gs/io/fs/stat.js +1 -1
- package/dist/gs/io/fs/stat.js.map +1 -1
- package/dist/gs/io/fs/sub.d.ts +1 -1
- package/dist/gs/io/fs/sub.js +1 -1
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/fs/walk.d.ts +1 -1
- package/dist/gs/io/fs/walk.js +1 -1
- package/dist/gs/io/fs/walk.js.map +1 -1
- package/dist/gs/io/io.d.ts +1 -1
- package/dist/gs/maps/iter.d.ts +1 -1
- package/dist/gs/maps/iter.js +1 -1
- package/dist/gs/maps/iter.js.map +1 -1
- package/dist/gs/maps/maps.d.ts +1 -1
- package/dist/gs/maps/maps.js +1 -1
- package/dist/gs/maps/maps.js.map +1 -1
- package/dist/gs/math/erfinv.gs.js +1 -1
- package/dist/gs/math/erfinv.gs.js.map +1 -1
- package/dist/gs/math/gamma.gs.js +1 -1
- package/dist/gs/math/gamma.gs.js.map +1 -1
- package/dist/gs/math/j0.gs.js +1 -1
- package/dist/gs/math/j0.gs.js.map +1 -1
- package/dist/gs/math/j1.gs.js +1 -1
- package/dist/gs/math/j1.gs.js.map +1 -1
- package/dist/gs/math/lgamma.gs.js +1 -1
- package/dist/gs/math/lgamma.gs.js.map +1 -1
- package/dist/gs/math/pow10.gs.js +1 -1
- package/dist/gs/math/pow10.gs.js.map +1 -1
- package/dist/gs/math/sin.gs.js +1 -1
- package/dist/gs/math/sin.gs.js.map +1 -1
- package/dist/gs/math/tan.gs.js +1 -1
- package/dist/gs/math/tan.gs.js.map +1 -1
- package/dist/gs/math/tanh.gs.js +1 -1
- package/dist/gs/math/tanh.gs.js.map +1 -1
- package/dist/gs/math/trig_reduce.gs.js +1 -1
- package/dist/gs/math/trig_reduce.gs.js.map +1 -1
- package/dist/gs/os/dir.gs.d.ts +1 -1
- package/dist/gs/os/dir_unix.gs.d.ts +1 -1
- package/dist/gs/os/dir_unix.gs.js +1 -1
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/dirent_js.gs.d.ts +1 -1
- package/dist/gs/os/env.gs.d.ts +1 -1
- package/dist/gs/os/env.gs.js +1 -1
- package/dist/gs/os/env.gs.js.map +1 -1
- package/dist/gs/os/error.gs.d.ts +1 -1
- package/dist/gs/os/error.gs.js +1 -1
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.d.ts +1 -1
- package/dist/gs/os/exec.gs.js +1 -1
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.d.ts +1 -1
- package/dist/gs/os/exec_posix.gs.js +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/exec_unix.gs.d.ts +1 -1
- package/dist/gs/os/executable.gs.d.ts +1 -1
- package/dist/gs/os/executable_js.gs.d.ts +1 -1
- package/dist/gs/os/executable_wasm.gs.d.ts +1 -1
- package/dist/gs/os/file_constants_js.gs.d.ts +1 -1
- package/dist/gs/os/file_constants_js.gs.js +1 -1
- package/dist/gs/os/file_constants_js.gs.js.map +1 -1
- package/dist/gs/os/file_js.gs.d.ts +1 -1
- package/dist/gs/os/file_open_unix.gs.d.ts +1 -1
- package/dist/gs/os/file_posix_js.gs.d.ts +1 -1
- package/dist/gs/os/file_unix_js.gs.d.ts +1 -1
- package/dist/gs/os/getwd_js.gs.d.ts +1 -1
- package/dist/gs/os/path.gs.d.ts +1 -1
- package/dist/gs/os/path.gs.js +1 -1
- package/dist/gs/os/path.gs.js.map +1 -1
- package/dist/gs/os/path_unix.gs.js +1 -1
- package/dist/gs/os/path_unix.gs.js.map +1 -1
- package/dist/gs/os/pidfd_js.gs.d.ts +1 -1
- package/dist/gs/os/pipe_wasm.gs.d.ts +1 -1
- package/dist/gs/os/proc.gs.d.ts +1 -1
- package/dist/gs/os/proc.gs.js +1 -1
- package/dist/gs/os/proc.gs.js.map +1 -1
- package/dist/gs/os/proc_js.gs.d.ts +1 -1
- package/dist/gs/os/proc_js.gs.js +1 -1
- package/dist/gs/os/proc_js.gs.js.map +1 -1
- package/dist/gs/os/rawconn_js.gs.d.ts +1 -1
- package/dist/gs/os/removeall_js.gs.d.ts +1 -1
- package/dist/gs/os/root_js.gs.d.ts +1 -1
- package/dist/gs/os/root_js.gs.js +1 -1
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/root_nonwindows.gs.d.ts +1 -1
- package/dist/gs/os/root_noopenat.gs.d.ts +1 -1
- package/dist/gs/os/stat.gs.d.ts +1 -1
- package/dist/gs/os/stat_js.gs.d.ts +1 -1
- package/dist/gs/os/stat_unix_js.gs.d.ts +1 -1
- package/dist/gs/os/sys.gs.d.ts +1 -1
- package/dist/gs/os/sys_bsd.gs.d.ts +1 -1
- package/dist/gs/os/sys_js.gs.d.ts +1 -1
- package/dist/gs/os/tempfile.gs.d.ts +1 -1
- package/dist/gs/os/types.gs.d.ts +1 -1
- package/dist/gs/os/types.gs.js +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +1 -1
- package/dist/gs/os/types_js.gs.js +1 -1
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.d.ts +1 -1
- package/dist/gs/os/types_unix.gs.js +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/os/zero_copy_posix.gs.d.ts +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
- package/dist/gs/path/filepath/path.d.ts +11 -10
- package/dist/gs/path/filepath/path.js +5 -4
- package/dist/gs/path/filepath/path.js.map +1 -1
- package/dist/gs/path/match.d.ts +1 -1
- package/dist/gs/path/match.js +1 -1
- package/dist/gs/path/match.js.map +1 -1
- package/dist/gs/path/path.js +1 -1
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/value.d.ts +1 -1
- package/dist/gs/reflect/value.js +1 -1
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.d.ts +1 -1
- package/dist/gs/reflect/visiblefields.js +1 -1
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/slices/slices.d.ts +1 -1
- package/dist/gs/slices/slices.js +1 -1
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/sort/search.gs.d.ts +1 -1
- package/dist/gs/sort/search.gs.js +1 -1
- package/dist/gs/sort/search.gs.js.map +1 -1
- package/dist/gs/sort/slice.gs.d.ts +1 -1
- package/dist/gs/sort/slice.gs.js +1 -1
- package/dist/gs/sort/slice.gs.js.map +1 -1
- package/dist/gs/sort/sort.gs.d.ts +1 -1
- package/dist/gs/sort/sort.gs.js +1 -1
- package/dist/gs/sort/sort.gs.js.map +1 -1
- package/dist/gs/strconv/atob.gs.d.ts +1 -1
- package/dist/gs/strconv/atob.gs.js +1 -1
- package/dist/gs/strconv/atob.gs.js.map +1 -1
- package/dist/gs/strconv/atof.gs.d.ts +1 -1
- package/dist/gs/strconv/atoi.gs.d.ts +1 -1
- package/dist/gs/strconv/atoi.gs.js +5 -6
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/ftoa.gs.d.ts +1 -1
- package/dist/gs/strconv/ftoa.gs.js +1 -1
- package/dist/gs/strconv/ftoa.gs.js.map +1 -1
- package/dist/gs/strconv/itoa.gs.d.ts +1 -1
- package/dist/gs/strconv/itoa.gs.js +1 -1
- package/dist/gs/strconv/itoa.gs.js.map +1 -1
- package/dist/gs/strconv/quote.gs.d.ts +1 -1
- package/dist/gs/strconv/quote.gs.js +1 -1
- package/dist/gs/strconv/quote.gs.js.map +1 -1
- package/dist/gs/strings/builder.d.ts +1 -1
- package/dist/gs/strings/builder.js +1 -1
- package/dist/gs/strings/builder.js.map +1 -1
- package/dist/gs/strings/iter.js +1 -1
- package/dist/gs/strings/iter.js.map +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +7 -8
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.d.ts +1 -1
- package/dist/gs/strings/replace.js +1 -1
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/strings.d.ts +1 -1
- package/dist/gs/strings/strings.js +1 -1
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/atomic/doc.gs.d.ts +1 -1
- package/dist/gs/sync/atomic/doc_64.gs.d.ts +1 -1
- package/dist/gs/sync/atomic/type.gs.d.ts +1 -1
- package/dist/gs/sync/atomic/type.gs.js +1 -1
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/atomic/value.gs.d.ts +1 -1
- package/dist/gs/sync/atomic/value.gs.js +1 -1
- package/dist/gs/sync/atomic/value.gs.js.map +1 -1
- package/dist/gs/syscall/index.d.ts +1 -1
- package/dist/gs/syscall/index.js +1 -1
- package/dist/gs/syscall/index.js.map +1 -1
- package/dist/gs/unicode/utf8/utf8.d.ts +1 -1
- package/dist/gs/unicode/utf8/utf8.js +1 -1
- package/dist/gs/unicode/utf8/utf8.js.map +1 -1
- package/gs/builtin/builtin.ts +16 -64
- package/gs/builtin/errors.ts +25 -0
- package/gs/builtin/index.ts +7 -0
- package/gs/builtin/slice.ts +125 -70
- package/gs/bytes/buffer.gs.ts +1 -1
- package/gs/bytes/bytes.gs.ts +1 -1
- package/gs/bytes/iter.gs.ts +1 -1
- package/gs/bytes/reader.gs.ts +1 -1
- package/gs/context/context.ts +1 -1
- package/gs/errors/errors.ts +3 -16
- package/gs/github.com/pkg/errors/errors.ts +1 -1
- package/gs/github.com/pkg/errors/go113.ts +2 -2
- package/gs/github.com/pkg/errors/stack.ts +1 -1
- package/gs/internal/byteorder/index.ts +1 -1
- package/gs/internal/oserror/errors.ts +1 -1
- package/gs/io/fs/format.ts +1 -1
- package/gs/io/fs/fs.ts +1 -1
- package/gs/io/fs/glob.ts +1 -1
- package/gs/io/fs/readdir.ts +1 -1
- package/gs/io/fs/readfile.ts +1 -1
- package/gs/io/fs/stat.ts +1 -1
- package/gs/io/fs/sub.ts +1 -1
- package/gs/io/fs/walk.ts +1 -1
- package/gs/io/io.ts +1 -1
- package/gs/maps/iter.ts +1 -1
- package/gs/maps/maps.ts +1 -1
- package/gs/math/abs.gs.ts +1 -1
- package/gs/math/acosh.gs.ts +1 -1
- package/gs/math/asinh.gs.ts +1 -1
- package/gs/math/atan.gs.ts +1 -1
- package/gs/math/atan2.gs.ts +1 -1
- package/gs/math/atanh.gs.ts +1 -1
- package/gs/math/bits.gs.ts +1 -1
- package/gs/math/cbrt.gs.ts +1 -1
- package/gs/math/const.gs.ts +1 -1
- package/gs/math/copysign.gs.ts +1 -1
- package/gs/math/dim.gs.ts +1 -1
- package/gs/math/erf.gs.ts +1 -1
- package/gs/math/erfinv.gs.ts +1 -1
- package/gs/math/exp.gs.ts +1 -1
- package/gs/math/expm1.gs.ts +1 -1
- package/gs/math/floor.gs.ts +1 -1
- package/gs/math/frexp.gs.ts +1 -1
- package/gs/math/gamma.gs.ts +1 -1
- package/gs/math/hypot.gs.ts +1 -1
- package/gs/math/j0.gs.ts +1 -1
- package/gs/math/j1.gs.ts +1 -1
- package/gs/math/jn.gs.ts +1 -1
- package/gs/math/ldexp.gs.ts +1 -1
- package/gs/math/lgamma.gs.ts +1 -1
- package/gs/math/log.gs.ts +1 -1
- package/gs/math/log10.gs.ts +1 -1
- package/gs/math/log1p.gs.ts +1 -1
- package/gs/math/logb.gs.ts +1 -1
- package/gs/math/mod.gs.ts +1 -1
- package/gs/math/modf.gs.ts +1 -1
- package/gs/math/nextafter.gs.ts +1 -1
- package/gs/math/pow.gs.ts +1 -1
- package/gs/math/pow10.gs.ts +1 -1
- package/gs/math/remainder.gs.ts +1 -1
- package/gs/math/signbit.gs.ts +1 -1
- package/gs/math/sin.gs.ts +1 -1
- package/gs/math/sincos.gs.ts +1 -1
- package/gs/math/sinh.gs.ts +1 -1
- package/gs/math/sqrt.gs.ts +1 -1
- package/gs/math/tan.gs.ts +1 -1
- package/gs/math/tanh.gs.ts +1 -1
- package/gs/math/trig_reduce.gs.ts +1 -1
- package/gs/math/unsafe.gs.ts +1 -1
- package/gs/os/dir.gs.ts +1 -1
- package/gs/os/dir_unix.gs.ts +1 -1
- package/gs/os/dirent_js.gs.ts +1 -1
- package/gs/os/env.gs.ts +1 -1
- package/gs/os/error.gs.ts +1 -1
- package/gs/os/error_errno.gs.ts +1 -1
- package/gs/os/exec.gs.ts +1 -1
- package/gs/os/exec_nohandle.gs.ts +1 -1
- package/gs/os/exec_posix.gs.ts +1 -1
- package/gs/os/exec_unix.gs.ts +1 -1
- package/gs/os/executable.gs.ts +1 -1
- package/gs/os/executable_js.gs.ts +1 -1
- package/gs/os/executable_wasm.gs.ts +1 -1
- package/gs/os/file_constants_js.gs.ts +1 -1
- package/gs/os/file_js.gs.ts +1 -1
- package/gs/os/file_open_unix.gs.ts +1 -1
- package/gs/os/file_posix_js.gs.ts +1 -1
- package/gs/os/file_unix_js.gs.ts +1 -1
- package/gs/os/getwd_js.gs.ts +1 -1
- package/gs/os/path.gs.ts +1 -1
- package/gs/os/path_unix.gs.ts +1 -1
- package/gs/os/pidfd_js.gs.ts +1 -1
- package/gs/os/pipe_wasm.gs.ts +1 -1
- package/gs/os/proc.gs.ts +1 -1
- package/gs/os/proc_js.gs.ts +1 -1
- package/gs/os/rawconn_js.gs.ts +1 -1
- package/gs/os/removeall_js.gs.ts +1 -1
- package/gs/os/root_js.gs.ts +1 -1
- package/gs/os/root_nonwindows.gs.ts +1 -1
- package/gs/os/root_noopenat.gs.ts +1 -1
- package/gs/os/stat.gs.ts +1 -1
- package/gs/os/stat_js.gs.ts +1 -1
- package/gs/os/stat_unix_js.gs.ts +1 -1
- package/gs/os/sticky_bsd.gs.ts +1 -1
- package/gs/os/sys.gs.ts +1 -1
- package/gs/os/sys_bsd.gs.ts +1 -1
- package/gs/os/sys_js.gs.ts +1 -1
- package/gs/os/tempfile.gs.ts +1 -1
- package/gs/os/types.gs.ts +1 -1
- package/gs/os/types_js.gs.ts +1 -1
- package/gs/os/types_unix.gs.ts +1 -1
- package/gs/os/wait_unimp.gs.ts +1 -1
- package/gs/os/zero_copy_posix.gs.ts +1 -1
- package/gs/os/zero_copy_stub.gs.ts +1 -1
- package/gs/path/filepath/path.ts +14 -13
- package/gs/path/match.ts +1 -1
- package/gs/path/path.ts +1 -1
- package/gs/reflect/value.ts +1 -1
- package/gs/reflect/visiblefields.ts +1 -1
- package/gs/slices/slices.ts +1 -1
- package/gs/sort/search.gs.ts +1 -1
- package/gs/sort/slice.gs.ts +1 -1
- package/gs/sort/sort.gs.ts +1 -1
- package/gs/strconv/atob.gs.ts +1 -1
- package/gs/strconv/atof.gs.ts +1 -1
- package/gs/strconv/atoi.gs.ts +5 -6
- package/gs/strconv/doc.gs.ts +1 -1
- package/gs/strconv/ftoa.gs.ts +1 -1
- package/gs/strconv/itoa.gs.ts +1 -1
- package/gs/strconv/quote.gs.ts +1 -1
- package/gs/strings/builder.ts +1 -1
- package/gs/strings/iter.ts +1 -1
- package/gs/strings/reader.ts +7 -9
- package/gs/strings/replace.ts +1 -1
- package/gs/strings/strings.ts +1 -1
- package/gs/sync/atomic/doc.gs.ts +1 -1
- package/gs/sync/atomic/doc_64.gs.ts +1 -1
- package/gs/sync/atomic/type.gs.ts +1 -1
- package/gs/sync/atomic/value.gs.ts +1 -1
- package/gs/syscall/index.ts +1 -1
- package/gs/unicode/utf8/utf8.ts +1 -1
- package/package.json +3 -3
- package/gs/builtin/io.ts +0 -22
package/compiler/analysis.go
CHANGED
|
@@ -43,6 +43,14 @@ type VariableUsageInfo struct {
|
|
|
43
43
|
Destinations []AssignmentInfo
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// ShadowingInfo tracks variable shadowing in if statement initializations
|
|
47
|
+
type ShadowingInfo struct {
|
|
48
|
+
// ShadowedVariables maps shadowed variable names to their outer scope objects
|
|
49
|
+
ShadowedVariables map[string]types.Object
|
|
50
|
+
// TempVariables maps shadowed variable names to temporary variable names
|
|
51
|
+
TempVariables map[string]string
|
|
52
|
+
}
|
|
53
|
+
|
|
46
54
|
// FunctionTypeInfo represents Go function type information for reflection
|
|
47
55
|
type FunctionTypeInfo struct {
|
|
48
56
|
Params []types.Type // Parameter types
|
|
@@ -69,8 +77,9 @@ type NodeInfo struct {
|
|
|
69
77
|
IsBareReturn bool
|
|
70
78
|
EnclosingFuncDecl *ast.FuncDecl
|
|
71
79
|
EnclosingFuncLit *ast.FuncLit
|
|
72
|
-
IsInsideFunction bool
|
|
73
|
-
IsMethodValue bool
|
|
80
|
+
IsInsideFunction bool // true if this declaration is inside a function body
|
|
81
|
+
IsMethodValue bool // true if this SelectorExpr is a method value that needs binding
|
|
82
|
+
ShadowingInfo *ShadowingInfo // variable shadowing information for if statements
|
|
74
83
|
}
|
|
75
84
|
|
|
76
85
|
// Analysis holds information gathered during the analysis phase of the Go code compilation.
|
|
@@ -270,6 +279,30 @@ func (a *Analysis) IsMethodValue(node *ast.SelectorExpr) bool {
|
|
|
270
279
|
return nodeInfo.IsMethodValue
|
|
271
280
|
}
|
|
272
281
|
|
|
282
|
+
// HasVariableShadowing returns whether the given node has variable shadowing issues
|
|
283
|
+
func (a *Analysis) HasVariableShadowing(node ast.Node) bool {
|
|
284
|
+
if node == nil {
|
|
285
|
+
return false
|
|
286
|
+
}
|
|
287
|
+
nodeInfo := a.NodeData[node]
|
|
288
|
+
if nodeInfo == nil {
|
|
289
|
+
return false
|
|
290
|
+
}
|
|
291
|
+
return nodeInfo.ShadowingInfo != nil
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// GetShadowingInfo returns the variable shadowing information for the given node
|
|
295
|
+
func (a *Analysis) GetShadowingInfo(node ast.Node) *ShadowingInfo {
|
|
296
|
+
if node == nil {
|
|
297
|
+
return nil
|
|
298
|
+
}
|
|
299
|
+
nodeInfo := a.NodeData[node]
|
|
300
|
+
if nodeInfo == nil {
|
|
301
|
+
return nil
|
|
302
|
+
}
|
|
303
|
+
return nodeInfo.ShadowingInfo
|
|
304
|
+
}
|
|
305
|
+
|
|
273
306
|
// analysisVisitor implements ast.Visitor and is used to traverse the AST during analysis.
|
|
274
307
|
type analysisVisitor struct {
|
|
275
308
|
// analysis stores information gathered during the traversal
|
|
@@ -631,6 +664,19 @@ func (v *analysisVisitor) Visit(node ast.Node) ast.Visitor {
|
|
|
631
664
|
return v // Continue traversal
|
|
632
665
|
|
|
633
666
|
case *ast.AssignStmt:
|
|
667
|
+
// Detect variable shadowing in any := assignment
|
|
668
|
+
if n.Tok == token.DEFINE {
|
|
669
|
+
shadowingInfo := v.detectVariableShadowing(n)
|
|
670
|
+
if shadowingInfo != nil {
|
|
671
|
+
// Store shadowing info on the assignment statement itself
|
|
672
|
+
if v.analysis.NodeData[n] == nil {
|
|
673
|
+
v.analysis.NodeData[n] = &NodeInfo{}
|
|
674
|
+
}
|
|
675
|
+
v.analysis.NodeData[n].ShadowingInfo = shadowingInfo
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// Continue with the existing assignment analysis logic
|
|
634
680
|
for i, currentLHSExpr := range n.Lhs {
|
|
635
681
|
if i >= len(n.Rhs) {
|
|
636
682
|
break // Should not happen in valid Go
|
|
@@ -779,6 +825,22 @@ func (v *analysisVisitor) Visit(node ast.Node) ast.Visitor {
|
|
|
779
825
|
}
|
|
780
826
|
}
|
|
781
827
|
return v // Continue traversal
|
|
828
|
+
|
|
829
|
+
case *ast.IfStmt:
|
|
830
|
+
// Detect variable shadowing in if statement initializations
|
|
831
|
+
if n.Init != nil {
|
|
832
|
+
if assignStmt, ok := n.Init.(*ast.AssignStmt); ok && assignStmt.Tok == token.DEFINE {
|
|
833
|
+
shadowingInfo := v.detectVariableShadowing(assignStmt)
|
|
834
|
+
if shadowingInfo != nil {
|
|
835
|
+
// Initialize NodeData for this if statement
|
|
836
|
+
if v.analysis.NodeData[n] == nil {
|
|
837
|
+
v.analysis.NodeData[n] = &NodeInfo{}
|
|
838
|
+
}
|
|
839
|
+
v.analysis.NodeData[n].ShadowingInfo = shadowingInfo
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
return v // Continue traversal
|
|
782
844
|
}
|
|
783
845
|
|
|
784
846
|
// For all other nodes, continue traversal
|
|
@@ -1225,3 +1287,112 @@ func (v *analysisVisitor) markFunctionVariable(ident *ast.Ident, funcType *types
|
|
|
1225
1287
|
v.analysis.MarkFunctionForReflection(funcNode, funcType)
|
|
1226
1288
|
}
|
|
1227
1289
|
}
|
|
1290
|
+
|
|
1291
|
+
// detectVariableShadowing detects variable shadowing in any := assignment
|
|
1292
|
+
func (v *analysisVisitor) detectVariableShadowing(assignStmt *ast.AssignStmt) *ShadowingInfo {
|
|
1293
|
+
shadowingInfo := &ShadowingInfo{
|
|
1294
|
+
ShadowedVariables: make(map[string]types.Object),
|
|
1295
|
+
TempVariables: make(map[string]string),
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
hasShadowing := false
|
|
1299
|
+
|
|
1300
|
+
// First, collect all LHS variable names that are being declared
|
|
1301
|
+
lhsVarNames := make(map[string]*ast.Ident)
|
|
1302
|
+
for _, lhsExpr := range assignStmt.Lhs {
|
|
1303
|
+
if lhsIdent, ok := lhsExpr.(*ast.Ident); ok && lhsIdent.Name != "_" {
|
|
1304
|
+
lhsVarNames[lhsIdent.Name] = lhsIdent
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
// Next, check all RHS expressions for usage of variables that are also being declared on LHS
|
|
1309
|
+
for _, rhsExpr := range assignStmt.Rhs {
|
|
1310
|
+
v.findVariableUsageInExpr(rhsExpr, lhsVarNames, shadowingInfo, &hasShadowing)
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
if hasShadowing {
|
|
1314
|
+
return shadowingInfo
|
|
1315
|
+
}
|
|
1316
|
+
return nil
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
// findVariableUsageInExpr recursively searches for variable usage in an expression
|
|
1320
|
+
func (v *analysisVisitor) findVariableUsageInExpr(expr ast.Expr, lhsVarNames map[string]*ast.Ident, shadowingInfo *ShadowingInfo, hasShadowing *bool) {
|
|
1321
|
+
if expr == nil {
|
|
1322
|
+
return
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
switch e := expr.(type) {
|
|
1326
|
+
case *ast.Ident:
|
|
1327
|
+
// Check if this identifier is being shadowed
|
|
1328
|
+
if lhsIdent, exists := lhsVarNames[e.Name]; exists {
|
|
1329
|
+
// This variable is being used on RHS but also declared on LHS - this is shadowing!
|
|
1330
|
+
|
|
1331
|
+
// Get the outer scope object for this variable
|
|
1332
|
+
if outerObj := v.pkg.TypesInfo.Uses[e]; outerObj != nil {
|
|
1333
|
+
// Make sure this isn't the same object as the LHS (which would mean no shadowing)
|
|
1334
|
+
if lhsObj := v.pkg.TypesInfo.Defs[lhsIdent]; lhsObj != outerObj {
|
|
1335
|
+
shadowingInfo.ShadowedVariables[e.Name] = outerObj
|
|
1336
|
+
shadowingInfo.TempVariables[e.Name] = "_temp_" + e.Name
|
|
1337
|
+
*hasShadowing = true
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
case *ast.CallExpr:
|
|
1343
|
+
// Check function arguments
|
|
1344
|
+
for _, arg := range e.Args {
|
|
1345
|
+
v.findVariableUsageInExpr(arg, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1346
|
+
}
|
|
1347
|
+
// Check function expression itself
|
|
1348
|
+
v.findVariableUsageInExpr(e.Fun, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1349
|
+
|
|
1350
|
+
case *ast.SelectorExpr:
|
|
1351
|
+
// Check the base expression (e.g., x in x.Method())
|
|
1352
|
+
v.findVariableUsageInExpr(e.X, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1353
|
+
|
|
1354
|
+
case *ast.IndexExpr:
|
|
1355
|
+
// Check both the expression and index (e.g., arr[i])
|
|
1356
|
+
v.findVariableUsageInExpr(e.X, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1357
|
+
v.findVariableUsageInExpr(e.Index, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1358
|
+
|
|
1359
|
+
case *ast.SliceExpr:
|
|
1360
|
+
// Check the expression and slice bounds
|
|
1361
|
+
v.findVariableUsageInExpr(e.X, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1362
|
+
if e.Low != nil {
|
|
1363
|
+
v.findVariableUsageInExpr(e.Low, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1364
|
+
}
|
|
1365
|
+
if e.High != nil {
|
|
1366
|
+
v.findVariableUsageInExpr(e.High, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1367
|
+
}
|
|
1368
|
+
if e.Max != nil {
|
|
1369
|
+
v.findVariableUsageInExpr(e.Max, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
case *ast.UnaryExpr:
|
|
1373
|
+
// Check the operand (e.g., &x, -x, !x)
|
|
1374
|
+
v.findVariableUsageInExpr(e.X, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1375
|
+
|
|
1376
|
+
case *ast.BinaryExpr:
|
|
1377
|
+
// Check both operands (e.g., x + y)
|
|
1378
|
+
v.findVariableUsageInExpr(e.X, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1379
|
+
v.findVariableUsageInExpr(e.Y, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1380
|
+
|
|
1381
|
+
case *ast.ParenExpr:
|
|
1382
|
+
// Check the parenthesized expression
|
|
1383
|
+
v.findVariableUsageInExpr(e.X, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1384
|
+
|
|
1385
|
+
case *ast.TypeAssertExpr:
|
|
1386
|
+
// Check the expression being type-asserted
|
|
1387
|
+
v.findVariableUsageInExpr(e.X, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1388
|
+
|
|
1389
|
+
case *ast.StarExpr:
|
|
1390
|
+
// Check the expression being dereferenced
|
|
1391
|
+
v.findVariableUsageInExpr(e.X, lhsVarNames, shadowingInfo, hasShadowing)
|
|
1392
|
+
|
|
1393
|
+
// Add more expression types as needed
|
|
1394
|
+
default:
|
|
1395
|
+
// For other expression types, we might need to add specific handling
|
|
1396
|
+
// For now, we'll ignore them as they're less common in shadowing scenarios
|
|
1397
|
+
}
|
|
1398
|
+
}
|
package/compiler/compiler.go
CHANGED
|
@@ -593,7 +593,7 @@ func (c *FileCompiler) Compile(ctx context.Context) error {
|
|
|
593
593
|
goWriter := NewGoToTSCompiler(c.codeWriter, c.pkg, c.Analysis)
|
|
594
594
|
|
|
595
595
|
// Add import for the goscript runtime using namespace import and alias
|
|
596
|
-
c.codeWriter.WriteLinef("import * as $ from %q;", "@goscript/builtin/
|
|
596
|
+
c.codeWriter.WriteLinef("import * as $ from %q;", "@goscript/builtin/index.js")
|
|
597
597
|
|
|
598
598
|
// Check if there are any .pb.go files in this package and add imports for them
|
|
599
599
|
if err := c.addProtobufImports(); err != nil {
|
|
@@ -639,6 +639,9 @@ type GoToTSCompiler struct {
|
|
|
639
639
|
pkg *packages.Package
|
|
640
640
|
|
|
641
641
|
analysis *Analysis
|
|
642
|
+
|
|
643
|
+
// shadowingContext tracks temporary variable mappings when we're in a shadowing context
|
|
644
|
+
shadowingContext map[string]string
|
|
642
645
|
}
|
|
643
646
|
|
|
644
647
|
// It initializes the compiler with a `TSCodeWriter` for output,
|
|
@@ -646,9 +649,10 @@ type GoToTSCompiler struct {
|
|
|
646
649
|
// analysis results (`Analysis`) to guide the translation process.
|
|
647
650
|
func NewGoToTSCompiler(tsw *TSCodeWriter, pkg *packages.Package, analysis *Analysis) *GoToTSCompiler {
|
|
648
651
|
return &GoToTSCompiler{
|
|
649
|
-
tsw:
|
|
650
|
-
pkg:
|
|
651
|
-
analysis:
|
|
652
|
+
tsw: tsw,
|
|
653
|
+
pkg: pkg,
|
|
654
|
+
analysis: analysis,
|
|
655
|
+
shadowingContext: make(map[string]string),
|
|
652
656
|
}
|
|
653
657
|
}
|
|
654
658
|
|
|
@@ -670,6 +674,12 @@ func (c *GoToTSCompiler) WriteIdent(exp *ast.Ident, accessVarRefedValue bool) {
|
|
|
670
674
|
return
|
|
671
675
|
}
|
|
672
676
|
|
|
677
|
+
// Check if we're in a shadowing context and should use a temporary variable
|
|
678
|
+
if tempVarName, exists := c.shadowingContext[exp.Name]; exists {
|
|
679
|
+
c.tsw.WriteLiterally(c.sanitizeIdentifier(tempVarName))
|
|
680
|
+
return
|
|
681
|
+
}
|
|
682
|
+
|
|
673
683
|
// Use TypesInfo to find the object associated with the identifier
|
|
674
684
|
var obj types.Object
|
|
675
685
|
obj = c.pkg.TypesInfo.Uses[exp]
|
package/compiler/expr-type.go
CHANGED
|
@@ -20,6 +20,31 @@ import (
|
|
|
20
20
|
// - Interface types -> TypeScript interface types or "any"
|
|
21
21
|
// - Function types -> TypeScript function signatures
|
|
22
22
|
func (c *GoToTSCompiler) WriteTypeExpr(a ast.Expr) {
|
|
23
|
+
// Handle selector expressions (e.g., os.FileInfo) specially to preserve qualified names
|
|
24
|
+
if selectorExpr, ok := a.(*ast.SelectorExpr); ok {
|
|
25
|
+
if pkgIdent, ok := selectorExpr.X.(*ast.Ident); ok {
|
|
26
|
+
// Check if this is a package selector (e.g., os.FileInfo)
|
|
27
|
+
if obj := c.pkg.TypesInfo.Uses[pkgIdent]; obj != nil {
|
|
28
|
+
if _, isPkg := obj.(*types.PkgName); isPkg {
|
|
29
|
+
// This is a package.Type reference - write the qualified name
|
|
30
|
+
c.tsw.WriteLiterally(pkgIdent.Name)
|
|
31
|
+
c.tsw.WriteLiterally(".")
|
|
32
|
+
c.tsw.WriteLiterally(selectorExpr.Sel.Name)
|
|
33
|
+
|
|
34
|
+
// Check if this is a function type and add | null
|
|
35
|
+
if typ := c.pkg.TypesInfo.TypeOf(a); typ != nil {
|
|
36
|
+
if namedType, isNamed := typ.(*types.Named); isNamed {
|
|
37
|
+
if _, isSignature := namedType.Underlying().(*types.Signature); isSignature {
|
|
38
|
+
c.tsw.WriteLiterally(" | null")
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
23
48
|
// Get type information for the expression and use WriteGoType
|
|
24
49
|
typ := c.pkg.TypesInfo.TypeOf(a)
|
|
25
50
|
c.WriteGoType(typ, GoTypeContextGeneral)
|
package/compiler/field.go
CHANGED
|
@@ -52,8 +52,8 @@ func (c *GoToTSCompiler) WriteFieldList(a *ast.FieldList, isArguments bool) {
|
|
|
52
52
|
}
|
|
53
53
|
c.tsw.WriteLiterally(c.sanitizeIdentifier(name.Name))
|
|
54
54
|
c.tsw.WriteLiterally(": ")
|
|
55
|
-
|
|
56
|
-
c.
|
|
55
|
+
// Use WriteTypeExpr to preserve qualified names like os.FileInfo
|
|
56
|
+
c.WriteTypeExpr(field.Type)
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -102,8 +102,8 @@ func (c *GoToTSCompiler) WriteFieldList(a *ast.FieldList, isArguments bool) {
|
|
|
102
102
|
}
|
|
103
103
|
c.tsw.WriteLiterally(c.sanitizeIdentifier(name.Name))
|
|
104
104
|
c.tsw.WriteLiterally(": ")
|
|
105
|
-
|
|
106
|
-
c.
|
|
105
|
+
// Use WriteTypeExpr to preserve qualified names like os.FileInfo
|
|
106
|
+
c.WriteTypeExpr(field.Type)
|
|
107
107
|
}
|
|
108
108
|
} else {
|
|
109
109
|
// For struct fields and other non-argument fields
|
package/compiler/spec.go
CHANGED
|
@@ -539,7 +539,7 @@ func (c *GoToTSCompiler) WriteImportSpec(a *ast.ImportSpec) {
|
|
|
539
539
|
// handwritten versions (in .goscript-assets) or transpiled versions (in goscript).
|
|
540
540
|
var tsImportPath string
|
|
541
541
|
if goPath == "github.com/aperturerobotics/goscript/builtin" {
|
|
542
|
-
tsImportPath = "@goscript/builtin/
|
|
542
|
+
tsImportPath = "@goscript/builtin/index.js"
|
|
543
543
|
} else {
|
|
544
544
|
tsImportPath = "@goscript/" + goPath
|
|
545
545
|
}
|
package/compiler/stmt.go
CHANGED
|
@@ -444,53 +444,90 @@ func (c *GoToTSCompiler) WriteStmtSend(exp *ast.SendStmt) error {
|
|
|
444
444
|
// recursively calling `WriteStmtIf`.
|
|
445
445
|
//
|
|
446
446
|
// The function aims to produce idiomatic TypeScript `if/else if/else` structures.
|
|
447
|
-
func (
|
|
447
|
+
func (c *GoToTSCompiler) WriteStmtIf(exp *ast.IfStmt) error {
|
|
448
448
|
if exp.Init != nil {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
449
|
+
// Check if we need to handle variable shadowing BEFORE creating the block
|
|
450
|
+
var shadowingInfo *ShadowingInfo
|
|
451
|
+
if assignStmt, ok := exp.Init.(*ast.AssignStmt); ok {
|
|
452
|
+
shadowingInfo = c.analysis.GetShadowingInfo(assignStmt)
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Generate temporary variables OUTSIDE the block to avoid temporal dead zone
|
|
456
|
+
if shadowingInfo != nil {
|
|
457
|
+
for varName, tempVarName := range shadowingInfo.TempVariables {
|
|
458
|
+
c.tsw.WriteLiterally("let ")
|
|
459
|
+
c.tsw.WriteLiterally(tempVarName)
|
|
460
|
+
c.tsw.WriteLiterally(" = ")
|
|
461
|
+
c.tsw.WriteLiterally(c.sanitizeIdentifier(varName))
|
|
462
|
+
c.tsw.WriteLine("")
|
|
463
|
+
}
|
|
464
|
+
}
|
|
452
465
|
|
|
453
|
-
|
|
454
|
-
|
|
466
|
+
c.tsw.WriteLiterally("{") // Write opening brace
|
|
467
|
+
c.tsw.WriteLine("") // Add newline immediately after opening brace
|
|
468
|
+
c.tsw.Indent(1) // Indent for the initializer
|
|
469
|
+
|
|
470
|
+
// Check if we need to handle variable shadowing
|
|
471
|
+
if assignStmt, ok := exp.Init.(*ast.AssignStmt); ok {
|
|
472
|
+
if shadowingInfo != nil {
|
|
473
|
+
// Write the assignment statement with special handling for shadowing
|
|
474
|
+
if err := c.writeShadowedAssignment(assignStmt, shadowingInfo); err != nil {
|
|
475
|
+
return err
|
|
476
|
+
}
|
|
477
|
+
} else {
|
|
478
|
+
// No shadowing, write normally
|
|
479
|
+
if err := c.WriteStmt(exp.Init); err != nil {
|
|
480
|
+
return err
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
} else {
|
|
484
|
+
// Not an assignment statement, write normally
|
|
485
|
+
if err := c.WriteStmt(exp.Init); err != nil {
|
|
486
|
+
return err
|
|
487
|
+
}
|
|
455
488
|
}
|
|
456
489
|
|
|
457
490
|
// This defer handles closing the synthetic block for the initializer
|
|
458
491
|
defer func() {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
492
|
+
c.tsw.Indent(-1)
|
|
493
|
+
c.tsw.WriteLiterally("}") // Write the closing brace at the now-correct indent level
|
|
494
|
+
c.tsw.WriteLine("") // Ensure a newline *after* this '}', critical for preventing '}}'
|
|
462
495
|
}()
|
|
463
496
|
}
|
|
464
497
|
|
|
465
|
-
|
|
466
|
-
|
|
498
|
+
// Ensure shadowing context is clear before writing condition
|
|
499
|
+
// (condition should refer to new local variables, not temp variables)
|
|
500
|
+
c.shadowingContext = make(map[string]string)
|
|
501
|
+
|
|
502
|
+
c.tsw.WriteLiterally("if (")
|
|
503
|
+
if err := c.WriteValueExpr(exp.Cond); err != nil { // Condition is a value
|
|
467
504
|
return err
|
|
468
505
|
}
|
|
469
|
-
|
|
506
|
+
c.tsw.WriteLiterally(") ")
|
|
470
507
|
|
|
471
508
|
if exp.Body != nil {
|
|
472
|
-
if err :=
|
|
509
|
+
if err := c.WriteStmtBlock(exp.Body, exp.Else != nil); err != nil {
|
|
473
510
|
return fmt.Errorf("failed to write if body block statement: %w", err)
|
|
474
511
|
}
|
|
475
512
|
} else {
|
|
476
513
|
// Handle nil body case using WriteStmtBlock with an empty block
|
|
477
|
-
if err :=
|
|
514
|
+
if err := c.WriteStmtBlock(&ast.BlockStmt{}, exp.Else != nil); err != nil {
|
|
478
515
|
return fmt.Errorf("failed to write empty block statement in if statement: %w", err)
|
|
479
516
|
}
|
|
480
517
|
}
|
|
481
518
|
|
|
482
519
|
// handle else branch
|
|
483
520
|
if exp.Else != nil {
|
|
484
|
-
|
|
521
|
+
c.tsw.WriteLiterally(" else ")
|
|
485
522
|
switch elseStmt := exp.Else.(type) {
|
|
486
523
|
case *ast.BlockStmt:
|
|
487
524
|
// Always pass false for suppressNewline here
|
|
488
|
-
if err :=
|
|
525
|
+
if err := c.WriteStmtBlock(elseStmt, false); err != nil {
|
|
489
526
|
return fmt.Errorf("failed to write else block statement in if statement: %w", err)
|
|
490
527
|
}
|
|
491
528
|
case *ast.IfStmt:
|
|
492
529
|
// Recursive call handles its own block formatting
|
|
493
|
-
if err :=
|
|
530
|
+
if err := c.WriteStmtIf(elseStmt); err != nil {
|
|
494
531
|
return fmt.Errorf("failed to write else if statement in if statement: %w", err)
|
|
495
532
|
}
|
|
496
533
|
}
|
|
@@ -897,3 +934,67 @@ func (c *GoToTSCompiler) WriteStmtLabeled(stmt *ast.LabeledStmt) error {
|
|
|
897
934
|
|
|
898
935
|
return nil
|
|
899
936
|
}
|
|
937
|
+
|
|
938
|
+
// writeShadowedAssignment writes an assignment statement that has variable shadowing,
|
|
939
|
+
// applying the shadowing context only to RHS expressions.
|
|
940
|
+
func (c *GoToTSCompiler) writeShadowedAssignment(stmt *ast.AssignStmt, shadowingInfo *ShadowingInfo) error {
|
|
941
|
+
// Write the LHS variables (these are new declarations, don't use temp variables)
|
|
942
|
+
for i, lhsExpr := range stmt.Lhs {
|
|
943
|
+
if i > 0 {
|
|
944
|
+
c.tsw.WriteLiterally(", ")
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
if ident, ok := lhsExpr.(*ast.Ident); ok {
|
|
948
|
+
if ident.Name == "_" {
|
|
949
|
+
c.tsw.WriteLiterally("_")
|
|
950
|
+
} else {
|
|
951
|
+
c.tsw.WriteLiterally("let ")
|
|
952
|
+
c.WriteIdent(ident, false) // Don't use temp variable for LHS
|
|
953
|
+
}
|
|
954
|
+
} else {
|
|
955
|
+
// For non-identifier LHS (shouldn't happen in := assignments), write normally
|
|
956
|
+
if err := c.WriteValueExpr(lhsExpr); err != nil {
|
|
957
|
+
return err
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
c.tsw.WriteLiterally(" = ")
|
|
963
|
+
|
|
964
|
+
// Set up shadowing context for RHS expressions only
|
|
965
|
+
originalContext := make(map[string]string)
|
|
966
|
+
for varName, tempVarName := range shadowingInfo.TempVariables {
|
|
967
|
+
originalContext[varName] = c.shadowingContext[varName] // backup original
|
|
968
|
+
c.shadowingContext[varName] = tempVarName
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
// Write RHS expressions with shadowing context
|
|
972
|
+
for i, rhsExpr := range stmt.Rhs {
|
|
973
|
+
if i > 0 {
|
|
974
|
+
c.tsw.WriteLiterally(", ")
|
|
975
|
+
}
|
|
976
|
+
if err := c.WriteValueExpr(rhsExpr); err != nil {
|
|
977
|
+
// Restore context on error
|
|
978
|
+
for varName := range shadowingInfo.TempVariables {
|
|
979
|
+
if original, existed := originalContext[varName]; existed {
|
|
980
|
+
c.shadowingContext[varName] = original
|
|
981
|
+
} else {
|
|
982
|
+
delete(c.shadowingContext, varName)
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
return err
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// Restore original context after writing RHS
|
|
990
|
+
for varName := range shadowingInfo.TempVariables {
|
|
991
|
+
if original, existed := originalContext[varName]; existed {
|
|
992
|
+
c.shadowingContext[varName] = original
|
|
993
|
+
} else {
|
|
994
|
+
delete(c.shadowingContext, varName)
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
c.tsw.WriteLine("")
|
|
999
|
+
return nil
|
|
1000
|
+
}
|
package/compiler/type.go
CHANGED
|
@@ -259,6 +259,11 @@ func (c *GoToTSCompiler) WriteNamedType(t *types.Named) {
|
|
|
259
259
|
}
|
|
260
260
|
c.tsw.WriteLiterally(">")
|
|
261
261
|
}
|
|
262
|
+
|
|
263
|
+
// Check if the underlying type is a function signature and add | null
|
|
264
|
+
if _, isSignature := t.Underlying().(*types.Signature); isSignature {
|
|
265
|
+
c.tsw.WriteLiterally(" | null")
|
|
266
|
+
}
|
|
262
267
|
return
|
|
263
268
|
}
|
|
264
269
|
|
|
@@ -282,6 +287,11 @@ func (c *GoToTSCompiler) WriteNamedType(t *types.Named) {
|
|
|
282
287
|
}
|
|
283
288
|
c.tsw.WriteLiterally(">")
|
|
284
289
|
}
|
|
290
|
+
|
|
291
|
+
// Check if the underlying type is a function signature and add | null
|
|
292
|
+
if _, isSignature := t.Underlying().(*types.Signature); isSignature {
|
|
293
|
+
c.tsw.WriteLiterally(" | null")
|
|
294
|
+
}
|
|
285
295
|
return
|
|
286
296
|
}
|
|
287
297
|
}
|
|
@@ -301,6 +311,11 @@ func (c *GoToTSCompiler) WriteNamedType(t *types.Named) {
|
|
|
301
311
|
}
|
|
302
312
|
c.tsw.WriteLiterally(">")
|
|
303
313
|
}
|
|
314
|
+
|
|
315
|
+
// Check if the underlying type is a function signature and add | null for local types too
|
|
316
|
+
if _, isSignature := t.Underlying().(*types.Signature); isSignature {
|
|
317
|
+
c.tsw.WriteLiterally(" | null")
|
|
318
|
+
}
|
|
304
319
|
}
|
|
305
320
|
|
|
306
321
|
// WritePointerType translates a Go pointer type (*T) to its TypeScript equivalent.
|
|
@@ -400,8 +415,8 @@ func (c *GoToTSCompiler) WriteFuncType(exp *ast.FuncType, isAsync bool) {
|
|
|
400
415
|
}
|
|
401
416
|
if len(exp.Results.List) == 1 {
|
|
402
417
|
// Single return type (named or unnamed)
|
|
403
|
-
|
|
404
|
-
c.
|
|
418
|
+
// Use WriteTypeExpr to preserve qualified names like os.FileInfo
|
|
419
|
+
c.WriteTypeExpr(exp.Results.List[0].Type)
|
|
405
420
|
} else {
|
|
406
421
|
// Multiple return types -> tuple
|
|
407
422
|
c.tsw.WriteLiterally("[")
|
|
@@ -409,8 +424,8 @@ func (c *GoToTSCompiler) WriteFuncType(exp *ast.FuncType, isAsync bool) {
|
|
|
409
424
|
if i > 0 {
|
|
410
425
|
c.tsw.WriteLiterally(", ")
|
|
411
426
|
}
|
|
412
|
-
|
|
413
|
-
c.
|
|
427
|
+
// Use WriteTypeExpr to preserve qualified names like os.FileInfo
|
|
428
|
+
c.WriteTypeExpr(field.Type)
|
|
414
429
|
}
|
|
415
430
|
c.tsw.WriteLiterally("]")
|
|
416
431
|
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
export * from './varRef.js';
|
|
2
|
-
export * from './channel.js';
|
|
3
|
-
export * from './defer.js';
|
|
4
|
-
export * from './io.js';
|
|
5
|
-
export * from './map.js';
|
|
6
|
-
export * from './slice.js';
|
|
7
|
-
export * from './type.js';
|
|
8
1
|
import type { Slice } from './slice.js';
|
|
2
|
+
/**
|
|
3
|
+
* Implementation of Go's built-in println function
|
|
4
|
+
* @param args Arguments to print
|
|
5
|
+
*/
|
|
6
|
+
export declare function println(...args: any[]): void;
|
|
7
|
+
/**
|
|
8
|
+
* Implementation of Go's built-in panic function
|
|
9
|
+
* @param args Arguments passed to panic
|
|
10
|
+
*/
|
|
11
|
+
export declare function panic(...args: any[]): void;
|
|
9
12
|
export type Bytes = Uint8Array | Slice<number>;
|
|
10
13
|
export declare function int(value: number): number;
|
|
11
|
-
export declare function copy<T>(dst: T[] | Uint8Array, src: T[] | Uint8Array | string): number;
|
|
12
14
|
export declare function multiplyDuration(duration: any, multiplier: number): any;
|
|
13
15
|
/**
|
|
14
16
|
* Normalizes various byte representations into a `Uint8Array` for protobuf compatibility.
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
export * from './varRef.js';
|
|
2
|
-
export * from './channel.js';
|
|
3
|
-
export * from './defer.js';
|
|
4
|
-
export * from './io.js';
|
|
5
|
-
export * from './map.js';
|
|
6
|
-
export * from './slice.js';
|
|
7
|
-
export * from './type.js';
|
|
8
1
|
import { isSliceProxy } from './slice.js';
|
|
2
|
+
/**
|
|
3
|
+
* Implementation of Go's built-in println function
|
|
4
|
+
* @param args Arguments to print
|
|
5
|
+
*/
|
|
6
|
+
export function println(...args) {
|
|
7
|
+
console.log(...args);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Implementation of Go's built-in panic function
|
|
11
|
+
* @param args Arguments passed to panic
|
|
12
|
+
*/
|
|
13
|
+
export function panic(...args) {
|
|
14
|
+
throw new Error(`panic: ${args.map((arg) => String(arg)).join(' ')}`);
|
|
15
|
+
}
|
|
9
16
|
// int converts a value to a Go int type, handling proper signed integer conversion
|
|
10
17
|
// This ensures that values like 2147483648 (2^31) are properly handled according to Go semantics
|
|
11
18
|
export function int(value) {
|
|
@@ -17,52 +24,6 @@ export function int(value) {
|
|
|
17
24
|
// since JavaScript numbers can safely represent integers up to Number.MAX_SAFE_INTEGER
|
|
18
25
|
return Math.trunc(value);
|
|
19
26
|
}
|
|
20
|
-
// Copy is the Go builtin function that copies the contents of one slice to another.
|
|
21
|
-
// It returns the number of elements copied.
|
|
22
|
-
export function copy(dst, src) {
|
|
23
|
-
// Handle string to Uint8Array copy (common in Go)
|
|
24
|
-
if (typeof src === 'string' && dst instanceof Uint8Array) {
|
|
25
|
-
const encoder = new TextEncoder();
|
|
26
|
-
const srcBytes = encoder.encode(src);
|
|
27
|
-
const n = Math.min(dst.length, srcBytes.length);
|
|
28
|
-
for (let i = 0; i < n; i++) {
|
|
29
|
-
dst[i] = srcBytes[i];
|
|
30
|
-
}
|
|
31
|
-
return n;
|
|
32
|
-
}
|
|
33
|
-
// Handle Uint8Array to Uint8Array copy
|
|
34
|
-
if (dst instanceof Uint8Array && src instanceof Uint8Array) {
|
|
35
|
-
const n = Math.min(dst.length, src.length);
|
|
36
|
-
for (let i = 0; i < n; i++) {
|
|
37
|
-
dst[i] = src[i];
|
|
38
|
-
}
|
|
39
|
-
return n;
|
|
40
|
-
}
|
|
41
|
-
// Handle array to array copy (original implementation)
|
|
42
|
-
if (Array.isArray(dst) && Array.isArray(src)) {
|
|
43
|
-
const n = Math.min(dst.length, src.length);
|
|
44
|
-
for (let i = 0; i < n; i++) {
|
|
45
|
-
dst[i] = src[i];
|
|
46
|
-
}
|
|
47
|
-
return n;
|
|
48
|
-
}
|
|
49
|
-
// Handle mixed types - convert to compatible format
|
|
50
|
-
if (dst instanceof Uint8Array && Array.isArray(src)) {
|
|
51
|
-
const n = Math.min(dst.length, src.length);
|
|
52
|
-
for (let i = 0; i < n; i++) {
|
|
53
|
-
dst[i] = src[i];
|
|
54
|
-
}
|
|
55
|
-
return n;
|
|
56
|
-
}
|
|
57
|
-
if (Array.isArray(dst) && src instanceof Uint8Array) {
|
|
58
|
-
const n = Math.min(dst.length, src.length);
|
|
59
|
-
for (let i = 0; i < n; i++) {
|
|
60
|
-
dst[i] = src[i];
|
|
61
|
-
}
|
|
62
|
-
return n;
|
|
63
|
-
}
|
|
64
|
-
throw new Error(`Unsupported copy operation between ${typeof dst} and ${typeof src}`);
|
|
65
|
-
}
|
|
66
27
|
// Duration multiplication helper for time package operations
|
|
67
28
|
// Handles expressions like time.Hour * 24
|
|
68
29
|
export function multiplyDuration(duration, multiplier) {
|