redscript-mc 1.2.30 → 2.1.0

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 (593) hide show
  1. package/.claudeignore +21 -0
  2. package/.github/workflows/ci.yml +1 -0
  3. package/README.md +12 -16
  4. package/README.zh.md +2 -2
  5. package/demo.gif +0 -0
  6. package/dist/cli.js +2 -554
  7. package/dist/compile.js +2 -266
  8. package/dist/index.js +2 -159
  9. package/dist/src/__tests__/budget.test.js +261 -0
  10. package/dist/src/__tests__/cli.test.js +104 -0
  11. package/dist/{__tests__ → src/__tests__}/dce.test.js +11 -47
  12. package/dist/{__tests__ → src/__tests__}/diagnostics.test.js +67 -40
  13. package/dist/src/__tests__/e2e/basic.test.d.ts +8 -0
  14. package/dist/src/__tests__/e2e/basic.test.js +140 -0
  15. package/dist/src/__tests__/e2e/coroutine.test.d.ts +7 -0
  16. package/dist/src/__tests__/e2e/coroutine.test.js +132 -0
  17. package/dist/src/__tests__/e2e/macros.test.d.ts +9 -0
  18. package/dist/src/__tests__/e2e/macros.test.js +182 -0
  19. package/dist/src/__tests__/e2e/migrate.test.d.ts +13 -0
  20. package/dist/src/__tests__/e2e/migrate.test.js +2739 -0
  21. package/dist/src/__tests__/e2e/stdlib-e2e.test.d.ts +10 -0
  22. package/dist/src/__tests__/e2e/stdlib-e2e.test.js +324 -0
  23. package/dist/src/__tests__/enum.test.d.ts +10 -0
  24. package/dist/src/__tests__/enum.test.js +389 -0
  25. package/dist/src/__tests__/generics.test.d.ts +14 -0
  26. package/dist/src/__tests__/generics.test.js +367 -0
  27. package/dist/src/__tests__/hir/desugar.test.js +234 -0
  28. package/dist/src/__tests__/incremental.test.d.ts +5 -0
  29. package/dist/src/__tests__/incremental.test.js +308 -0
  30. package/dist/src/__tests__/lir/lower.test.js +559 -0
  31. package/dist/src/__tests__/lir/types.test.js +185 -0
  32. package/dist/src/__tests__/lir/verify.test.js +221 -0
  33. package/dist/src/__tests__/lsp.test.d.ts +7 -0
  34. package/dist/src/__tests__/lsp.test.js +245 -0
  35. package/dist/{__tests__ → src/__tests__}/mc-integration.test.js +1 -3
  36. package/dist/src/__tests__/mc-version.test.d.ts +10 -0
  37. package/dist/src/__tests__/mc-version.test.js +154 -0
  38. package/dist/src/__tests__/mir/arithmetic.test.js +130 -0
  39. package/dist/src/__tests__/mir/control-flow.test.js +205 -0
  40. package/dist/src/__tests__/mir/verify.test.js +223 -0
  41. package/dist/src/__tests__/modules.test.d.ts +7 -0
  42. package/dist/src/__tests__/modules.test.js +333 -0
  43. package/dist/src/__tests__/optimizer/block_merge.test.js +78 -0
  44. package/dist/src/__tests__/optimizer/branch_simplify.test.js +58 -0
  45. package/dist/src/__tests__/optimizer/constant_fold.test.js +131 -0
  46. package/dist/src/__tests__/optimizer/copy_prop.test.js +91 -0
  47. package/dist/src/__tests__/optimizer/coroutine.test.d.ts +12 -0
  48. package/dist/src/__tests__/optimizer/coroutine.test.js +251 -0
  49. package/dist/src/__tests__/optimizer/dce.test.d.ts +1 -0
  50. package/dist/src/__tests__/optimizer/dce.test.js +76 -0
  51. package/dist/src/__tests__/optimizer/interprocedural.test.d.ts +1 -0
  52. package/dist/src/__tests__/optimizer/interprocedural.test.js +145 -0
  53. package/dist/src/__tests__/optimizer/lir/const_imm.test.d.ts +1 -0
  54. package/dist/src/__tests__/optimizer/lir/const_imm.test.js +138 -0
  55. package/dist/src/__tests__/optimizer/lir/dead_slot.test.d.ts +1 -0
  56. package/dist/src/__tests__/optimizer/lir/dead_slot.test.js +141 -0
  57. package/dist/src/__tests__/optimizer/lir/peephole.test.d.ts +1 -0
  58. package/dist/src/__tests__/optimizer/lir/peephole.test.js +126 -0
  59. package/dist/src/__tests__/optimizer/lir/pipeline.test.d.ts +1 -0
  60. package/dist/src/__tests__/optimizer/lir/pipeline.test.js +84 -0
  61. package/dist/src/__tests__/optimizer/nbt-batch.test.d.ts +1 -0
  62. package/dist/src/__tests__/optimizer/nbt-batch.test.js +110 -0
  63. package/dist/src/__tests__/optimizer/pipeline.test.d.ts +1 -0
  64. package/dist/src/__tests__/optimizer/pipeline.test.js +102 -0
  65. package/dist/src/__tests__/optimizer/selector-cache.test.d.ts +1 -0
  66. package/dist/src/__tests__/optimizer/selector-cache.test.js +103 -0
  67. package/dist/src/__tests__/optimizer/unroll.test.d.ts +1 -0
  68. package/dist/src/__tests__/optimizer/unroll.test.js +206 -0
  69. package/dist/src/__tests__/option.test.d.ts +14 -0
  70. package/dist/src/__tests__/option.test.js +275 -0
  71. package/dist/src/__tests__/parser.test.d.ts +1 -0
  72. package/dist/src/__tests__/repl.test.d.ts +1 -0
  73. package/dist/src/__tests__/schedule.test.d.ts +7 -0
  74. package/dist/src/__tests__/schedule.test.js +98 -0
  75. package/dist/src/__tests__/sourcemap.test.d.ts +7 -0
  76. package/dist/src/__tests__/sourcemap.test.js +227 -0
  77. package/dist/src/__tests__/tuple.test.d.ts +11 -0
  78. package/dist/src/__tests__/tuple.test.js +202 -0
  79. package/dist/src/__tests__/typechecker-strict.test.d.ts +10 -0
  80. package/dist/src/__tests__/typechecker-strict.test.js +197 -0
  81. package/dist/src/__tests__/typechecker.test.d.ts +1 -0
  82. package/dist/{ast → src/ast}/types.d.ts +58 -3
  83. package/dist/src/cache/deps.d.ts +41 -0
  84. package/dist/src/cache/deps.js +158 -0
  85. package/dist/src/cache/incremental.d.ts +35 -0
  86. package/dist/src/cache/incremental.js +165 -0
  87. package/dist/src/cache/index.d.ts +37 -0
  88. package/dist/src/cache/index.js +152 -0
  89. package/dist/{cli.d.ts → src/cli.d.ts} +1 -1
  90. package/dist/src/cli.js +474 -0
  91. package/dist/src/compile.d.ts +37 -0
  92. package/dist/src/compile.js +165 -0
  93. package/dist/{diagnostics → src/diagnostics}/index.d.ts +1 -1
  94. package/dist/{diagnostics → src/diagnostics}/index.js +8 -11
  95. package/dist/src/emit/compile.d.ts +29 -0
  96. package/dist/src/emit/compile.js +143 -0
  97. package/dist/src/emit/index.d.ts +26 -0
  98. package/dist/src/emit/index.js +223 -0
  99. package/dist/src/emit/modules.d.ts +29 -0
  100. package/dist/src/emit/modules.js +492 -0
  101. package/dist/src/emit/sourcemap.d.ts +53 -0
  102. package/dist/src/emit/sourcemap.js +73 -0
  103. package/dist/src/hir/lower.d.ts +15 -0
  104. package/dist/src/hir/lower.js +399 -0
  105. package/dist/src/hir/monomorphize.d.ts +22 -0
  106. package/dist/src/hir/monomorphize.js +379 -0
  107. package/dist/src/hir/types.d.ts +406 -0
  108. package/dist/src/hir/types.js +16 -0
  109. package/dist/src/index.d.ts +39 -0
  110. package/dist/src/index.js +67 -0
  111. package/dist/{lexer → src/lexer}/index.d.ts +1 -1
  112. package/dist/{lexer → src/lexer}/index.js +1 -0
  113. package/dist/src/lir/budget.d.ts +37 -0
  114. package/dist/src/lir/budget.js +280 -0
  115. package/dist/src/lir/lower.d.ts +15 -0
  116. package/dist/src/lir/lower.js +472 -0
  117. package/dist/src/lir/types.d.ts +139 -0
  118. package/dist/src/lir/types.js +11 -0
  119. package/dist/src/lir/verify.d.ts +14 -0
  120. package/dist/src/lir/verify.js +113 -0
  121. package/dist/src/lsp/main.d.ts +8 -0
  122. package/dist/src/lsp/main.js +11 -0
  123. package/dist/src/lsp/server.d.ts +11 -0
  124. package/dist/src/lsp/server.js +352 -0
  125. package/dist/{mc-test → src/mc-test}/runner.js +4 -3
  126. package/dist/src/mir/lower.d.ts +9 -0
  127. package/dist/src/mir/lower.js +1264 -0
  128. package/dist/src/mir/macro.d.ts +22 -0
  129. package/dist/src/mir/macro.js +168 -0
  130. package/dist/src/mir/types.d.ts +191 -0
  131. package/dist/src/mir/types.js +11 -0
  132. package/dist/src/mir/verify.d.ts +16 -0
  133. package/dist/src/mir/verify.js +216 -0
  134. package/dist/src/optimizer/block_merge.d.ts +12 -0
  135. package/dist/src/optimizer/block_merge.js +84 -0
  136. package/dist/src/optimizer/branch_simplify.d.ts +9 -0
  137. package/dist/src/optimizer/branch_simplify.js +28 -0
  138. package/dist/src/optimizer/constant_fold.d.ts +10 -0
  139. package/dist/src/optimizer/constant_fold.js +85 -0
  140. package/dist/src/optimizer/copy_prop.d.ts +9 -0
  141. package/dist/src/optimizer/copy_prop.js +113 -0
  142. package/dist/src/optimizer/coroutine.d.ts +34 -0
  143. package/dist/src/optimizer/coroutine.js +789 -0
  144. package/dist/src/optimizer/dce.d.ts +8 -0
  145. package/dist/src/optimizer/dce.js +156 -0
  146. package/dist/src/optimizer/interprocedural.d.ts +14 -0
  147. package/dist/src/optimizer/interprocedural.js +186 -0
  148. package/dist/src/optimizer/lir/const_imm.d.ts +12 -0
  149. package/dist/src/optimizer/lir/const_imm.js +139 -0
  150. package/dist/src/optimizer/lir/dead_slot.d.ts +14 -0
  151. package/dist/src/optimizer/lir/dead_slot.js +130 -0
  152. package/dist/src/optimizer/lir/peephole.d.ts +21 -0
  153. package/dist/src/optimizer/lir/peephole.js +52 -0
  154. package/dist/src/optimizer/lir/pipeline.d.ts +10 -0
  155. package/dist/src/optimizer/lir/pipeline.js +34 -0
  156. package/dist/src/optimizer/nbt-batch.d.ts +11 -0
  157. package/dist/src/optimizer/nbt-batch.js +51 -0
  158. package/dist/src/optimizer/pipeline.d.ts +14 -0
  159. package/dist/src/optimizer/pipeline.js +58 -0
  160. package/dist/src/optimizer/selector-cache.d.ts +22 -0
  161. package/dist/src/optimizer/selector-cache.js +100 -0
  162. package/dist/src/optimizer/unroll.d.ts +32 -0
  163. package/dist/src/optimizer/unroll.js +348 -0
  164. package/dist/{parser → src/parser}/index.d.ts +8 -0
  165. package/dist/{parser → src/parser}/index.js +204 -14
  166. package/dist/{repl.d.ts → src/repl.d.ts} +1 -1
  167. package/dist/{runtime → src/runtime}/index.js +1 -1
  168. package/dist/{typechecker → src/typechecker}/index.d.ts +4 -0
  169. package/dist/{typechecker → src/typechecker}/index.js +198 -13
  170. package/dist/src/types/mc-version.d.ts +24 -0
  171. package/dist/src/types/mc-version.js +49 -0
  172. package/docs/ROADMAP.md +395 -0
  173. package/docs/compiler-pipeline-redesign.md +2260 -0
  174. package/docs/optimization-ideas.md +1076 -0
  175. package/editors/vscode/out/extension.js +25176 -8000
  176. package/editors/vscode/package-lock.json +90 -6
  177. package/editors/vscode/package.json +3 -2
  178. package/editors/vscode/src/extension.ts +97 -67
  179. package/examples/showcase.mcrs +3 -3
  180. package/package.json +13 -6
  181. package/scripts/postbuild.js +15 -0
  182. package/src/__tests__/budget.test.ts +297 -0
  183. package/src/__tests__/cli.test.ts +8 -220
  184. package/src/__tests__/dce.test.ts +11 -56
  185. package/src/__tests__/diagnostics.test.ts +61 -41
  186. package/src/__tests__/e2e/basic.test.ts +154 -0
  187. package/src/__tests__/e2e/coroutine.test.ts +142 -0
  188. package/src/__tests__/e2e/macros.test.ts +199 -0
  189. package/src/__tests__/e2e/migrate.test.ts +3008 -0
  190. package/src/__tests__/e2e/stdlib-e2e.test.ts +348 -0
  191. package/src/__tests__/enum.test.ts +425 -0
  192. package/src/__tests__/generics.test.ts +390 -0
  193. package/src/__tests__/hir/desugar.test.ts +263 -0
  194. package/src/__tests__/incremental.test.ts +337 -0
  195. package/src/__tests__/lir/lower.test.ts +619 -0
  196. package/src/__tests__/lir/types.test.ts +207 -0
  197. package/src/__tests__/lir/verify.test.ts +249 -0
  198. package/src/__tests__/lsp.test.ts +270 -0
  199. package/src/__tests__/mc-integration.test.ts +1 -2
  200. package/src/__tests__/mc-version.test.ts +178 -0
  201. package/src/__tests__/mir/arithmetic.test.ts +156 -0
  202. package/src/__tests__/mir/control-flow.test.ts +242 -0
  203. package/src/__tests__/mir/verify.test.ts +254 -0
  204. package/src/__tests__/modules.test.ts +365 -0
  205. package/src/__tests__/optimizer/block_merge.test.ts +84 -0
  206. package/src/__tests__/optimizer/branch_simplify.test.ts +64 -0
  207. package/src/__tests__/optimizer/constant_fold.test.ts +145 -0
  208. package/src/__tests__/optimizer/copy_prop.test.ts +99 -0
  209. package/src/__tests__/optimizer/coroutine.test.ts +312 -0
  210. package/src/__tests__/optimizer/dce.test.ts +83 -0
  211. package/src/__tests__/optimizer/interprocedural.test.ts +174 -0
  212. package/src/__tests__/optimizer/lir/const_imm.test.ts +151 -0
  213. package/src/__tests__/optimizer/lir/dead_slot.test.ts +156 -0
  214. package/src/__tests__/optimizer/lir/peephole.test.ts +136 -0
  215. package/src/__tests__/optimizer/lir/pipeline.test.ts +113 -0
  216. package/src/__tests__/optimizer/nbt-batch.test.ts +119 -0
  217. package/src/__tests__/optimizer/pipeline.test.ts +116 -0
  218. package/src/__tests__/optimizer/selector-cache.test.ts +112 -0
  219. package/src/__tests__/optimizer/unroll.test.ts +231 -0
  220. package/src/__tests__/option.test.ts +299 -0
  221. package/src/__tests__/schedule.test.ts +105 -0
  222. package/src/__tests__/sourcemap.test.ts +254 -0
  223. package/src/__tests__/tuple.test.ts +220 -0
  224. package/src/__tests__/typechecker-strict.test.ts +216 -0
  225. package/src/ast/types.ts +39 -3
  226. package/src/cache/deps.ts +132 -0
  227. package/src/cache/incremental.ts +173 -0
  228. package/src/cache/index.ts +135 -0
  229. package/src/cli.ts +111 -195
  230. package/src/compile.ts +6 -162
  231. package/src/diagnostics/index.ts +8 -11
  232. package/src/emit/compile.ts +177 -0
  233. package/src/emit/index.ts +286 -0
  234. package/src/emit/modules.ts +581 -0
  235. package/src/emit/sourcemap.ts +101 -0
  236. package/src/hir/lower.ts +455 -0
  237. package/src/hir/monomorphize.ts +416 -0
  238. package/src/hir/types.ts +228 -0
  239. package/src/index.ts +37 -182
  240. package/src/lexer/index.ts +2 -1
  241. package/src/lir/budget.ts +321 -0
  242. package/src/lir/lower.ts +587 -0
  243. package/src/lir/types.ts +113 -0
  244. package/src/lir/verify.ts +129 -0
  245. package/src/lsp/main.ts +9 -0
  246. package/src/lsp/server.ts +414 -0
  247. package/src/mc-test/runner.ts +4 -3
  248. package/src/mir/lower.ts +1403 -0
  249. package/src/mir/macro.ts +167 -0
  250. package/src/mir/types.ts +117 -0
  251. package/src/mir/verify.ts +218 -0
  252. package/src/optimizer/block_merge.ts +93 -0
  253. package/src/optimizer/branch_simplify.ts +27 -0
  254. package/src/optimizer/constant_fold.ts +88 -0
  255. package/src/optimizer/copy_prop.ts +106 -0
  256. package/src/optimizer/coroutine.ts +996 -0
  257. package/src/optimizer/dce.ts +108 -653
  258. package/src/optimizer/interprocedural.ts +177 -0
  259. package/src/optimizer/lir/const_imm.ts +143 -0
  260. package/src/optimizer/lir/dead_slot.ts +123 -0
  261. package/src/optimizer/lir/peephole.ts +57 -0
  262. package/src/optimizer/lir/pipeline.ts +37 -0
  263. package/src/optimizer/nbt-batch.ts +50 -0
  264. package/src/optimizer/pipeline.ts +59 -0
  265. package/src/optimizer/selector-cache.ts +103 -0
  266. package/src/optimizer/unroll.ts +386 -0
  267. package/src/parser/index.ts +213 -16
  268. package/src/repl.ts +1 -1
  269. package/src/runtime/index.ts +1 -1
  270. package/src/stdlib/math.mcrs +4 -4
  271. package/src/templates/quest.mcrs +4 -4
  272. package/src/typechecker/index.ts +215 -15
  273. package/src/types/mc-version.ts +46 -0
  274. package/tsconfig.json +1 -1
  275. package/dist/__tests__/cli.test.js +0 -278
  276. package/dist/__tests__/codegen.test.js +0 -152
  277. package/dist/__tests__/e2e.test.d.ts +0 -6
  278. package/dist/__tests__/e2e.test.js +0 -1847
  279. package/dist/__tests__/entity-types.test.js +0 -203
  280. package/dist/__tests__/lowering.test.js +0 -1015
  281. package/dist/__tests__/macro.test.d.ts +0 -8
  282. package/dist/__tests__/macro.test.js +0 -305
  283. package/dist/__tests__/nbt.test.js +0 -82
  284. package/dist/__tests__/optimizer-advanced.test.js +0 -124
  285. package/dist/__tests__/optimizer.test.js +0 -149
  286. package/dist/__tests__/runtime.test.js +0 -289
  287. package/dist/__tests__/stdlib-advanced.test.d.ts +0 -4
  288. package/dist/__tests__/stdlib-advanced.test.js +0 -378
  289. package/dist/__tests__/stdlib-bigint.test.d.ts +0 -7
  290. package/dist/__tests__/stdlib-bigint.test.js +0 -428
  291. package/dist/__tests__/stdlib-math.test.d.ts +0 -7
  292. package/dist/__tests__/stdlib-math.test.js +0 -352
  293. package/dist/__tests__/stdlib-vec.test.d.ts +0 -4
  294. package/dist/__tests__/stdlib-vec.test.js +0 -264
  295. package/dist/__tests__/structure-optimizer.test.js +0 -33
  296. package/dist/__tests__/var-allocator.test.js +0 -69
  297. package/dist/codegen/cmdblock/index.d.ts +0 -26
  298. package/dist/codegen/cmdblock/index.js +0 -45
  299. package/dist/codegen/mcfunction/index.d.ts +0 -40
  300. package/dist/codegen/mcfunction/index.js +0 -606
  301. package/dist/codegen/structure/index.d.ts +0 -24
  302. package/dist/codegen/structure/index.js +0 -279
  303. package/dist/codegen/var-allocator.d.ts +0 -45
  304. package/dist/codegen/var-allocator.js +0 -104
  305. package/dist/compile.d.ts +0 -68
  306. package/dist/data/arena/function/__load.mcfunction +0 -6
  307. package/dist/data/arena/function/__tick.mcfunction +0 -2
  308. package/dist/data/arena/function/announce_leaders/else_1.mcfunction +0 -3
  309. package/dist/data/arena/function/announce_leaders/foreach_0/merge_2.mcfunction +0 -1
  310. package/dist/data/arena/function/announce_leaders/foreach_0/then_0.mcfunction +0 -3
  311. package/dist/data/arena/function/announce_leaders/foreach_0.mcfunction +0 -7
  312. package/dist/data/arena/function/announce_leaders/foreach_1/merge_2.mcfunction +0 -1
  313. package/dist/data/arena/function/announce_leaders/foreach_1/then_0.mcfunction +0 -4
  314. package/dist/data/arena/function/announce_leaders/foreach_1.mcfunction +0 -6
  315. package/dist/data/arena/function/announce_leaders/merge_2.mcfunction +0 -1
  316. package/dist/data/arena/function/announce_leaders/then_0.mcfunction +0 -4
  317. package/dist/data/arena/function/announce_leaders.mcfunction +0 -6
  318. package/dist/data/arena/function/arena_tick/merge_2.mcfunction +0 -1
  319. package/dist/data/arena/function/arena_tick/then_0.mcfunction +0 -4
  320. package/dist/data/arena/function/arena_tick.mcfunction +0 -11
  321. package/dist/data/counter/function/__load.mcfunction +0 -5
  322. package/dist/data/counter/function/__tick.mcfunction +0 -2
  323. package/dist/data/counter/function/counter_tick/merge_2.mcfunction +0 -1
  324. package/dist/data/counter/function/counter_tick/then_0.mcfunction +0 -3
  325. package/dist/data/counter/function/counter_tick.mcfunction +0 -11
  326. package/dist/data/gcd2/function/__load.mcfunction +0 -3
  327. package/dist/data/gcd2/function/abs/merge_2.mcfunction +0 -3
  328. package/dist/data/gcd2/function/abs/then_0.mcfunction +0 -5
  329. package/dist/data/gcd2/function/abs.mcfunction +0 -7
  330. package/dist/data/gcd2/function/gcd/loop_body_1.mcfunction +0 -7
  331. package/dist/data/gcd2/function/gcd/loop_check_0.mcfunction +0 -5
  332. package/dist/data/gcd2/function/gcd/loop_exit_2.mcfunction +0 -3
  333. package/dist/data/gcd2/function/gcd.mcfunction +0 -14
  334. package/dist/data/gcd3/function/__load.mcfunction +0 -3
  335. package/dist/data/gcd3/function/abs/merge_2.mcfunction +0 -3
  336. package/dist/data/gcd3/function/abs/then_0.mcfunction +0 -5
  337. package/dist/data/gcd3/function/abs.mcfunction +0 -7
  338. package/dist/data/gcd3/function/gcd/loop_body_1.mcfunction +0 -7
  339. package/dist/data/gcd3/function/gcd/loop_check_0.mcfunction +0 -5
  340. package/dist/data/gcd3/function/gcd/loop_exit_2.mcfunction +0 -3
  341. package/dist/data/gcd3/function/gcd.mcfunction +0 -14
  342. package/dist/data/gcd3/function/test.mcfunction +0 -7
  343. package/dist/data/gcd3nm/function/__load.mcfunction +0 -3
  344. package/dist/data/gcd3nm/function/abs/merge_2.mcfunction +0 -3
  345. package/dist/data/gcd3nm/function/abs/then_0.mcfunction +0 -5
  346. package/dist/data/gcd3nm/function/abs.mcfunction +0 -7
  347. package/dist/data/gcd3nm/function/gcd/loop_body_1.mcfunction +0 -7
  348. package/dist/data/gcd3nm/function/gcd/loop_check_0.mcfunction +0 -5
  349. package/dist/data/gcd3nm/function/gcd/loop_exit_2.mcfunction +0 -3
  350. package/dist/data/gcd3nm/function/gcd.mcfunction +0 -14
  351. package/dist/data/gcd3nm/function/test.mcfunction +0 -7
  352. package/dist/data/gcd_test/function/__load.mcfunction +0 -3
  353. package/dist/data/gcd_test/function/abs/merge_2.mcfunction +0 -3
  354. package/dist/data/gcd_test/function/abs/then_0.mcfunction +0 -5
  355. package/dist/data/gcd_test/function/abs.mcfunction +0 -7
  356. package/dist/data/gcd_test/function/gcd/loop_body_1.mcfunction +0 -7
  357. package/dist/data/gcd_test/function/gcd/loop_check_0.mcfunction +0 -5
  358. package/dist/data/gcd_test/function/gcd/loop_exit_2.mcfunction +0 -3
  359. package/dist/data/gcd_test/function/gcd.mcfunction +0 -14
  360. package/dist/data/isqrttest/function/__load.mcfunction +0 -6
  361. package/dist/data/isqrttest/function/isqrt/loop_body_4.mcfunction +0 -12
  362. package/dist/data/isqrttest/function/isqrt/loop_check_3.mcfunction +0 -5
  363. package/dist/data/isqrttest/function/isqrt/loop_exit_5.mcfunction +0 -3
  364. package/dist/data/isqrttest/function/isqrt/merge_2.mcfunction +0 -4
  365. package/dist/data/isqrttest/function/isqrt/merge_8.mcfunction +0 -6
  366. package/dist/data/isqrttest/function/isqrt/then_0.mcfunction +0 -3
  367. package/dist/data/isqrttest/function/isqrt/then_6.mcfunction +0 -3
  368. package/dist/data/isqrttest/function/isqrt.mcfunction +0 -7
  369. package/dist/data/isqrttest/function/test.mcfunction +0 -6
  370. package/dist/data/mathtest/function/__load.mcfunction +0 -3
  371. package/dist/data/mathtest/function/abs/merge_2.mcfunction +0 -3
  372. package/dist/data/mathtest/function/abs/then_0.mcfunction +0 -5
  373. package/dist/data/mathtest/function/abs.mcfunction +0 -6
  374. package/dist/data/mathtest/function/test.mcfunction +0 -5
  375. package/dist/data/minecraft/tags/function/load.json +0 -5
  376. package/dist/data/minecraft/tags/function/tick.json +0 -5
  377. package/dist/data/mypack/function/__load.mcfunction +0 -13
  378. package/dist/data/mypack/function/_atan_init.mcfunction +0 -2
  379. package/dist/data/mypack/function/abs/merge_2.mcfunction +0 -3
  380. package/dist/data/mypack/function/abs/then_0.mcfunction +0 -5
  381. package/dist/data/mypack/function/abs.mcfunction +0 -6
  382. package/dist/data/mypack/function/atan2_fixed/__sgi_1.mcfunction +0 -2
  383. package/dist/data/mypack/function/atan2_fixed/else_34.mcfunction +0 -3
  384. package/dist/data/mypack/function/atan2_fixed/loop_body_31.mcfunction +0 -19
  385. package/dist/data/mypack/function/atan2_fixed/loop_check_30.mcfunction +0 -5
  386. package/dist/data/mypack/function/atan2_fixed/loop_exit_32.mcfunction +0 -6
  387. package/dist/data/mypack/function/atan2_fixed/merge_11.mcfunction +0 -6
  388. package/dist/data/mypack/function/atan2_fixed/merge_14.mcfunction +0 -3
  389. package/dist/data/mypack/function/atan2_fixed/merge_17.mcfunction +0 -6
  390. package/dist/data/mypack/function/atan2_fixed/merge_2.mcfunction +0 -5
  391. package/dist/data/mypack/function/atan2_fixed/merge_20.mcfunction +0 -5
  392. package/dist/data/mypack/function/atan2_fixed/merge_23.mcfunction +0 -5
  393. package/dist/data/mypack/function/atan2_fixed/merge_26.mcfunction +0 -6
  394. package/dist/data/mypack/function/atan2_fixed/merge_29.mcfunction +0 -4
  395. package/dist/data/mypack/function/atan2_fixed/merge_38.mcfunction +0 -5
  396. package/dist/data/mypack/function/atan2_fixed/merge_41.mcfunction +0 -5
  397. package/dist/data/mypack/function/atan2_fixed/merge_44.mcfunction +0 -5
  398. package/dist/data/mypack/function/atan2_fixed/merge_47.mcfunction +0 -5
  399. package/dist/data/mypack/function/atan2_fixed/merge_5.mcfunction +0 -5
  400. package/dist/data/mypack/function/atan2_fixed/merge_8.mcfunction +0 -3
  401. package/dist/data/mypack/function/atan2_fixed/then_0.mcfunction +0 -5
  402. package/dist/data/mypack/function/atan2_fixed/then_12.mcfunction +0 -3
  403. package/dist/data/mypack/function/atan2_fixed/then_15.mcfunction +0 -5
  404. package/dist/data/mypack/function/atan2_fixed/then_18.mcfunction +0 -5
  405. package/dist/data/mypack/function/atan2_fixed/then_21.mcfunction +0 -3
  406. package/dist/data/mypack/function/atan2_fixed/then_24.mcfunction +0 -3
  407. package/dist/data/mypack/function/atan2_fixed/then_27.mcfunction +0 -6
  408. package/dist/data/mypack/function/atan2_fixed/then_3.mcfunction +0 -3
  409. package/dist/data/mypack/function/atan2_fixed/then_33.mcfunction +0 -5
  410. package/dist/data/mypack/function/atan2_fixed/then_36.mcfunction +0 -5
  411. package/dist/data/mypack/function/atan2_fixed/then_39.mcfunction +0 -5
  412. package/dist/data/mypack/function/atan2_fixed/then_42.mcfunction +0 -3
  413. package/dist/data/mypack/function/atan2_fixed/then_45.mcfunction +0 -5
  414. package/dist/data/mypack/function/atan2_fixed/then_6.mcfunction +0 -3
  415. package/dist/data/mypack/function/atan2_fixed/then_9.mcfunction +0 -5
  416. package/dist/data/mypack/function/atan2_fixed.mcfunction +0 -7
  417. package/dist/data/mypack/function/my_game.mcfunction +0 -10
  418. package/dist/data/quiz/function/__load.mcfunction +0 -16
  419. package/dist/data/quiz/function/__tick.mcfunction +0 -6
  420. package/dist/data/quiz/function/__trigger_quiz_a_dispatch.mcfunction +0 -4
  421. package/dist/data/quiz/function/__trigger_quiz_b_dispatch.mcfunction +0 -4
  422. package/dist/data/quiz/function/__trigger_quiz_c_dispatch.mcfunction +0 -4
  423. package/dist/data/quiz/function/__trigger_quiz_start_dispatch.mcfunction +0 -4
  424. package/dist/data/quiz/function/answer_a.mcfunction +0 -4
  425. package/dist/data/quiz/function/answer_b.mcfunction +0 -4
  426. package/dist/data/quiz/function/answer_c.mcfunction +0 -4
  427. package/dist/data/quiz/function/ask_question/else_1.mcfunction +0 -5
  428. package/dist/data/quiz/function/ask_question/else_4.mcfunction +0 -5
  429. package/dist/data/quiz/function/ask_question/else_7.mcfunction +0 -4
  430. package/dist/data/quiz/function/ask_question/merge_2.mcfunction +0 -1
  431. package/dist/data/quiz/function/ask_question/merge_5.mcfunction +0 -2
  432. package/dist/data/quiz/function/ask_question/merge_8.mcfunction +0 -2
  433. package/dist/data/quiz/function/ask_question/then_0.mcfunction +0 -4
  434. package/dist/data/quiz/function/ask_question/then_3.mcfunction +0 -4
  435. package/dist/data/quiz/function/ask_question/then_6.mcfunction +0 -4
  436. package/dist/data/quiz/function/ask_question.mcfunction +0 -7
  437. package/dist/data/quiz/function/finish_quiz.mcfunction +0 -6
  438. package/dist/data/quiz/function/handle_answer/else_1.mcfunction +0 -5
  439. package/dist/data/quiz/function/handle_answer/else_10.mcfunction +0 -3
  440. package/dist/data/quiz/function/handle_answer/else_16.mcfunction +0 -3
  441. package/dist/data/quiz/function/handle_answer/else_4.mcfunction +0 -3
  442. package/dist/data/quiz/function/handle_answer/else_7.mcfunction +0 -5
  443. package/dist/data/quiz/function/handle_answer/merge_11.mcfunction +0 -2
  444. package/dist/data/quiz/function/handle_answer/merge_14.mcfunction +0 -2
  445. package/dist/data/quiz/function/handle_answer/merge_17.mcfunction +0 -2
  446. package/dist/data/quiz/function/handle_answer/merge_2.mcfunction +0 -8
  447. package/dist/data/quiz/function/handle_answer/merge_5.mcfunction +0 -2
  448. package/dist/data/quiz/function/handle_answer/merge_8.mcfunction +0 -2
  449. package/dist/data/quiz/function/handle_answer/then_0.mcfunction +0 -5
  450. package/dist/data/quiz/function/handle_answer/then_12.mcfunction +0 -5
  451. package/dist/data/quiz/function/handle_answer/then_15.mcfunction +0 -6
  452. package/dist/data/quiz/function/handle_answer/then_3.mcfunction +0 -6
  453. package/dist/data/quiz/function/handle_answer/then_6.mcfunction +0 -5
  454. package/dist/data/quiz/function/handle_answer/then_9.mcfunction +0 -6
  455. package/dist/data/quiz/function/handle_answer.mcfunction +0 -11
  456. package/dist/data/quiz/function/start_quiz.mcfunction +0 -5
  457. package/dist/data/reqtest/function/__load.mcfunction +0 -4
  458. package/dist/data/reqtest/function/_table_init.mcfunction +0 -2
  459. package/dist/data/reqtest/function/no_trig.mcfunction +0 -3
  460. package/dist/data/reqtest/function/use_table.mcfunction +0 -4
  461. package/dist/data/reqtest2/function/__load.mcfunction +0 -3
  462. package/dist/data/reqtest2/function/no_trig.mcfunction +0 -3
  463. package/dist/data/runtime/function/__load.mcfunction +0 -5
  464. package/dist/data/runtime/function/__tick.mcfunction +0 -2
  465. package/dist/data/runtime/function/counter_tick/then_0.mcfunction +0 -3
  466. package/dist/data/runtime/function/counter_tick.mcfunction +0 -13
  467. package/dist/data/shop/function/__load.mcfunction +0 -7
  468. package/dist/data/shop/function/__tick.mcfunction +0 -3
  469. package/dist/data/shop/function/__trigger_shop_buy_dispatch.mcfunction +0 -4
  470. package/dist/data/shop/function/complete_purchase/else_1.mcfunction +0 -5
  471. package/dist/data/shop/function/complete_purchase/else_4.mcfunction +0 -5
  472. package/dist/data/shop/function/complete_purchase/else_7.mcfunction +0 -3
  473. package/dist/data/shop/function/complete_purchase/merge_2.mcfunction +0 -2
  474. package/dist/data/shop/function/complete_purchase/merge_5.mcfunction +0 -2
  475. package/dist/data/shop/function/complete_purchase/merge_8.mcfunction +0 -2
  476. package/dist/data/shop/function/complete_purchase/then_0.mcfunction +0 -4
  477. package/dist/data/shop/function/complete_purchase/then_3.mcfunction +0 -4
  478. package/dist/data/shop/function/complete_purchase/then_6.mcfunction +0 -4
  479. package/dist/data/shop/function/complete_purchase.mcfunction +0 -7
  480. package/dist/data/shop/function/handle_shop_trigger.mcfunction +0 -3
  481. package/dist/data/swap_test/function/__load.mcfunction +0 -3
  482. package/dist/data/swap_test/function/gcd_old/loop_body_1.mcfunction +0 -7
  483. package/dist/data/swap_test/function/gcd_old/loop_check_0.mcfunction +0 -5
  484. package/dist/data/swap_test/function/gcd_old/loop_exit_2.mcfunction +0 -3
  485. package/dist/data/swap_test/function/gcd_old.mcfunction +0 -8
  486. package/dist/data/turret/function/__load.mcfunction +0 -5
  487. package/dist/data/turret/function/__tick.mcfunction +0 -4
  488. package/dist/data/turret/function/__trigger_deploy_turret_dispatch.mcfunction +0 -4
  489. package/dist/data/turret/function/deploy_turret.mcfunction +0 -8
  490. package/dist/data/turret/function/turret_tick/at_1.mcfunction +0 -2
  491. package/dist/data/turret/function/turret_tick/foreach_0.mcfunction +0 -2
  492. package/dist/data/turret/function/turret_tick/foreach_2.mcfunction +0 -2
  493. package/dist/data/turret/function/turret_tick/tick_body.mcfunction +0 -3
  494. package/dist/data/turret/function/turret_tick/tick_skip.mcfunction +0 -1
  495. package/dist/data/turret/function/turret_tick.mcfunction +0 -5
  496. package/dist/gcd2.map.json +0 -15
  497. package/dist/gcd3.map.json +0 -17
  498. package/dist/gcd_test.map.json +0 -15
  499. package/dist/index.d.ts +0 -62
  500. package/dist/ir/builder.d.ts +0 -33
  501. package/dist/ir/builder.js +0 -99
  502. package/dist/ir/types.d.ts +0 -132
  503. package/dist/ir/types.js +0 -15
  504. package/dist/isqrttest.map.json +0 -15
  505. package/dist/lowering/index.d.ts +0 -188
  506. package/dist/lowering/index.js +0 -3403
  507. package/dist/mathtest.map.json +0 -6
  508. package/dist/mypack.map.json +0 -27
  509. package/dist/optimizer/commands.d.ts +0 -38
  510. package/dist/optimizer/commands.js +0 -451
  511. package/dist/optimizer/dce.d.ts +0 -34
  512. package/dist/optimizer/dce.js +0 -639
  513. package/dist/optimizer/passes.d.ts +0 -34
  514. package/dist/optimizer/passes.js +0 -243
  515. package/dist/optimizer/structure.d.ts +0 -9
  516. package/dist/optimizer/structure.js +0 -356
  517. package/dist/pack.mcmeta +0 -6
  518. package/dist/reqtest.map.json +0 -4
  519. package/dist/reqtest2.map.json +0 -4
  520. package/dist/runtime.map.json +0 -7
  521. package/dist/swap_test.map.json +0 -14
  522. package/src/__tests__/codegen.test.ts +0 -161
  523. package/src/__tests__/e2e.test.ts +0 -2039
  524. package/src/__tests__/entity-types.test.ts +0 -236
  525. package/src/__tests__/lowering.test.ts +0 -1185
  526. package/src/__tests__/macro.test.ts +0 -343
  527. package/src/__tests__/nbt.test.ts +0 -58
  528. package/src/__tests__/optimizer-advanced.test.ts +0 -144
  529. package/src/__tests__/optimizer.test.ts +0 -162
  530. package/src/__tests__/runtime.test.ts +0 -305
  531. package/src/__tests__/stdlib-advanced.test.ts +0 -379
  532. package/src/__tests__/stdlib-bigint.test.ts +0 -427
  533. package/src/__tests__/stdlib-math.test.ts +0 -374
  534. package/src/__tests__/stdlib-vec.test.ts +0 -259
  535. package/src/__tests__/structure-optimizer.test.ts +0 -38
  536. package/src/__tests__/var-allocator.test.ts +0 -75
  537. package/src/codegen/cmdblock/index.ts +0 -63
  538. package/src/codegen/mcfunction/index.ts +0 -662
  539. package/src/codegen/structure/index.ts +0 -346
  540. package/src/codegen/var-allocator.ts +0 -104
  541. package/src/ir/builder.ts +0 -116
  542. package/src/ir/types.ts +0 -134
  543. package/src/lowering/index.ts +0 -3876
  544. package/src/optimizer/commands.ts +0 -534
  545. package/src/optimizer/passes.ts +0 -250
  546. package/src/optimizer/structure.ts +0 -450
  547. /package/dist/{__tests__/cli.test.d.ts → src/__tests__/budget.test.d.ts} +0 -0
  548. /package/dist/{__tests__/codegen.test.d.ts → src/__tests__/cli.test.d.ts} +0 -0
  549. /package/dist/{__tests__ → src/__tests__}/compile-all.test.d.ts +0 -0
  550. /package/dist/{__tests__ → src/__tests__}/compile-all.test.js +0 -0
  551. /package/dist/{__tests__ → src/__tests__}/dce.test.d.ts +0 -0
  552. /package/dist/{__tests__ → src/__tests__}/diagnostics.test.d.ts +0 -0
  553. /package/dist/{__tests__ → src/__tests__}/formatter.test.d.ts +0 -0
  554. /package/dist/{__tests__ → src/__tests__}/formatter.test.js +0 -0
  555. /package/dist/{__tests__/entity-types.test.d.ts → src/__tests__/hir/desugar.test.d.ts} +0 -0
  556. /package/dist/{__tests__ → src/__tests__}/lexer.test.d.ts +0 -0
  557. /package/dist/{__tests__ → src/__tests__}/lexer.test.js +0 -0
  558. /package/dist/{__tests__/lowering.test.d.ts → src/__tests__/lir/lower.test.d.ts} +0 -0
  559. /package/dist/{__tests__/mc-syntax.test.d.ts → src/__tests__/lir/types.test.d.ts} +0 -0
  560. /package/dist/{__tests__/nbt.test.d.ts → src/__tests__/lir/verify.test.d.ts} +0 -0
  561. /package/dist/{__tests__ → src/__tests__}/mc-integration.test.d.ts +0 -0
  562. /package/dist/{__tests__/optimizer-advanced.test.d.ts → src/__tests__/mc-syntax.test.d.ts} +0 -0
  563. /package/dist/{__tests__ → src/__tests__}/mc-syntax.test.js +0 -0
  564. /package/dist/{__tests__/optimizer.test.d.ts → src/__tests__/mir/arithmetic.test.d.ts} +0 -0
  565. /package/dist/{__tests__/parser.test.d.ts → src/__tests__/mir/control-flow.test.d.ts} +0 -0
  566. /package/dist/{__tests__/repl.test.d.ts → src/__tests__/mir/verify.test.d.ts} +0 -0
  567. /package/dist/{__tests__/runtime.test.d.ts → src/__tests__/optimizer/block_merge.test.d.ts} +0 -0
  568. /package/dist/{__tests__/structure-optimizer.test.d.ts → src/__tests__/optimizer/branch_simplify.test.d.ts} +0 -0
  569. /package/dist/{__tests__/typechecker.test.d.ts → src/__tests__/optimizer/constant_fold.test.d.ts} +0 -0
  570. /package/dist/{__tests__/var-allocator.test.d.ts → src/__tests__/optimizer/copy_prop.test.d.ts} +0 -0
  571. /package/dist/{__tests__ → src/__tests__}/parser.test.js +0 -0
  572. /package/dist/{__tests__ → src/__tests__}/repl.test.js +0 -0
  573. /package/dist/{__tests__ → src/__tests__}/typechecker.test.js +0 -0
  574. /package/dist/{ast → src/ast}/types.js +0 -0
  575. /package/dist/{builtins → src/builtins}/metadata.d.ts +0 -0
  576. /package/dist/{builtins → src/builtins}/metadata.js +0 -0
  577. /package/dist/{events → src/events}/types.d.ts +0 -0
  578. /package/dist/{events → src/events}/types.js +0 -0
  579. /package/dist/{formatter → src/formatter}/index.d.ts +0 -0
  580. /package/dist/{formatter → src/formatter}/index.js +0 -0
  581. /package/dist/{mc-test → src/mc-test}/client.d.ts +0 -0
  582. /package/dist/{mc-test → src/mc-test}/client.js +0 -0
  583. /package/dist/{mc-test → src/mc-test}/runner.d.ts +0 -0
  584. /package/dist/{mc-test → src/mc-test}/setup.d.ts +0 -0
  585. /package/dist/{mc-test → src/mc-test}/setup.js +0 -0
  586. /package/dist/{mc-validator → src/mc-validator}/index.d.ts +0 -0
  587. /package/dist/{mc-validator → src/mc-validator}/index.js +0 -0
  588. /package/dist/{nbt → src/nbt}/index.d.ts +0 -0
  589. /package/dist/{nbt → src/nbt}/index.js +0 -0
  590. /package/dist/{repl.js → src/repl.js} +0 -0
  591. /package/dist/{runtime → src/runtime}/index.d.ts +0 -0
  592. /package/dist/{types → src/types}/entity-hierarchy.d.ts +0 -0
  593. /package/dist/{types → src/types}/entity-hierarchy.js +0 -0
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Tests for Phase 2b: Multi-return values / Tuple types
3
+ *
4
+ * Covers:
5
+ * - Tuple type parsing: (int, int)
6
+ * - Tuple literal parsing: (a, b)
7
+ * - Destructuring let: let (q, r) = ...
8
+ * - Function return type: fn f(): (int, int)
9
+ * - Full compilation to scoreboard commands
10
+ */
11
+
12
+ import { Lexer } from '../lexer'
13
+ import { Parser } from '../parser'
14
+ import { compile } from '../emit/compile'
15
+ import type { Program, Stmt, Expr } from '../ast/types'
16
+
17
+ function parse(source: string, namespace = 'test'): Program {
18
+ const tokens = new Lexer(source).tokenize()
19
+ return new Parser(tokens).parse(namespace)
20
+ }
21
+
22
+ function parseStmt(source: string): Stmt {
23
+ const program = parse(`fn _test() { ${source} }`)
24
+ return program.declarations[0].body[0]
25
+ }
26
+
27
+ function getFile(files: { path: string; content: string }[], pathSubstr: string): string | undefined {
28
+ const f = files.find(f => f.path.includes(pathSubstr))
29
+ return f?.content
30
+ }
31
+
32
+ // ---------------------------------------------------------------------------
33
+ // Parser tests
34
+ // ---------------------------------------------------------------------------
35
+
36
+ describe('Tuple: Parser', () => {
37
+ it('parses tuple type (int, int) as return type', () => {
38
+ const program = parse('fn f(a: int, b: int): (int, int) {}')
39
+ const fn = program.declarations[0]
40
+ expect(fn.returnType).toEqual({ kind: 'tuple', elements: [
41
+ { kind: 'named', name: 'int' },
42
+ { kind: 'named', name: 'int' },
43
+ ]})
44
+ })
45
+
46
+ it('parses tuple type with 3 elements', () => {
47
+ const program = parse('fn f(): (int, bool, int) {}')
48
+ expect(program.declarations[0].returnType).toEqual({ kind: 'tuple', elements: [
49
+ { kind: 'named', name: 'int' },
50
+ { kind: 'named', name: 'bool' },
51
+ { kind: 'named', name: 'int' },
52
+ ]})
53
+ })
54
+
55
+ it('parses tuple literal expression (a, b)', () => {
56
+ const program = parse(`fn _test(a: int, b: int): (int, int) { return (a, b); }`)
57
+ const ret = program.declarations[0].body[0]
58
+ expect(ret.kind).toBe('return')
59
+ if (ret.kind === 'return' && ret.value) {
60
+ expect(ret.value.kind).toBe('tuple_lit')
61
+ if (ret.value.kind === 'tuple_lit') {
62
+ expect(ret.value.elements).toHaveLength(2)
63
+ expect(ret.value.elements[0]).toMatchObject({ kind: 'ident', name: 'a' })
64
+ expect(ret.value.elements[1]).toMatchObject({ kind: 'ident', name: 'b' })
65
+ }
66
+ }
67
+ })
68
+
69
+ it('parses destructuring let statement', () => {
70
+ const stmt = parseStmt('let (q, r) = divmod(10, 3);')
71
+ expect(stmt.kind).toBe('let_destruct')
72
+ if (stmt.kind === 'let_destruct') {
73
+ expect(stmt.names).toEqual(['q', 'r'])
74
+ expect(stmt.init).toMatchObject({ kind: 'call', fn: 'divmod' })
75
+ }
76
+ })
77
+
78
+ it('parses destructuring with 3 bindings', () => {
79
+ const stmt = parseStmt('let (a, b, c) = get_triple(1);')
80
+ expect(stmt.kind).toBe('let_destruct')
81
+ if (stmt.kind === 'let_destruct') {
82
+ expect(stmt.names).toEqual(['a', 'b', 'c'])
83
+ }
84
+ })
85
+
86
+ it('does not confuse (expr) grouped expression with tuple literal', () => {
87
+ const program = parse(`fn _test(): int { return (1 + 2); }`)
88
+ const ret = program.declarations[0].body[0]
89
+ expect(ret.kind).toBe('return')
90
+ if (ret.kind === 'return' && ret.value) {
91
+ expect(ret.value.kind).toBe('binary')
92
+ }
93
+ })
94
+
95
+ it('still parses function type (int) -> int correctly', () => {
96
+ const program = parse('fn apply(f: (int) -> int, x: int): int {}')
97
+ const param = program.declarations[0].params[0]
98
+ expect(param.type).toEqual({ kind: 'function_type', params: [{ kind: 'named', name: 'int' }], return: { kind: 'named', name: 'int' } })
99
+ })
100
+ })
101
+
102
+ // ---------------------------------------------------------------------------
103
+ // E2E compilation tests
104
+ // ---------------------------------------------------------------------------
105
+
106
+ describe('Tuple: E2E compilation', () => {
107
+ test('basic divmod function compiles and writes $ret_0 and $ret_1', () => {
108
+ const source = `
109
+ fn divmod(a: int, b: int): (int, int) {
110
+ return (a / b, a % b);
111
+ }
112
+ `
113
+ const result = compile(source, { namespace: 'test' })
114
+ const fn = getFile(result.files, 'divmod.mcfunction')
115
+ expect(fn).toBeDefined()
116
+ // MIR __rf_0 → LIR $ret_0 (see lir/lower.ts slot() method)
117
+ expect(fn).toContain('$ret_0')
118
+ expect(fn).toContain('$ret_1')
119
+ })
120
+
121
+ test('destructuring let reads from $ret_ slots after call', () => {
122
+ const source = `
123
+ fn divmod(a: int, b: int): (int, int) {
124
+ return (a / b, a % b);
125
+ }
126
+ fn use_divmod(): int {
127
+ let (q, r) = divmod(10, 3);
128
+ return q + r;
129
+ }
130
+ `
131
+ const result = compile(source, { namespace: 'test' })
132
+ const fn = getFile(result.files, 'use_divmod.mcfunction')
133
+ expect(fn).toBeDefined()
134
+ // Should call divmod and then read from $ret_ slots
135
+ expect(fn).toContain('divmod')
136
+ expect(fn).toContain('$ret_0')
137
+ expect(fn).toContain('$ret_1')
138
+ })
139
+
140
+ test('tuple literal assigned directly via destructuring', () => {
141
+ const source = `
142
+ fn make_sum(a: int, b: int): int {
143
+ let (x, y) = (a + 1, b + 2);
144
+ return x + y;
145
+ }
146
+ `
147
+ const result = compile(source, { namespace: 'test' })
148
+ const fn = getFile(result.files, 'make_sum.mcfunction')
149
+ expect(fn).toBeDefined()
150
+ expect(fn).toContain('scoreboard players operation')
151
+ })
152
+
153
+ test('tuple values used in subsequent computation', () => {
154
+ const source = `
155
+ fn divmod(a: int, b: int): (int, int) {
156
+ return (a / b, a % b);
157
+ }
158
+ fn compute(): int {
159
+ let (q, r) = divmod(10, 3);
160
+ return q + r;
161
+ }
162
+ `
163
+ const result = compile(source, { namespace: 'test' })
164
+ const fn = getFile(result.files, 'compute.mcfunction')
165
+ expect(fn).toBeDefined()
166
+ expect(fn).toContain('scoreboard players operation')
167
+ })
168
+
169
+ test('3-tuple return and destructuring', () => {
170
+ const source = `
171
+ fn triple(a: int): (int, int, int) {
172
+ return (a, a + 1, a + 2);
173
+ }
174
+ fn use_triple(): int {
175
+ let (x, y, z) = triple(5);
176
+ return x + y + z;
177
+ }
178
+ `
179
+ const result = compile(source, { namespace: 'test' })
180
+ const tripleFn = getFile(result.files, 'triple.mcfunction')
181
+ expect(tripleFn).toBeDefined()
182
+ expect(tripleFn).toContain('$ret_0')
183
+ expect(tripleFn).toContain('$ret_1')
184
+ expect(tripleFn).toContain('$ret_2')
185
+ })
186
+
187
+ test('enum and tuple combined: return (int, Phase)', () => {
188
+ const source = `
189
+ enum Phase { Idle, Running, Done }
190
+ fn get_state(): (int, int) {
191
+ return (42, Phase::Running);
192
+ }
193
+ fn use_state(): int {
194
+ let (count, phase) = get_state();
195
+ return count + phase;
196
+ }
197
+ `
198
+ const result = compile(source, { namespace: 'test' })
199
+ const fn = getFile(result.files, 'get_state.mcfunction')
200
+ expect(fn).toBeDefined()
201
+ expect(fn).toContain('$ret_0')
202
+ expect(fn).toContain('$ret_1')
203
+ // Phase::Running = 1
204
+ expect(fn).toContain('1')
205
+ })
206
+
207
+ test('tuple return type appears in generated mcfunction with correct objective', () => {
208
+ const source = `
209
+ fn minmax(a: int, b: int): (int, int) {
210
+ return (a, b);
211
+ }
212
+ `
213
+ const result = compile(source, { namespace: 'ns' })
214
+ const fn = getFile(result.files, 'minmax.mcfunction')
215
+ expect(fn).toBeDefined()
216
+ // MIR __rf_0 → LIR $ret_0
217
+ expect(fn).toContain('$ret_0')
218
+ expect(fn).toContain('__ns')
219
+ })
220
+ })
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Phase 6b: TypeChecker strict (error-mode) tests
3
+ *
4
+ * Covers:
5
+ * - Type errors now block compilation (error-mode default)
6
+ * - --lenient flag demotes type errors to warnings
7
+ * - int/float implicit conversion detection
8
+ * - redscript check command correctly reports type errors
9
+ */
10
+
11
+ import { compile } from '../emit/compile'
12
+ import { Lexer } from '../lexer'
13
+ import { Parser } from '../parser'
14
+ import { TypeChecker } from '../typechecker'
15
+ import type { DiagnosticError } from '../diagnostics'
16
+
17
+ // Helper: run TypeChecker directly
18
+ function typeCheck(source: string): DiagnosticError[] {
19
+ const tokens = new Lexer(source).tokenize()
20
+ const ast = new Parser(tokens).parse('test')
21
+ const checker = new TypeChecker(source)
22
+ return checker.check(ast)
23
+ }
24
+
25
+ // Helper: compile in strict mode (default)
26
+ function compileStrict(source: string): void {
27
+ compile(source, { namespace: 'test' })
28
+ }
29
+
30
+ // Helper: compile in lenient mode
31
+ function compileLenient(source: string): { warnings: string[] } {
32
+ return compile(source, { namespace: 'test', lenient: true })
33
+ }
34
+
35
+ describe('TypeChecker error-mode (Phase 6b)', () => {
36
+ describe('type errors block compilation', () => {
37
+ it('throws on undeclared variable usage', () => {
38
+ expect(() => compileStrict(`
39
+ fn test() {
40
+ let x: int = undeclared;
41
+ }
42
+ `)).toThrow()
43
+ })
44
+
45
+ it('throws on return type mismatch', () => {
46
+ expect(() => compileStrict(`
47
+ fn get_bool() -> bool {
48
+ return 5;
49
+ }
50
+ `)).toThrow()
51
+ })
52
+
53
+ it('throws on wrong argument count', () => {
54
+ expect(() => compileStrict(`
55
+ fn add(a: int, b: int) -> int {
56
+ return a + b;
57
+ }
58
+ fn test() {
59
+ let x: int = add(1);
60
+ }
61
+ `)).toThrow()
62
+ })
63
+
64
+ it('does not throw for valid programs', () => {
65
+ expect(() => compileStrict(`
66
+ fn add(a: int, b: int) -> int {
67
+ return a + b;
68
+ }
69
+ fn test() {
70
+ let x: int = add(1, 2);
71
+ }
72
+ `)).not.toThrow()
73
+ })
74
+ })
75
+
76
+ describe('--lenient mode', () => {
77
+ it('does not throw on type errors in lenient mode', () => {
78
+ expect(() => compileLenient(`
79
+ fn test() {
80
+ let x: int = undeclared;
81
+ }
82
+ `)).not.toThrow()
83
+ })
84
+
85
+ it('returns type errors as warnings in lenient mode', () => {
86
+ const result = compileLenient(`
87
+ fn test() {
88
+ let x: int = undeclared;
89
+ }
90
+ `)
91
+ expect(result.warnings.length).toBeGreaterThan(0)
92
+ expect(result.warnings[0]).toContain('TypeError')
93
+ })
94
+
95
+ it('emits no warnings for valid programs in lenient mode', () => {
96
+ const result = compileLenient(`
97
+ fn test() {
98
+ let x: int = 5;
99
+ }
100
+ `)
101
+ expect(result.warnings).toHaveLength(0)
102
+ })
103
+ })
104
+
105
+ describe('int/float implicit conversion checks', () => {
106
+ it('detects int assigned to float variable', () => {
107
+ // int literal assigned to float — different types
108
+ const errors = typeCheck(`
109
+ fn test() {
110
+ let x: float = 5;
111
+ }
112
+ `)
113
+ expect(errors.length).toBeGreaterThan(0)
114
+ expect(errors[0].message).toContain('cannot implicitly convert int to float')
115
+ expect(errors[0].message).toContain('as float')
116
+ })
117
+
118
+ it('detects float assigned to int variable', () => {
119
+ const errors = typeCheck(`
120
+ fn get_f() -> float {
121
+ return 3.14;
122
+ }
123
+ fn test() {
124
+ let x: int = get_f();
125
+ }
126
+ `)
127
+ expect(errors.length).toBeGreaterThan(0)
128
+ expect(errors[0].message).toContain('cannot implicitly convert')
129
+ })
130
+
131
+ it('detects int/float return type mismatch', () => {
132
+ const errors = typeCheck(`
133
+ fn get_float() -> float {
134
+ return 5;
135
+ }
136
+ `)
137
+ expect(errors.length).toBeGreaterThan(0)
138
+ expect(errors[0].message).toContain('cannot implicitly convert int to float')
139
+ expect(errors[0].message).toContain('as float')
140
+ })
141
+
142
+ it('detects float/int return type mismatch', () => {
143
+ const errors = typeCheck(`
144
+ fn get_int() -> int {
145
+ return 3.14;
146
+ }
147
+ `)
148
+ expect(errors.length).toBeGreaterThan(0)
149
+ expect(errors[0].message).toContain('cannot implicitly convert float to int')
150
+ expect(errors[0].message).toContain('as int')
151
+ })
152
+
153
+ it('allows int assigned to int variable', () => {
154
+ const errors = typeCheck(`
155
+ fn test() {
156
+ let x: int = 5;
157
+ }
158
+ `)
159
+ expect(errors).toHaveLength(0)
160
+ })
161
+
162
+ it('allows float assigned to float variable', () => {
163
+ const errors = typeCheck(`
164
+ fn get_f() -> float {
165
+ return 3.14;
166
+ }
167
+ fn test() {
168
+ let x: float = get_f();
169
+ }
170
+ `)
171
+ expect(errors).toHaveLength(0)
172
+ })
173
+
174
+ it('blocks compilation on int→float mismatch', () => {
175
+ expect(() => compileStrict(`
176
+ fn get_float() -> float {
177
+ return 5;
178
+ }
179
+ `)).toThrow()
180
+ })
181
+
182
+ it('int→float mismatch demoted to warning in lenient mode', () => {
183
+ const result = compileLenient(`
184
+ fn get_float() -> float {
185
+ return 5;
186
+ }
187
+ `)
188
+ expect(result.warnings.length).toBeGreaterThan(0)
189
+ expect(result.warnings[0]).toContain('TypeError')
190
+ })
191
+ })
192
+
193
+ describe('redscript check command behavior', () => {
194
+ it('TypeChecker check() returns errors for type mismatches', () => {
195
+ const errors = typeCheck(`
196
+ fn test() {
197
+ let x: int = undeclared;
198
+ let y: bool = 1;
199
+ }
200
+ `)
201
+ expect(errors.length).toBeGreaterThanOrEqual(1)
202
+ })
203
+
204
+ it('TypeChecker check() returns empty array for valid programs', () => {
205
+ const errors = typeCheck(`
206
+ struct Point { x: int, y: int }
207
+
208
+ fn test() {
209
+ let p: Point = { x: 10, y: 20 };
210
+ let val: int = p.x;
211
+ }
212
+ `)
213
+ expect(errors).toHaveLength(0)
214
+ })
215
+ })
216
+ })
package/src/ast/types.ts CHANGED
@@ -5,7 +5,12 @@
5
5
  * The AST is produced by the parser and consumed by the lowering pass.
