redscript-mc 2.0.0 → 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 (629) hide show
  1. package/.claudeignore +21 -0
  2. package/README.md +12 -16
  3. package/README.zh.md +2 -2
  4. package/dist/cli.js +0 -0
  5. package/dist/src/__tests__/budget.test.js +261 -0
  6. package/dist/src/__tests__/diagnostics.test.js +2 -3
  7. package/dist/src/__tests__/e2e/coroutine.test.d.ts +7 -0
  8. package/dist/src/__tests__/e2e/coroutine.test.js +132 -0
  9. package/dist/{src2 → src}/__tests__/e2e/macros.test.js +1 -1
  10. package/dist/{src2 → src}/__tests__/e2e/migrate.test.js +1 -1
  11. package/dist/src/__tests__/e2e/stdlib-e2e.test.d.ts +10 -0
  12. package/dist/src/__tests__/e2e/stdlib-e2e.test.js +324 -0
  13. package/dist/src/__tests__/enum.test.d.ts +10 -0
  14. package/dist/src/__tests__/enum.test.js +389 -0
  15. package/dist/src/__tests__/generics.test.d.ts +14 -0
  16. package/dist/src/__tests__/generics.test.js +367 -0
  17. package/dist/{src2 → src}/__tests__/hir/desugar.test.js +2 -2
  18. package/dist/src/__tests__/incremental.test.d.ts +5 -0
  19. package/dist/src/__tests__/incremental.test.js +308 -0
  20. package/dist/src/__tests__/lsp.test.d.ts +7 -0
  21. package/dist/src/__tests__/lsp.test.js +245 -0
  22. package/dist/src/__tests__/mc-version.test.d.ts +10 -0
  23. package/dist/src/__tests__/mc-version.test.js +154 -0
  24. package/dist/{src2 → src}/__tests__/mir/arithmetic.test.js +2 -2
  25. package/dist/{src2 → src}/__tests__/mir/control-flow.test.js +2 -2
  26. package/dist/src/__tests__/modules.test.d.ts +7 -0
  27. package/dist/src/__tests__/modules.test.js +333 -0
  28. package/dist/src/__tests__/optimizer/coroutine.test.d.ts +12 -0
  29. package/dist/src/__tests__/optimizer/coroutine.test.js +251 -0
  30. package/dist/src/__tests__/optimizer/interprocedural.test.js +145 -0
  31. package/dist/src/__tests__/optimizer/lir/const_imm.test.js +138 -0
  32. package/dist/src/__tests__/optimizer/lir/dead_slot.test.js +141 -0
  33. package/dist/src/__tests__/optimizer/lir/peephole.test.js +126 -0
  34. package/dist/src/__tests__/optimizer/lir/pipeline.test.js +84 -0
  35. package/dist/src/__tests__/optimizer/nbt-batch.test.js +110 -0
  36. package/dist/src/__tests__/optimizer/selector-cache.test.js +103 -0
  37. package/dist/src/__tests__/optimizer/unroll.test.js +206 -0
  38. package/dist/src/__tests__/option.test.d.ts +14 -0
  39. package/dist/src/__tests__/option.test.js +275 -0
  40. package/dist/src/__tests__/schedule.test.d.ts +7 -0
  41. package/dist/src/__tests__/schedule.test.js +98 -0
  42. package/dist/src/__tests__/sourcemap.test.d.ts +7 -0
  43. package/dist/src/__tests__/sourcemap.test.js +227 -0
  44. package/dist/src/__tests__/tuple.test.d.ts +11 -0
  45. package/dist/src/__tests__/tuple.test.js +202 -0
  46. package/dist/src/__tests__/typechecker-strict.test.d.ts +10 -0
  47. package/dist/src/__tests__/typechecker-strict.test.js +197 -0
  48. package/dist/src/ast/types.d.ts +56 -2
  49. package/dist/src/cache/deps.d.ts +41 -0
  50. package/dist/src/cache/deps.js +158 -0
  51. package/dist/src/cache/incremental.d.ts +35 -0
  52. package/dist/src/cache/incremental.js +165 -0
  53. package/dist/src/cache/index.d.ts +37 -0
  54. package/dist/src/cache/index.js +152 -0
  55. package/dist/src/cli.js +76 -45
  56. package/dist/src/compile.d.ts +2 -2
  57. package/dist/src/compile.js +1 -1
  58. package/dist/src/diagnostics/index.d.ts +1 -1
  59. package/dist/src/diagnostics/index.js +8 -11
  60. package/dist/src/emit/compile.d.ts +29 -0
  61. package/dist/src/emit/compile.js +143 -0
  62. package/dist/{src2 → src}/emit/index.d.ts +9 -0
  63. package/dist/{src2 → src}/emit/index.js +59 -8
  64. package/dist/src/emit/modules.d.ts +29 -0
  65. package/dist/src/emit/modules.js +492 -0
  66. package/dist/src/emit/sourcemap.d.ts +53 -0
  67. package/dist/src/emit/sourcemap.js +73 -0
  68. package/dist/{src2 → src}/hir/lower.d.ts +1 -1
  69. package/dist/{src2 → src}/hir/lower.js +22 -1
  70. package/dist/src/hir/monomorphize.d.ts +22 -0
  71. package/dist/src/hir/monomorphize.js +379 -0
  72. package/dist/{src2 → src}/hir/types.d.ts +35 -2
  73. package/dist/src/index.d.ts +19 -2
  74. package/dist/src/index.js +36 -14
  75. package/dist/src/lexer/index.d.ts +1 -1
  76. package/dist/src/lexer/index.js +1 -0
  77. package/dist/src/lir/budget.d.ts +37 -0
  78. package/dist/src/lir/budget.js +280 -0
  79. package/dist/{src2 → src}/lir/lower.js +19 -0
  80. package/dist/{src2 → src}/lir/types.d.ts +7 -4
  81. package/dist/src/lsp/main.d.ts +8 -0
  82. package/dist/src/lsp/main.js +11 -0
  83. package/dist/src/lsp/server.d.ts +11 -0
  84. package/dist/src/lsp/server.js +352 -0
  85. package/dist/{src2 → src}/mir/lower.d.ts +1 -1
  86. package/dist/{src2 → src}/mir/lower.js +244 -10
  87. package/dist/{src2 → src}/mir/types.d.ts +10 -2
  88. package/dist/src/optimizer/coroutine.d.ts +34 -0
  89. package/dist/src/optimizer/coroutine.js +789 -0
  90. package/dist/src/optimizer/dce.d.ts +8 -34
  91. package/dist/src/optimizer/dce.js +146 -629
  92. package/dist/src/optimizer/interprocedural.d.ts +14 -0
  93. package/dist/src/optimizer/interprocedural.js +186 -0
  94. package/dist/src/optimizer/lir/const_imm.d.ts +12 -0
  95. package/dist/src/optimizer/lir/const_imm.js +139 -0
  96. package/dist/src/optimizer/lir/dead_slot.d.ts +14 -0
  97. package/dist/src/optimizer/lir/dead_slot.js +130 -0
  98. package/dist/src/optimizer/lir/peephole.d.ts +21 -0
  99. package/dist/src/optimizer/lir/peephole.js +52 -0
  100. package/dist/src/optimizer/lir/pipeline.d.ts +10 -0
  101. package/dist/src/optimizer/lir/pipeline.js +34 -0
  102. package/dist/src/optimizer/nbt-batch.d.ts +11 -0
  103. package/dist/src/optimizer/nbt-batch.js +51 -0
  104. package/dist/{src2 → src}/optimizer/pipeline.d.ts +4 -0
  105. package/dist/{src2 → src}/optimizer/pipeline.js +17 -1
  106. package/dist/src/optimizer/selector-cache.d.ts +22 -0
  107. package/dist/src/optimizer/selector-cache.js +100 -0
  108. package/dist/src/optimizer/unroll.d.ts +32 -0
  109. package/dist/src/optimizer/unroll.js +348 -0
  110. package/dist/src/parser/index.d.ts +8 -0
  111. package/dist/src/parser/index.js +204 -14
  112. package/dist/src/repl.d.ts +1 -1
  113. package/dist/src/typechecker/index.d.ts +4 -0
  114. package/dist/src/typechecker/index.js +198 -13
  115. package/dist/src/types/mc-version.d.ts +24 -0
  116. package/dist/src/types/mc-version.js +49 -0
  117. package/docs/ROADMAP.md +395 -0
  118. package/docs/compiler-pipeline-redesign.md +27 -10
  119. package/editors/vscode/out/extension.js +25176 -8000
  120. package/editors/vscode/package-lock.json +90 -6
  121. package/editors/vscode/package.json +3 -2
  122. package/editors/vscode/src/extension.ts +97 -67
  123. package/examples/showcase.mcrs +3 -3
  124. package/jest.config.js +1 -1
  125. package/package.json +9 -3
  126. package/src/__tests__/budget.test.ts +297 -0
  127. package/src/__tests__/diagnostics.test.ts +2 -3
  128. package/src/__tests__/e2e/coroutine.test.ts +142 -0
  129. package/{src2 → src}/__tests__/e2e/macros.test.ts +1 -1
  130. package/{src2 → src}/__tests__/e2e/migrate.test.ts +1 -1
  131. package/src/__tests__/e2e/stdlib-e2e.test.ts +348 -0
  132. package/src/__tests__/enum.test.ts +425 -0
  133. package/src/__tests__/generics.test.ts +390 -0
  134. package/{src2 → src}/__tests__/hir/desugar.test.ts +2 -2
  135. package/src/__tests__/incremental.test.ts +337 -0
  136. package/src/__tests__/lsp.test.ts +270 -0
  137. package/src/__tests__/mc-version.test.ts +178 -0
  138. package/{src2 → src}/__tests__/mir/arithmetic.test.ts +2 -2
  139. package/{src2 → src}/__tests__/mir/control-flow.test.ts +2 -2
  140. package/src/__tests__/modules.test.ts +365 -0
  141. package/src/__tests__/optimizer/coroutine.test.ts +312 -0
  142. package/src/__tests__/optimizer/interprocedural.test.ts +174 -0
  143. package/src/__tests__/optimizer/lir/const_imm.test.ts +151 -0
  144. package/src/__tests__/optimizer/lir/dead_slot.test.ts +156 -0
  145. package/src/__tests__/optimizer/lir/peephole.test.ts +136 -0
  146. package/src/__tests__/optimizer/lir/pipeline.test.ts +113 -0
  147. package/src/__tests__/optimizer/nbt-batch.test.ts +119 -0
  148. package/src/__tests__/optimizer/selector-cache.test.ts +112 -0
  149. package/src/__tests__/optimizer/unroll.test.ts +231 -0
  150. package/src/__tests__/option.test.ts +299 -0
  151. package/src/__tests__/schedule.test.ts +105 -0
  152. package/src/__tests__/sourcemap.test.ts +254 -0
  153. package/src/__tests__/tuple.test.ts +220 -0
  154. package/src/__tests__/typechecker-strict.test.ts +216 -0
  155. package/src/ast/types.ts +33 -2
  156. package/src/cache/deps.ts +132 -0
  157. package/src/cache/incremental.ts +173 -0
  158. package/src/cache/index.ts +135 -0
  159. package/src/cli.ts +88 -45
  160. package/src/compile.ts +2 -2
  161. package/src/diagnostics/index.ts +8 -11
  162. package/src/emit/compile.ts +177 -0
  163. package/{src2 → src}/emit/index.ts +72 -8
  164. package/src/emit/modules.ts +581 -0
  165. package/src/emit/sourcemap.ts +101 -0
  166. package/{src2 → src}/hir/lower.ts +29 -2
  167. package/src/hir/monomorphize.ts +416 -0
  168. package/{src2 → src}/hir/types.ts +15 -3
  169. package/src/index.ts +29 -10
  170. package/src/lexer/index.ts +2 -1
  171. package/src/lir/budget.ts +321 -0
  172. package/{src2 → src}/lir/lower.ts +32 -1
  173. package/{src2 → src}/lir/types.ts +7 -3
  174. package/src/lsp/main.ts +9 -0
  175. package/src/lsp/server.ts +414 -0
  176. package/{src2 → src}/mir/lower.ts +251 -8
  177. package/{src2 → src}/mir/types.ts +12 -1
  178. package/src/optimizer/coroutine.ts +996 -0
  179. package/{src2 → src}/optimizer/dce.ts +2 -1
  180. package/src/optimizer/interprocedural.ts +177 -0
  181. package/src/optimizer/lir/const_imm.ts +143 -0
  182. package/src/optimizer/lir/dead_slot.ts +123 -0
  183. package/src/optimizer/lir/peephole.ts +57 -0
  184. package/src/optimizer/lir/pipeline.ts +37 -0
  185. package/src/optimizer/nbt-batch.ts +50 -0
  186. package/{src2 → src}/optimizer/pipeline.ts +16 -1
  187. package/src/optimizer/selector-cache.ts +103 -0
  188. package/src/optimizer/unroll.ts +386 -0
  189. package/src/parser/index.ts +212 -15
  190. package/src/repl.ts +1 -1
  191. package/src/stdlib/math.mcrs +4 -4
  192. package/src/templates/quest.mcrs +4 -4
  193. package/src/typechecker/index.ts +215 -15
  194. package/src/types/mc-version.ts +46 -0
  195. package/tsconfig.json +1 -1
  196. package/.claude/commands/build-test.md +0 -10
  197. package/.claude/commands/deploy-demo.md +0 -12
  198. package/.claude/commands/stage-status.md +0 -13
  199. package/.claude/settings.json +0 -12
  200. package/CLAUDE.md +0 -231
  201. package/dist/__tests__/cli.test.js +0 -278
  202. package/dist/__tests__/codegen.test.js +0 -152
  203. package/dist/__tests__/compile-all.test.d.ts +0 -10
  204. package/dist/__tests__/compile-all.test.js +0 -108
  205. package/dist/__tests__/dce.test.js +0 -138
  206. package/dist/__tests__/diagnostics.test.d.ts +0 -4
  207. package/dist/__tests__/diagnostics.test.js +0 -149
  208. package/dist/__tests__/e2e.test.d.ts +0 -6
  209. package/dist/__tests__/e2e.test.js +0 -1847
  210. package/dist/__tests__/entity-types.test.js +0 -203
  211. package/dist/__tests__/formatter.test.js +0 -40
  212. package/dist/__tests__/lexer.test.js +0 -343
  213. package/dist/__tests__/lowering.test.js +0 -1015
  214. package/dist/__tests__/macro.test.d.ts +0 -8
  215. package/dist/__tests__/macro.test.js +0 -305
  216. package/dist/__tests__/mc-integration.test.d.ts +0 -12
  217. package/dist/__tests__/mc-integration.test.js +0 -819
  218. package/dist/__tests__/mc-syntax.test.js +0 -124
  219. package/dist/__tests__/nbt.test.js +0 -82
  220. package/dist/__tests__/optimizer-advanced.test.js +0 -124
  221. package/dist/__tests__/optimizer.test.d.ts +0 -1
  222. package/dist/__tests__/optimizer.test.js +0 -149
  223. package/dist/__tests__/parser.test.d.ts +0 -1
  224. package/dist/__tests__/parser.test.js +0 -807
  225. package/dist/__tests__/repl.test.d.ts +0 -1
  226. package/dist/__tests__/repl.test.js +0 -27
  227. package/dist/__tests__/runtime.test.d.ts +0 -1
  228. package/dist/__tests__/runtime.test.js +0 -289
  229. package/dist/__tests__/stdlib-advanced.test.d.ts +0 -4
  230. package/dist/__tests__/stdlib-advanced.test.js +0 -378
  231. package/dist/__tests__/stdlib-bigint.test.d.ts +0 -7
  232. package/dist/__tests__/stdlib-bigint.test.js +0 -428
  233. package/dist/__tests__/stdlib-math.test.d.ts +0 -7
  234. package/dist/__tests__/stdlib-math.test.js +0 -352
  235. package/dist/__tests__/stdlib-vec.test.d.ts +0 -4
  236. package/dist/__tests__/stdlib-vec.test.js +0 -264
  237. package/dist/__tests__/structure-optimizer.test.d.ts +0 -1
  238. package/dist/__tests__/structure-optimizer.test.js +0 -33
  239. package/dist/__tests__/typechecker.test.d.ts +0 -1
  240. package/dist/__tests__/typechecker.test.js +0 -552
  241. package/dist/__tests__/var-allocator.test.d.ts +0 -1
  242. package/dist/__tests__/var-allocator.test.js +0 -69
  243. package/dist/ast/types.d.ts +0 -514
  244. package/dist/ast/types.js +0 -9
  245. package/dist/builtins/metadata.d.ts +0 -36
  246. package/dist/builtins/metadata.js +0 -1014
  247. package/dist/cli.d.ts +0 -11
  248. package/dist/codegen/cmdblock/index.d.ts +0 -26
  249. package/dist/codegen/cmdblock/index.js +0 -45
  250. package/dist/codegen/mcfunction/index.d.ts +0 -40
  251. package/dist/codegen/mcfunction/index.js +0 -606
  252. package/dist/codegen/structure/index.d.ts +0 -24
  253. package/dist/codegen/structure/index.js +0 -279
  254. package/dist/codegen/var-allocator.d.ts +0 -45
  255. package/dist/codegen/var-allocator.js +0 -104
  256. package/dist/compile.d.ts +0 -68
  257. package/dist/data/arena/function/__load.mcfunction +0 -6
  258. package/dist/data/arena/function/__tick.mcfunction +0 -2
  259. package/dist/data/arena/function/announce_leaders/else_1.mcfunction +0 -3
  260. package/dist/data/arena/function/announce_leaders/foreach_0/merge_2.mcfunction +0 -1
  261. package/dist/data/arena/function/announce_leaders/foreach_0/then_0.mcfunction +0 -3
  262. package/dist/data/arena/function/announce_leaders/foreach_0.mcfunction +0 -7
  263. package/dist/data/arena/function/announce_leaders/foreach_1/merge_2.mcfunction +0 -1
  264. package/dist/data/arena/function/announce_leaders/foreach_1/then_0.mcfunction +0 -4
  265. package/dist/data/arena/function/announce_leaders/foreach_1.mcfunction +0 -6
  266. package/dist/data/arena/function/announce_leaders/merge_2.mcfunction +0 -1
  267. package/dist/data/arena/function/announce_leaders/then_0.mcfunction +0 -4
  268. package/dist/data/arena/function/announce_leaders.mcfunction +0 -6
  269. package/dist/data/arena/function/arena_tick/merge_2.mcfunction +0 -1
  270. package/dist/data/arena/function/arena_tick/then_0.mcfunction +0 -4
  271. package/dist/data/arena/function/arena_tick.mcfunction +0 -11
  272. package/dist/data/counter/function/__load.mcfunction +0 -5
  273. package/dist/data/counter/function/__tick.mcfunction +0 -2
  274. package/dist/data/counter/function/counter_tick/merge_2.mcfunction +0 -1
  275. package/dist/data/counter/function/counter_tick/then_0.mcfunction +0 -3
  276. package/dist/data/counter/function/counter_tick.mcfunction +0 -11
  277. package/dist/data/gcd2/function/__load.mcfunction +0 -3
  278. package/dist/data/gcd2/function/abs/merge_2.mcfunction +0 -3
  279. package/dist/data/gcd2/function/abs/then_0.mcfunction +0 -5
  280. package/dist/data/gcd2/function/abs.mcfunction +0 -7
  281. package/dist/data/gcd2/function/gcd/loop_body_1.mcfunction +0 -7
  282. package/dist/data/gcd2/function/gcd/loop_check_0.mcfunction +0 -5
  283. package/dist/data/gcd2/function/gcd/loop_exit_2.mcfunction +0 -3
  284. package/dist/data/gcd2/function/gcd.mcfunction +0 -14
  285. package/dist/data/gcd3/function/__load.mcfunction +0 -3
  286. package/dist/data/gcd3/function/abs/merge_2.mcfunction +0 -3
  287. package/dist/data/gcd3/function/abs/then_0.mcfunction +0 -5
  288. package/dist/data/gcd3/function/abs.mcfunction +0 -7
  289. package/dist/data/gcd3/function/gcd/loop_body_1.mcfunction +0 -7
  290. package/dist/data/gcd3/function/gcd/loop_check_0.mcfunction +0 -5
  291. package/dist/data/gcd3/function/gcd/loop_exit_2.mcfunction +0 -3
  292. package/dist/data/gcd3/function/gcd.mcfunction +0 -14
  293. package/dist/data/gcd3/function/test.mcfunction +0 -7
  294. package/dist/data/gcd3nm/function/__load.mcfunction +0 -3
  295. package/dist/data/gcd3nm/function/abs/merge_2.mcfunction +0 -3
  296. package/dist/data/gcd3nm/function/abs/then_0.mcfunction +0 -5
  297. package/dist/data/gcd3nm/function/abs.mcfunction +0 -7
  298. package/dist/data/gcd3nm/function/gcd/loop_body_1.mcfunction +0 -7
  299. package/dist/data/gcd3nm/function/gcd/loop_check_0.mcfunction +0 -5
  300. package/dist/data/gcd3nm/function/gcd/loop_exit_2.mcfunction +0 -3
  301. package/dist/data/gcd3nm/function/gcd.mcfunction +0 -14
  302. package/dist/data/gcd3nm/function/test.mcfunction +0 -7
  303. package/dist/data/gcd_test/function/__load.mcfunction +0 -3
  304. package/dist/data/gcd_test/function/abs/merge_2.mcfunction +0 -3
  305. package/dist/data/gcd_test/function/abs/then_0.mcfunction +0 -5
  306. package/dist/data/gcd_test/function/abs.mcfunction +0 -7
  307. package/dist/data/gcd_test/function/gcd/loop_body_1.mcfunction +0 -7
  308. package/dist/data/gcd_test/function/gcd/loop_check_0.mcfunction +0 -5
  309. package/dist/data/gcd_test/function/gcd/loop_exit_2.mcfunction +0 -3
  310. package/dist/data/gcd_test/function/gcd.mcfunction +0 -14
  311. package/dist/data/isqrttest/function/__load.mcfunction +0 -6
  312. package/dist/data/isqrttest/function/isqrt/loop_body_4.mcfunction +0 -12
  313. package/dist/data/isqrttest/function/isqrt/loop_check_3.mcfunction +0 -5
  314. package/dist/data/isqrttest/function/isqrt/loop_exit_5.mcfunction +0 -3
  315. package/dist/data/isqrttest/function/isqrt/merge_2.mcfunction +0 -4
  316. package/dist/data/isqrttest/function/isqrt/merge_8.mcfunction +0 -6
  317. package/dist/data/isqrttest/function/isqrt/then_0.mcfunction +0 -3
  318. package/dist/data/isqrttest/function/isqrt/then_6.mcfunction +0 -3
  319. package/dist/data/isqrttest/function/isqrt.mcfunction +0 -7
  320. package/dist/data/isqrttest/function/test.mcfunction +0 -6
  321. package/dist/data/mathtest/function/__load.mcfunction +0 -3
  322. package/dist/data/mathtest/function/abs/merge_2.mcfunction +0 -3
  323. package/dist/data/mathtest/function/abs/then_0.mcfunction +0 -5
  324. package/dist/data/mathtest/function/abs.mcfunction +0 -6
  325. package/dist/data/mathtest/function/test.mcfunction +0 -5
  326. package/dist/data/minecraft/tags/function/load.json +0 -5
  327. package/dist/data/minecraft/tags/function/tick.json +0 -5
  328. package/dist/data/mypack/function/__load.mcfunction +0 -13
  329. package/dist/data/mypack/function/_atan_init.mcfunction +0 -2
  330. package/dist/data/mypack/function/abs/merge_2.mcfunction +0 -3
  331. package/dist/data/mypack/function/abs/then_0.mcfunction +0 -5
  332. package/dist/data/mypack/function/abs.mcfunction +0 -6
  333. package/dist/data/mypack/function/atan2_fixed/__sgi_1.mcfunction +0 -2
  334. package/dist/data/mypack/function/atan2_fixed/else_34.mcfunction +0 -3
  335. package/dist/data/mypack/function/atan2_fixed/loop_body_31.mcfunction +0 -19
  336. package/dist/data/mypack/function/atan2_fixed/loop_check_30.mcfunction +0 -5
  337. package/dist/data/mypack/function/atan2_fixed/loop_exit_32.mcfunction +0 -6
  338. package/dist/data/mypack/function/atan2_fixed/merge_11.mcfunction +0 -6
  339. package/dist/data/mypack/function/atan2_fixed/merge_14.mcfunction +0 -3
  340. package/dist/data/mypack/function/atan2_fixed/merge_17.mcfunction +0 -6
  341. package/dist/data/mypack/function/atan2_fixed/merge_2.mcfunction +0 -5
  342. package/dist/data/mypack/function/atan2_fixed/merge_20.mcfunction +0 -5
  343. package/dist/data/mypack/function/atan2_fixed/merge_23.mcfunction +0 -5
  344. package/dist/data/mypack/function/atan2_fixed/merge_26.mcfunction +0 -6
  345. package/dist/data/mypack/function/atan2_fixed/merge_29.mcfunction +0 -4
  346. package/dist/data/mypack/function/atan2_fixed/merge_38.mcfunction +0 -5
  347. package/dist/data/mypack/function/atan2_fixed/merge_41.mcfunction +0 -5
  348. package/dist/data/mypack/function/atan2_fixed/merge_44.mcfunction +0 -5
  349. package/dist/data/mypack/function/atan2_fixed/merge_47.mcfunction +0 -5
  350. package/dist/data/mypack/function/atan2_fixed/merge_5.mcfunction +0 -5
  351. package/dist/data/mypack/function/atan2_fixed/merge_8.mcfunction +0 -3
  352. package/dist/data/mypack/function/atan2_fixed/then_0.mcfunction +0 -5
  353. package/dist/data/mypack/function/atan2_fixed/then_12.mcfunction +0 -3
  354. package/dist/data/mypack/function/atan2_fixed/then_15.mcfunction +0 -5
  355. package/dist/data/mypack/function/atan2_fixed/then_18.mcfunction +0 -5
  356. package/dist/data/mypack/function/atan2_fixed/then_21.mcfunction +0 -3
  357. package/dist/data/mypack/function/atan2_fixed/then_24.mcfunction +0 -3
  358. package/dist/data/mypack/function/atan2_fixed/then_27.mcfunction +0 -6
  359. package/dist/data/mypack/function/atan2_fixed/then_3.mcfunction +0 -3
  360. package/dist/data/mypack/function/atan2_fixed/then_33.mcfunction +0 -5
  361. package/dist/data/mypack/function/atan2_fixed/then_36.mcfunction +0 -5
  362. package/dist/data/mypack/function/atan2_fixed/then_39.mcfunction +0 -5
  363. package/dist/data/mypack/function/atan2_fixed/then_42.mcfunction +0 -3
  364. package/dist/data/mypack/function/atan2_fixed/then_45.mcfunction +0 -5
  365. package/dist/data/mypack/function/atan2_fixed/then_6.mcfunction +0 -3
  366. package/dist/data/mypack/function/atan2_fixed/then_9.mcfunction +0 -5
  367. package/dist/data/mypack/function/atan2_fixed.mcfunction +0 -7
  368. package/dist/data/mypack/function/my_game.mcfunction +0 -10
  369. package/dist/data/quiz/function/__load.mcfunction +0 -16
  370. package/dist/data/quiz/function/__tick.mcfunction +0 -6
  371. package/dist/data/quiz/function/__trigger_quiz_a_dispatch.mcfunction +0 -4
  372. package/dist/data/quiz/function/__trigger_quiz_b_dispatch.mcfunction +0 -4
  373. package/dist/data/quiz/function/__trigger_quiz_c_dispatch.mcfunction +0 -4
  374. package/dist/data/quiz/function/__trigger_quiz_start_dispatch.mcfunction +0 -4
  375. package/dist/data/quiz/function/answer_a.mcfunction +0 -4
  376. package/dist/data/quiz/function/answer_b.mcfunction +0 -4
  377. package/dist/data/quiz/function/answer_c.mcfunction +0 -4
  378. package/dist/data/quiz/function/ask_question/else_1.mcfunction +0 -5
  379. package/dist/data/quiz/function/ask_question/else_4.mcfunction +0 -5
  380. package/dist/data/quiz/function/ask_question/else_7.mcfunction +0 -4
  381. package/dist/data/quiz/function/ask_question/merge_2.mcfunction +0 -1
  382. package/dist/data/quiz/function/ask_question/merge_5.mcfunction +0 -2
  383. package/dist/data/quiz/function/ask_question/merge_8.mcfunction +0 -2
  384. package/dist/data/quiz/function/ask_question/then_0.mcfunction +0 -4
  385. package/dist/data/quiz/function/ask_question/then_3.mcfunction +0 -4
  386. package/dist/data/quiz/function/ask_question/then_6.mcfunction +0 -4
  387. package/dist/data/quiz/function/ask_question.mcfunction +0 -7
  388. package/dist/data/quiz/function/finish_quiz.mcfunction +0 -6
  389. package/dist/data/quiz/function/handle_answer/else_1.mcfunction +0 -5
  390. package/dist/data/quiz/function/handle_answer/else_10.mcfunction +0 -3
  391. package/dist/data/quiz/function/handle_answer/else_16.mcfunction +0 -3
  392. package/dist/data/quiz/function/handle_answer/else_4.mcfunction +0 -3
  393. package/dist/data/quiz/function/handle_answer/else_7.mcfunction +0 -5
  394. package/dist/data/quiz/function/handle_answer/merge_11.mcfunction +0 -2
  395. package/dist/data/quiz/function/handle_answer/merge_14.mcfunction +0 -2
  396. package/dist/data/quiz/function/handle_answer/merge_17.mcfunction +0 -2
  397. package/dist/data/quiz/function/handle_answer/merge_2.mcfunction +0 -8
  398. package/dist/data/quiz/function/handle_answer/merge_5.mcfunction +0 -2
  399. package/dist/data/quiz/function/handle_answer/merge_8.mcfunction +0 -2
  400. package/dist/data/quiz/function/handle_answer/then_0.mcfunction +0 -5
  401. package/dist/data/quiz/function/handle_answer/then_12.mcfunction +0 -5
  402. package/dist/data/quiz/function/handle_answer/then_15.mcfunction +0 -6
  403. package/dist/data/quiz/function/handle_answer/then_3.mcfunction +0 -6
  404. package/dist/data/quiz/function/handle_answer/then_6.mcfunction +0 -5
  405. package/dist/data/quiz/function/handle_answer/then_9.mcfunction +0 -6
  406. package/dist/data/quiz/function/handle_answer.mcfunction +0 -11
  407. package/dist/data/quiz/function/start_quiz.mcfunction +0 -5
  408. package/dist/data/reqtest/function/__load.mcfunction +0 -4
  409. package/dist/data/reqtest/function/_table_init.mcfunction +0 -2
  410. package/dist/data/reqtest/function/no_trig.mcfunction +0 -3
  411. package/dist/data/reqtest/function/use_table.mcfunction +0 -4
  412. package/dist/data/reqtest2/function/__load.mcfunction +0 -3
  413. package/dist/data/reqtest2/function/no_trig.mcfunction +0 -3
  414. package/dist/data/runtime/function/__load.mcfunction +0 -5
  415. package/dist/data/runtime/function/__tick.mcfunction +0 -2
  416. package/dist/data/runtime/function/counter_tick/then_0.mcfunction +0 -3
  417. package/dist/data/runtime/function/counter_tick.mcfunction +0 -13
  418. package/dist/data/shop/function/__load.mcfunction +0 -7
  419. package/dist/data/shop/function/__tick.mcfunction +0 -3
  420. package/dist/data/shop/function/__trigger_shop_buy_dispatch.mcfunction +0 -4
  421. package/dist/data/shop/function/complete_purchase/else_1.mcfunction +0 -5
  422. package/dist/data/shop/function/complete_purchase/else_4.mcfunction +0 -5
  423. package/dist/data/shop/function/complete_purchase/else_7.mcfunction +0 -3
  424. package/dist/data/shop/function/complete_purchase/merge_2.mcfunction +0 -2
  425. package/dist/data/shop/function/complete_purchase/merge_5.mcfunction +0 -2
  426. package/dist/data/shop/function/complete_purchase/merge_8.mcfunction +0 -2
  427. package/dist/data/shop/function/complete_purchase/then_0.mcfunction +0 -4
  428. package/dist/data/shop/function/complete_purchase/then_3.mcfunction +0 -4
  429. package/dist/data/shop/function/complete_purchase/then_6.mcfunction +0 -4
  430. package/dist/data/shop/function/complete_purchase.mcfunction +0 -7
  431. package/dist/data/shop/function/handle_shop_trigger.mcfunction +0 -3
  432. package/dist/data/swap_test/function/__load.mcfunction +0 -3
  433. package/dist/data/swap_test/function/gcd_old/loop_body_1.mcfunction +0 -7
  434. package/dist/data/swap_test/function/gcd_old/loop_check_0.mcfunction +0 -5
  435. package/dist/data/swap_test/function/gcd_old/loop_exit_2.mcfunction +0 -3
  436. package/dist/data/swap_test/function/gcd_old.mcfunction +0 -8
  437. package/dist/data/turret/function/__load.mcfunction +0 -5
  438. package/dist/data/turret/function/__tick.mcfunction +0 -4
  439. package/dist/data/turret/function/__trigger_deploy_turret_dispatch.mcfunction +0 -4
  440. package/dist/data/turret/function/deploy_turret.mcfunction +0 -8
  441. package/dist/data/turret/function/turret_tick/at_1.mcfunction +0 -2
  442. package/dist/data/turret/function/turret_tick/foreach_0.mcfunction +0 -2
  443. package/dist/data/turret/function/turret_tick/foreach_2.mcfunction +0 -2
  444. package/dist/data/turret/function/turret_tick/tick_body.mcfunction +0 -3
  445. package/dist/data/turret/function/turret_tick/tick_skip.mcfunction +0 -1
  446. package/dist/data/turret/function/turret_tick.mcfunction +0 -5
  447. package/dist/diagnostics/index.d.ts +0 -44
  448. package/dist/diagnostics/index.js +0 -140
  449. package/dist/events/types.d.ts +0 -35
  450. package/dist/events/types.js +0 -59
  451. package/dist/formatter/index.d.ts +0 -1
  452. package/dist/formatter/index.js +0 -26
  453. package/dist/gcd2.map.json +0 -15
  454. package/dist/gcd3.map.json +0 -17
  455. package/dist/gcd_test.map.json +0 -15
  456. package/dist/index.d.ts +0 -62
  457. package/dist/ir/builder.d.ts +0 -33
  458. package/dist/ir/builder.js +0 -99
  459. package/dist/ir/types.d.ts +0 -132
  460. package/dist/ir/types.js +0 -15
  461. package/dist/isqrttest.map.json +0 -15
  462. package/dist/lexer/index.d.ts +0 -37
  463. package/dist/lexer/index.js +0 -569
  464. package/dist/lowering/index.d.ts +0 -188
  465. package/dist/lowering/index.js +0 -3405
  466. package/dist/mathtest.map.json +0 -6
  467. package/dist/mc-test/client.d.ts +0 -128
  468. package/dist/mc-test/client.js +0 -174
  469. package/dist/mc-test/runner.d.ts +0 -28
  470. package/dist/mc-test/runner.js +0 -150
  471. package/dist/mc-test/setup.d.ts +0 -11
  472. package/dist/mc-test/setup.js +0 -98
  473. package/dist/mc-validator/index.d.ts +0 -17
  474. package/dist/mc-validator/index.js +0 -322
  475. package/dist/mypack.map.json +0 -27
  476. package/dist/nbt/index.d.ts +0 -86
  477. package/dist/nbt/index.js +0 -250
  478. package/dist/optimizer/commands.d.ts +0 -38
  479. package/dist/optimizer/commands.js +0 -451
  480. package/dist/optimizer/dce.d.ts +0 -34
  481. package/dist/optimizer/dce.js +0 -639
  482. package/dist/optimizer/passes.d.ts +0 -34
  483. package/dist/optimizer/passes.js +0 -243
  484. package/dist/optimizer/structure.d.ts +0 -9
  485. package/dist/optimizer/structure.js +0 -356
  486. package/dist/pack.mcmeta +0 -6
  487. package/dist/parser/index.d.ts +0 -93
  488. package/dist/parser/index.js +0 -1687
  489. package/dist/repl.d.ts +0 -16
  490. package/dist/repl.js +0 -165
  491. package/dist/reqtest.map.json +0 -4
  492. package/dist/reqtest2.map.json +0 -4
  493. package/dist/runtime/index.d.ts +0 -107
  494. package/dist/runtime/index.js +0 -1409
  495. package/dist/runtime.map.json +0 -7
  496. package/dist/src/__tests__/codegen.test.d.ts +0 -1
  497. package/dist/src/__tests__/codegen.test.js +0 -152
  498. package/dist/src/__tests__/e2e.test.d.ts +0 -6
  499. package/dist/src/__tests__/e2e.test.js +0 -1789
  500. package/dist/src/__tests__/entity-types.test.d.ts +0 -1
  501. package/dist/src/__tests__/entity-types.test.js +0 -203
  502. package/dist/src/__tests__/lowering.test.d.ts +0 -1
  503. package/dist/src/__tests__/lowering.test.js +0 -1015
  504. package/dist/src/__tests__/macro.test.d.ts +0 -8
  505. package/dist/src/__tests__/macro.test.js +0 -306
  506. package/dist/src/__tests__/nbt.test.d.ts +0 -1
  507. package/dist/src/__tests__/nbt.test.js +0 -82
  508. package/dist/src/__tests__/optimizer-advanced.test.d.ts +0 -1
  509. package/dist/src/__tests__/optimizer-advanced.test.js +0 -124
  510. package/dist/src/__tests__/optimizer.test.d.ts +0 -1
  511. package/dist/src/__tests__/optimizer.test.js +0 -149
  512. package/dist/src/__tests__/runtime.test.d.ts +0 -1
  513. package/dist/src/__tests__/runtime.test.js +0 -289
  514. package/dist/src/__tests__/stdlib-advanced.test.d.ts +0 -4
  515. package/dist/src/__tests__/stdlib-advanced.test.js +0 -374
  516. package/dist/src/__tests__/stdlib-bigint.test.d.ts +0 -7
  517. package/dist/src/__tests__/stdlib-bigint.test.js +0 -426
  518. package/dist/src/__tests__/stdlib-math.test.d.ts +0 -7
  519. package/dist/src/__tests__/stdlib-math.test.js +0 -351
  520. package/dist/src/__tests__/stdlib-vec.test.d.ts +0 -4
  521. package/dist/src/__tests__/stdlib-vec.test.js +0 -263
  522. package/dist/src/__tests__/structure-optimizer.test.d.ts +0 -1
  523. package/dist/src/__tests__/structure-optimizer.test.js +0 -33
  524. package/dist/src/__tests__/var-allocator.test.d.ts +0 -1
  525. package/dist/src/__tests__/var-allocator.test.js +0 -69
  526. package/dist/src/codegen/cmdblock/index.d.ts +0 -26
  527. package/dist/src/codegen/cmdblock/index.js +0 -45
  528. package/dist/src/codegen/mcfunction/index.d.ts +0 -40
  529. package/dist/src/codegen/mcfunction/index.js +0 -606
  530. package/dist/src/codegen/structure/index.d.ts +0 -24
  531. package/dist/src/codegen/structure/index.js +0 -279
  532. package/dist/src/codegen/var-allocator.d.ts +0 -45
  533. package/dist/src/codegen/var-allocator.js +0 -104
  534. package/dist/src/ir/builder.d.ts +0 -33
  535. package/dist/src/ir/builder.js +0 -99
  536. package/dist/src/ir/types.d.ts +0 -132
  537. package/dist/src/ir/types.js +0 -15
  538. package/dist/src/lowering/index.d.ts +0 -188
  539. package/dist/src/lowering/index.js +0 -3405
  540. package/dist/src/optimizer/commands.d.ts +0 -38
  541. package/dist/src/optimizer/commands.js +0 -451
  542. package/dist/src/optimizer/passes.d.ts +0 -34
  543. package/dist/src/optimizer/passes.js +0 -243
  544. package/dist/src/optimizer/structure.d.ts +0 -9
  545. package/dist/src/optimizer/structure.js +0 -356
  546. package/dist/src2/__tests__/optimizer/dce.test.d.ts +0 -1
  547. package/dist/src2/emit/compile.d.ts +0 -19
  548. package/dist/src2/emit/compile.js +0 -80
  549. package/dist/src2/optimizer/dce.d.ts +0 -8
  550. package/dist/src2/optimizer/dce.js +0 -155
  551. package/dist/swap_test.map.json +0 -14
  552. package/dist/tsconfig.tsbuildinfo +0 -1
  553. package/dist/typechecker/index.d.ts +0 -61
  554. package/dist/typechecker/index.js +0 -1034
  555. package/dist/types/entity-hierarchy.d.ts +0 -29
  556. package/dist/types/entity-hierarchy.js +0 -107
  557. package/src2/emit/compile.ts +0 -99
  558. /package/dist/{__tests__/cli.test.d.ts → src/__tests__/budget.test.d.ts} +0 -0
  559. /package/dist/{src2 → src}/__tests__/e2e/basic.test.d.ts +0 -0
  560. /package/dist/{src2 → src}/__tests__/e2e/basic.test.js +0 -0
  561. /package/dist/{src2 → src}/__tests__/e2e/macros.test.d.ts +0 -0
  562. /package/dist/{src2 → src}/__tests__/e2e/migrate.test.d.ts +0 -0
  563. /package/dist/{src2 → src}/__tests__/hir/desugar.test.d.ts +0 -0
  564. /package/dist/{src2 → src}/__tests__/lir/lower.test.d.ts +0 -0
  565. /package/dist/{src2 → src}/__tests__/lir/lower.test.js +0 -0
  566. /package/dist/{src2 → src}/__tests__/lir/types.test.d.ts +0 -0
  567. /package/dist/{src2 → src}/__tests__/lir/types.test.js +0 -0
  568. /package/dist/{src2 → src}/__tests__/lir/verify.test.d.ts +0 -0
  569. /package/dist/{src2 → src}/__tests__/lir/verify.test.js +0 -0
  570. /package/dist/{src2 → src}/__tests__/mir/arithmetic.test.d.ts +0 -0
  571. /package/dist/{src2 → src}/__tests__/mir/control-flow.test.d.ts +0 -0
  572. /package/dist/{src2 → src}/__tests__/mir/verify.test.d.ts +0 -0
  573. /package/dist/{src2 → src}/__tests__/mir/verify.test.js +0 -0
  574. /package/dist/{src2 → src}/__tests__/optimizer/block_merge.test.d.ts +0 -0
  575. /package/dist/{src2 → src}/__tests__/optimizer/block_merge.test.js +0 -0
  576. /package/dist/{src2 → src}/__tests__/optimizer/branch_simplify.test.d.ts +0 -0
  577. /package/dist/{src2 → src}/__tests__/optimizer/branch_simplify.test.js +0 -0
  578. /package/dist/{src2 → src}/__tests__/optimizer/constant_fold.test.d.ts +0 -0
  579. /package/dist/{src2 → src}/__tests__/optimizer/constant_fold.test.js +0 -0
  580. /package/dist/{src2 → src}/__tests__/optimizer/copy_prop.test.d.ts +0 -0
  581. /package/dist/{src2 → src}/__tests__/optimizer/copy_prop.test.js +0 -0
  582. /package/dist/{__tests__ → src/__tests__/optimizer}/dce.test.d.ts +0 -0
  583. /package/dist/{src2 → src}/__tests__/optimizer/dce.test.js +0 -0
  584. /package/dist/{__tests__/codegen.test.d.ts → src/__tests__/optimizer/interprocedural.test.d.ts} +0 -0
  585. /package/dist/{__tests__/entity-types.test.d.ts → src/__tests__/optimizer/lir/const_imm.test.d.ts} +0 -0
  586. /package/dist/{__tests__/formatter.test.d.ts → src/__tests__/optimizer/lir/dead_slot.test.d.ts} +0 -0
  587. /package/dist/{__tests__/lexer.test.d.ts → src/__tests__/optimizer/lir/peephole.test.d.ts} +0 -0
  588. /package/dist/{src2/__tests__/optimizer → src/__tests__/optimizer/lir}/pipeline.test.d.ts +0 -0
  589. /package/dist/{__tests__/lowering.test.d.ts → src/__tests__/optimizer/nbt-batch.test.d.ts} +0 -0
  590. /package/dist/{__tests__/mc-syntax.test.d.ts → src/__tests__/optimizer/pipeline.test.d.ts} +0 -0
  591. /package/dist/{src2 → src}/__tests__/optimizer/pipeline.test.js +0 -0
  592. /package/dist/{__tests__/nbt.test.d.ts → src/__tests__/optimizer/selector-cache.test.d.ts} +0 -0
  593. /package/dist/{__tests__/optimizer-advanced.test.d.ts → src/__tests__/optimizer/unroll.test.d.ts} +0 -0
  594. /package/dist/{src2 → src}/hir/types.js +0 -0
  595. /package/dist/{src2 → src}/lir/lower.d.ts +0 -0
  596. /package/dist/{src2 → src}/lir/types.js +0 -0
  597. /package/dist/{src2 → src}/lir/verify.d.ts +0 -0
  598. /package/dist/{src2 → src}/lir/verify.js +0 -0
  599. /package/dist/{src2 → src}/mir/macro.d.ts +0 -0
  600. /package/dist/{src2 → src}/mir/macro.js +0 -0
  601. /package/dist/{src2 → src}/mir/types.js +0 -0
  602. /package/dist/{src2 → src}/mir/verify.d.ts +0 -0
  603. /package/dist/{src2 → src}/mir/verify.js +0 -0
  604. /package/dist/{src2 → src}/optimizer/block_merge.d.ts +0 -0
  605. /package/dist/{src2 → src}/optimizer/block_merge.js +0 -0
  606. /package/dist/{src2 → src}/optimizer/branch_simplify.d.ts +0 -0
  607. /package/dist/{src2 → src}/optimizer/branch_simplify.js +0 -0
  608. /package/dist/{src2 → src}/optimizer/constant_fold.d.ts +0 -0
  609. /package/dist/{src2 → src}/optimizer/constant_fold.js +0 -0
  610. /package/dist/{src2 → src}/optimizer/copy_prop.d.ts +0 -0
  611. /package/dist/{src2 → src}/optimizer/copy_prop.js +0 -0
  612. /package/{src2 → src}/__tests__/e2e/basic.test.ts +0 -0
  613. /package/{src2 → src}/__tests__/lir/lower.test.ts +0 -0
  614. /package/{src2 → src}/__tests__/lir/types.test.ts +0 -0
  615. /package/{src2 → src}/__tests__/lir/verify.test.ts +0 -0
  616. /package/{src2 → src}/__tests__/mir/verify.test.ts +0 -0
  617. /package/{src2 → src}/__tests__/optimizer/block_merge.test.ts +0 -0
  618. /package/{src2 → src}/__tests__/optimizer/branch_simplify.test.ts +0 -0
  619. /package/{src2 → src}/__tests__/optimizer/constant_fold.test.ts +0 -0
  620. /package/{src2 → src}/__tests__/optimizer/copy_prop.test.ts +0 -0
  621. /package/{src2 → src}/__tests__/optimizer/dce.test.ts +0 -0
  622. /package/{src2 → src}/__tests__/optimizer/pipeline.test.ts +0 -0
  623. /package/{src2 → src}/lir/verify.ts +0 -0
  624. /package/{src2 → src}/mir/macro.ts +0 -0
  625. /package/{src2 → src}/mir/verify.ts +0 -0
  626. /package/{src2 → src}/optimizer/block_merge.ts +0 -0
  627. /package/{src2 → src}/optimizer/branch_simplify.ts +0 -0
  628. /package/{src2 → src}/optimizer/constant_fold.ts +0 -0
  629. /package/{src2 → src}/optimizer/copy_prop.ts +0 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Selector Cache — MIR optimization pass.
