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,789 @@
1
+ "use strict";
2
+ /**
3
+ * Coroutine Transform — MIR module-level pass.
4
+ *
5
+ * Transforms functions annotated with @coroutine(batch=N, onDone=fn) into
6
+ * tick-spread state machines. Each loop back-edge becomes a yield point,
7
+ * and the function is split into continuation functions dispatched by a
8
+ * @tick function via a pc (program counter) scoreboard slot.
9
+ *
10
+ * Algorithm:
11
+ * 1. Compute dominator tree → find back edges (yield points)
12
+ * 2. Backward liveness analysis at yield points
13
+ * 3. Split CFG into continuations at yield points
14
+ * 4. Promote live variables to persistent scoreboard slots
15
+ * 5. Generate @tick dispatcher function
16
+ *
17
+ * Spec: docs/compiler-pipeline-redesign.md § "Coroutine Transform"
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.coroutineTransform = coroutineTransform;
21
+ /**
22
+ * Apply the coroutine transform to all functions in `infos`.
23
+ * Returns a new module with continuations + dispatchers injected,
24
+ * and the original function replaced with initialization code.
25
+ */
26
+ function coroutineTransform(mod, infos) {
27
+ if (infos.length === 0)
28
+ return { module: mod, generatedTickFunctions: [] };
29
+ const infoMap = new Map(infos.map(i => [i.fnName, i]));
30
+ const newFunctions = [];
31
+ const tickFns = [];
32
+ for (const fn of mod.functions) {
33
+ const info = infoMap.get(fn.name);
34
+ if (!info) {
35
+ newFunctions.push(fn);
36
+ continue;
37
+ }
38
+ const transformed = transformCoroutine(fn, info, mod.objective);
39
+ newFunctions.push(transformed.initFn);
40
+ newFunctions.push(...transformed.continuations);
41
+ newFunctions.push(transformed.dispatcher);
42
+ tickFns.push(transformed.dispatcher.name);
43
+ }
44
+ return {
45
+ module: { ...mod, functions: newFunctions },
46
+ generatedTickFunctions: tickFns,
47
+ };
48
+ }
49
+ function transformCoroutine(fn, info, objective) {
50
+ const prefix = `_coro_${fn.name}`;
51
+ const pcTemp = `${prefix}_pc`;
52
+ const batchCountTemp = `${prefix}_batch_count`;
53
+ // Step 1: Build dominator tree and find back edges
54
+ const blockMap = new Map(fn.blocks.map(b => [b.id, b]));
55
+ const doms = computeDominators(fn.blocks, fn.entry);
56
+ const backEdges = findBackEdges(fn.blocks, doms);
57
+ // If no back edges (no loops), the function doesn't need coroutine splitting.
58
+ // Just wrap it as a single continuation.
59
+ if (backEdges.length === 0) {
60
+ return buildSingleContinuation(fn, info, prefix, pcTemp, objective);
61
+ }
62
+ // Step 2: Liveness analysis — find live variables at each yield point
63
+ const liveAtYield = computeLivenessAtYieldPoints(fn.blocks, backEdges, fn.params);
64
+ // Collect all live variables across all yield points (these need promotion)
65
+ const allLiveVars = new Set();
66
+ for (const liveSet of liveAtYield.values()) {
67
+ for (const v of liveSet)
68
+ allLiveVars.add(v);
69
+ }
70
+ // Build promoted variable names: original temp → persistent slot name
71
+ const promoted = new Map();
72
+ for (const v of allLiveVars) {
73
+ promoted.set(v, `${prefix}_${v}`);
74
+ }
75
+ // Step 3: Split CFG into continuations
76
+ // Each continuation runs from a loop header to the next yield point.
77
+ // For simplicity, we split at loop headers (targets of back edges).
78
+ const loopHeaders = new Set(backEdges.map(e => e.target));
79
+ // Partition blocks into continuation groups.
80
+ // Continuation 1: entry block → until first yield
81
+ // Continuation N: from loop header → until next yield or exit
82
+ const continuations = partitionIntoContinuations(fn, loopHeaders, backEdges);
83
+ // Step 4: Build continuation functions with batch counting and variable promotion
84
+ const contFunctions = [];
85
+ for (let i = 0; i < continuations.length; i++) {
86
+ const contId = i + 1;
87
+ const cont = continuations[i];
88
+ const contFn = buildContinuationFunction(`${prefix}_cont_${contId}`, cont, info.batch, contId, continuations.length, promoted, pcTemp, batchCountTemp, objective, info.onDone, fn.name);
89
+ contFunctions.push(contFn);
90
+ }
91
+ // Step 5: Build the init function (replaces original)
92
+ const initFn = buildInitFunction(fn, promoted, pcTemp, prefix, objective);
93
+ // Step 6: Build the @tick dispatcher
94
+ const dispatcher = buildDispatcher(`${prefix}_tick`, contFunctions, pcTemp, objective, fn.name);
95
+ return { initFn, continuations: contFunctions, dispatcher };
96
+ }
97
+ // ---------------------------------------------------------------------------
98
+ // Step 1: Dominator tree & back-edge detection
99
+ // ---------------------------------------------------------------------------
100
+ function computeDominators(blocks, entry) {
101
+ // Simple iterative dominator algorithm (Cooper, Harvey, Kennedy)
102
+ const blockIds = blocks.map(b => b.id);
103
+ const idom = new Map();
104
+ // RPO ordering
105
+ const rpo = reversePostorder(blocks, entry);
106
+ const rpoIndex = new Map(rpo.map((id, i) => [id, i]));
107
+ // Initialize: entry dominates itself
108
+ idom.set(entry, entry);
109
+ let changed = true;
110
+ while (changed) {
111
+ changed = false;
112
+ for (const bId of rpo) {
113
+ if (bId === entry)
114
+ continue;
115
+ const block = blocks.find(b => b.id === bId);
116
+ if (!block)
117
+ continue;
118
+ // Find first processed predecessor
119
+ const processedPreds = block.preds.filter(p => idom.has(p));
120
+ if (processedPreds.length === 0)
121
+ continue;
122
+ let newIdom = processedPreds[0];
123
+ for (let i = 1; i < processedPreds.length; i++) {
124
+ newIdom = intersect(newIdom, processedPreds[i], idom, rpoIndex);
125
+ }
126
+ if (idom.get(bId) !== newIdom) {
127
+ idom.set(bId, newIdom);
128
+ changed = true;
129
+ }
130
+ }
131
+ }
132
+ return idom;
133
+ }
134
+ function intersect(a, b, idom, rpoIndex) {
135
+ let f1 = a;
136
+ let f2 = b;
137
+ while (f1 !== f2) {
138
+ while ((rpoIndex.get(f1) ?? 0) > (rpoIndex.get(f2) ?? 0)) {
139
+ f1 = idom.get(f1) ?? f1;
140
+ }
141
+ while ((rpoIndex.get(f2) ?? 0) > (rpoIndex.get(f1) ?? 0)) {
142
+ f2 = idom.get(f2) ?? f2;
143
+ }
144
+ }
145
+ return f1;
146
+ }
147
+ function reversePostorder(blocks, entry) {
148
+ const visited = new Set();
149
+ const order = [];
150
+ const blockMap = new Map(blocks.map(b => [b.id, b]));
151
+ function dfs(id) {
152
+ if (visited.has(id))
153
+ return;
154
+ visited.add(id);
155
+ const block = blockMap.get(id);
156
+ if (!block)
157
+ return;
158
+ for (const succ of getSuccessors(block.term)) {
159
+ dfs(succ);
160
+ }
161
+ order.push(id);
162
+ }
163
+ dfs(entry);
164
+ return order.reverse();
165
+ }
166
+ function findBackEdges(blocks, doms) {
167
+ const edges = [];
168
+ for (const block of blocks) {
169
+ for (const succ of getSuccessors(block.term)) {
170
+ if (dominates(succ, block.id, doms)) {
171
+ edges.push({ source: block.id, target: succ });
172
+ }
173
+ }
174
+ }
175
+ return edges;
176
+ }
177
+ function dominates(a, b, doms) {
178
+ let cur = b;
179
+ while (cur !== a) {
180
+ const idom = doms.get(cur);
181
+ if (!idom || idom === cur)
182
+ return false;
183
+ cur = idom;
184
+ }
185
+ return true;
186
+ }
187
+ // ---------------------------------------------------------------------------
188
+ // Step 2: Liveness analysis
189
+ // ---------------------------------------------------------------------------
190
+ function computeLivenessAtYieldPoints(blocks, backEdges, params) {
191
+ // Standard backward liveness: live_in[B] = use[B] ∪ (live_out[B] \ def[B])
192
+ const blockMap = new Map(blocks.map(b => [b.id, b]));
193
+ // Compute use/def for each block
194
+ const useSets = new Map();
195
+ const defSets = new Map();
196
+ for (const block of blocks) {
197
+ const use = new Set();
198
+ const def = new Set();
199
+ for (const instr of [...block.instrs, block.term]) {
200
+ // Uses before defs
201
+ for (const t of getUsedTemps(instr)) {
202
+ if (!def.has(t))
203
+ use.add(t);
204
+ }
205
+ const dst = getDst(instr);
206
+ if (dst)
207
+ def.add(dst);
208
+ }
209
+ useSets.set(block.id, use);
210
+ defSets.set(block.id, def);
211
+ }
212
+ // Iterative liveness
213
+ const liveIn = new Map();
214
+ const liveOut = new Map();
215
+ for (const block of blocks) {
216
+ liveIn.set(block.id, new Set());
217
+ liveOut.set(block.id, new Set());
218
+ }
219
+ let changed = true;
220
+ while (changed) {
221
+ changed = false;
222
+ for (const block of [...blocks].reverse()) {
223
+ // live_out = ∪ live_in[succ]
224
+ const newOut = new Set();
225
+ for (const succ of getSuccessors(block.term)) {
226
+ const succIn = liveIn.get(succ);
227
+ if (succIn)
228
+ for (const t of succIn)
229
+ newOut.add(t);
230
+ }
231
+ // live_in = use ∪ (live_out \ def)
232
+ const newIn = new Set(useSets.get(block.id) ?? []);
233
+ const def = defSets.get(block.id) ?? new Set();
234
+ for (const t of newOut) {
235
+ if (!def.has(t))
236
+ newIn.add(t);
237
+ }
238
+ const prevIn = liveIn.get(block.id);
239
+ const prevOut = liveOut.get(block.id);
240
+ if (!setsEqual(newIn, prevIn) || !setsEqual(newOut, prevOut)) {
241
+ liveIn.set(block.id, newIn);
242
+ liveOut.set(block.id, newOut);
243
+ changed = true;
244
+ }
245
+ }
246
+ }
247
+ // At each yield point (back edge source → target), the live vars
248
+ // are the live-out of the source block
249
+ const result = new Map();
250
+ for (const edge of backEdges) {
251
+ const lo = liveOut.get(edge.source) ?? new Set();
252
+ result.set(edge.source, lo);
253
+ }
254
+ return result;
255
+ }
256
+ function setsEqual(a, b) {
257
+ if (a.size !== b.size)
258
+ return false;
259
+ for (const v of a)
260
+ if (!b.has(v))
261
+ return false;
262
+ return true;
263
+ }
264
+ function partitionIntoContinuations(fn, loopHeaders, backEdges) {
265
+ const blockMap = new Map(fn.blocks.map(b => [b.id, b]));
266
+ const backEdgeTargets = new Set(backEdges.map(e => e.target));
267
+ const backEdgeSources = new Set(backEdges.map(e => e.source));
268
+ // Find which blocks belong to which loop (blocks between header and back edge)
269
+ // We use a simple approach: BFS from entry, split at loop headers
270
+ const loopBlocks = new Map(); // header → blocks in loop
271
+ for (const header of loopHeaders) {
272
+ const inLoop = new Set();
273
+ // Find all blocks that can reach the back edge source without leaving the loop
274
+ // i.e., blocks dominated by the header that can reach a back edge source
275
+ const sources = backEdges.filter(e => e.target === header).map(e => e.source);
276
+ // Backward BFS from back-edge sources to header
277
+ const queue = [...sources];
278
+ for (const s of sources)
279
+ inLoop.add(s);
280
+ inLoop.add(header);
281
+ while (queue.length > 0) {
282
+ const bid = queue.shift();
283
+ const block = blockMap.get(bid);
284
+ if (!block)
285
+ continue;
286
+ for (const pred of block.preds) {
287
+ if (!inLoop.has(pred) && pred !== header) {
288
+ inLoop.add(pred);
289
+ queue.push(pred);
290
+ }
291
+ }
292
+ }
293
+ inLoop.add(header);
294
+ loopBlocks.set(header, inLoop);
295
+ }
296
+ // Build continuations:
297
+ // Continuation 1 = loop body (the main one — header + loop blocks)
298
+ // Continuation 2 = post-loop (blocks after loop exit)
299
+ const conts = [];
300
+ // For each loop, create a loop-body continuation
301
+ for (const header of loopHeaders) {
302
+ const lb = loopBlocks.get(header);
303
+ const loopBlocksList = fn.blocks.filter(b => lb.has(b.id));
304
+ const exitBlocks = new Set();
305
+ // Find exit blocks: blocks in the loop that branch to blocks outside the loop
306
+ for (const block of loopBlocksList) {
307
+ for (const succ of getSuccessors(block.term)) {
308
+ if (!lb.has(succ))
309
+ exitBlocks.add(block.id);
310
+ }
311
+ }
312
+ conts.push({
313
+ blocks: loopBlocksList,
314
+ isLoopBody: true,
315
+ loopHeaderId: header,
316
+ exitBlocks,
317
+ });
318
+ }
319
+ // Post-loop continuation: all blocks not in any loop
320
+ const allLoopBlockIds = new Set();
321
+ for (const lb of loopBlocks.values()) {
322
+ for (const id of lb)
323
+ allLoopBlockIds.add(id);
324
+ }
325
+ // Also exclude the entry block if it's not in a loop (it becomes the init fn)
326
+ const postLoopBlocks = fn.blocks.filter(b => !allLoopBlockIds.has(b.id) && b.id !== fn.entry);
327
+ if (postLoopBlocks.length > 0) {
328
+ conts.push({
329
+ blocks: postLoopBlocks,
330
+ isLoopBody: false,
331
+ exitBlocks: new Set(),
332
+ });
333
+ }
334
+ return conts;
335
+ }
336
+ // ---------------------------------------------------------------------------
337
+ // Step 4: Build continuation functions
338
+ // ---------------------------------------------------------------------------
339
+ function buildContinuationFunction(name, cont, batch, contId, totalConts, promoted, pcTemp, batchCountTemp, objective, onDone, originalFnName) {
340
+ if (cont.isLoopBody) {
341
+ return buildLoopContinuation(name, cont, batch, contId, totalConts, promoted, pcTemp, batchCountTemp, objective, onDone);
342
+ }
343
+ else {
344
+ return buildPostLoopContinuation(name, cont, contId, promoted, pcTemp, objective, onDone);
345
+ }
346
+ }
347
+ function buildLoopContinuation(name, cont, batch, contId, totalConts, promoted, pcTemp, batchCountTemp, objective, onDone) {
348
+ // Build a new function that:
349
+ // 1. Initializes batch_count = 0
350
+ // 2. Runs the loop body up to `batch` iterations
351
+ // 3. At back edge: if batch_count >= batch, yield (return)
352
+ // 4. On loop exit: return (dispatcher handles next continuation via pc)
353
+ //
354
+ // IMPORTANT: The LIR lowerer handles multi-pred blocks via `jump` terminators
355
+ // correctly (emits a function call) but `branch → multi-pred` can cause infinite
356
+ // recursion. So we ensure back edges use `jump` via a trampoline block, and
357
+ // batch-done checks use `branch → yield_block | continue_block` where both
358
+ // targets have single predecessors.
359
+ const blocks = [];
360
+ const batchCmpTemp = `${batchCountTemp}_cmp`;
361
+ // Entry: set batch_count = 0, then jump to loop header
362
+ const entryBlock = {
363
+ id: 'entry',
364
+ instrs: [
365
+ { kind: 'const', dst: batchCountTemp, value: 0 },
366
+ ],
367
+ term: { kind: 'jump', target: cont.loopHeaderId ?? cont.blocks[0].id },
368
+ preds: [],
369
+ };
370
+ blocks.push(entryBlock);
371
+ // Clone and rewrite the loop blocks with promoted variable names
372
+ for (const block of cont.blocks) {
373
+ const rewritten = rewriteBlock(block, promoted);
374
+ const succs = getSuccessors(rewritten.term);
375
+ const isBackEdgeBlock = cont.loopHeaderId && succs.includes(cont.loopHeaderId);
376
+ if (isBackEdgeBlock) {
377
+ // This block has a back edge to the loop header.
378
+ // Append batch counting to the body, then branch:
379
+ // batch_done → yield (return), !batch_done → continue (jump → header)
380
+ //
381
+ // body_block → branch(batch_done) → yield_block | continue_block
382
+ // continue_block → jump → loop_header (uses 'jump', safe for multi-pred)
383
+ // yield_block → return
384
+ const continueBlockId = `${block.id}_continue`;
385
+ const yieldBlockId = `${block.id}_yield`;
386
+ // Append batch check instructions to the body block
387
+ const bodyInstrs = [
388
+ ...rewritten.instrs,
389
+ { kind: 'add', dst: batchCountTemp, a: { kind: 'temp', name: batchCountTemp }, b: { kind: 'const', value: 1 } },
390
+ { kind: 'cmp', dst: batchCmpTemp, op: 'ge', a: { kind: 'temp', name: batchCountTemp }, b: { kind: 'const', value: batch } },
391
+ ];
392
+ blocks.push({
393
+ ...rewritten,
394
+ instrs: bodyInstrs,
395
+ // Rewrite terminator: instead of jumping to header, branch on batch check
396
+ term: {
397
+ kind: 'branch',
398
+ cond: { kind: 'temp', name: batchCmpTemp },
399
+ then: yieldBlockId,
400
+ else: continueBlockId,
401
+ },
402
+ });
403
+ // Continue block: jump back to loop header (uses jump → multi-pred = call)
404
+ blocks.push({
405
+ id: continueBlockId,
406
+ instrs: [],
407
+ term: { kind: 'jump', target: cont.loopHeaderId },
408
+ preds: [block.id],
409
+ });
410
+ // Yield block: return (resume next tick)
411
+ blocks.push({
412
+ id: yieldBlockId,
413
+ instrs: [],
414
+ term: { kind: 'return', value: null },
415
+ preds: [block.id],
416
+ });
417
+ }
418
+ else {
419
+ // Check if this block exits the loop
420
+ const exitSuccs = succs.filter(s => !cont.blocks.some(b => b.id === s));
421
+ if (exitSuccs.length > 0) {
422
+ // Redirect exit branch to an exit block that returns
423
+ const exitBlockId = `${block.id}_exit`;
424
+ const exitBlock = {
425
+ id: exitBlockId,
426
+ instrs: [],
427
+ term: { kind: 'return', value: null },
428
+ preds: [block.id],
429
+ };
430
+ if (rewritten.term.kind === 'branch') {
431
+ const branchTerm = rewritten.term;
432
+ const thenInLoop = cont.blocks.some(b => b.id === branchTerm.then);
433
+ const elseInLoop = cont.blocks.some(b => b.id === branchTerm.else);
434
+ if (!thenInLoop && elseInLoop) {
435
+ blocks.push({
436
+ ...rewritten,
437
+ term: { ...branchTerm, then: exitBlockId },
438
+ });
439
+ }
440
+ else if (thenInLoop && !elseInLoop) {
441
+ blocks.push({
442
+ ...rewritten,
443
+ term: { ...branchTerm, else: exitBlockId },
444
+ });
445
+ }
446
+ else {
447
+ blocks.push(rewritten);
448
+ }
449
+ }
450
+ else {
451
+ blocks.push(rewritten);
452
+ }
453
+ blocks.push(exitBlock);
454
+ }
455
+ else {
456
+ blocks.push(rewritten);
457
+ }
458
+ }
459
+ }
460
+ // Deduplicate blocks by ID
461
+ const seenIds = new Set();
462
+ const dedupBlocks = [];
463
+ for (const b of blocks) {
464
+ if (!seenIds.has(b.id)) {
465
+ seenIds.add(b.id);
466
+ dedupBlocks.push(b);
467
+ }
468
+ }
469
+ return {
470
+ name,
471
+ params: [],
472
+ blocks: dedupBlocks,
473
+ entry: 'entry',
474
+ isMacro: false,
475
+ };
476
+ }
477
+ function buildPostLoopContinuation(name, cont, contId, promoted, pcTemp, objective, onDone) {
478
+ const blocks = [];
479
+ // Rewrite blocks with promoted variables
480
+ for (const block of cont.blocks) {
481
+ blocks.push(rewriteBlock(block, promoted));
482
+ }
483
+ // The entry is the first block in the continuation
484
+ const entry = cont.blocks[0]?.id ?? 'entry';
485
+ // Add onDone call if this is the last continuation
486
+ if (onDone) {
487
+ // Find blocks with return terminators and add onDone call before them
488
+ for (let i = 0; i < blocks.length; i++) {
489
+ if (blocks[i].term.kind === 'return') {
490
+ blocks[i] = {
491
+ ...blocks[i],
492
+ instrs: [
493
+ ...blocks[i].instrs,
494
+ { kind: 'call', dst: null, fn: onDone, args: [] },
495
+ ],
496
+ };
497
+ }
498
+ }
499
+ }
500
+ return {
501
+ name,
502
+ params: [],
503
+ blocks,
504
+ entry,
505
+ isMacro: false,
506
+ };
507
+ }
508
+ // ---------------------------------------------------------------------------
509
+ // Step 5: Build init function (replaces original)
510
+ // ---------------------------------------------------------------------------
511
+ function buildInitFunction(originalFn, promoted, pcTemp, prefix, objective) {
512
+ // The init function:
513
+ // 1. Sets pc = 1 (start from continuation 1)
514
+ // 2. Initializes promoted variables from the entry block's pre-loop code
515
+ const instrs = [];
516
+ // Set pc = 1
517
+ instrs.push({ kind: 'const', dst: pcTemp, value: 1 });
518
+ // Initialize promoted variables from entry block instructions
519
+ // Walk the entry block and copy any const/copy instructions for promoted vars
520
+ const entryBlock = originalFn.blocks.find(b => b.id === originalFn.entry);
521
+ if (entryBlock) {
522
+ for (const instr of entryBlock.instrs) {
523
+ const dst = getDst(instr);
524
+ if (dst && promoted.has(dst)) {
525
+ // Rewrite to use promoted name
526
+ instrs.push(rewriteInstr(instr, promoted));
527
+ }
528
+ }
529
+ }
530
+ const block = {
531
+ id: 'entry',
532
+ instrs,
533
+ term: { kind: 'return', value: null },
534
+ preds: [],
535
+ };
536
+ return {
537
+ name: originalFn.name,
538
+ params: originalFn.params,
539
+ blocks: [block],
540
+ entry: 'entry',
541
+ isMacro: originalFn.isMacro,
542
+ };
543
+ }
544
+ // ---------------------------------------------------------------------------
545
+ // Step 6: Build dispatcher
546
+ // ---------------------------------------------------------------------------
547
+ function buildDispatcher(name, continuations, pcTemp, objective, originalFnName) {
548
+ // Generates a dispatcher function that checks pc and calls the right continuation.
549
+ // For each continuation i (1-indexed):
550
+ // execute if score $coro_pc __ns matches i run function ns:_coro_cont_i
551
+ //
552
+ // We model this as a chain of branches in MIR.
553
+ const blocks = [];
554
+ if (continuations.length === 0) {
555
+ // No continuations — just return
556
+ blocks.push({
557
+ id: 'entry',
558
+ instrs: [],
559
+ term: { kind: 'return', value: null },
560
+ preds: [],
561
+ });
562
+ }
563
+ else {
564
+ // Build a chain: check pc==1 → call cont_1, else check pc==2 → call cont_2, ...
565
+ for (let i = 0; i < continuations.length; i++) {
566
+ const contFn = continuations[i];
567
+ const blockId = i === 0 ? 'entry' : `check_${i + 1}`;
568
+ const cmpTemp = `${name}_cmp_${i + 1}`;
569
+ const nextBlock = i < continuations.length - 1 ? `check_${i + 2}` : 'done';
570
+ const callBlock = `call_${i + 1}`;
571
+ blocks.push({
572
+ id: blockId,
573
+ instrs: [
574
+ { kind: 'cmp', dst: cmpTemp, op: 'eq', a: { kind: 'temp', name: pcTemp }, b: { kind: 'const', value: i + 1 } },
575
+ ],
576
+ term: { kind: 'branch', cond: { kind: 'temp', name: cmpTemp }, then: callBlock, else: nextBlock },
577
+ preds: i === 0 ? [] : [`check_${i}`],
578
+ });
579
+ blocks.push({
580
+ id: callBlock,
581
+ instrs: [
582
+ { kind: 'call', dst: null, fn: contFn.name, args: [] },
583
+ ],
584
+ term: { kind: 'return', value: null },
585
+ preds: [blockId],
586
+ });
587
+ }
588
+ // Done block (pc doesn't match any continuation — coroutine finished)
589
+ blocks.push({
590
+ id: 'done',
591
+ instrs: [],
592
+ term: { kind: 'return', value: null },
593
+ preds: [continuations.length === 1 ? 'entry' : `check_${continuations.length}`],
594
+ });
595
+ }
596
+ return {
597
+ name,
598
+ params: [],
599
+ blocks,
600
+ entry: 'entry',
601
+ isMacro: false,
602
+ };
603
+ }
604
+ // ---------------------------------------------------------------------------
605
+ // Single-continuation fallback (no loops)
606
+ // ---------------------------------------------------------------------------
607
+ function buildSingleContinuation(fn, info, prefix, pcTemp, objective) {
608
+ // If there are no loops, the entire function body runs in one tick.
609
+ // We still wrap it in the coroutine pattern for consistency (init → cont_1 → done).
610
+ const contName = `${prefix}_cont_1`;
611
+ // Continuation = entire original function body, plus set pc=-1 at the end
612
+ const contBlocks = fn.blocks.map(block => {
613
+ if (block.term.kind === 'return') {
614
+ const instrs = [...block.instrs];
615
+ if (info.onDone) {
616
+ instrs.push({ kind: 'call', dst: null, fn: info.onDone, args: [] });
617
+ }
618
+ return { ...block, instrs };
619
+ }
620
+ return block;
621
+ });
622
+ const contFn = {
623
+ name: contName,
624
+ params: [],
625
+ blocks: contBlocks,
626
+ entry: fn.entry,
627
+ isMacro: false,
628
+ };
629
+ // Init: set pc = 1
630
+ const initBlock = {
631
+ id: 'entry',
632
+ instrs: [
633
+ { kind: 'const', dst: pcTemp, value: 1 },
634
+ ],
635
+ term: { kind: 'return', value: null },
636
+ preds: [],
637
+ };
638
+ const initFn = {
639
+ name: fn.name,
640
+ params: fn.params,
641
+ blocks: [initBlock],
642
+ entry: 'entry',
643
+ isMacro: fn.isMacro,
644
+ };
645
+ const dispatcher = buildDispatcher(`${prefix}_tick`, [contFn], pcTemp, objective, fn.name);
646
+ return { initFn, continuations: [contFn], dispatcher };
647
+ }
648
+ // ---------------------------------------------------------------------------
649
+ // Helpers: instruction rewriting
650
+ // ---------------------------------------------------------------------------
651
+ function rewriteBlock(block, promoted) {
652
+ return {
653
+ ...block,
654
+ instrs: block.instrs.map(i => rewriteInstr(i, promoted)),
655
+ term: rewriteInstr(block.term, promoted),
656
+ };
657
+ }
658
+ function rewriteInstr(instr, promoted) {
659
+ // Deep-rewrite all temp references through the promoted map
660
+ const rTemp = (t) => promoted.get(t) ?? t;
661
+ const rOp = (op) => op.kind === 'temp' ? { kind: 'temp', name: rTemp(op.name) } : op;
662
+ switch (instr.kind) {
663
+ case 'const':
664
+ return { ...instr, dst: rTemp(instr.dst) };
665
+ case 'copy':
666
+ return { ...instr, dst: rTemp(instr.dst), src: rOp(instr.src) };
667
+ case 'add':
668
+ case 'sub':
669
+ case 'mul':
670
+ case 'div':
671
+ case 'mod':
672
+ return { ...instr, dst: rTemp(instr.dst), a: rOp(instr.a), b: rOp(instr.b) };
673
+ case 'neg':
674
+ return { ...instr, dst: rTemp(instr.dst), src: rOp(instr.src) };
675
+ case 'cmp':
676
+ return { ...instr, dst: rTemp(instr.dst), a: rOp(instr.a), b: rOp(instr.b) };
677
+ case 'and':
678
+ case 'or':
679
+ return { ...instr, dst: rTemp(instr.dst), a: rOp(instr.a), b: rOp(instr.b) };
680
+ case 'not':
681
+ return { ...instr, dst: rTemp(instr.dst), src: rOp(instr.src) };
682
+ case 'nbt_read':
683
+ return { ...instr, dst: rTemp(instr.dst) };
684
+ case 'nbt_write':
685
+ return { ...instr, src: rOp(instr.src) };
686
+ case 'call':
687
+ return { ...instr, dst: instr.dst ? rTemp(instr.dst) : null, args: instr.args.map(rOp) };
688
+ case 'call_macro':
689
+ return { ...instr, dst: instr.dst ? rTemp(instr.dst) : null, args: instr.args.map(a => ({ ...a, value: rOp(a.value) })) };
690
+ case 'call_context':
691
+ return instr;
692
+ case 'branch':
693
+ return { ...instr, cond: rOp(instr.cond) };
694
+ case 'return':
695
+ return { ...instr, value: instr.value ? rOp(instr.value) : null };
696
+ case 'jump':
697
+ return instr;
698
+ default:
699
+ return instr;
700
+ }
701
+ }
702
+ function rewriteTerminator(term, from, to) {
703
+ switch (term.kind) {
704
+ case 'jump':
705
+ return term.target === from ? { ...term, target: to } : term;
706
+ case 'branch':
707
+ return {
708
+ ...term,
709
+ then: term.then === from ? to : term.then,
710
+ else: term.else === from ? to : term.else,
711
+ };
712
+ default:
713
+ return term;
714
+ }
715
+ }
716
+ // ---------------------------------------------------------------------------
717
+ // Helpers: MIR instruction queries
718
+ // ---------------------------------------------------------------------------
719
+ function getSuccessors(term) {
720
+ switch (term.kind) {
721
+ case 'jump': return [term.target];
722
+ case 'branch': return [term.then, term.else];
723
+ default: return [];
724
+ }
725
+ }
726
+ function getDst(instr) {
727
+ switch (instr.kind) {
728
+ case 'const':
729
+ case 'copy':
730
+ case 'add':
731
+ case 'sub':
732
+ case 'mul':
733
+ case 'div':
734
+ case 'mod':
735
+ case 'neg':
736
+ case 'cmp':
737
+ case 'and':
738
+ case 'or':
739
+ case 'not':
740
+ case 'nbt_read':
741
+ return instr.dst;
742
+ case 'call':
743
+ case 'call_macro':
744
+ return instr.dst;
745
+ default:
746
+ return null;
747
+ }
748
+ }
749
+ function getUsedTemps(instr) {
750
+ const temps = [];
751
+ const addOp = (op) => { if (op.kind === 'temp')
752
+ temps.push(op.name); };
753
+ switch (instr.kind) {
754
+ case 'copy':
755
+ case 'neg':
756
+ case 'not':
757
+ addOp(instr.src);
758
+ break;
759
+ case 'add':
760
+ case 'sub':
761
+ case 'mul':
762
+ case 'div':
763
+ case 'mod':
764
+ case 'cmp':
765
+ case 'and':
766
+ case 'or':
767
+ addOp(instr.a);
768
+ addOp(instr.b);
769
+ break;
770
+ case 'nbt_write':
771
+ addOp(instr.src);
772
+ break;
773
+ case 'call':
774
+ instr.args.forEach(addOp);
775
+ break;
776
+ case 'call_macro':
777
+ instr.args.forEach(a => addOp(a.value));
778
+ break;
779
+ case 'branch':
780
+ addOp(instr.cond);
781
+ break;
782
+ case 'return':
783
+ if (instr.value)
784
+ addOp(instr.value);
785
+ break;
786
+ }
787
+ return temps;
788
+ }
789
+ //# sourceMappingURL=coroutine.js.map