6
6
  */
7
7
 
8
- import type { BinOp, CmpOp } from '../ir/types'
8
+ // ---------------------------------------------------------------------------
9
+ // Binary / comparison operators (shared across AST, HIR, MIR)
10
+ // ---------------------------------------------------------------------------
11
+
12
+ export type BinOp = '+' | '-' | '*' | '/' | '%'
13
+ export type CmpOp = '==' | '!=' | '<' | '<=' | '>' | '>='
9
14
 
10
15
  // ---------------------------------------------------------------------------
11
16
  // Source Span
@@ -48,6 +53,8 @@ export type TypeNode =
48
53
  | { kind: 'function_type'; params: TypeNode[]; return: TypeNode }
49
54
  | { kind: 'entity'; entityType: EntityTypeName } // Entity types
50
55
  | { kind: 'selector'; entityType?: string } // Selector type, optionally parameterized: selector<Player>
56
+ | { kind: 'tuple'; elements: TypeNode[] } // Tuple type: (int, int, bool)
57
+ | { kind: 'option'; inner: TypeNode } // Option<T> — null safety wrapper
51
58
 
52
59
  export interface LambdaParam {
53
60
  name: string
@@ -158,7 +165,7 @@ export type Expr =
158
165
  | { kind: 'is_check'; expr: Expr; entityType: EntityTypeName; span?: Span }
159
166
  | { kind: 'unary'; op: '!' | '-'; operand: Expr; span?: Span }
160
167
  | { kind: 'assign'; target: string; op: AssignOp; value: Expr; span?: Span }
161
- | { kind: 'call'; fn: string; args: Expr[]; span?: Span }
168
+ | { kind: 'call'; fn: string; args: Expr[]; typeArgs?: TypeNode[]; span?: Span }
162
169
  | { kind: 'invoke'; callee: Expr; args: Expr[]; span?: Span }
163
170
  | { kind: 'member'; obj: Expr; field: string; span?: Span }
164
171
  | { kind: 'struct_lit'; fields: { name: string; value: Expr }[]; span?: Span }
@@ -166,7 +173,11 @@ export type Expr =
166
173
  | { kind: 'index'; obj: Expr; index: Expr; span?: Span }
167
174
  | { kind: 'array_lit'; elements: Expr[]; span?: Span }
168
175
  | { kind: 'static_call'; type: string; method: string; args: Expr[]; span?: Span }
176
+ | { kind: 'path_expr'; enumName: string; variant: string; span?: Span }
169
177
  | (LambdaExpr & { span?: Span })
178
+ | { kind: 'tuple_lit'; elements: Expr[]; span?: Span }
179
+ | { kind: 'some_lit'; value: Expr; span?: Span } // Some(expr)
180
+ | { kind: 'none_lit'; span?: Span } // None
170
181
 
171
182
  export type LiteralExpr =
172
183
  | Extract<Expr, { kind: 'int_lit' }>
@@ -212,6 +223,7 @@ export type ExecuteSubcommand =
212
223
 
213
224
  export type Stmt =
214
225
  | { kind: 'let'; name: string; type?: TypeNode; init: Expr; span?: Span }
226
+ | { kind: 'let_destruct'; names: string[]; type?: TypeNode; init: Expr; span?: Span }
215
227
  | { kind: 'expr'; expr: Expr; span?: Span }
216
228
  | { kind: 'return'; value?: Expr; span?: Span }
217
229
  | { kind: 'break'; span?: Span }
@@ -222,6 +234,7 @@ export type Stmt =
222
234
  | { kind: 'foreach'; binding: string; iterable: Expr; body: Block; executeContext?: string; span?: Span }
223
235
  | { kind: 'for_range'; varName: string; start: Expr; end: Expr; body: Block; span?: Span }
224
236
  | { kind: 'match'; expr: Expr; arms: { pattern: Expr | null; body: Block }[]; span?: Span }
237
+ | { kind: 'if_let_some'; binding: string; init: Expr; then: Block; else_?: Block; span?: Span }
225
238
  | { kind: 'as_block'; selector: EntitySelector; body: Block; span?: Span }
226
239
  | { kind: 'at_block'; selector: EntitySelector; body: Block; span?: Span }
227
240
  | { kind: 'as_at'; as_sel: EntitySelector; at_sel: EntitySelector; body: Block; span?: Span }
@@ -235,7 +248,7 @@ export type Block = Stmt[]
235
248
  // ---------------------------------------------------------------------------
236
249
 
237
250
  export interface Decorator {
238
- name: 'tick' | 'load' | 'on' | 'on_trigger' | 'on_advancement' | 'on_craft' | 'on_death' | 'on_login' | 'on_join_team' | 'keep' | 'require_on_load'
251
+ name: 'tick' | 'load' | 'on' | 'on_trigger' | 'on_advancement' | 'on_craft' | 'on_death' | 'on_login' | 'on_join_team' | 'keep' | 'require_on_load' | 'coroutine' | 'schedule'
239
252
  args?: {
240
253
  rate?: number
241
254
  eventType?: string
@@ -243,6 +256,9 @@ export interface Decorator {
243
256
  advancement?: string
244
257
  item?: string
245
258
  team?: string
259
+ batch?: number
260
+ onDone?: string
261
+ ticks?: number
246
262
  }
247
263
  /** Raw positional arguments (used by @requires and future generic decorators). */
248
264
  rawArgs?: Array<{ kind: 'string'; value: string } | { kind: 'number'; value: number }>
@@ -263,7 +279,11 @@ export interface FnDecl {
263
279
  * Library functions are NOT MC entry points — DCE only keeps them if they
264
280
  * are reachable from a non-library (user) entry point. */
265
281
  isLibraryFn?: boolean
282
+ /** True when declared with `export fn` or `@keep fn` — survives DCE. */
283
+ isExported?: boolean
266
284
  name: string
285
+ /** Generic type parameter names, e.g. ['T'] for fn foo<T>(...) */
286
+ typeParams?: string[]
267
287
  params: Param[]
268
288
  returnType: TypeNode
269
289
  decorators: Decorator[]
@@ -320,18 +340,34 @@ export interface GlobalDecl {
320
340
  span?: Span
321
341
  }
322
342
 
343
+ // ---------------------------------------------------------------------------
344
+ // Import Declarations (Phase 5b module system)
345
+ // ---------------------------------------------------------------------------
346
+
347
+ export interface ImportDecl {
348
+ /** The module being imported from, e.g. "math" in `import math::sin` */
349
+ moduleName: string
350
+ /** The symbol being imported, or '*' for wildcard */
351
+ symbol: string // '*' | identifier
352
+ span?: Span
353
+ }
354
+
323
355
  // ---------------------------------------------------------------------------
324
356
  // Program (Top-Level)
325
357
  // ---------------------------------------------------------------------------
326
358
 
327
359
  export interface Program {
328
360
  namespace: string // Inferred from filename or `namespace mypack;`
361
+ /** Module name declared with `module <name>;` (undefined if no module decl) */
362
+ moduleName?: string
329
363
  globals: GlobalDecl[]
330
364
  declarations: FnDecl[]
331
365
  structs: StructDecl[]
332
366
  implBlocks: ImplBlock[]
333
367
  enums: EnumDecl[]
334
368
  consts: ConstDecl[]
369
+ /** Phase 5b: module imports (`import math::sin;`) */
370
+ imports: ImportDecl[]
335
371
  /** True when the source file declares `module library;`.
336
372
  * Library-mode: all functions are DCE-eligible by default — none are treated
337
373
  * as MC entry points unless they carry @tick / @load / @on / @keep etc. */
@@ -0,0 +1,132 @@
1
+ /**
2
+ * DependencyGraph — tracks import relationships between .mcrs files.
3
+ *
4
+ * Builds a forward dependency map (file → files it imports) and supports
5
+ * reverse lookups (file → files that depend on it) for change propagation.
6
+ */
7
+
8
+ import * as fs from 'fs'
9
+ import * as path from 'path'
10
+
11
+ const IMPORT_RE = /^\s*import\s+"([^"]+)"\s*;?\s*$/
12
+
13
+ /**
14
+ * Parse import statements from a source file's content.
15
+ * Returns absolute paths of imported files.
16
+ */
17
+ export function parseImports(filePath: string, source?: string): string[] {
18
+ const absPath = path.resolve(filePath)
19
+ const content = source ?? fs.readFileSync(absPath, 'utf-8')
20
+ const dir = path.dirname(absPath)
21
+ const imports: string[] = []
22
+
23
+ for (const line of content.split('\n')) {
24
+ const trimmed = line.trim()
25
+ // Stop at first non-comment, non-blank, non-import line
26
+ if (!trimmed || trimmed.startsWith('//')) continue
27
+ const match = trimmed.match(IMPORT_RE)
28
+ if (match) {
29
+ imports.push(path.resolve(dir, match[1]))
30
+ } else {
31
+ // Past the import header
32
+ break
33
+ }
34
+ }
35
+
36
+ return imports
37
+ }
38
+
39
+ export class DependencyGraph {
40
+ /** Forward edges: file → set of files it imports */
41
+ private deps = new Map<string, Set<string>>()
42
+
43
+ /** Add a file and its direct imports to the graph. */
44
+ addFile(filePath: string, source?: string): void {
45
+ const absPath = path.resolve(filePath)
46
+ const imports = parseImports(absPath, source)
47
+ this.deps.set(absPath, new Set(imports))
48
+ }
49
+
50
+ /** Remove a file from the graph. */
51
+ removeFile(filePath: string): void {
52
+ this.deps.delete(path.resolve(filePath))
53
+ }
54
+
55
+ /** Get direct imports of a file. */
56
+ getDirectDeps(filePath: string): Set<string> {
57
+ return this.deps.get(path.resolve(filePath)) ?? new Set()
58
+ }
59
+
60
+ /**
61
+ * Get transitive dependencies of a file (all files it depends on,
62
+ * directly or indirectly).
63
+ */
64
+ getTransitiveDeps(filePath: string): Set<string> {
65
+ const absPath = path.resolve(filePath)
66
+ const result = new Set<string>()
67
+ const stack = [absPath]
68
+
69
+ while (stack.length > 0) {
70
+ const current = stack.pop()!
71
+ const directDeps = this.deps.get(current)
72
+ if (!directDeps) continue
73
+ for (const dep of directDeps) {
74
+ if (!result.has(dep)) {
75
+ result.add(dep)
76
+ stack.push(dep)
77
+ }
78
+ }
79
+ }
80
+
81
+ return result
82
+ }
83
+
84
+ /**
85
+ * Get reverse dependents: all files that (transitively) depend on the
86
+ * given file. Used for change propagation — when `filePath` changes,
87
+ * all returned files need recompilation.
88
+ */
89
+ getDependents(filePath: string): Set<string> {
90
+ const absPath = path.resolve(filePath)
91
+ const result = new Set<string>()
92
+ const stack = [absPath]
93
+
94
+ while (stack.length > 0) {
95
+ const current = stack.pop()!
96
+ for (const [file, deps] of this.deps) {
97
+ if (deps.has(current) && !result.has(file)) {
98
+ result.add(file)
99
+ stack.push(file)
100
+ }
101
+ }
102
+ }
103
+
104
+ return result
105
+ }
106
+
107
+ /**
108
+ * Given a set of changed files, compute the full set of dirty files
109
+ * (changed files + all their reverse dependents).
110
+ */
111
+ computeDirtySet(changedFiles: Set<string>): Set<string> {
112
+ const dirty = new Set<string>()
113
+ for (const file of changedFiles) {
114
+ const absFile = path.resolve(file)
115
+ dirty.add(absFile)
116
+ for (const dep of this.getDependents(absFile)) {
117
+ dirty.add(dep)
118
+ }
119
+ }
120
+ return dirty
121
+ }
122
+
123
+ /** Get all tracked files. */
124
+ getAllFiles(): string[] {
125
+ return [...this.deps.keys()]
126
+ }
127
+
128
+ /** Clear the graph. */
129
+ clear(): void {
130
+ this.deps.clear()
131
+ }
132
+ }