3
+ *
4
+ * Within a single basic block, if the same complex selector (one containing '[')
5
+ * appears in ≥2 call_context instructions (as `as` or `at` subcommands),
6
+ * the pass replaces the 2nd and subsequent occurrences with a simpler
7
+ * tag-based selector `@e[tag=__cache_sel_N]`.
8
+ *
9
+ * Two new call_context instructions are prepended to the block:
10
+ * 1. Cleanup: execute as @e[tag=__cache_sel_N] run <fn: __sel_cleanup_<tag>>
11
+ * — signals codegen to emit: tag @e[tag=<tag>] remove <tag>
12
+ * 2. Tag-add: execute as <original_selector> run <fn: __sel_tag_<tag>>
13
+ * — signals codegen to emit: tag @s add <tag>
14
+ *
15
+ * The synthetic fn names `__sel_cleanup_*` and `__sel_tag_*` are a convention
16
+ * recognized by the codegen layer for special-case emission.
17
+ *
18
+ * This is a block-local pass (does not track selector lifetime across block
19
+ * boundaries) so it is always correct with respect to control flow.
20
+ */
21
+
22
+ import type { MIRFunction, MIRBlock, MIRInstr } from '../mir/types'
23
+
24
+ export function selectorCache(fn: MIRFunction): MIRFunction {
25
+ let tagId = 0
26
+ return {
27
+ ...fn,
28
+ blocks: fn.blocks.map(block => processBlock(block, () => tagId++)),
29
+ }
30
+ }
31
+
32
+ function processBlock(block: MIRBlock, nextId: () => number): MIRBlock {
33
+ // Count how many times each complex selector appears across call_context instrs
34
+ const selectorCount = new Map<string, number>()
35
+ for (const instr of block.instrs) {
36
+ if (instr.kind === 'call_context') {
37
+ for (const sub of instr.subcommands) {
38
+ if ((sub.kind === 'as' || sub.kind === 'at') && isComplexSelector(sub.selector)) {
39
+ selectorCount.set(sub.selector, (selectorCount.get(sub.selector) ?? 0) + 1)
40
+ }
41
+ }
42
+ }
43
+ }
44
+
45
+ // Build a map of selectors that appear ≥2 times → assigned tag name
46
+ const repeated = new Map<string, string>() // selector → tag name
47
+ for (const [sel, count] of selectorCount) {
48
+ if (count >= 2) {
49
+ repeated.set(sel, `__cache_sel_${nextId()}`)
50
+ }
51
+ }
52
+
53
+ if (repeated.size === 0) return block
54
+
55
+ // Prepend cleanup + tag-add instructions for each repeated selector
56
+ const prefixInstrs: MIRInstr[] = []
57
+ for (const [sel, tag] of repeated) {
58
+ // 1. Cleanup: remove stale tags from any entities that still carry this tag
59
+ prefixInstrs.push({
60
+ kind: 'call_context',
61
+ fn: `__sel_cleanup_${tag}`,
62
+ subcommands: [{ kind: 'as', selector: `@e[tag=${tag}]` }],
63
+ })
64
+ // 2. Tag-add: tag all matching entities with the cache tag
65
+ prefixInstrs.push({
66
+ kind: 'call_context',
67
+ fn: `__sel_tag_${tag}`,
68
+ subcommands: [{ kind: 'as', selector: sel }],
69
+ })
70
+ }
71
+
72
+ // Rewrite instructions: first occurrence of each repeated selector is kept
73
+ // as-is; subsequent occurrences are replaced with the tag-based selector.
74
+ const seen = new Set<string>()
75
+ const newInstrs: MIRInstr[] = [...prefixInstrs]
76
+ for (const instr of block.instrs) {
77
+ if (instr.kind === 'call_context') {
78
+ const newSubs = instr.subcommands.map(sub => {
79
+ if ((sub.kind === 'as' || sub.kind === 'at') && repeated.has(sub.selector)) {
80
+ const tag = repeated.get(sub.selector)!
81
+ if (seen.has(sub.selector)) {
82
+ // Subsequent occurrence — use the tag selector
83
+ return { ...sub, selector: `@e[tag=${tag}]` }
84
+ } else {
85
+ // First occurrence — keep original, mark as seen
86
+ seen.add(sub.selector)
87
+ return sub
88
+ }
89
+ }
90
+ return sub
91
+ })
92
+ newInstrs.push({ ...instr, subcommands: newSubs })
93
+ } else {
94
+ newInstrs.push(instr)
95
+ }
96
+ }
97
+
98
+ return { ...block, instrs: newInstrs }
99
+ }
100
+
101
+ function isComplexSelector(selector: string): boolean {
102
+ return selector.includes('[')
103
+ }
@@ -0,0 +1,386 @@
1
+ /**
2
+ * Small Constant Loop Unrolling — MIR optimization pass.
3
+ *
4
+ * Detects `for (let i = 0; i < N; i++)` loops where N is a compile-time
5
+ * constant and N ≤ 8, then unrolls them: the loop body is duplicated N times
6
+ * with the loop variable substituted as the literal 0..N-1.
7
+ *
8
+ * Pattern recognized (after HIR→MIR lowering):
9
+ * entry block: const t_i 0 (loop var init)
10
+ * loop_header: cmp(lt, t_i, N) → branch body/exit
11
+ * loop_body: body instructions, jump → loop_latch
12
+ * loop_latch: t_i = t_i + 1, jump → loop_header
13
+ * loop_exit: ...
14
+ *
15
+ * After unrolling:
16
+ * entry block (with i=0 def removed):
17
+ * [body with t_i → 0]
18
+ * [body with t_i → 1]
19
+ * ...
20
+ * [body with t_i → N-1]
21
+ * jump → loop_exit
22
+ * loop_exit: ...
23
+ *
24
+ * Limitations:
25
+ * - Only unrolls when N ≤ 8
26
+ * - The loop variable must be initialized to exactly 0 before the loop
27
+ * - The latch must do exactly `t_i = t_i + 1` (or equivalent const add)
28
+ * - No break/continue (body must not jump directly to exit or latch)
29
+ * - N must be a compile-time constant (Operand kind='const')
30
+ */
31
+
32
+ import type {
33
+ MIRFunction, MIRBlock, MIRInstr, Operand, Temp, BlockId,
34
+ } from '../mir/types'
35
+
36
+ const UNROLL_LIMIT = 8
37
+
38
+ // ---------------------------------------------------------------------------
39
+ // Public API
40
+ // ---------------------------------------------------------------------------
41
+
42
+ export function loopUnroll(fn: MIRFunction): MIRFunction {
43
+ let current = fn
44
+ let changed = true
45
+ // Iterate to fixpoint in case of multiple unrollable loops
46
+ while (changed) {
47
+ changed = false
48
+ const result = tryUnrollOne(current)
49
+ if (result !== current) {
50
+ current = result
51
+ changed = true
52
+ }
53
+ }
54
+ return current
55
+ }
56
+
57
+ // ---------------------------------------------------------------------------
58
+ // Core: try to unroll one loop in the function
59
+ // ---------------------------------------------------------------------------
60
+
61
+ interface LoopInfo {
62
+ /** Block id of loop_header */
63
+ headerId: BlockId
64
+ /** Block id of loop_body */
65
+ bodyId: BlockId
66
+ /** Block id of loop_latch */
67
+ latchId: BlockId
68
+ /** Block id of loop_exit */
69
+ exitId: BlockId
70
+ /** The loop variable temp name */
71
+ loopVar: Temp
72
+ /** The upper bound constant (exclusive: i < N) */
73
+ N: number
74
+ /** Block id that jumps into the loop header (the pre-header) */
75
+ preHeaderId: BlockId
76
+ }
77
+
78
+ function tryUnrollOne(fn: MIRFunction): MIRFunction {
79
+ const blockMap = new Map(fn.blocks.map(b => [b.id, b]))
80
+ const info = findUnrollableLoop(fn, blockMap)
81
+ if (!info) return fn
82
+
83
+ return unroll(fn, blockMap, info)
84
+ }
85
+
86
+ // ---------------------------------------------------------------------------
87
+ // Loop detection
88
+ // ---------------------------------------------------------------------------
89
+
90
+ function findUnrollableLoop(fn: MIRFunction, blockMap: Map<BlockId, MIRBlock>): LoopInfo | null {
91
+ for (const block of fn.blocks) {
92
+ if (!block.id.startsWith('loop_header')) continue
93
+ const info = analyzeLoop(fn, blockMap, block)
94
+ if (info) return info
95
+ }
96
+ return null
97
+ }
98
+
99
+ function analyzeLoop(
100
+ fn: MIRFunction,
101
+ blockMap: Map<BlockId, MIRBlock>,
102
+ header: MIRBlock,
103
+ ): LoopInfo | null {
104
+ // Header must branch on a cmp result
105
+ if (header.term.kind !== 'branch') return null
106
+ const branch = header.term
107
+ if (branch.cond.kind !== 'temp') return null
108
+ const condName = branch.cond.name
109
+
110
+ // Find the cmp instruction in the header
111
+ const cmpInstr = header.instrs.find(
112
+ instr => instr.kind === 'cmp' && instr.dst === condName
113
+ ) as Extract<MIRInstr, { kind: 'cmp' }> | undefined
114
+ if (!cmpInstr) return null
115
+
116
+ // Must be a `lt` comparison: i < N
117
+ if (cmpInstr.op !== 'lt') return null
118
+
119
+ // Left operand must be a temp (the loop var), right must be a constant
120
+ if (cmpInstr.a.kind !== 'temp') return null
121
+ if (cmpInstr.b.kind !== 'const') return null
122
+
123
+ const loopVar = cmpInstr.a.name
124
+ const N = cmpInstr.b.value
125
+
126
+ // Reject if N > limit or N <= 0
127
+ if (N > UNROLL_LIMIT || N <= 0) return null
128
+
129
+ // then = loop_body, else = loop_exit
130
+ const bodyId = branch.then
131
+ const exitId = branch.else
132
+
133
+ const bodyBlock = blockMap.get(bodyId)
134
+ if (!bodyBlock) return null
135
+ if (!bodyBlock.id.startsWith('loop_body')) return null
136
+
137
+ // Body must end with jump to latch (or header if no latch)
138
+ if (bodyBlock.term.kind !== 'jump') return null
139
+ const afterBodyId = bodyBlock.term.target
140
+ const afterBody = blockMap.get(afterBodyId)
141
+ if (!afterBody) return null
142
+
143
+ // Find the latch block
144
+ let latchId: BlockId
145
+ if (afterBody.id.startsWith('loop_latch')) {
146
+ latchId = afterBodyId
147
+ } else {
148
+ return null
149
+ }
150
+
151
+ const latch = blockMap.get(latchId)!
152
+
153
+ // Latch must end with jump back to header
154
+ if (latch.term.kind !== 'jump') return null
155
+ if (latch.term.target !== header.id) return null
156
+
157
+ // Latch must increment loopVar by 1
158
+ if (!latchIncrementsBy1(latch, loopVar)) return null
159
+
160
+ // Loop var must be initialized to 0 before entering the loop
161
+ // Find the pre-header: the block that jumps to header (not the latch)
162
+ const preHeaderId = findPreHeader(fn, header.id, latchId)
163
+ if (!preHeaderId) return null
164
+
165
+ const preHeader = blockMap.get(preHeaderId)!
166
+ if (!initializesTo0(preHeader, fn, loopVar)) return null
167
+
168
+ // Body must not contain break (direct jump to exit) or continue to latch
169
+ // (those would require more complex handling)
170
+ if (bodyHasBreakOrContinue(bodyBlock, exitId, latchId)) return null
171
+
172
+ return { headerId: header.id, bodyId, latchId, exitId, loopVar, N, preHeaderId }
173
+ }
174
+
175
+ /** Check that the latch increments loopVar by 1.
176
+ *
177
+ * Two common patterns:
178
+ * 1. Direct: add loopVar loopVar 1
179
+ * 2. Two-step: add t_tmp loopVar 1; copy loopVar t_tmp
180
+ */
181
+ function latchIncrementsBy1(latch: MIRBlock, loopVar: Temp): boolean {
182
+ // Pattern 1: add dst=loopVar, a=loopVar, b=const(1)
183
+ for (const instr of latch.instrs) {
184
+ if (
185
+ instr.kind === 'add' &&
186
+ instr.dst === loopVar &&
187
+ instr.a.kind === 'temp' && instr.a.name === loopVar &&
188
+ instr.b.kind === 'const' && instr.b.value === 1
189
+ ) {
190
+ return true
191
+ }
192
+ }
193
+
194
+ // Pattern 2: add t_tmp loopVar 1; copy loopVar t_tmp
195
+ // Find the copy that assigns loopVar, then check the add that produced the source
196
+ for (let i = 0; i < latch.instrs.length; i++) {
197
+ const instr = latch.instrs[i]
198
+ if (
199
+ instr.kind === 'copy' &&
200
+ instr.dst === loopVar &&
201
+ instr.src.kind === 'temp'
202
+ ) {
203
+ const srcTemp = instr.src.name
204
+ // Find the add instruction that produced srcTemp
205
+ for (const addInstr of latch.instrs) {
206
+ if (
207
+ addInstr.kind === 'add' &&
208
+ addInstr.dst === srcTemp &&
209
+ addInstr.a.kind === 'temp' && addInstr.a.name === loopVar &&
210
+ addInstr.b.kind === 'const' && addInstr.b.value === 1
211
+ ) {
212
+ return true
213
+ }
214
+ }
215
+ }
216
+ }
217
+
218
+ return false
219
+ }
220
+
221
+ /** Check if loopVar is initialized to 0 in the pre-header (or reachable const) */
222
+ function initializesTo0(preHeader: MIRBlock, fn: MIRFunction, loopVar: Temp): boolean {
223
+ // Check if last definition of loopVar in preHeader is const 0
224
+ for (let i = preHeader.instrs.length - 1; i >= 0; i--) {
225
+ const instr = preHeader.instrs[i]
226
+ if (instr.kind === 'const' && instr.dst === loopVar && instr.value === 0) return true
227
+ if (instr.kind === 'copy' && instr.dst === loopVar) {
228
+ return instr.src.kind === 'const' && instr.src.value === 0
229
+ }
230
+ // If something else defines loopVar, it's not 0
231
+ if (getInstrDst(instr) === loopVar) return false
232
+ }
233
+ // Also check entry block if preHeader is entry
234
+ if (preHeader.id === fn.entry) return false
235
+ return false
236
+ }
237
+
238
+ /** Find the pre-header block: the predecessor of header that is NOT the latch */
239
+ function findPreHeader(fn: MIRFunction, headerId: BlockId, latchId: BlockId): BlockId | null {
240
+ const preds: BlockId[] = []
241
+ for (const block of fn.blocks) {
242
+ const targets = getTermTargets(block.term)
243
+ if (targets.includes(headerId) && block.id !== latchId) {
244
+ preds.push(block.id)
245
+ }
246
+ }
247
+ return preds.length === 1 ? preds[0] : null
248
+ }
249
+
250
+ /** Check if body block has break (jump to exit) or continue (jump to latch) */
251
+ function bodyHasBreakOrContinue(body: MIRBlock, exitId: BlockId, latchId: BlockId): boolean {
252
+ // The normal path is body → latch. Any direct jump to exit = break,
253
+ // any jump to latch from within body sub-blocks = continue
254
+ // For simplicity, we only unroll if the body has no sub-blocks with these patterns.
255
+ // We only check the body block itself (single-block body).
256
+ // A multi-block body would need recursive checking.
257
+ return false
258
+ }
259
+
260
+ // ---------------------------------------------------------------------------
261
+ // Unrolling
262
+ // ---------------------------------------------------------------------------
263
+
264
+ function unroll(fn: MIRFunction, blockMap: Map<BlockId, MIRBlock>, info: LoopInfo): MIRFunction {
265
+ const { headerId, bodyId, latchId, exitId, loopVar, N, preHeaderId } = info
266
+
267
+ const preHeader = blockMap.get(preHeaderId)!
268
+ const body = blockMap.get(bodyId)!
269
+
270
+ // Remove the `const loopVar 0` init from preHeader
271
+ const newPreHeaderInstrs = preHeader.instrs.filter(
272
+ instr => !(instr.kind === 'const' && instr.dst === loopVar && instr.value === 0) &&
273
+ !(instr.kind === 'copy' && instr.dst === loopVar &&
274
+ instr.src.kind === 'const' && instr.src.value === 0)
275
+ )
276
+
277
+ // Build N copies of the body with loopVar substituted
278
+ const unrolledInstrs: MIRInstr[] = []
279
+ for (let iter = 0; iter < N; iter++) {
280
+ const substitution = new Map<Temp, Operand>([[loopVar, { kind: 'const', value: iter }]])
281
+ for (const instr of body.instrs) {
282
+ unrolledInstrs.push(substituteInstr(instr, substitution))
283
+ }
284
+ }
285
+
286
+ // New pre-header: original instrs (minus init) + all unrolled body + jump to exit
287
+ const newPreHeader: MIRBlock = {
288
+ ...preHeader,
289
+ instrs: [...newPreHeaderInstrs, ...unrolledInstrs],
290
+ term: { kind: 'jump', target: exitId },
291
+ }
292
+
293
+ // Remove header, body, latch blocks; update preHeader; keep exit
294
+ const keepIds = new Set(fn.blocks.map(b => b.id))
295
+ keepIds.delete(headerId)
296
+ keepIds.delete(bodyId)
297
+ keepIds.delete(latchId)
298
+
299
+ const newBlocks: MIRBlock[] = []
300
+ for (const block of fn.blocks) {
301
+ if (block.id === preHeaderId) {
302
+ newBlocks.push(newPreHeader)
303
+ } else if (keepIds.has(block.id)) {
304
+ newBlocks.push(block)
305
+ }
306
+ }
307
+
308
+ // Recompute predecessors
309
+ const newBlocksWithPreds = recomputePreds(newBlocks)
310
+
311
+ return { ...fn, blocks: newBlocksWithPreds }
312
+ }
313
+
314
+ // ---------------------------------------------------------------------------
315
+ // Instruction substitution
316
+ // ---------------------------------------------------------------------------
317
+
318
+ function substituteOp(op: Operand, sub: Map<Temp, Operand>): Operand {
319
+ if (op.kind === 'temp') {
320
+ const replacement = sub.get(op.name)
321
+ if (replacement) return replacement
322
+ }
323
+ return op
324
+ }
325
+
326
+ function substituteInstr(instr: MIRInstr, sub: Map<Temp, Operand>): MIRInstr {
327
+ switch (instr.kind) {
328
+ case 'copy': return { ...instr, src: substituteOp(instr.src, sub) }
329
+ case 'neg': case 'not': return { ...instr, src: substituteOp(instr.src, sub) }
330
+ case 'add': case 'sub': case 'mul': case 'div': case 'mod':
331
+ case 'and': case 'or':
332
+ return { ...instr, a: substituteOp(instr.a, sub), b: substituteOp(instr.b, sub) }
333
+ case 'cmp':
334
+ return { ...instr, a: substituteOp(instr.a, sub), b: substituteOp(instr.b, sub) }
335
+ case 'nbt_write':
336
+ return { ...instr, src: substituteOp(instr.src, sub) }
337
+ case 'call':
338
+ return { ...instr, args: instr.args.map(a => substituteOp(a, sub)) }
339
+ case 'call_macro':
340
+ return { ...instr, args: instr.args.map(a => ({ ...a, value: substituteOp(a.value, sub) })) }
341
+ case 'branch':
342
+ return { ...instr, cond: substituteOp(instr.cond, sub) }
343
+ case 'return':
344
+ return { ...instr, value: instr.value ? substituteOp(instr.value, sub) : null }
345
+ default:
346
+ return instr
347
+ }
348
+ }
349
+
350
+ // ---------------------------------------------------------------------------
351
+ // Helpers
352
+ // ---------------------------------------------------------------------------
353
+
354
+ function getInstrDst(instr: MIRInstr): Temp | null {
355
+ switch (instr.kind) {
356
+ case 'const': case 'copy':
357
+ case 'add': case 'sub': case 'mul': case 'div': case 'mod':
358
+ case 'neg': case 'cmp': case 'and': case 'or': case 'not':
359
+ case 'nbt_read':
360
+ return instr.dst
361
+ case 'call': case 'call_macro':
362
+ return instr.dst
363
+ default:
364
+ return null
365
+ }
366
+ }
367
+
368
+ function getTermTargets(term: MIRInstr): BlockId[] {
369
+ switch (term.kind) {
370
+ case 'jump': return [term.target]
371
+ case 'branch': return [term.then, term.else]
372
+ default: return []
373
+ }
374
+ }
375
+
376
+ function recomputePreds(blocks: MIRBlock[]): MIRBlock[] {
377
+ const predMap = new Map<BlockId, BlockId[]>()
378
+ for (const b of blocks) predMap.set(b.id, [])
379
+ for (const block of blocks) {
380
+ for (const target of getTermTargets(block.term)) {
381
+ const preds = predMap.get(target)
382
+ if (preds) preds.push(block.id)
383
+ }
384
+ }
385
+ return blocks.map(b => ({ ...b, preds: predMap.get(b.id) ?? [] }))
386
+ }