goscript 0.0.84 → 0.1.1

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 (428) hide show
  1. package/README.md +267 -243
  2. package/cmd/goscript/cmd-test.go +193 -0
  3. package/cmd/goscript/cmd-test_test.go +76 -0
  4. package/cmd/goscript/cmd_compile.go +70 -69
  5. package/cmd/goscript/cmd_compile_test.go +79 -0
  6. package/cmd/goscript/main.go +11 -5
  7. package/compiler/build-flags.go +38 -0
  8. package/compiler/compile-request.go +220 -0
  9. package/compiler/compiler.go +16 -1336
  10. package/compiler/compliance_test.go +188 -0
  11. package/compiler/config.go +6 -13
  12. package/compiler/diagnostic.go +70 -0
  13. package/compiler/gotest/owner.go +24 -0
  14. package/compiler/gotest/package-result.go +67 -0
  15. package/compiler/gotest/request.go +145 -0
  16. package/compiler/gotest/result.go +28 -0
  17. package/compiler/gotest/runner.go +588 -0
  18. package/compiler/gotest/runner_test.go +627 -0
  19. package/compiler/gotest/test.go +9 -0
  20. package/compiler/index.test.ts +28 -28
  21. package/compiler/index.ts +40 -72
  22. package/compiler/lowered-program.go +184 -0
  23. package/compiler/lowering.go +8072 -0
  24. package/compiler/override-facts.go +307 -0
  25. package/compiler/override-registry.go +283 -0
  26. package/compiler/override-registry_test.go +254 -0
  27. package/compiler/package-graph.go +254 -0
  28. package/compiler/package-graph_test.go +316 -0
  29. package/compiler/package-test-function.go +9 -0
  30. package/compiler/package-test-graph-package.go +40 -0
  31. package/compiler/package-test-graph-variant.go +105 -0
  32. package/compiler/package-test-graph.go +117 -0
  33. package/compiler/package-test-graph_test.go +144 -0
  34. package/compiler/result.go +13 -0
  35. package/compiler/runtime-contract.go +439 -0
  36. package/compiler/runtime-contract_test.go +104 -0
  37. package/compiler/semantic-model-types.go +113 -0
  38. package/compiler/semantic-model.go +1422 -0
  39. package/compiler/semantic-model_test.go +471 -0
  40. package/compiler/service.go +133 -0
  41. package/compiler/skeleton_test.go +1775 -0
  42. package/compiler/tsworkspace/owner.go +334 -0
  43. package/compiler/tsworkspace/owner_test.go +93 -0
  44. package/compiler/tsworkspace/result.go +17 -0
  45. package/compiler/typescript-emitter.go +1040 -0
  46. package/compiler/wasm/compile.go +2 -3
  47. package/compiler/wasm/compile_test.go +79 -0
  48. package/compiler/wasm_api.go +140 -124
  49. package/dist/compiler/index.d.ts +1 -3
  50. package/dist/compiler/index.js +31 -55
  51. package/dist/compiler/index.js.map +1 -1
  52. package/dist/gs/builtin/builtin.d.ts +33 -2
  53. package/dist/gs/builtin/builtin.js +217 -6
  54. package/dist/gs/builtin/builtin.js.map +1 -1
  55. package/dist/gs/builtin/channel.d.ts +11 -3
  56. package/dist/gs/builtin/channel.js +12 -0
  57. package/dist/gs/builtin/channel.js.map +1 -1
  58. package/dist/gs/builtin/hostio.d.ts +15 -1
  59. package/dist/gs/builtin/hostio.js +134 -49
  60. package/dist/gs/builtin/hostio.js.map +1 -1
  61. package/dist/gs/builtin/index.d.ts +1 -0
  62. package/dist/gs/builtin/index.js +1 -0
  63. package/dist/gs/builtin/index.js.map +1 -1
  64. package/dist/gs/builtin/slice.d.ts +23 -3
  65. package/dist/gs/builtin/slice.js +216 -44
  66. package/dist/gs/builtin/slice.js.map +1 -1
  67. package/dist/gs/builtin/type.d.ts +16 -2
  68. package/dist/gs/builtin/type.js +134 -21
  69. package/dist/gs/builtin/type.js.map +1 -1
  70. package/dist/gs/builtin/varRef.d.ts +5 -0
  71. package/dist/gs/builtin/varRef.js +23 -0
  72. package/dist/gs/builtin/varRef.js.map +1 -1
  73. package/dist/gs/bytes/buffer.gs.js +48 -44
  74. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  75. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  76. package/dist/gs/bytes/reader.gs.js +20 -18
  77. package/dist/gs/bytes/reader.gs.js.map +1 -1
  78. package/dist/gs/context/context.d.ts +5 -4
  79. package/dist/gs/context/context.js +10 -10
  80. package/dist/gs/context/context.js.map +1 -1
  81. package/dist/gs/crypto/internal/fips140deps/byteorder/index.d.ts +1 -0
  82. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js +2 -0
  83. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js.map +1 -0
  84. package/dist/gs/crypto/internal/fips140deps/godebug/index.d.ts +1 -0
  85. package/dist/gs/crypto/internal/fips140deps/godebug/index.js +2 -0
  86. package/dist/gs/crypto/internal/fips140deps/godebug/index.js.map +1 -0
  87. package/dist/gs/crypto/rand/index.d.ts +5 -0
  88. package/dist/gs/crypto/rand/index.js +77 -0
  89. package/dist/gs/crypto/rand/index.js.map +1 -0
  90. package/dist/gs/embed/index.d.ts +7 -0
  91. package/dist/gs/embed/index.js +16 -0
  92. package/dist/gs/embed/index.js.map +1 -0
  93. package/dist/gs/encoding/json/index.d.ts +4 -0
  94. package/dist/gs/encoding/json/index.js +178 -0
  95. package/dist/gs/encoding/json/index.js.map +1 -0
  96. package/dist/gs/errors/errors.d.ts +4 -0
  97. package/dist/gs/errors/errors.js +81 -0
  98. package/dist/gs/errors/errors.js.map +1 -1
  99. package/dist/gs/fmt/fmt.d.ts +4 -4
  100. package/dist/gs/fmt/fmt.js +42 -11
  101. package/dist/gs/fmt/fmt.js.map +1 -1
  102. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +36 -1
  103. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +212 -2
  104. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  105. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +189 -0
  106. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +825 -0
  107. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -0
  108. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +163 -0
  109. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +449 -0
  110. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -0
  111. package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
  112. package/dist/gs/github.com/klauspost/compress/internal/le/index.d.ts +9 -0
  113. package/dist/gs/github.com/klauspost/compress/internal/le/index.js +71 -0
  114. package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -0
  115. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  116. package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
  117. package/dist/gs/go/internal/scannerhooks/index.d.ts +3 -0
  118. package/dist/gs/go/internal/scannerhooks/index.js +5 -0
  119. package/dist/gs/go/internal/scannerhooks/index.js.map +1 -0
  120. package/dist/gs/go/scanner/index.d.ts +42 -0
  121. package/dist/gs/go/scanner/index.js +155 -0
  122. package/dist/gs/go/scanner/index.js.map +1 -0
  123. package/dist/gs/go/token/index.d.ts +187 -0
  124. package/dist/gs/go/token/index.js +578 -0
  125. package/dist/gs/go/token/index.js.map +1 -0
  126. package/dist/gs/internal/abi/index.d.ts +4 -0
  127. package/dist/gs/internal/abi/index.js +10 -0
  128. package/dist/gs/internal/abi/index.js.map +1 -1
  129. package/dist/gs/internal/bytealg/index.d.ts +2 -0
  130. package/dist/gs/internal/bytealg/index.js +14 -0
  131. package/dist/gs/internal/bytealg/index.js.map +1 -1
  132. package/dist/gs/internal/byteorder/index.d.ts +8 -2
  133. package/dist/gs/internal/byteorder/index.js +56 -25
  134. package/dist/gs/internal/byteorder/index.js.map +1 -1
  135. package/dist/gs/internal/godebug/index.d.ts +12 -0
  136. package/dist/gs/internal/godebug/index.js +30 -0
  137. package/dist/gs/internal/godebug/index.js.map +1 -0
  138. package/dist/gs/io/fs/fs.js.map +1 -1
  139. package/dist/gs/io/fs/index.d.ts +1 -0
  140. package/dist/gs/io/fs/index.js +1 -0
  141. package/dist/gs/io/fs/index.js.map +1 -1
  142. package/dist/gs/io/fs/readdir.js.map +1 -1
  143. package/dist/gs/io/fs/readfile.js.map +1 -1
  144. package/dist/gs/io/fs/readlink.d.ts +8 -0
  145. package/dist/gs/io/fs/readlink.js +64 -0
  146. package/dist/gs/io/fs/readlink.js.map +1 -0
  147. package/dist/gs/io/fs/stat.js.map +1 -1
  148. package/dist/gs/io/fs/sub.js.map +1 -1
  149. package/dist/gs/io/fs/walk.d.ts +3 -3
  150. package/dist/gs/io/fs/walk.js +7 -7
  151. package/dist/gs/io/fs/walk.js.map +1 -1
  152. package/dist/gs/io/io.d.ts +40 -6
  153. package/dist/gs/io/io.js +151 -26
  154. package/dist/gs/io/io.js.map +1 -1
  155. package/dist/gs/maps/iter.d.ts +3 -3
  156. package/dist/gs/maps/iter.js +3 -3
  157. package/dist/gs/maps/iter.js.map +1 -1
  158. package/dist/gs/maps/maps.d.ts +2 -2
  159. package/dist/gs/maps/maps.js +1 -1
  160. package/dist/gs/maps/maps.js.map +1 -1
  161. package/dist/gs/math/bits/index.d.ts +13 -4
  162. package/dist/gs/math/bits/index.js +66 -34
  163. package/dist/gs/math/bits/index.js.map +1 -1
  164. package/dist/gs/math/const.gs.d.ts +5 -5
  165. package/dist/gs/math/const.gs.js +4 -4
  166. package/dist/gs/math/const.gs.js.map +1 -1
  167. package/dist/gs/mime/index.d.ts +1 -0
  168. package/dist/gs/mime/index.js +50 -0
  169. package/dist/gs/mime/index.js.map +1 -0
  170. package/dist/gs/net/http/httptest/index.d.ts +11 -0
  171. package/dist/gs/net/http/httptest/index.js +21 -0
  172. package/dist/gs/net/http/httptest/index.js.map +1 -0
  173. package/dist/gs/net/http/index.d.ts +27 -0
  174. package/dist/gs/net/http/index.js +61 -0
  175. package/dist/gs/net/http/index.js.map +1 -0
  176. package/dist/gs/os/dir_unix.gs.js +2 -2
  177. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  178. package/dist/gs/os/error.gs.js +2 -4
  179. package/dist/gs/os/error.gs.js.map +1 -1
  180. package/dist/gs/os/exec.gs.js.map +1 -1
  181. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  182. package/dist/gs/os/rawconn_js.gs.js.map +1 -1
  183. package/dist/gs/os/root_js.gs.js.map +1 -1
  184. package/dist/gs/os/tempfile.gs.js +66 -9
  185. package/dist/gs/os/tempfile.gs.js.map +1 -1
  186. package/dist/gs/os/types.gs.js.map +1 -1
  187. package/dist/gs/os/types_js.gs.js +9 -9
  188. package/dist/gs/os/types_js.gs.js.map +1 -1
  189. package/dist/gs/os/types_unix.gs.js.map +1 -1
  190. package/dist/gs/path/filepath/match.js +165 -3
  191. package/dist/gs/path/filepath/match.js.map +1 -1
  192. package/dist/gs/path/filepath/path.d.ts +3 -1
  193. package/dist/gs/path/filepath/path.js +133 -4
  194. package/dist/gs/path/filepath/path.js.map +1 -1
  195. package/dist/gs/path/match.js.map +1 -1
  196. package/dist/gs/path/path.d.ts +4 -1
  197. package/dist/gs/path/path.js +16 -4
  198. package/dist/gs/path/path.js.map +1 -1
  199. package/dist/gs/reflect/index.d.ts +3 -3
  200. package/dist/gs/reflect/index.js +2 -2
  201. package/dist/gs/reflect/index.js.map +1 -1
  202. package/dist/gs/reflect/map.js +3 -0
  203. package/dist/gs/reflect/map.js.map +1 -1
  204. package/dist/gs/reflect/type.d.ts +9 -5
  205. package/dist/gs/reflect/type.js +233 -21
  206. package/dist/gs/reflect/type.js.map +1 -1
  207. package/dist/gs/reflect/types.js.map +1 -1
  208. package/dist/gs/reflect/visiblefields.js.map +1 -1
  209. package/dist/gs/runtime/debug/index.d.ts +2 -0
  210. package/dist/gs/runtime/debug/index.js +8 -0
  211. package/dist/gs/runtime/debug/index.js.map +1 -0
  212. package/dist/gs/runtime/runtime.d.ts +35 -3
  213. package/dist/gs/runtime/runtime.js +72 -0
  214. package/dist/gs/runtime/runtime.js.map +1 -1
  215. package/dist/gs/slices/slices.d.ts +24 -5
  216. package/dist/gs/slices/slices.js +214 -5
  217. package/dist/gs/slices/slices.js.map +1 -1
  218. package/dist/gs/sort/slice.gs.d.ts +3 -3
  219. package/dist/gs/sort/slice.gs.js +6 -6
  220. package/dist/gs/sort/slice.gs.js.map +1 -1
  221. package/dist/gs/sort/sort.gs.d.ts +4 -4
  222. package/dist/gs/sort/sort.gs.js +11 -8
  223. package/dist/gs/sort/sort.gs.js.map +1 -1
  224. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  225. package/dist/gs/strconv/quote.gs.js.map +1 -1
  226. package/dist/gs/strings/builder.d.ts +1 -1
  227. package/dist/gs/strings/builder.js +3 -2
  228. package/dist/gs/strings/builder.js.map +1 -1
  229. package/dist/gs/strings/reader.js.map +1 -1
  230. package/dist/gs/strings/replace.js.map +1 -1
  231. package/dist/gs/sync/atomic/type.gs.d.ts +9 -8
  232. package/dist/gs/sync/atomic/type.gs.js +0 -2
  233. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  234. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  235. package/dist/gs/sync/sync.d.ts +3 -0
  236. package/dist/gs/sync/sync.js +39 -0
  237. package/dist/gs/sync/sync.js.map +1 -1
  238. package/dist/gs/syscall/constants.d.ts +36 -24
  239. package/dist/gs/syscall/constants.js +12 -0
  240. package/dist/gs/syscall/constants.js.map +1 -1
  241. package/dist/gs/syscall/errors.d.ts +2 -0
  242. package/dist/gs/syscall/errors.js +8 -0
  243. package/dist/gs/syscall/errors.js.map +1 -1
  244. package/dist/gs/syscall/fs.d.ts +43 -0
  245. package/dist/gs/syscall/fs.js +102 -0
  246. package/dist/gs/syscall/fs.js.map +1 -1
  247. package/dist/gs/syscall/js/index.d.ts +90 -0
  248. package/dist/gs/syscall/js/index.js +375 -0
  249. package/dist/gs/syscall/js/index.js.map +1 -0
  250. package/dist/gs/syscall/types.d.ts +22 -0
  251. package/dist/gs/syscall/types.js +45 -1
  252. package/dist/gs/syscall/types.js.map +1 -1
  253. package/dist/gs/testing/index.d.ts +1 -0
  254. package/dist/gs/testing/index.js +2 -0
  255. package/dist/gs/testing/index.js.map +1 -0
  256. package/dist/gs/testing/testing.d.ts +77 -0
  257. package/dist/gs/testing/testing.js +301 -0
  258. package/dist/gs/testing/testing.js.map +1 -0
  259. package/dist/gs/time/time.d.ts +41 -4
  260. package/dist/gs/time/time.js +205 -36
  261. package/dist/gs/time/time.js.map +1 -1
  262. package/dist/gs/unicode/unicode.d.ts +23 -1
  263. package/dist/gs/unicode/unicode.js +79 -10
  264. package/dist/gs/unicode/unicode.js.map +1 -1
  265. package/dist/gs/unicode/utf8/utf8.d.ts +4 -4
  266. package/dist/gs/unicode/utf8/utf8.js +24 -11
  267. package/dist/gs/unicode/utf8/utf8.js.map +1 -1
  268. package/dist/gs/unique/index.d.ts +11 -0
  269. package/dist/gs/unique/index.js +71 -0
  270. package/dist/gs/unique/index.js.map +1 -0
  271. package/go.mod +2 -2
  272. package/go.sum +9 -0
  273. package/gs/builtin/builtin.ts +266 -8
  274. package/gs/builtin/channel.ts +22 -0
  275. package/gs/builtin/hostio.test.ts +177 -0
  276. package/gs/builtin/hostio.ts +171 -56
  277. package/gs/builtin/index.ts +1 -0
  278. package/gs/builtin/runtime-contract.test.ts +356 -0
  279. package/gs/builtin/slice.ts +259 -50
  280. package/gs/builtin/type.ts +188 -30
  281. package/gs/builtin/varRef.ts +38 -1
  282. package/gs/bytes/buffer.gs.ts +48 -44
  283. package/gs/bytes/meta.json +8 -3
  284. package/gs/bytes/reader.gs.ts +20 -19
  285. package/gs/context/context.test.ts +41 -0
  286. package/gs/context/context.ts +22 -26
  287. package/gs/crypto/internal/fips140deps/byteorder/index.ts +1 -0
  288. package/gs/crypto/internal/fips140deps/godebug/index.ts +1 -0
  289. package/gs/crypto/rand/index.test.ts +32 -0
  290. package/gs/crypto/rand/index.ts +90 -0
  291. package/gs/crypto/rand/meta.json +5 -0
  292. package/gs/embed/index.ts +20 -0
  293. package/gs/embed/meta.json +5 -0
  294. package/gs/encoding/json/index.test.ts +79 -0
  295. package/gs/encoding/json/index.ts +210 -0
  296. package/gs/errors/errors.test.ts +82 -0
  297. package/gs/errors/errors.ts +104 -0
  298. package/gs/fmt/fmt.ts +56 -16
  299. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +95 -0
  300. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +300 -2
  301. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +159 -0
  302. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +1005 -0
  303. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +719 -0
  304. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +40 -0
  305. package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/meta.json +3 -1
  306. package/gs/github.com/klauspost/compress/internal/le/index.test.ts +36 -0
  307. package/gs/github.com/klauspost/compress/internal/le/index.ts +114 -0
  308. package/gs/go/internal/scannerhooks/index.test.ts +14 -0
  309. package/gs/go/internal/scannerhooks/index.ts +9 -0
  310. package/gs/go/scanner/index.test.ts +72 -0
  311. package/gs/go/scanner/index.ts +204 -0
  312. package/gs/go/token/index.test.ts +67 -0
  313. package/gs/go/token/index.ts +686 -0
  314. package/gs/internal/abi/index.test.ts +18 -0
  315. package/gs/internal/abi/index.ts +14 -0
  316. package/gs/internal/bytealg/index.test.ts +18 -0
  317. package/gs/internal/bytealg/index.ts +16 -0
  318. package/gs/internal/byteorder/index.test.ts +39 -0
  319. package/gs/internal/byteorder/index.ts +100 -27
  320. package/gs/internal/godebug/index.test.ts +16 -0
  321. package/gs/internal/godebug/index.ts +35 -0
  322. package/gs/io/fs/index.ts +1 -0
  323. package/gs/io/fs/meta.json +5 -0
  324. package/gs/io/fs/readlink.test.ts +43 -0
  325. package/gs/io/fs/readlink.ts +77 -0
  326. package/gs/io/fs/walk.test.ts +61 -0
  327. package/gs/io/fs/walk.ts +9 -9
  328. package/gs/io/io.ts +174 -31
  329. package/gs/io/meta.json +10 -2
  330. package/gs/maps/iter.ts +12 -6
  331. package/gs/maps/maps.ts +8 -6
  332. package/gs/math/bits/index.ts +103 -47
  333. package/gs/math/const.gs.test.ts +11 -5
  334. package/gs/math/const.gs.ts +5 -6
  335. package/gs/mime/index.ts +54 -0
  336. package/gs/net/http/httptest/index.ts +25 -0
  337. package/gs/net/http/index.test.ts +20 -0
  338. package/gs/net/http/index.ts +81 -0
  339. package/gs/os/dir_unix.gs.ts +2 -3
  340. package/gs/os/file_unix_js.test.ts +50 -0
  341. package/gs/os/meta.json +1 -2
  342. package/gs/os/tempfile.gs.test.ts +85 -0
  343. package/gs/os/tempfile.gs.ts +71 -11
  344. package/gs/os/types_js.gs.ts +11 -11
  345. package/gs/path/filepath/match.test.ts +31 -12
  346. package/gs/path/filepath/match.ts +178 -3
  347. package/gs/path/filepath/path.test.ts +25 -0
  348. package/gs/path/filepath/path.ts +159 -5
  349. package/gs/path/path.ts +20 -5
  350. package/gs/reflect/index.ts +2 -1
  351. package/gs/reflect/map.test.ts +19 -0
  352. package/gs/reflect/map.ts +4 -0
  353. package/gs/reflect/type.ts +298 -29
  354. package/gs/reflect/typefor.test.ts +75 -0
  355. package/gs/runtime/debug/index.test.ts +24 -0
  356. package/gs/runtime/debug/index.ts +8 -0
  357. package/gs/runtime/runtime.test.ts +19 -0
  358. package/gs/runtime/runtime.ts +98 -3
  359. package/gs/slices/slices.test.ts +94 -0
  360. package/gs/slices/slices.ts +245 -5
  361. package/gs/sort/meta.json +7 -0
  362. package/gs/sort/slice.gs.ts +16 -7
  363. package/gs/sort/sort.gs.ts +16 -13
  364. package/gs/strings/builder.ts +4 -3
  365. package/gs/sync/atomic/type.gs.ts +13 -14
  366. package/gs/sync/meta.json +3 -1
  367. package/gs/sync/sync.test.ts +36 -0
  368. package/gs/sync/sync.ts +39 -0
  369. package/gs/syscall/constants.ts +39 -24
  370. package/gs/syscall/errors.ts +10 -0
  371. package/gs/syscall/fs.ts +195 -0
  372. package/gs/syscall/js/index.ts +458 -0
  373. package/gs/syscall/js/meta.json +4 -0
  374. package/gs/syscall/net.test.ts +85 -0
  375. package/gs/syscall/types.ts +56 -0
  376. package/gs/testing/index.ts +1 -0
  377. package/gs/testing/meta.json +5 -0
  378. package/gs/testing/testing.test.ts +90 -0
  379. package/gs/testing/testing.ts +382 -0
  380. package/gs/time/time.test.ts +106 -0
  381. package/gs/time/time.ts +278 -57
  382. package/gs/unicode/unicode.test.ts +25 -0
  383. package/gs/unicode/unicode.ts +119 -9
  384. package/gs/unicode/utf8/utf8.test.ts +13 -0
  385. package/gs/unicode/utf8/utf8.ts +28 -16
  386. package/gs/unique/index.ts +91 -0
  387. package/package.json +14 -13
  388. package/compiler/analysis.go +0 -3475
  389. package/compiler/analysis_test.go +0 -338
  390. package/compiler/assignment.go +0 -580
  391. package/compiler/builtin_test.go +0 -92
  392. package/compiler/code-writer.go +0 -115
  393. package/compiler/compiler_test.go +0 -149
  394. package/compiler/composite-lit.go +0 -779
  395. package/compiler/config_test.go +0 -62
  396. package/compiler/constraint.go +0 -86
  397. package/compiler/decl.go +0 -801
  398. package/compiler/expr-call-async.go +0 -188
  399. package/compiler/expr-call-builtins.go +0 -208
  400. package/compiler/expr-call-helpers.go +0 -382
  401. package/compiler/expr-call-make.go +0 -318
  402. package/compiler/expr-call-type-conversion.go +0 -520
  403. package/compiler/expr-call.go +0 -413
  404. package/compiler/expr-selector.go +0 -343
  405. package/compiler/expr-star.go +0 -82
  406. package/compiler/expr-type.go +0 -442
  407. package/compiler/expr-value.go +0 -89
  408. package/compiler/expr.go +0 -773
  409. package/compiler/field.go +0 -183
  410. package/compiler/gs_dependencies_test.go +0 -298
  411. package/compiler/lit.go +0 -322
  412. package/compiler/output.go +0 -72
  413. package/compiler/primitive.go +0 -149
  414. package/compiler/protobuf.go +0 -697
  415. package/compiler/sanitize.go +0 -100
  416. package/compiler/spec-struct.go +0 -995
  417. package/compiler/spec-value.go +0 -540
  418. package/compiler/spec.go +0 -725
  419. package/compiler/stmt-assign.go +0 -664
  420. package/compiler/stmt-for.go +0 -266
  421. package/compiler/stmt-range.go +0 -475
  422. package/compiler/stmt-select.go +0 -262
  423. package/compiler/stmt-type-switch.go +0 -147
  424. package/compiler/stmt.go +0 -1308
  425. package/compiler/type-assert.go +0 -386
  426. package/compiler/type-info.go +0 -156
  427. package/compiler/type-utils.go +0 -207
  428. package/compiler/type.go +0 -892
@@ -0,0 +1,1040 @@
1
+ package compiler
2
+
3
+ import (
4
+ "context"
5
+ "os"
6
+ "path/filepath"
7
+ "slices"
8
+ "strconv"
9
+ "strings"
10
+ )
11
+
12
+ // TypeScriptEmitOwner owns deterministic TypeScript file emission.
13
+ type TypeScriptEmitOwner struct {
14
+ runtimeOwner *RuntimeContractOwner
15
+ }
16
+
17
+ // NewTypeScriptEmitOwner creates the TypeScript emit owner.
18
+ func NewTypeScriptEmitOwner(runtimeOwners ...*RuntimeContractOwner) *TypeScriptEmitOwner {
19
+ runtimeOwner := NewRuntimeContractOwner()
20
+ if len(runtimeOwners) != 0 && runtimeOwners[0] != nil {
21
+ runtimeOwner = runtimeOwners[0]
22
+ }
23
+ return &TypeScriptEmitOwner{runtimeOwner: runtimeOwner}
24
+ }
25
+
26
+ // Emit writes a lowered program to the configured TypeScript output tree.
27
+ func (o *TypeScriptEmitOwner) Emit(
28
+ ctx context.Context,
29
+ req *CompileRequest,
30
+ program *LoweredProgram,
31
+ ) ([]string, []Diagnostic) {
32
+ if err := ctx.Err(); err != nil {
33
+ return nil, []Diagnostic{{
34
+ Severity: DiagnosticSeverityError,
35
+ Code: "goscript/context:canceled",
36
+ Message: err.Error(),
37
+ }}
38
+ }
39
+ if req == nil {
40
+ return nil, []Diagnostic{{
41
+ Severity: DiagnosticSeverityError,
42
+ Code: "goscript/emitter:no-request",
43
+ Message: "TypeScript emission requires a compile request",
44
+ }}
45
+ }
46
+ if program == nil {
47
+ return nil, []Diagnostic{{
48
+ Severity: DiagnosticSeverityError,
49
+ Code: "goscript/emitter:no-program",
50
+ Message: "TypeScript emission requires a lowered program",
51
+ }}
52
+ }
53
+
54
+ files, diagnostics := o.EmitToMemory(ctx, program)
55
+ if diagnosticsHaveErrors(diagnostics) {
56
+ return nil, diagnostics
57
+ }
58
+ var compiled []string
59
+ for _, pkg := range program.packages {
60
+ if err := ctx.Err(); err != nil {
61
+ diagnostics = append(diagnostics, Diagnostic{
62
+ Severity: DiagnosticSeverityError,
63
+ Code: "goscript/context:canceled",
64
+ Message: err.Error(),
65
+ })
66
+ break
67
+ }
68
+ pkgDir := filepath.Join(req.OutputPath, "@goscript", filepath.FromSlash(pkg.pkgPath))
69
+ if err := os.MkdirAll(pkgDir, 0o755); err != nil {
70
+ diagnostics = append(diagnostics, emitError("create package output", pkg.pkgPath, err))
71
+ continue
72
+ }
73
+ for _, file := range pkg.files {
74
+ filePath := "@goscript/" + pkg.pkgPath + "/" + file.outputName
75
+ path := filepath.Join(req.OutputPath, filepath.FromSlash(filePath))
76
+ if err := os.WriteFile(path, []byte(files[filePath]), 0o644); err != nil {
77
+ diagnostics = append(diagnostics, emitError("write TypeScript file", path, err))
78
+ }
79
+ }
80
+ indexPath := "@goscript/" + pkg.pkgPath + "/index.ts"
81
+ if err := os.WriteFile(filepath.Join(pkgDir, "index.ts"), []byte(files[indexPath]), 0o644); err != nil {
82
+ diagnostics = append(diagnostics, emitError("write package index", pkg.pkgPath, err))
83
+ continue
84
+ }
85
+ compiled = append(compiled, pkg.pkgPath)
86
+ }
87
+ return compiled, diagnostics
88
+ }
89
+
90
+ // EmitToMemory renders a lowered program into deterministic slash-path files.
91
+ func (o *TypeScriptEmitOwner) EmitToMemory(
92
+ ctx context.Context,
93
+ program *LoweredProgram,
94
+ ) (map[string]string, []Diagnostic) {
95
+ if err := ctx.Err(); err != nil {
96
+ return nil, []Diagnostic{contextCanceledDiagnostic(err)}
97
+ }
98
+ if program == nil {
99
+ return nil, []Diagnostic{{
100
+ Severity: DiagnosticSeverityError,
101
+ Code: "goscript/emitter:no-program",
102
+ Message: "TypeScript emission requires a lowered program",
103
+ }}
104
+ }
105
+ files := make(map[string]string)
106
+ for _, pkg := range program.packages {
107
+ if err := ctx.Err(); err != nil {
108
+ return files, []Diagnostic{contextCanceledDiagnostic(err)}
109
+ }
110
+ for _, file := range pkg.files {
111
+ files["@goscript/"+pkg.pkgPath+"/"+file.outputName] = o.renderLoweredFile(pkg, file)
112
+ }
113
+ files["@goscript/"+pkg.pkgPath+"/index.ts"] = renderIndex(pkg)
114
+ }
115
+ return files, nil
116
+ }
117
+
118
+ func (o *TypeScriptEmitOwner) renderLoweredFile(pkg *loweredPackage, file *loweredFile) string {
119
+ var b strings.Builder
120
+ if file.sourcePath != "" {
121
+ b.WriteString("// Generated file based on ")
122
+ b.WriteString(filepath.Base(file.sourcePath))
123
+ b.WriteString("\n// Updated when compliance tests are re-run, DO NOT EDIT!\n\n")
124
+ }
125
+ for idx, imp := range file.imports {
126
+ if idx != 0 {
127
+ b.WriteString("\n")
128
+ }
129
+ b.WriteString("import * as ")
130
+ b.WriteString(imp.alias)
131
+ b.WriteString(" from \"")
132
+ b.WriteString(imp.source)
133
+ b.WriteString("\"\n")
134
+ }
135
+ if len(file.imports) != 0 {
136
+ b.WriteString("\n")
137
+ }
138
+ hasMain := false
139
+ wroteDecl := false
140
+ writeSeparator := func() {
141
+ if wroteDecl {
142
+ b.WriteString("\n")
143
+ }
144
+ wroteDecl = true
145
+ }
146
+ writeDecl := func(decl loweredDecl) {
147
+ if decl.structType != nil {
148
+ writeSeparator()
149
+ renderStruct(&b, decl.structType, o.runtimeOwner)
150
+ return
151
+ }
152
+ if decl.function != nil {
153
+ writeSeparator()
154
+ renderFunction(&b, decl.function)
155
+ if decl.function.name == "main" {
156
+ hasMain = true
157
+ }
158
+ return
159
+ }
160
+ writeSeparator()
161
+ b.WriteString(decl.code)
162
+ b.WriteString("\n")
163
+ }
164
+ for _, decl := range file.decls {
165
+ if decl.typeIndexExport != "" && decl.code != "" {
166
+ writeDecl(decl)
167
+ }
168
+ }
169
+ for _, decl := range sortedStructDecls(file.decls) {
170
+ if decl.structType != nil {
171
+ writeDecl(decl)
172
+ }
173
+ }
174
+ for _, decl := range file.decls {
175
+ if decl.structType != nil || (decl.typeIndexExport != "" && decl.code != "") {
176
+ continue
177
+ }
178
+ writeDecl(decl)
179
+ }
180
+ if pkg.name == "main" && hasMain {
181
+ writeSeparator()
182
+ b.WriteString("if (")
183
+ b.WriteString(o.runtimeOwner.QualifiedHelper(RuntimeHelperIsMainScript))
184
+ b.WriteString("(import.meta)) {\n")
185
+ b.WriteString("\tawait main()\n")
186
+ b.WriteString("}\n")
187
+ }
188
+ return b.String()
189
+ }
190
+
191
+ func sortedStructDecls(decls []loweredDecl) []loweredDecl {
192
+ structs := make([]loweredDecl, 0)
193
+ names := make(map[string]bool)
194
+ for _, decl := range decls {
195
+ if decl.structType == nil {
196
+ continue
197
+ }
198
+ structs = append(structs, decl)
199
+ names[decl.structType.name] = true
200
+ }
201
+ if len(structs) < 2 {
202
+ return structs
203
+ }
204
+ byName := make(map[string]loweredDecl, len(structs))
205
+ for _, decl := range structs {
206
+ byName[decl.structType.name] = decl
207
+ }
208
+ visiting := make(map[string]bool, len(structs))
209
+ visited := make(map[string]bool, len(structs))
210
+ sorted := make([]loweredDecl, 0, len(structs))
211
+ var visit func(loweredDecl)
212
+ visit = func(decl loweredDecl) {
213
+ name := decl.structType.name
214
+ if visited[name] || visiting[name] {
215
+ return
216
+ }
217
+ visiting[name] = true
218
+ for _, dep := range structZeroValueDeps(decl.structType, names) {
219
+ if depDecl, ok := byName[dep]; ok {
220
+ visit(depDecl)
221
+ }
222
+ }
223
+ visiting[name] = false
224
+ visited[name] = true
225
+ sorted = append(sorted, decl)
226
+ }
227
+ for _, decl := range structs {
228
+ visit(decl)
229
+ }
230
+ return sorted
231
+ }
232
+
233
+ func structZeroValueDeps(structType *loweredStruct, names map[string]bool) []string {
234
+ var deps []string
235
+ for _, field := range structType.fields {
236
+ if !field.structValue {
237
+ continue
238
+ }
239
+ for name := range names {
240
+ if name == structType.name {
241
+ continue
242
+ }
243
+ if strings.Contains(field.zero, "new "+name+"(") {
244
+ deps = append(deps, name)
245
+ }
246
+ }
247
+ }
248
+ return deps
249
+ }
250
+
251
+ func renderStruct(b *strings.Builder, structType *loweredStruct, runtimeOwner *RuntimeContractOwner) {
252
+ varRef := runtimeOwner.QualifiedHelper(RuntimeHelperVarRef)
253
+ markStructValue := runtimeOwner.QualifiedHelper(RuntimeHelperMarkAsStructValue)
254
+ registerStructType := runtimeOwner.QualifiedHelper(RuntimeHelperRegisterStructType)
255
+ if structType.exported {
256
+ b.WriteString("export ")
257
+ }
258
+ b.WriteString("class ")
259
+ b.WriteString(structType.name)
260
+ b.WriteString(" {\n")
261
+ for _, field := range structType.fields {
262
+ writeLineComment(b, "\t", field.doc)
263
+ b.WriteString("\tpublic get ")
264
+ b.WriteString(field.name)
265
+ b.WriteString("(): ")
266
+ b.WriteString(field.typ)
267
+ b.WriteString(" {\n\t\treturn this._fields.")
268
+ b.WriteString(field.name)
269
+ b.WriteString(".value\n\t}\n")
270
+ b.WriteString("\tpublic set ")
271
+ b.WriteString(field.name)
272
+ b.WriteString("(value: ")
273
+ b.WriteString(field.typ)
274
+ b.WriteString(") {\n\t\tthis._fields.")
275
+ b.WriteString(field.name)
276
+ b.WriteString(".value = value\n\t}\n\n")
277
+ }
278
+ b.WriteString("\tpublic _fields: {\n")
279
+ for _, field := range structType.fields {
280
+ b.WriteString("\t\t")
281
+ b.WriteString(field.name)
282
+ b.WriteString(": $.VarRef<")
283
+ b.WriteString(field.typ)
284
+ b.WriteString(">\n")
285
+ }
286
+ b.WriteString("\t}\n\n")
287
+ b.WriteString("\tconstructor(init?: Partial<{")
288
+ for idx, field := range structType.fields {
289
+ if idx != 0 {
290
+ b.WriteString(", ")
291
+ }
292
+ b.WriteString(field.name)
293
+ b.WriteString("?: ")
294
+ b.WriteString(field.typ)
295
+ }
296
+ b.WriteString("}>) {\n\t\tthis._fields = {\n")
297
+ for idx, field := range structType.fields {
298
+ b.WriteString("\t\t\t")
299
+ b.WriteString(field.name)
300
+ b.WriteString(": ")
301
+ b.WriteString(varRef)
302
+ b.WriteString("(")
303
+ if field.structValue {
304
+ b.WriteString("init?.")
305
+ b.WriteString(field.name)
306
+ b.WriteString(" ? ")
307
+ b.WriteString(markStructValue)
308
+ b.WriteString("(init.")
309
+ b.WriteString(field.name)
310
+ b.WriteString(".clone()) : ")
311
+ b.WriteString(field.zero)
312
+ } else {
313
+ b.WriteString("init?.")
314
+ b.WriteString(field.name)
315
+ b.WriteString(" ?? ")
316
+ b.WriteString(field.zero)
317
+ }
318
+ b.WriteString(")")
319
+ if idx != len(structType.fields)-1 {
320
+ b.WriteString(",")
321
+ }
322
+ b.WriteString("\n")
323
+ }
324
+ b.WriteString("\t\t}\n\t}\n\n")
325
+ b.WriteString("\tpublic ")
326
+ b.WriteString(structType.cloneMethod)
327
+ b.WriteString("(): ")
328
+ b.WriteString(structType.name)
329
+ b.WriteString(" {\n\t\tconst cloned = new ")
330
+ b.WriteString(structType.name)
331
+ b.WriteString("()\n\t\tcloned._fields = {\n")
332
+ for idx, field := range structType.fields {
333
+ b.WriteString("\t\t\t")
334
+ b.WriteString(field.name)
335
+ b.WriteString(": ")
336
+ b.WriteString(varRef)
337
+ b.WriteString("(")
338
+ if field.structValue {
339
+ b.WriteString(markStructValue)
340
+ b.WriteString("(this._fields.")
341
+ b.WriteString(field.name)
342
+ b.WriteString(".value.clone())")
343
+ } else {
344
+ b.WriteString("this._fields.")
345
+ b.WriteString(field.name)
346
+ b.WriteString(".value")
347
+ }
348
+ b.WriteString(")")
349
+ if idx != len(structType.fields)-1 {
350
+ b.WriteString(",")
351
+ }
352
+ b.WriteString("\n")
353
+ }
354
+ b.WriteString("\t\t}\n\t\treturn ")
355
+ b.WriteString(markStructValue)
356
+ b.WriteString("(cloned)\n\t}\n")
357
+ for _, method := range structType.methods {
358
+ b.WriteString("\n")
359
+ renderMethod(b, &method)
360
+ }
361
+ b.WriteString("\n\tstatic __typeInfo = ")
362
+ b.WriteString(registerStructType)
363
+ b.WriteString("(\n")
364
+ b.WriteString("\t\t")
365
+ b.WriteString(strconvQuote(structType.typeName))
366
+ b.WriteString(",\n\t\t() => new ")
367
+ b.WriteString(structType.name)
368
+ b.WriteString("(),\n\t\t[")
369
+ for idx, method := range structType.methods {
370
+ if idx != 0 {
371
+ b.WriteString(", ")
372
+ }
373
+ methodName := method.name
374
+ if method.runtimeName != "" {
375
+ methodName = method.runtimeName
376
+ }
377
+ b.WriteString("{ name: ")
378
+ b.WriteString(strconvQuote(methodName))
379
+ b.WriteString(", args: [], returns: [] }")
380
+ }
381
+ b.WriteString("],\n\t\t")
382
+ b.WriteString(structType.name)
383
+ b.WriteString(",\n\t\t{")
384
+ for idx, field := range structType.fields {
385
+ if idx != 0 {
386
+ b.WriteString(", ")
387
+ }
388
+ b.WriteString(strconvQuote(field.name))
389
+ b.WriteString(": ")
390
+ b.WriteString(runtimeStructFieldInfoExpr(field.runtimeType, field.runtimeName, field.tag))
391
+ }
392
+ b.WriteString("}\n\t)\n")
393
+ b.WriteString("}\n")
394
+ }
395
+
396
+ func writeLineComment(b *strings.Builder, indent string, comment string) {
397
+ comment = strings.TrimSpace(comment)
398
+ if comment == "" {
399
+ return
400
+ }
401
+ for line := range strings.SplitSeq(comment, "\n") {
402
+ line = strings.TrimRight(line, "\r")
403
+ if strings.TrimSpace(line) == "" {
404
+ b.WriteString(indent)
405
+ b.WriteString("//\n")
406
+ continue
407
+ }
408
+ b.WriteString(indent)
409
+ b.WriteString("// ")
410
+ b.WriteString(line)
411
+ b.WriteString("\n")
412
+ }
413
+ }
414
+
415
+ func renderFunction(b *strings.Builder, fn *loweredFunction) {
416
+ if fn.exported {
417
+ b.WriteString("export ")
418
+ }
419
+ if fn.async {
420
+ b.WriteString("async ")
421
+ }
422
+ b.WriteString("function ")
423
+ b.WriteString(fn.name)
424
+ b.WriteString("(")
425
+ for idx, param := range fn.params {
426
+ if idx != 0 {
427
+ b.WriteString(", ")
428
+ }
429
+ b.WriteString(param.name)
430
+ b.WriteString(": ")
431
+ b.WriteString(param.typ)
432
+ }
433
+ b.WriteString("): ")
434
+ b.WriteString(fn.result)
435
+ b.WriteString(" {\n")
436
+ if fn.receiverAlias != "" && fn.receiverAlias != "_" {
437
+ writeIndent(b, 1)
438
+ if fn.receiverMutable {
439
+ b.WriteString("let ")
440
+ } else {
441
+ b.WriteString("const ")
442
+ }
443
+ b.WriteString(fn.receiverAlias)
444
+ if fn.receiverType != "" {
445
+ b.WriteString(": ")
446
+ b.WriteString(fn.receiverType)
447
+ }
448
+ b.WriteString(" = ")
449
+ b.WriteString(receiverValue(fn))
450
+ b.WriteString("\n")
451
+ }
452
+ renderStmts(b, fn.paramBindings, 1)
453
+ renderNamedResults(b, fn.namedResults, 1)
454
+ renderDeferStack(b, fn.deferState, 1)
455
+ renderStmts(b, fn.body, 1)
456
+ b.WriteString("}\n")
457
+ }
458
+
459
+ func renderMethod(b *strings.Builder, fn *loweredFunction) {
460
+ writeIndent(b, 1)
461
+ b.WriteString("public ")
462
+ if fn.async {
463
+ b.WriteString("async ")
464
+ }
465
+ b.WriteString(fn.name)
466
+ b.WriteString("(")
467
+ for idx, param := range fn.params {
468
+ if idx != 0 {
469
+ b.WriteString(", ")
470
+ }
471
+ b.WriteString(param.name)
472
+ b.WriteString(": ")
473
+ b.WriteString(param.typ)
474
+ }
475
+ b.WriteString("): ")
476
+ b.WriteString(fn.result)
477
+ b.WriteString(" {\n")
478
+ if fn.receiverAlias != "" && fn.receiverAlias != "_" {
479
+ writeIndent(b, 2)
480
+ if fn.receiverMutable {
481
+ b.WriteString("let ")
482
+ } else {
483
+ b.WriteString("const ")
484
+ }
485
+ b.WriteString(fn.receiverAlias)
486
+ if fn.receiverType != "" {
487
+ b.WriteString(": ")
488
+ b.WriteString(fn.receiverType)
489
+ }
490
+ b.WriteString(" = ")
491
+ b.WriteString(receiverValue(fn))
492
+ b.WriteString("\n")
493
+ }
494
+ renderStmts(b, fn.paramBindings, 2)
495
+ renderNamedResults(b, fn.namedResults, 2)
496
+ renderDeferStack(b, fn.deferState, 2)
497
+ renderStmts(b, fn.body, 2)
498
+ writeIndent(b, 1)
499
+ b.WriteString("}\n")
500
+ }
501
+
502
+ func receiverValue(fn *loweredFunction) string {
503
+ if fn.receiverValue != "" {
504
+ return fn.receiverValue
505
+ }
506
+ return "this"
507
+ }
508
+
509
+ func renderNamedResults(b *strings.Builder, results []loweredNamedResult, indent int) {
510
+ for _, result := range results {
511
+ writeIndent(b, indent)
512
+ b.WriteString("let ")
513
+ b.WriteString(result.name)
514
+ b.WriteString(": ")
515
+ b.WriteString(result.typ)
516
+ b.WriteString(" = ")
517
+ b.WriteString(result.zero)
518
+ b.WriteString("\n")
519
+ }
520
+ }
521
+
522
+ func renderDeferStack(b *strings.Builder, state *loweredDeferState, indent int) {
523
+ if state == nil || !state.used {
524
+ return
525
+ }
526
+ writeIndent(b, indent)
527
+ if state.async {
528
+ b.WriteString("await using __defer = new $.AsyncDisposableStack()\n")
529
+ return
530
+ }
531
+ b.WriteString("using __defer = new $.DisposableStack()\n")
532
+ }
533
+
534
+ func renderStmts(b *strings.Builder, stmts []loweredStmt, indent int) {
535
+ for idx, stmt := range stmts {
536
+ renderLeadingLines(b, stmt.leading, indent)
537
+ if stmt.rangeFunc != nil {
538
+ renderRangeFunc(b, stmt.rangeFunc, indent)
539
+ continue
540
+ }
541
+ if stmt.switchStmt != nil {
542
+ renderSwitch(b, stmt.switchStmt, indent)
543
+ continue
544
+ }
545
+ if stmt.selectStmt != nil {
546
+ renderSelect(b, stmt.selectStmt, indent)
547
+ continue
548
+ }
549
+ if stmt.typeSwitch != nil {
550
+ renderTypeSwitch(b, stmt.typeSwitch, indent)
551
+ continue
552
+ }
553
+ writeIndent(b, indent)
554
+ if stmt.text == "" && (stmt.hasBlock || len(stmt.children) != 0) {
555
+ b.WriteString("{\n")
556
+ renderStmts(b, stmt.children, indent+1)
557
+ writeIndent(b, indent)
558
+ b.WriteString("}\n")
559
+ continue
560
+ }
561
+ writeIndentedText(b, stmt.text, indent)
562
+ if !stmt.hasBlock && len(stmt.children) == 0 {
563
+ if idx+1 < len(stmts) && needsASIBarrier(stmt, stmts[idx+1]) {
564
+ b.WriteString(";")
565
+ }
566
+ b.WriteString("\n")
567
+ continue
568
+ }
569
+ b.WriteString(" {\n")
570
+ renderStmts(b, stmt.children, indent+1)
571
+ writeIndent(b, indent)
572
+ b.WriteString("}")
573
+ if len(stmt.elseBody) == 0 {
574
+ b.WriteString("\n")
575
+ continue
576
+ }
577
+ b.WriteString(" else {\n")
578
+ renderStmts(b, stmt.elseBody, indent+1)
579
+ writeIndent(b, indent)
580
+ b.WriteString("}\n")
581
+ }
582
+ }
583
+
584
+ func needsASIBarrier(current loweredStmt, next loweredStmt) bool {
585
+ if current.text == "" ||
586
+ current.hasBlock ||
587
+ len(current.children) != 0 ||
588
+ current.rangeFunc != nil ||
589
+ current.switchStmt != nil ||
590
+ current.selectStmt != nil ||
591
+ current.typeSwitch != nil {
592
+ return false
593
+ }
594
+ if strings.HasSuffix(strings.TrimSpace(current.text), ";") {
595
+ return false
596
+ }
597
+ nextText := strings.TrimLeft(next.text, " \t")
598
+ return strings.HasPrefix(nextText, "(") || strings.HasPrefix(nextText, "[")
599
+ }
600
+
601
+ func renderLeadingLines(b *strings.Builder, lines []string, indent int) {
602
+ for _, line := range lines {
603
+ if strings.TrimSpace(line) == "" {
604
+ b.WriteString("\n")
605
+ continue
606
+ }
607
+ writeIndent(b, indent)
608
+ b.WriteString(line)
609
+ b.WriteString("\n")
610
+ }
611
+ }
612
+
613
+ func writeIndentedText(b *strings.Builder, text string, indent int) {
614
+ lines := strings.Split(text, "\n")
615
+ for idx, line := range lines {
616
+ if idx != 0 {
617
+ b.WriteString("\n")
618
+ if line != "" {
619
+ writeIndent(b, indent)
620
+ }
621
+ }
622
+ b.WriteString(line)
623
+ }
624
+ }
625
+
626
+ func renderSwitch(b *strings.Builder, stmt *loweredSwitch, indent int) {
627
+ writeIndent(b, indent)
628
+ b.WriteString("switch (")
629
+ b.WriteString(stmt.value)
630
+ b.WriteString(") {\n")
631
+ for _, switchCase := range stmt.cases {
632
+ if switchCase.defaultCase {
633
+ writeIndent(b, indent+1)
634
+ b.WriteString("default:\n")
635
+ } else {
636
+ for _, value := range switchCase.values {
637
+ writeIndent(b, indent+1)
638
+ b.WriteString("case ")
639
+ b.WriteString(value)
640
+ b.WriteString(":\n")
641
+ }
642
+ }
643
+ renderSwitchBody(b, switchCase.body, switchCase.fallsThrough, indent+1)
644
+ }
645
+ writeIndent(b, indent)
646
+ b.WriteString("}\n")
647
+ }
648
+
649
+ func renderSwitchBody(b *strings.Builder, body []loweredStmt, fallsThrough bool, indent int) {
650
+ writeIndent(b, indent)
651
+ b.WriteString("{\n")
652
+ renderStmts(b, body, indent+1)
653
+ if !fallsThrough {
654
+ writeIndent(b, indent+1)
655
+ b.WriteString("break\n")
656
+ }
657
+ writeIndent(b, indent)
658
+ b.WriteString("}\n")
659
+ }
660
+
661
+ func renderRangeFunc(b *strings.Builder, stmt *loweredRangeFunc, indent int) {
662
+ if stmt.returnBranch != nil {
663
+ writeIndent(b, indent)
664
+ b.WriteString("let ")
665
+ b.WriteString(stmt.returnBranch.hasReturn)
666
+ b.WriteString(" = false\n")
667
+ if stmt.returnBranch.value != "" {
668
+ writeIndent(b, indent)
669
+ b.WriteString("let ")
670
+ b.WriteString(stmt.returnBranch.value)
671
+ b.WriteString(": ")
672
+ b.WriteString(stmt.returnBranch.resultType)
673
+ b.WriteString(" | undefined\n")
674
+ }
675
+ }
676
+ writeIndent(b, indent)
677
+ if stmt.async {
678
+ b.WriteString(";await (async () => {\n")
679
+ } else {
680
+ b.WriteString(";(() => {\n")
681
+ }
682
+ writeIndent(b, indent+1)
683
+ if stmt.async {
684
+ b.WriteString("await ")
685
+ }
686
+ b.WriteString(stmt.value)
687
+ b.WriteString("!(")
688
+ if stmt.async {
689
+ b.WriteString("async ")
690
+ }
691
+ b.WriteString("(")
692
+ b.WriteString(strings.Join(stmt.params, ", "))
693
+ b.WriteString(") => {\n")
694
+ renderStmts(b, stmt.body, indent+2)
695
+ writeIndent(b, indent+2)
696
+ b.WriteString("return true\n")
697
+ writeIndent(b, indent+1)
698
+ b.WriteString("})\n")
699
+ writeIndent(b, indent)
700
+ b.WriteString("})()\n")
701
+ if stmt.returnBranch == nil {
702
+ return
703
+ }
704
+ writeIndent(b, indent)
705
+ b.WriteString("if (")
706
+ b.WriteString(stmt.returnBranch.hasReturn)
707
+ b.WriteString(")")
708
+ if stmt.parentBranch != nil {
709
+ b.WriteString(" {\n")
710
+ writeIndent(b, indent+1)
711
+ b.WriteString(stmt.parentBranch.hasReturn)
712
+ b.WriteString(" = true\n")
713
+ if stmt.parentBranch.value != "" && stmt.returnBranch.value != "" {
714
+ writeIndent(b, indent+1)
715
+ b.WriteString(stmt.parentBranch.value)
716
+ b.WriteString(" = ")
717
+ b.WriteString(stmt.returnBranch.value)
718
+ b.WriteString("!\n")
719
+ }
720
+ writeIndent(b, indent+1)
721
+ b.WriteString("return false\n")
722
+ writeIndent(b, indent)
723
+ b.WriteString("}\n")
724
+ return
725
+ }
726
+ if stmt.returnBranch.value == "" {
727
+ b.WriteString(" {\n")
728
+ writeIndent(b, indent+1)
729
+ b.WriteString("return\n")
730
+ writeIndent(b, indent)
731
+ b.WriteString("}\n")
732
+ return
733
+ }
734
+ b.WriteString(" {\n")
735
+ writeIndent(b, indent+1)
736
+ b.WriteString("return ")
737
+ b.WriteString(stmt.returnBranch.value)
738
+ b.WriteString("!")
739
+ b.WriteString("\n")
740
+ writeIndent(b, indent)
741
+ b.WriteString("}\n")
742
+ }
743
+
744
+ func renderNamedStructConversion(expr *loweredNamedStructConversionExpr) string {
745
+ if expr == nil {
746
+ return "undefined"
747
+ }
748
+ if expr.castOnly {
749
+ return "(" + expr.value.text + " as unknown as " + expr.castTarget + ")"
750
+ }
751
+ fields := make([]string, 0, len(expr.fields))
752
+ for _, field := range expr.fields {
753
+ fields = append(fields, field.name+": "+expr.temp+"."+field.name)
754
+ }
755
+ body := "const " + expr.temp + " = " + expr.value.text + "; return " +
756
+ expr.helper + "(new " + expr.target + "({" + strings.Join(fields, ", ") + "}))"
757
+ if expr.value.async {
758
+ return "(await (async () => { " + body + " })())"
759
+ }
760
+ return "(() => { " + body + " })()"
761
+ }
762
+
763
+ func renderSelect(b *strings.Builder, stmt *loweredSelect, indent int) {
764
+ writeIndent(b, indent)
765
+ b.WriteString("const [")
766
+ b.WriteString(stmt.hasReturn)
767
+ b.WriteString(", ")
768
+ b.WriteString(stmt.value)
769
+ b.WriteString("] = await $.selectStatement<any, ")
770
+ if stmt.external {
771
+ b.WriteString("any")
772
+ } else {
773
+ b.WriteString(stmt.resultType)
774
+ }
775
+ b.WriteString(">([\n")
776
+ for idx, switchCase := range stmt.cases {
777
+ renderSelectCase(b, switchCase, stmt.external, indent+1)
778
+ if idx != len(stmt.cases)-1 {
779
+ b.WriteString(",")
780
+ }
781
+ b.WriteString("\n")
782
+ }
783
+ writeIndent(b, indent)
784
+ b.WriteString("], ")
785
+ hasDefault := "false"
786
+ if stmt.hasDefault {
787
+ hasDefault = "true"
788
+ }
789
+ b.WriteString(hasDefault)
790
+ b.WriteString(")\n")
791
+ if stmt.external {
792
+ renderSelectExternalBodies(b, stmt, indent)
793
+ return
794
+ }
795
+ writeIndent(b, indent)
796
+ b.WriteString("if (")
797
+ b.WriteString(stmt.hasReturn)
798
+ b.WriteString(") {\n")
799
+ writeIndent(b, indent+1)
800
+ b.WriteString("return ")
801
+ b.WriteString(stmt.value)
802
+ b.WriteString("\n")
803
+ writeIndent(b, indent)
804
+ b.WriteString("}\n")
805
+ if stmt.returns {
806
+ writeIndent(b, indent)
807
+ b.WriteString("throw new Error(\"unreachable select\")\n")
808
+ }
809
+ }
810
+
811
+ func renderSelectExternalBodies(b *strings.Builder, stmt *loweredSelect, indent int) {
812
+ writeIndent(b, indent)
813
+ b.WriteString("switch (")
814
+ b.WriteString(stmt.value)
815
+ b.WriteString("?.id) {\n")
816
+ for _, switchCase := range stmt.cases {
817
+ writeIndent(b, indent+1)
818
+ b.WriteString("case ")
819
+ b.WriteString(strconv.Itoa(switchCase.id))
820
+ b.WriteString(":\n")
821
+ writeIndent(b, indent+2)
822
+ b.WriteString("{\n")
823
+ writeIndent(b, indent+3)
824
+ b.WriteString("const result = ")
825
+ b.WriteString(stmt.value)
826
+ b.WriteString("\n")
827
+ renderStmts(b, switchCase.prelude, indent+3)
828
+ renderStmts(b, switchCase.body, indent+3)
829
+ writeIndent(b, indent+3)
830
+ b.WriteString("break\n")
831
+ writeIndent(b, indent+2)
832
+ b.WriteString("}\n")
833
+ }
834
+ writeIndent(b, indent)
835
+ b.WriteString("}\n")
836
+ if stmt.returns {
837
+ writeIndent(b, indent)
838
+ b.WriteString("throw new Error(\"unreachable select\")\n")
839
+ }
840
+ }
841
+
842
+ func renderSelectCase(b *strings.Builder, switchCase loweredSelectCase, external bool, indent int) {
843
+ writeIndent(b, indent)
844
+ b.WriteString("{\n")
845
+ writeIndent(b, indent+1)
846
+ b.WriteString("id: ")
847
+ b.WriteString(strconv.Itoa(switchCase.id))
848
+ b.WriteString(",\n")
849
+ writeIndent(b, indent+1)
850
+ b.WriteString("isSend: ")
851
+ isSend := "false"
852
+ if switchCase.isSend {
853
+ isSend = "true"
854
+ }
855
+ b.WriteString(isSend)
856
+ b.WriteString(",\n")
857
+ writeIndent(b, indent+1)
858
+ b.WriteString("channel: ")
859
+ b.WriteString(switchCase.channel)
860
+ b.WriteString(",\n")
861
+ if switchCase.isSend {
862
+ writeIndent(b, indent+1)
863
+ b.WriteString("value: ")
864
+ b.WriteString(switchCase.value)
865
+ b.WriteString(",\n")
866
+ }
867
+ writeIndent(b, indent+1)
868
+ b.WriteString("onSelected: async (result) => {\n")
869
+ if external {
870
+ writeIndent(b, indent+2)
871
+ b.WriteString("return result\n")
872
+ writeIndent(b, indent+1)
873
+ b.WriteString("}\n")
874
+ writeIndent(b, indent)
875
+ b.WriteString("}")
876
+ return
877
+ }
878
+ renderStmts(b, switchCase.prelude, indent+2)
879
+ renderStmts(b, switchCase.body, indent+2)
880
+ writeIndent(b, indent+1)
881
+ b.WriteString("}\n")
882
+ writeIndent(b, indent)
883
+ b.WriteString("}")
884
+ }
885
+
886
+ func renderTypeSwitch(b *strings.Builder, stmt *loweredTypeSwitch, indent int) {
887
+ writeIndent(b, indent)
888
+ b.WriteString("{\n")
889
+ writeIndent(b, indent+1)
890
+ b.WriteString("const __goscriptTypeSwitchValue = ")
891
+ b.WriteString(stmt.value)
892
+ b.WriteString("\n")
893
+ writeIndent(b, indent+1)
894
+ b.WriteString("switch (true) {\n")
895
+ for _, switchCase := range stmt.cases {
896
+ renderTypeSwitchCase(b, stmt.varName, stmt.varRef, switchCase, indent+2)
897
+ }
898
+ if len(stmt.defaultBody) != 0 {
899
+ writeIndent(b, indent+2)
900
+ b.WriteString("default:\n")
901
+ renderTypeSwitchInlineBody(b, stmt.varName, stmt.varRef || stmt.defaultRef, "any", "__goscriptTypeSwitchValue", stmt.defaultBody, indent+3)
902
+ writeIndent(b, indent+3)
903
+ b.WriteString("break\n")
904
+ }
905
+ writeIndent(b, indent+1)
906
+ b.WriteString("}\n")
907
+ writeIndent(b, indent)
908
+ b.WriteString("}\n")
909
+ }
910
+
911
+ func renderTypeSwitchCase(b *strings.Builder, varName string, varRef bool, switchCase loweredTypeSwitchCase, indent int) {
912
+ if len(switchCase.types) == 0 {
913
+ return
914
+ }
915
+ writeIndent(b, indent)
916
+ b.WriteString("case ")
917
+ if len(switchCase.types) == 1 {
918
+ b.WriteString("$.typeAssert<")
919
+ b.WriteString(typeSwitchAssertType(switchCase, 0))
920
+ b.WriteString(">(__goscriptTypeSwitchValue, ")
921
+ b.WriteString(switchCase.types[0])
922
+ b.WriteString(").ok")
923
+ } else {
924
+ for idx, typ := range switchCase.types {
925
+ if idx != 0 {
926
+ b.WriteString(" || ")
927
+ }
928
+ b.WriteString("$.is(__goscriptTypeSwitchValue, ")
929
+ b.WriteString(typ)
930
+ b.WriteString(")")
931
+ }
932
+ }
933
+ b.WriteString(":\n")
934
+ value := "__goscriptTypeSwitchValue"
935
+ if len(switchCase.types) == 1 {
936
+ value = "$.typeAssert<" + typeSwitchAssertType(switchCase, 0) +
937
+ ">(__goscriptTypeSwitchValue, " + switchCase.types[0] + ").value"
938
+ }
939
+ renderTypeSwitchInlineBody(b, varName, varRef || switchCase.varRef, typeSwitchCaseVariableType(switchCase), value, switchCase.body, indent+1)
940
+ writeIndent(b, indent+1)
941
+ b.WriteString("break\n")
942
+ }
943
+
944
+ func typeSwitchAssertType(switchCase loweredTypeSwitchCase, idx int) string {
945
+ if idx < len(switchCase.tsTypes) && switchCase.tsTypes[idx] != "" {
946
+ return switchCase.tsTypes[idx]
947
+ }
948
+ return "any"
949
+ }
950
+
951
+ func typeSwitchCaseVariableType(switchCase loweredTypeSwitchCase) string {
952
+ if len(switchCase.types) == 1 {
953
+ return typeSwitchAssertType(switchCase, 0)
954
+ }
955
+ return ""
956
+ }
957
+
958
+ func renderTypeSwitchInlineBody(
959
+ b *strings.Builder,
960
+ varName string,
961
+ varRef bool,
962
+ varType string,
963
+ value string,
964
+ body []loweredStmt,
965
+ indent int,
966
+ ) {
967
+ if varName == "" {
968
+ renderStmts(b, body, indent)
969
+ return
970
+ }
971
+ writeIndent(b, indent)
972
+ b.WriteString("{\n")
973
+ writeIndent(b, indent+1)
974
+ b.WriteString("let ")
975
+ b.WriteString(varName)
976
+ if varRef {
977
+ if varType == "" {
978
+ varType = "any"
979
+ }
980
+ b.WriteString(": $.VarRef<")
981
+ b.WriteString(varType)
982
+ b.WriteString("> = $.varRef(")
983
+ b.WriteString(value)
984
+ b.WriteString(")\n")
985
+ renderStmts(b, body, indent+1)
986
+ writeIndent(b, indent)
987
+ b.WriteString("}\n")
988
+ return
989
+ }
990
+ if varType != "" {
991
+ b.WriteString(": ")
992
+ b.WriteString(varType)
993
+ }
994
+ b.WriteString(" = ")
995
+ b.WriteString(value)
996
+ b.WriteString("\n")
997
+ renderStmts(b, body, indent+1)
998
+ writeIndent(b, indent)
999
+ b.WriteString("}\n")
1000
+ }
1001
+
1002
+ func renderIndex(pkg *loweredPackage) string {
1003
+ var lines []string
1004
+ for _, file := range pkg.files {
1005
+ exports := slices.Clone(file.exports)
1006
+ slices.Sort(exports)
1007
+ if len(exports) != 0 {
1008
+ lines = append(lines, "export { "+strings.Join(exports, ", ")+" } from \"./"+file.outputName+"\"")
1009
+ }
1010
+ typeExports := slices.Clone(file.typeExports)
1011
+ slices.Sort(typeExports)
1012
+ if len(typeExports) != 0 {
1013
+ lines = append(lines, "export type { "+strings.Join(typeExports, ", ")+" } from \"./"+file.outputName+"\"")
1014
+ }
1015
+ }
1016
+ slices.Sort(lines)
1017
+ if len(lines) == 0 {
1018
+ return ""
1019
+ }
1020
+ return strings.Join(lines, "\n") + "\n"
1021
+ }
1022
+
1023
+ func writeIndent(b *strings.Builder, indent int) {
1024
+ for range indent {
1025
+ b.WriteString("\t")
1026
+ }
1027
+ }
1028
+
1029
+ func strconvQuote(value string) string {
1030
+ return strconv.Quote(value)
1031
+ }
1032
+
1033
+ func emitError(action string, subject string, err error) Diagnostic {
1034
+ return Diagnostic{
1035
+ Severity: DiagnosticSeverityError,
1036
+ Code: "goscript/emitter:write",
1037
+ Message: "failed to " + action,
1038
+ Detail: subject + ": " + err.Error(),
1039
+ }
1040
+ }