redscript-mc 2.6.2 → 3.0.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 (636) hide show
  1. package/.github/workflows/ci.yml +11 -0
  2. package/CHANGELOG.md +18 -9
  3. package/README-benchmarks.md +48 -0
  4. package/README-vscode-test.md +251 -0
  5. package/RELEASE_NOTES.md +74 -0
  6. package/ROADMAP.md +131 -167
  7. package/benchmarks/_shared.ts +468 -0
  8. package/benchmarks/baseline.json +2816 -0
  9. package/benchmarks/baseline.md +13 -0
  10. package/benchmarks/compiler-perf.report.json +207 -0
  11. package/benchmarks/compiler-perf.ts +76 -0
  12. package/benchmarks/results.md +13 -0
  13. package/benchmarks/stdlib-complexity.report.json +2606 -0
  14. package/benchmarks/stdlib-complexity.ts +54 -0
  15. package/benchmarks/stdlib-size.md +57 -0
  16. package/benchmarks/stdlib-size.ts +91 -0
  17. package/coverage-report.md +177 -0
  18. package/dist/src/__tests__/budget.test.js +4 -0
  19. package/dist/src/__tests__/cache/cache-behavior.test.d.ts +10 -0
  20. package/dist/src/__tests__/cache/cache-behavior.test.js +425 -0
  21. package/dist/src/__tests__/cache-extra.test.d.ts +5 -0
  22. package/dist/src/__tests__/cache-extra.test.js +211 -0
  23. package/dist/src/__tests__/cli-init.test.d.ts +1 -0
  24. package/dist/src/__tests__/cli-init.test.js +97 -0
  25. package/dist/src/__tests__/cli-publish.test.d.ts +9 -0
  26. package/dist/src/__tests__/cli-publish.test.js +189 -0
  27. package/dist/src/__tests__/cli.test.js +76 -0
  28. package/dist/src/__tests__/compile-preprocess.test.d.ts +11 -0
  29. package/dist/src/__tests__/compile-preprocess.test.js +328 -0
  30. package/dist/src/__tests__/compiler/break-stmt.test.d.ts +1 -0
  31. package/dist/src/__tests__/compiler/break-stmt.test.js +58 -0
  32. package/dist/src/__tests__/compiler/const-decl.test.d.ts +1 -0
  33. package/dist/src/__tests__/compiler/const-decl.test.js +123 -0
  34. package/dist/src/__tests__/compiler/continue-stmt.test.d.ts +1 -0
  35. package/dist/src/__tests__/compiler/continue-stmt.test.js +67 -0
  36. package/dist/src/__tests__/compiler/coroutine-extended.test.d.ts +17 -0
  37. package/dist/src/__tests__/compiler/coroutine-extended.test.js +565 -0
  38. package/dist/src/__tests__/compiler/deprecated.test.d.ts +4 -0
  39. package/dist/src/__tests__/compiler/deprecated.test.js +285 -0
  40. package/dist/src/__tests__/compiler/do-while.test.d.ts +1 -0
  41. package/dist/src/__tests__/compiler/do-while.test.js +120 -0
  42. package/dist/src/__tests__/compiler/enum-payload.test.d.ts +9 -0
  43. package/dist/src/__tests__/compiler/enum-payload.test.js +272 -0
  44. package/dist/src/__tests__/compiler/interface.test.d.ts +10 -0
  45. package/dist/src/__tests__/compiler/interface.test.js +258 -0
  46. package/dist/src/__tests__/compiler/labeled-loops.test.d.ts +1 -0
  47. package/dist/src/__tests__/compiler/labeled-loops.test.js +263 -0
  48. package/dist/src/__tests__/compiler/match-string.test.d.ts +1 -0
  49. package/dist/src/__tests__/compiler/match-string.test.js +43 -0
  50. package/dist/src/__tests__/compiler/memoize.test.d.ts +1 -0
  51. package/dist/src/__tests__/compiler/memoize.test.js +113 -0
  52. package/dist/src/__tests__/compiler/method-chain.test.d.ts +5 -0
  53. package/dist/src/__tests__/compiler/method-chain.test.js +115 -0
  54. package/dist/src/__tests__/compiler/module-import.test.d.ts +12 -0
  55. package/dist/src/__tests__/compiler/module-import.test.js +261 -0
  56. package/dist/src/__tests__/compiler/option-extensions.test.d.ts +6 -0
  57. package/dist/src/__tests__/compiler/option-extensions.test.js +191 -0
  58. package/dist/src/__tests__/compiler/profile-decorator.test.d.ts +1 -0
  59. package/dist/src/__tests__/compiler/profile-decorator.test.js +69 -0
  60. package/dist/src/__tests__/compiler/string-advanced.test.d.ts +7 -0
  61. package/dist/src/__tests__/compiler/string-advanced.test.js +281 -0
  62. package/dist/src/__tests__/compiler/struct-extends.test.d.ts +1 -0
  63. package/dist/src/__tests__/compiler/struct-extends.test.js +95 -0
  64. package/dist/src/__tests__/compiler/throttle-retry.test.d.ts +1 -0
  65. package/dist/src/__tests__/compiler/throttle-retry.test.js +166 -0
  66. package/dist/src/__tests__/compiler/tuple-type.test.d.ts +10 -0
  67. package/dist/src/__tests__/compiler/tuple-type.test.js +229 -0
  68. package/dist/src/__tests__/compiler/watch-decorator.test.d.ts +1 -0
  69. package/dist/src/__tests__/compiler/watch-decorator.test.js +65 -0
  70. package/dist/src/__tests__/config/project-config.test.d.ts +1 -0
  71. package/dist/src/__tests__/config/project-config.test.js +199 -0
  72. package/dist/src/__tests__/config-decorator.test.d.ts +8 -0
  73. package/dist/src/__tests__/config-decorator.test.js +142 -0
  74. package/dist/src/__tests__/diagnostics-extra.test.d.ts +6 -0
  75. package/dist/src/__tests__/diagnostics-extra.test.js +132 -0
  76. package/dist/src/__tests__/emit/compile-branches.test.d.ts +1 -0
  77. package/dist/src/__tests__/emit/compile-branches.test.js +123 -0
  78. package/dist/src/__tests__/emit/compile-coverage.test.d.ts +25 -0
  79. package/dist/src/__tests__/emit/compile-coverage.test.js +617 -0
  80. package/dist/src/__tests__/emit/compile-extra-branches.test.d.ts +12 -0
  81. package/dist/src/__tests__/emit/compile-extra-branches.test.js +225 -0
  82. package/dist/src/__tests__/emit/compile-mocked-branches.test.d.ts +0 -0
  83. package/dist/src/__tests__/emit/compile-mocked-branches.test.js +238 -0
  84. package/dist/src/__tests__/emit/execute-chain.test.d.ts +10 -0
  85. package/dist/src/__tests__/emit/execute-chain.test.js +94 -0
  86. package/dist/src/__tests__/emit/index.test.js +2 -1
  87. package/dist/src/__tests__/emit/modules-branches.test.d.ts +1 -0
  88. package/dist/src/__tests__/emit/modules-branches.test.js +88 -0
  89. package/dist/src/__tests__/emit/modules-coverage.test.d.ts +15 -0
  90. package/dist/src/__tests__/emit/modules-coverage.test.js +221 -0
  91. package/dist/src/__tests__/emit/modules-errors.test.d.ts +12 -0
  92. package/dist/src/__tests__/emit/modules-errors.test.js +169 -0
  93. package/dist/src/__tests__/emit/modules-rewrite.test.d.ts +17 -0
  94. package/dist/src/__tests__/emit/modules-rewrite.test.js +204 -0
  95. package/dist/src/__tests__/emit/source-map.test.d.ts +1 -0
  96. package/dist/src/__tests__/emit/source-map.test.js +167 -0
  97. package/dist/src/__tests__/enum.test.js +9 -4
  98. package/dist/src/__tests__/error-recovery.test.d.ts +7 -0
  99. package/dist/src/__tests__/error-recovery.test.js +217 -0
  100. package/dist/src/__tests__/events-types-extra.test.d.ts +10 -0
  101. package/dist/src/__tests__/events-types-extra.test.js +91 -0
  102. package/dist/src/__tests__/events-types.test.d.ts +4 -0
  103. package/dist/src/__tests__/events-types.test.js +56 -0
  104. package/dist/src/__tests__/formatter.test.js +13 -5
  105. package/dist/src/__tests__/hir/lower-extra.test.d.ts +9 -0
  106. package/dist/src/__tests__/hir/lower-extra.test.js +140 -0
  107. package/dist/src/__tests__/hir/monomorphize-extra.test.d.ts +15 -0
  108. package/dist/src/__tests__/hir/monomorphize-extra.test.js +200 -0
  109. package/dist/src/__tests__/hir/monomorphize-extra2.test.d.ts +16 -0
  110. package/dist/src/__tests__/hir/monomorphize-extra2.test.js +316 -0
  111. package/dist/src/__tests__/incremental.test.js +10 -2
  112. package/dist/src/__tests__/index-extra.test.d.ts +10 -0
  113. package/dist/src/__tests__/index-extra.test.js +71 -0
  114. package/dist/src/__tests__/lexer.test.js +2 -2
  115. package/dist/src/__tests__/lint/rules.test.d.ts +5 -0
  116. package/dist/src/__tests__/lint/rules.test.js +208 -0
  117. package/dist/src/__tests__/lir/lower.test.js +29 -0
  118. package/dist/src/__tests__/lir/verify.test.js +30 -0
  119. package/dist/src/__tests__/lsp/completion.test.d.ts +7 -0
  120. package/dist/src/__tests__/lsp/completion.test.js +583 -0
  121. package/dist/src/__tests__/lsp/definition.test.d.ts +7 -0
  122. package/dist/src/__tests__/lsp/definition.test.js +454 -0
  123. package/dist/src/__tests__/lsp/diagnostics.test.d.ts +10 -0
  124. package/dist/src/__tests__/lsp/diagnostics.test.js +98 -0
  125. package/dist/src/__tests__/lsp/hover-docs.test.d.ts +10 -0
  126. package/dist/src/__tests__/lsp/hover-docs.test.js +210 -0
  127. package/dist/src/__tests__/lsp.test.js +4 -1
  128. package/dist/src/__tests__/mc-integration/item-entity-events.test.js +4 -0
  129. package/dist/src/__tests__/mc-integration/stdlib-coverage-2.test.js +4 -0
  130. package/dist/src/__tests__/mc-integration/stdlib-coverage-3.test.d.ts +13 -0
  131. package/dist/src/__tests__/mc-integration/stdlib-coverage-3.test.js +1227 -0
  132. package/dist/src/__tests__/mc-integration/stdlib-coverage-4.test.d.ts +13 -0
  133. package/dist/src/__tests__/mc-integration/stdlib-coverage-4.test.js +1509 -0
  134. package/dist/src/__tests__/mc-integration/stdlib-coverage-5.test.d.ts +14 -0
  135. package/dist/src/__tests__/mc-integration/stdlib-coverage-5.test.js +1374 -0
  136. package/dist/src/__tests__/mc-integration/stdlib-coverage-6.test.d.ts +10 -0
  137. package/dist/src/__tests__/mc-integration/stdlib-coverage-6.test.js +759 -0
  138. package/dist/src/__tests__/mc-integration/stdlib-coverage-7.test.d.ts +13 -0
  139. package/dist/src/__tests__/mc-integration/stdlib-coverage-7.test.js +855 -0
  140. package/dist/src/__tests__/mc-integration/stdlib-coverage.test.js +4 -0
  141. package/dist/src/__tests__/mc-integration/syntax-coverage.test.js +4 -0
  142. package/dist/src/__tests__/mc-validator-coverage.test.d.ts +13 -0
  143. package/dist/src/__tests__/mc-validator-coverage.test.js +296 -0
  144. package/dist/src/__tests__/mc-validator-extra.test.d.ts +13 -0
  145. package/dist/src/__tests__/mc-validator-extra.test.js +245 -0
  146. package/dist/src/__tests__/mir/lower-extra.test.d.ts +20 -0
  147. package/dist/src/__tests__/mir/lower-extra.test.js +361 -0
  148. package/dist/src/__tests__/mir/lower-extra2.test.d.ts +17 -0
  149. package/dist/src/__tests__/mir/lower-extra2.test.js +317 -0
  150. package/dist/src/__tests__/mir/lower-extra3.test.d.ts +19 -0
  151. package/dist/src/__tests__/mir/lower-extra3.test.js +249 -0
  152. package/dist/src/__tests__/mir/lower-extra4.test.d.ts +23 -0
  153. package/dist/src/__tests__/mir/lower-extra4.test.js +606 -0
  154. package/dist/src/__tests__/mir/lower-extra5.test.d.ts +25 -0
  155. package/dist/src/__tests__/mir/lower-extra5.test.js +543 -0
  156. package/dist/src/__tests__/mir/lower-extra6.test.d.ts +16 -0
  157. package/dist/src/__tests__/mir/lower-extra6.test.js +471 -0
  158. package/dist/src/__tests__/mir/lower-extra7.test.d.ts +35 -0
  159. package/dist/src/__tests__/mir/lower-extra7.test.js +921 -0
  160. package/dist/src/__tests__/mir/lower-extra8.test.d.ts +19 -0
  161. package/dist/src/__tests__/mir/lower-extra8.test.js +626 -0
  162. package/dist/src/__tests__/mir/lower-extra9.test.d.ts +14 -0
  163. package/dist/src/__tests__/mir/lower-extra9.test.js +717 -0
  164. package/dist/src/__tests__/optimizer/auto-inline.test.d.ts +1 -0
  165. package/dist/src/__tests__/optimizer/auto-inline.test.js +176 -0
  166. package/dist/src/__tests__/optimizer/cse.test.d.ts +4 -0
  167. package/dist/src/__tests__/optimizer/cse.test.js +178 -0
  168. package/dist/src/__tests__/optimizer/inline_fn.test.d.ts +1 -0
  169. package/dist/src/__tests__/optimizer/inline_fn.test.js +221 -0
  170. package/dist/src/__tests__/optimizer/licm.test.d.ts +1 -0
  171. package/dist/src/__tests__/optimizer/licm.test.js +244 -0
  172. package/dist/src/__tests__/optimizer/optimizer-extended.test.d.ts +12 -0
  173. package/dist/src/__tests__/optimizer/optimizer-extended.test.js +993 -0
  174. package/dist/src/__tests__/optimizer/strength-reduction.test.d.ts +1 -0
  175. package/dist/src/__tests__/optimizer/strength-reduction.test.js +86 -0
  176. package/dist/src/__tests__/optimizer/tco.test.d.ts +14 -0
  177. package/dist/src/__tests__/optimizer/tco.test.js +203 -0
  178. package/dist/src/__tests__/parser-coverage.test.d.ts +25 -0
  179. package/dist/src/__tests__/parser-coverage.test.js +491 -0
  180. package/dist/src/__tests__/parser-extra.test.d.ts +6 -0
  181. package/dist/src/__tests__/parser-extra.test.js +451 -0
  182. package/dist/src/__tests__/parser.test.js +12 -0
  183. package/dist/src/__tests__/repl-extra.test.d.ts +13 -0
  184. package/dist/src/__tests__/repl-extra.test.js +174 -0
  185. package/dist/src/__tests__/repl-server-extra.test.d.ts +10 -0
  186. package/dist/src/__tests__/repl-server-extra.test.js +161 -0
  187. package/dist/src/__tests__/repl-server.test.d.ts +6 -0
  188. package/dist/src/__tests__/repl-server.test.js +146 -0
  189. package/dist/src/__tests__/runtime-extra.test.d.ts +15 -0
  190. package/dist/src/__tests__/runtime-extra.test.js +732 -0
  191. package/dist/src/__tests__/singleton-decorator.test.d.ts +11 -0
  192. package/dist/src/__tests__/singleton-decorator.test.js +260 -0
  193. package/dist/src/__tests__/sourcemap.test.js +1 -1
  194. package/dist/src/__tests__/stdlib/advanced.test.d.ts +5 -0
  195. package/dist/src/__tests__/stdlib/advanced.test.js +301 -0
  196. package/dist/src/__tests__/stdlib/bigint.test.d.ts +4 -0
  197. package/dist/src/__tests__/stdlib/bigint.test.js +83 -0
  198. package/dist/src/__tests__/stdlib/bits.test.d.ts +4 -0
  199. package/dist/src/__tests__/stdlib/bits.test.js +96 -0
  200. package/dist/src/__tests__/stdlib/bossbar.test.d.ts +4 -0
  201. package/dist/src/__tests__/stdlib/bossbar.test.js +72 -0
  202. package/dist/src/__tests__/stdlib/color.test.d.ts +4 -0
  203. package/dist/src/__tests__/stdlib/color.test.js +84 -0
  204. package/dist/src/__tests__/stdlib/combat.test.d.ts +4 -0
  205. package/dist/src/__tests__/stdlib/combat.test.js +64 -0
  206. package/dist/src/__tests__/stdlib/cooldown.test.d.ts +4 -0
  207. package/dist/src/__tests__/stdlib/cooldown.test.js +64 -0
  208. package/dist/src/__tests__/stdlib/dialog.test.js +15 -7
  209. package/dist/src/__tests__/stdlib/ecs.test.d.ts +4 -0
  210. package/dist/src/__tests__/stdlib/ecs.test.js +81 -0
  211. package/dist/src/__tests__/stdlib/effects.test.d.ts +4 -0
  212. package/dist/src/__tests__/stdlib/effects.test.js +72 -0
  213. package/dist/src/__tests__/stdlib/events.test.d.ts +4 -0
  214. package/dist/src/__tests__/stdlib/events.test.js +55 -0
  215. package/dist/src/__tests__/stdlib/expr.test.d.ts +4 -0
  216. package/dist/src/__tests__/stdlib/expr.test.js +77 -0
  217. package/dist/src/__tests__/stdlib/fft.test.d.ts +4 -0
  218. package/dist/src/__tests__/stdlib/fft.test.js +82 -0
  219. package/dist/src/__tests__/stdlib/graph.test.d.ts +4 -0
  220. package/dist/src/__tests__/stdlib/graph.test.js +102 -0
  221. package/dist/src/__tests__/stdlib/interactions.test.d.ts +4 -0
  222. package/dist/src/__tests__/stdlib/interactions.test.js +60 -0
  223. package/dist/src/__tests__/stdlib/inventory.test.d.ts +4 -0
  224. package/dist/src/__tests__/stdlib/inventory.test.js +68 -0
  225. package/dist/src/__tests__/stdlib/linalg.test.d.ts +5 -0
  226. package/dist/src/__tests__/stdlib/linalg.test.js +78 -0
  227. package/dist/src/__tests__/stdlib/map.test.d.ts +1 -0
  228. package/dist/src/__tests__/stdlib/map.test.js +84 -0
  229. package/dist/src/__tests__/stdlib/math.test.js +19 -6
  230. package/dist/src/__tests__/stdlib/math_hp.test.d.ts +4 -0
  231. package/dist/src/__tests__/stdlib/math_hp.test.js +80 -0
  232. package/dist/src/__tests__/stdlib/mobs.test.d.ts +4 -0
  233. package/dist/src/__tests__/stdlib/mobs.test.js +61 -0
  234. package/dist/src/__tests__/stdlib/noise.test.d.ts +4 -0
  235. package/dist/src/__tests__/stdlib/noise.test.js +73 -0
  236. package/dist/src/__tests__/stdlib/ode.test.d.ts +4 -0
  237. package/dist/src/__tests__/stdlib/ode.test.js +68 -0
  238. package/dist/src/__tests__/stdlib/parabola.test.d.ts +4 -0
  239. package/dist/src/__tests__/stdlib/parabola.test.js +77 -0
  240. package/dist/src/__tests__/stdlib/particles.test.d.ts +4 -0
  241. package/dist/src/__tests__/stdlib/particles.test.js +68 -0
  242. package/dist/src/__tests__/stdlib/physics.test.d.ts +4 -0
  243. package/dist/src/__tests__/stdlib/physics.test.js +76 -0
  244. package/dist/src/__tests__/stdlib/player.test.d.ts +4 -0
  245. package/dist/src/__tests__/stdlib/player.test.js +64 -0
  246. package/dist/src/__tests__/stdlib/quaternion.test.d.ts +4 -0
  247. package/dist/src/__tests__/stdlib/quaternion.test.js +73 -0
  248. package/dist/src/__tests__/stdlib/queue.test.d.ts +1 -0
  249. package/dist/src/__tests__/stdlib/queue.test.js +97 -0
  250. package/dist/src/__tests__/stdlib/random.test.d.ts +4 -0
  251. package/dist/src/__tests__/stdlib/random.test.js +76 -0
  252. package/dist/src/__tests__/stdlib/result.test.d.ts +12 -0
  253. package/dist/src/__tests__/stdlib/result.test.js +329 -0
  254. package/dist/src/__tests__/stdlib/scheduler.test.js +19 -8
  255. package/dist/src/__tests__/stdlib/set_int.test.d.ts +1 -0
  256. package/dist/src/__tests__/stdlib/set_int.test.js +88 -0
  257. package/dist/src/__tests__/stdlib/sets.test.d.ts +6 -0
  258. package/dist/src/__tests__/stdlib/sets.test.js +60 -0
  259. package/dist/src/__tests__/stdlib/signal.test.d.ts +4 -0
  260. package/dist/src/__tests__/stdlib/signal.test.js +84 -0
  261. package/dist/src/__tests__/stdlib/spawn.test.d.ts +4 -0
  262. package/dist/src/__tests__/stdlib/spawn.test.js +68 -0
  263. package/dist/src/__tests__/stdlib/string.test.d.ts +12 -0
  264. package/dist/src/__tests__/stdlib/string.test.js +231 -0
  265. package/dist/src/__tests__/stdlib/strings.test.d.ts +4 -0
  266. package/dist/src/__tests__/stdlib/strings.test.js +83 -0
  267. package/dist/src/__tests__/stdlib/tags.test.d.ts +4 -0
  268. package/dist/src/__tests__/stdlib/tags.test.js +57 -0
  269. package/dist/src/__tests__/stdlib/teams.test.d.ts +4 -0
  270. package/dist/src/__tests__/stdlib/teams.test.js +72 -0
  271. package/dist/src/__tests__/stdlib/timer.test.d.ts +4 -0
  272. package/dist/src/__tests__/stdlib/timer.test.js +79 -0
  273. package/dist/src/__tests__/stdlib/vec.test.d.ts +5 -0
  274. package/dist/src/__tests__/stdlib/vec.test.js +94 -0
  275. package/dist/src/__tests__/stdlib/world.test.d.ts +4 -0
  276. package/dist/src/__tests__/stdlib/world.test.js +72 -0
  277. package/dist/src/__tests__/struct-display.test.d.ts +1 -0
  278. package/dist/src/__tests__/struct-display.test.js +64 -0
  279. package/dist/src/__tests__/test-framework/runner.test.d.ts +10 -0
  280. package/dist/src/__tests__/test-framework/runner.test.js +193 -0
  281. package/dist/src/__tests__/tuner/adapters.test.d.ts +14 -0
  282. package/dist/src/__tests__/tuner/adapters.test.js +194 -0
  283. package/dist/src/__tests__/tuner/simulator-extra.test.d.ts +4 -0
  284. package/dist/src/__tests__/tuner/simulator-extra.test.js +193 -0
  285. package/dist/src/__tests__/typechecker-coverage.test.d.ts +30 -0
  286. package/dist/src/__tests__/typechecker-coverage.test.js +627 -0
  287. package/dist/src/__tests__/typechecker.test.js +3 -3
  288. package/dist/src/__tests__/watch-decorator.test.d.ts +1 -0
  289. package/dist/src/__tests__/watch-decorator.test.js +54 -0
  290. package/dist/src/ast/types.d.ts +102 -3
  291. package/dist/src/cache/incremental.d.ts +13 -14
  292. package/dist/src/cache/incremental.js +106 -89
  293. package/dist/src/cache/index.d.ts +8 -2
  294. package/dist/src/cache/index.js +18 -6
  295. package/dist/src/cli.d.ts +1 -0
  296. package/dist/src/cli.js +466 -17
  297. package/dist/src/config/project-config.d.ts +29 -0
  298. package/dist/src/config/project-config.js +180 -0
  299. package/dist/src/diagnostics/index.d.ts +9 -0
  300. package/dist/src/diagnostics/index.js +18 -1
  301. package/dist/src/emit/compile.d.ts +10 -0
  302. package/dist/src/emit/compile.js +395 -50
  303. package/dist/src/emit/index.d.ts +40 -0
  304. package/dist/src/emit/index.js +307 -14
  305. package/dist/src/emit/modules.js +21 -3
  306. package/dist/src/emit/sourcemap.d.ts +23 -27
  307. package/dist/src/emit/sourcemap.js +52 -30
  308. package/dist/src/formatter/index.js +33 -8
  309. package/dist/src/hir/deprecated.d.ts +13 -0
  310. package/dist/src/hir/deprecated.js +218 -0
  311. package/dist/src/hir/lower.js +114 -8
  312. package/dist/src/hir/monomorphize.js +22 -2
  313. package/dist/src/hir/types.d.ts +65 -1
  314. package/dist/src/index.d.ts +6 -0
  315. package/dist/src/index.js +18 -3
  316. package/dist/src/lexer/index.d.ts +2 -1
  317. package/dist/src/lexer/index.js +39 -3
  318. package/dist/src/lint/index.d.ts +45 -0
  319. package/dist/src/lint/index.js +930 -0
  320. package/dist/src/lir/lower.js +29 -2
  321. package/dist/src/lir/types.d.ts +2 -0
  322. package/dist/src/lsp/server.js +92 -5
  323. package/dist/src/mir/lower.js +775 -34
  324. package/dist/src/mir/macro.js +36 -2
  325. package/dist/src/mir/types.d.ts +12 -0
  326. package/dist/src/mir/verify.js +9 -0
  327. package/dist/src/optimizer/auto-inline.d.ts +2 -0
  328. package/dist/src/optimizer/auto-inline.js +67 -0
  329. package/dist/src/optimizer/cse.d.ts +20 -0
  330. package/dist/src/optimizer/cse.js +234 -0
  331. package/dist/src/optimizer/inline.d.ts +26 -0
  332. package/dist/src/optimizer/inline.js +286 -0
  333. package/dist/src/optimizer/interprocedural.js +4 -0
  334. package/dist/src/optimizer/licm.d.ts +32 -0
  335. package/dist/src/optimizer/licm.js +371 -0
  336. package/dist/src/optimizer/pipeline.js +12 -2
  337. package/dist/src/optimizer/strength_reduction.d.ts +15 -0
  338. package/dist/src/optimizer/strength_reduction.js +90 -0
  339. package/dist/src/optimizer/tco.d.ts +53 -0
  340. package/dist/src/optimizer/tco.js +238 -0
  341. package/dist/src/parser/index.d.ts +32 -0
  342. package/dist/src/parser/index.js +421 -59
  343. package/dist/src/repl-server.d.ts +13 -0
  344. package/dist/src/repl-server.js +127 -0
  345. package/dist/src/structs/expand.d.ts +15 -0
  346. package/dist/src/structs/expand.js +46 -0
  347. package/dist/src/testing/runner.d.ts +40 -0
  348. package/dist/src/testing/runner.js +237 -0
  349. package/dist/src/typechecker/index.d.ts +3 -0
  350. package/dist/src/typechecker/index.js +254 -9
  351. package/dist/tsconfig.tsbuildinfo +1 -1
  352. package/doc-drafts/redscript-docs/docs/en/stdlib/graph.md +104 -0
  353. package/doc-drafts/redscript-docs/docs/en/stdlib/parabola.md +113 -0
  354. package/doc-drafts/redscript-docs/docs/en/stdlib/pathfind.md +104 -0
  355. package/doc-drafts/redscript-docs/docs/en/stdlib/physics.md +134 -0
  356. package/doc-drafts/redscript-docs/docs/en/stdlib/quaternion.md +135 -0
  357. package/doc-drafts/redscript-docs/docs/zh/stdlib/graph.md +104 -0
  358. package/doc-drafts/redscript-docs/docs/zh/stdlib/parabola.md +113 -0
  359. package/doc-drafts/redscript-docs/docs/zh/stdlib/pathfind.md +104 -0
  360. package/doc-drafts/redscript-docs/docs/zh/stdlib/physics.md +134 -0
  361. package/doc-drafts/redscript-docs/docs/zh/stdlib/quaternion.md +135 -0
  362. package/docs/stdlib/result.md +156 -0
  363. package/docs/stdlib/result.zh.md +156 -0
  364. package/editors/vscode/fixtures/test.mcrs +7 -0
  365. package/editors/vscode/out/extension.js +2095 -225
  366. package/editors/vscode/out/lsp-server.js +519 -51
  367. package/editors/vscode/package-lock.json +9 -4
  368. package/editors/vscode/package.json +1 -1
  369. package/examples/display-demo.mcrs +64 -0
  370. package/examples/game/racing.mcrs +301 -0
  371. package/examples/game/tower_defense.mcrs +311 -0
  372. package/examples/math/physics_sim.mcrs +322 -0
  373. package/examples/rpg/boss_fight.mcrs +313 -0
  374. package/examples/rpg/health_system.mcrs +237 -0
  375. package/examples/rpg/inventory.mcrs +265 -0
  376. package/examples/util/debug_hud.mcrs +279 -0
  377. package/jest.config.js +10 -0
  378. package/package.json +12 -3
  379. package/playground/index.html +823 -0
  380. package/scripts/gen-docs.ts +533 -0
  381. package/scripts/update-redscript-docs-stdlib.sh +770 -0
  382. package/src/__tests__/budget.test.ts +5 -0
  383. package/src/__tests__/cache/cache-behavior.test.ts +480 -0
  384. package/src/__tests__/cache-extra.test.ts +199 -0
  385. package/src/__tests__/cli-docs.test.ts +77 -0
  386. package/src/__tests__/cli-init.test.ts +91 -0
  387. package/src/__tests__/cli-publish.test.ts +190 -0
  388. package/src/__tests__/cli.test.ts +117 -1
  389. package/src/__tests__/compile-preprocess.test.ts +366 -0
  390. package/src/__tests__/compiler/break-stmt.test.ts +66 -0
  391. package/src/__tests__/compiler/const-decl.test.ts +141 -0
  392. package/src/__tests__/compiler/continue-stmt.test.ts +81 -0
  393. package/src/__tests__/compiler/coroutine-extended.test.ts +723 -0
  394. package/src/__tests__/compiler/deprecated.test.ts +305 -0
  395. package/src/__tests__/compiler/do-while.test.ts +130 -0
  396. package/src/__tests__/compiler/enum-payload.test.ts +299 -0
  397. package/src/__tests__/compiler/interface.test.ts +287 -0
  398. package/src/__tests__/compiler/labeled-loops.test.ts +279 -0
  399. package/src/__tests__/compiler/match-string.test.ts +45 -0
  400. package/src/__tests__/compiler/memoize.test.ts +126 -0
  401. package/src/__tests__/compiler/method-chain.test.ts +121 -0
  402. package/src/__tests__/compiler/module-import.test.ts +240 -0
  403. package/src/__tests__/compiler/option-extensions.test.ts +207 -0
  404. package/src/__tests__/compiler/profile-decorator.test.ts +79 -0
  405. package/src/__tests__/compiler/string-advanced.test.ts +310 -0
  406. package/src/__tests__/compiler/struct-extends.test.ts +109 -0
  407. package/src/__tests__/compiler/throttle-retry.test.ts +191 -0
  408. package/src/__tests__/compiler/tuple-type.test.ts +263 -0
  409. package/src/__tests__/compiler/watch-decorator.test.ts +72 -0
  410. package/src/__tests__/config/project-config.test.ts +181 -0
  411. package/src/__tests__/config-decorator.test.ts +157 -0
  412. package/src/__tests__/diagnostics-extra.test.ts +155 -0
  413. package/src/__tests__/emit/compile-branches.test.ts +135 -0
  414. package/src/__tests__/emit/compile-coverage.test.ts +696 -0
  415. package/src/__tests__/emit/compile-extra-branches.test.ts +228 -0
  416. package/src/__tests__/emit/compile-mocked-branches.test.ts +249 -0
  417. package/src/__tests__/emit/compile.test.ts +6 -1
  418. package/src/__tests__/emit/execute-chain.test.ts +114 -0
  419. package/src/__tests__/emit/index.test.ts +2 -1
  420. package/src/__tests__/emit/modules-branches.test.ts +90 -0
  421. package/src/__tests__/emit/modules-coverage.test.ts +241 -0
  422. package/src/__tests__/emit/modules-errors.test.ts +192 -0
  423. package/src/__tests__/emit/modules-rewrite.test.ts +232 -0
  424. package/src/__tests__/emit/source-map.test.ts +152 -0
  425. package/src/__tests__/enum.test.ts +9 -4
  426. package/src/__tests__/error-recovery.test.ts +226 -0
  427. package/src/__tests__/events-types-extra.test.ts +110 -0
  428. package/src/__tests__/events-types.test.ts +66 -0
  429. package/src/__tests__/formatter.test.ts +15 -5
  430. package/src/__tests__/generics.test.ts +16 -9
  431. package/src/__tests__/hir/lower-extra.test.ts +151 -0
  432. package/src/__tests__/hir/monomorphize-coverage.test.ts +432 -0
  433. package/src/__tests__/hir/monomorphize-extra.test.ts +220 -0
  434. package/src/__tests__/hir/monomorphize-extra2.test.ts +350 -0
  435. package/src/__tests__/impl.test.ts +12 -8
  436. package/src/__tests__/incremental.test.ts +10 -2
  437. package/src/__tests__/index-extra.test.ts +79 -0
  438. package/src/__tests__/lexer.test.ts +2 -2
  439. package/src/__tests__/lint/hir-coverage.test.ts +1716 -0
  440. package/src/__tests__/lint/rules-coverage.test.ts +598 -0
  441. package/src/__tests__/lint/rules.test.ts +230 -0
  442. package/src/__tests__/lir/lower.test.ts +33 -0
  443. package/src/__tests__/lir/verify.test.ts +33 -0
  444. package/src/__tests__/lsp/completion.test.ts +687 -0
  445. package/src/__tests__/lsp/definition.test.ts +499 -0
  446. package/src/__tests__/lsp/diagnostics.test.ts +108 -0
  447. package/src/__tests__/lsp/hover-docs.test.ts +222 -0
  448. package/src/__tests__/lsp.test.ts +4 -1
  449. package/src/__tests__/mc-integration/item-entity-events.test.ts +5 -0
  450. package/src/__tests__/mc-integration/stdlib-coverage-2.test.ts +5 -0
  451. package/src/__tests__/mc-integration/stdlib-coverage-3.test.ts +1105 -0
  452. package/src/__tests__/mc-integration/stdlib-coverage-4.test.ts +1366 -0
  453. package/src/__tests__/mc-integration/stdlib-coverage-5.test.ts +1245 -0
  454. package/src/__tests__/mc-integration/stdlib-coverage-6.test.ts +755 -0
  455. package/src/__tests__/mc-integration/stdlib-coverage-7.test.ts +771 -0
  456. package/src/__tests__/mc-integration/stdlib-coverage.test.ts +5 -0
  457. package/src/__tests__/mc-integration/syntax-coverage.test.ts +5 -0
  458. package/src/__tests__/mc-validator-coverage.test.ts +325 -0
  459. package/src/__tests__/mc-validator-extra.test.ts +252 -0
  460. package/src/__tests__/mir/lower-extra.test.ts +402 -0
  461. package/src/__tests__/mir/lower-extra2.test.ts +348 -0
  462. package/src/__tests__/mir/lower-extra3.test.ts +277 -0
  463. package/src/__tests__/mir/lower-extra4.test.ts +636 -0
  464. package/src/__tests__/mir/lower-extra5.test.ts +612 -0
  465. package/src/__tests__/mir/lower-extra6.test.ts +520 -0
  466. package/src/__tests__/mir/lower-extra7.test.ts +1045 -0
  467. package/src/__tests__/mir/lower-extra8.test.ts +704 -0
  468. package/src/__tests__/mir/lower-extra9.test.ts +821 -0
  469. package/src/__tests__/optimizer/auto-inline.test.ts +206 -0
  470. package/src/__tests__/optimizer/cse.test.ts +195 -0
  471. package/src/__tests__/optimizer/inline_fn.test.ts +263 -0
  472. package/src/__tests__/optimizer/licm.test.ts +358 -0
  473. package/src/__tests__/optimizer/nbt-coalesce.test.ts +147 -0
  474. package/src/__tests__/optimizer/optimizer-extended.test.ts +1081 -0
  475. package/src/__tests__/optimizer/scoreboard-batch.test.ts +141 -0
  476. package/src/__tests__/optimizer/strength-reduction.test.ts +111 -0
  477. package/src/__tests__/optimizer/tco-coverage.test.ts +309 -0
  478. package/src/__tests__/optimizer/tco.test.ts +238 -0
  479. package/src/__tests__/option.test.ts +14 -7
  480. package/src/__tests__/parser-coverage.test.ts +576 -0
  481. package/src/__tests__/parser-extra.test.ts +531 -0
  482. package/src/__tests__/parser.test.ts +14 -0
  483. package/src/__tests__/repl-extra.test.ts +195 -0
  484. package/src/__tests__/repl-server-extra.test.ts +150 -0
  485. package/src/__tests__/repl-server.test.ts +122 -0
  486. package/src/__tests__/runtime-extra.test.ts +862 -0
  487. package/src/__tests__/singleton-decorator.test.ts +285 -0
  488. package/src/__tests__/sourcemap.test.ts +1 -1
  489. package/src/__tests__/stdlib/advanced.test.ts +312 -0
  490. package/src/__tests__/stdlib/bigint.test.ts +57 -0
  491. package/src/__tests__/stdlib/bits.test.ts +75 -0
  492. package/src/__tests__/stdlib/bossbar.test.ts +45 -0
  493. package/src/__tests__/stdlib/color.test.ts +60 -0
  494. package/src/__tests__/stdlib/combat.test.ts +35 -0
  495. package/src/__tests__/stdlib/cooldown.test.ts +35 -0
  496. package/src/__tests__/stdlib/dialog.test.ts +14 -6
  497. package/src/__tests__/stdlib/ecs.test.ts +54 -0
  498. package/src/__tests__/stdlib/effects.test.ts +45 -0
  499. package/src/__tests__/stdlib/events.test.ts +23 -0
  500. package/src/__tests__/stdlib/expr.test.ts +48 -0
  501. package/src/__tests__/stdlib/fft.test.ts +54 -0
  502. package/src/__tests__/stdlib/graph.test.ts +77 -0
  503. package/src/__tests__/stdlib/interactions.test.ts +30 -0
  504. package/src/__tests__/stdlib/inventory.test.ts +40 -0
  505. package/src/__tests__/stdlib/linalg.test.ts +52 -0
  506. package/src/__tests__/stdlib/map.test.ts +55 -0
  507. package/src/__tests__/stdlib/math.test.ts +19 -5
  508. package/src/__tests__/stdlib/math_hp.test.ts +55 -0
  509. package/src/__tests__/stdlib/mobs.test.ts +40 -0
  510. package/src/__tests__/stdlib/noise.test.ts +46 -0
  511. package/src/__tests__/stdlib/ode.test.ts +40 -0
  512. package/src/__tests__/stdlib/parabola.test.ts +51 -0
  513. package/src/__tests__/stdlib/particles.test.ts +40 -0
  514. package/src/__tests__/stdlib/physics.test.ts +50 -0
  515. package/src/__tests__/stdlib/player.test.ts +35 -0
  516. package/src/__tests__/stdlib/quaternion.test.ts +46 -0
  517. package/src/__tests__/stdlib/queue.test.ts +73 -0
  518. package/src/__tests__/stdlib/random.test.ts +50 -0
  519. package/src/__tests__/stdlib/result.test.ts +326 -0
  520. package/src/__tests__/stdlib/scheduler.test.ts +18 -7
  521. package/src/__tests__/stdlib/set_int.test.ts +62 -0
  522. package/src/__tests__/stdlib/sets.test.ts +28 -0
  523. package/src/__tests__/stdlib/signal.test.ts +60 -0
  524. package/src/__tests__/stdlib/spawn.test.ts +40 -0
  525. package/src/__tests__/stdlib/string.test.ts +224 -0
  526. package/src/__tests__/stdlib/strings.test.ts +55 -0
  527. package/src/__tests__/stdlib/tags.test.ts +32 -0
  528. package/src/__tests__/stdlib/teams.test.ts +45 -0
  529. package/src/__tests__/stdlib/timer.test.ts +53 -0
  530. package/src/__tests__/stdlib/vec.test.ts +72 -0
  531. package/src/__tests__/stdlib/world.test.ts +45 -0
  532. package/src/__tests__/struct-display.test.ts +69 -0
  533. package/src/__tests__/test-framework/runner.test.ts +208 -0
  534. package/src/__tests__/tuner/adapters.test.ts +232 -0
  535. package/src/__tests__/tuner/simulator-extra.test.ts +222 -0
  536. package/src/__tests__/tuple.test.ts +11 -4
  537. package/src/__tests__/typechecker-coverage.test.ts +671 -0
  538. package/src/__tests__/typechecker.test.ts +4 -3
  539. package/src/__tests__/watch-decorator.test.ts +59 -0
  540. package/src/ast/types.ts +65 -3
  541. package/src/cache/incremental.ts +128 -99
  542. package/src/cache/index.ts +35 -8
  543. package/src/cli.ts +538 -29
  544. package/src/config/project-config.ts +176 -0
  545. package/src/diagnostics/index.ts +22 -0
  546. package/src/docs.ts +98 -0
  547. package/src/emit/compile.ts +408 -51
  548. package/src/emit/index.ts +366 -18
  549. package/src/emit/modules.ts +19 -3
  550. package/src/emit/sourcemap.ts +64 -43
  551. package/src/formatter/index.ts +35 -8
  552. package/src/hir/deprecated.ts +212 -0
  553. package/src/hir/lower.ts +128 -8
  554. package/src/hir/monomorphize.ts +24 -2
  555. package/src/hir/types.ts +26 -1
  556. package/src/index.ts +23 -3
  557. package/src/lexer/index.ts +45 -6
  558. package/src/lint/index.ts +922 -0
  559. package/src/lir/lower.ts +30 -2
  560. package/src/lir/types.ts +4 -0
  561. package/src/lsp/server.ts +100 -1
  562. package/src/mir/lower.ts +785 -40
  563. package/src/mir/macro.ts +30 -2
  564. package/src/mir/types.ts +13 -0
  565. package/src/mir/verify.ts +10 -2
  566. package/src/optimizer/auto-inline.ts +86 -0
  567. package/src/optimizer/copy_prop.ts +2 -2
  568. package/src/optimizer/coroutine.ts +3 -3
  569. package/src/optimizer/cse.ts +205 -0
  570. package/src/optimizer/dce.ts +2 -2
  571. package/src/optimizer/inline.ts +335 -0
  572. package/src/optimizer/interprocedural.ts +5 -1
  573. package/src/optimizer/licm.ts +454 -0
  574. package/src/optimizer/nbt-coalesce.ts +109 -0
  575. package/src/optimizer/pipeline.ts +16 -2
  576. package/src/optimizer/scoreboard-batch.ts +52 -0
  577. package/src/optimizer/strength_reduction.ts +95 -0
  578. package/src/optimizer/tco.ts +267 -0
  579. package/src/optimizer/unroll.ts +2 -2
  580. package/src/parser/index.ts +426 -53
  581. package/src/repl-server.ts +102 -0
  582. package/src/stdlib/advanced.mcrs +271 -101
  583. package/src/stdlib/bigint.mcrs +97 -11
  584. package/src/stdlib/bits.mcrs +75 -12
  585. package/src/stdlib/bossbar.mcrs +37 -8
  586. package/src/stdlib/calculus.mcrs +82 -26
  587. package/src/stdlib/color.mcrs +98 -16
  588. package/src/stdlib/combat.mcrs +23 -5
  589. package/src/stdlib/cooldown.mcrs +19 -0
  590. package/src/stdlib/dialog.mcrs +45 -7
  591. package/src/stdlib/easing.mcrs +132 -12
  592. package/src/stdlib/ecs.mcrs +142 -25
  593. package/src/stdlib/effects.mcrs +88 -12
  594. package/src/stdlib/events.mcrs +21 -2
  595. package/src/stdlib/expr.mcrs +18 -3
  596. package/src/stdlib/fft.mcrs +66 -56
  597. package/src/stdlib/geometry.mcrs +137 -39
  598. package/src/stdlib/graph.mcrs +73 -0
  599. package/src/stdlib/heap.mcrs +49 -8
  600. package/src/stdlib/i18n/zh.yaml +2891 -0
  601. package/src/stdlib/interactions.mcrs +43 -20
  602. package/src/stdlib/inventory.mcrs +14 -3
  603. package/src/stdlib/linalg.mcrs +185 -30
  604. package/src/stdlib/list.mcrs +168 -18
  605. package/src/stdlib/map.mcrs +112 -0
  606. package/src/stdlib/math.mcrs +68 -18
  607. package/src/stdlib/math_hp.mcrs +124 -33
  608. package/src/stdlib/matrix.mcrs +133 -20
  609. package/src/stdlib/mobs.mcrs +87 -0
  610. package/src/stdlib/noise.mcrs +65 -21
  611. package/src/stdlib/ode.mcrs +96 -0
  612. package/src/stdlib/parabola.mcrs +104 -29
  613. package/src/stdlib/particles.mcrs +78 -21
  614. package/src/stdlib/pathfind.mcrs +89 -35
  615. package/src/stdlib/physics.mcrs +134 -26
  616. package/src/stdlib/player.mcrs +18 -0
  617. package/src/stdlib/quaternion.mcrs +213 -9
  618. package/src/stdlib/queue.mcrs +123 -0
  619. package/src/stdlib/random.mcrs +63 -18
  620. package/src/stdlib/result.mcrs +111 -0
  621. package/src/stdlib/scheduler.mcrs +59 -10
  622. package/src/stdlib/set_int.mcrs +240 -0
  623. package/src/stdlib/sets.mcrs +49 -19
  624. package/src/stdlib/signal.mcrs +151 -79
  625. package/src/stdlib/sort.mcrs +44 -24
  626. package/src/stdlib/spawn.mcrs +30 -7
  627. package/src/stdlib/state.mcrs +40 -5
  628. package/src/stdlib/strings.mcrs +131 -3
  629. package/src/stdlib/tags.mcrs +2 -2
  630. package/src/stdlib/teams.mcrs +22 -10
  631. package/src/stdlib/timer.mcrs +36 -6
  632. package/src/stdlib/vec.mcrs +44 -9
  633. package/src/stdlib/world.mcrs +57 -25
  634. package/src/structs/expand.ts +64 -0
  635. package/src/testing/runner.ts +271 -0
  636. package/src/typechecker/index.ts +273 -9
package/src/emit/index.ts CHANGED
@@ -6,7 +6,13 @@
6
6
  */
7
7
 
8
8
  import type { LIRModule, LIRFunction, LIRInstr, Slot, CmpOp, ExecuteSubcmd } from '../lir/types'
9
- import { SourceMapBuilder, serializeSourceMap, sourceMapPath } from './sourcemap'
9
+ import {
10
+ NamespaceSourceMapBuilder,
11
+ SourceMapBuilder,
12
+ namespaceSourceMapPath,
13
+ serializeSourceMap,
14
+ sourceMapPath,
15
+ } from './sourcemap'
10
16
  import { McVersion, DEFAULT_MC_VERSION } from '../types/mc-version'
11
17
 
12
18
  export interface DatapackFile {
@@ -14,17 +20,35 @@ export interface DatapackFile {
14
20
  content: string
15
21
  }
16
22
 
23
+ export interface WatchFunction {
24
+ name: string
25
+ objective: string
26
+ }
27
+
17
28
  export interface EmitOptions {
18
29
  namespace: string
19
30
  tickFunctions?: string[]
20
31
  loadFunctions?: string[]
21
32
  scheduleFunctions?: Array<{ name: string; ticks: number }>
33
+ watchFunctions?: WatchFunction[]
22
34
  /** When true, generate a .sourcemap.json sidecar file for each .mcfunction */
23
35
  generateSourceMap?: boolean
24
36
  /** Target Minecraft version; controls which MC features are used in codegen */
25
37
  mcVersion?: McVersion
26
38
  /** Map of EventTypeName → list of fully-qualified function references for @on handlers */
27
39
  eventHandlers?: Map<string, string[]>
40
+ /** Scoreboard objective names for @singleton struct fields — added to load.mcfunction */
41
+ singletonObjectives?: string[]
42
+ /** Functions decorated with @profile. */
43
+ profiledFunctions?: string[]
44
+ /** Emit debug-only profiling instrumentation and helpers. */
45
+ enableProfiling?: boolean
46
+ /** Functions decorated with @throttle. */
47
+ throttleFunctions?: Array<{ name: string; ticks: number }>
48
+ /** Functions decorated with @retry. */
49
+ retryFunctions?: Array<{ name: string; max: number }>
50
+ /** Functions decorated with @memoize — single-arg int result caching (LRU-1). */
51
+ memoizeFunctions?: string[]
28
52
  }
29
53
 
30
54
  // ---------------------------------------------------------------------------
@@ -36,10 +60,17 @@ export function emit(module: LIRModule, options: EmitOptions): DatapackFile[] {
36
60
  const tickFns = options.tickFunctions ?? []
37
61
  const loadFns = options.loadFunctions ?? []
38
62
  const scheduleFns = options.scheduleFunctions ?? []
63
+ const watchFns = options.watchFunctions ?? []
64
+ const profiledFns = options.profiledFunctions ?? []
65
+ const enableProfiling = options.enableProfiling ?? false
66
+ const throttleFns = options.throttleFunctions ?? []
67
+ const retryFns = options.retryFunctions ?? []
68
+ const memoizeFns = options.memoizeFunctions ?? []
39
69
  const objective = module.objective
40
70
  const genSourceMap = options.generateSourceMap ?? false
41
71
  const mcVersion = options.mcVersion ?? DEFAULT_MC_VERSION
42
72
  const files: DatapackFile[] = []
73
+ const namespaceMapBuilder = genSourceMap ? new NamespaceSourceMapBuilder() : null
43
74
 
44
75
  // pack.mcmeta
45
76
  files.push({
@@ -49,8 +80,23 @@ export function emit(module: LIRModule, options: EmitOptions): DatapackFile[] {
49
80
  }, null, 2) + '\n',
50
81
  })
51
82
 
83
+ const singletonObjectives = options.singletonObjectives ?? []
84
+
52
85
  // load.mcfunction — creates the scoreboard objective
53
- const loadCmds = [`scoreboard objectives add ${objective} dummy`]
86
+ const loadCmds = [
87
+ `scoreboard objectives add ${objective} dummy`,
88
+ ...watchFns.map(watch => `scoreboard objectives add ${watchPrevObjective(watch.name)} dummy`),
89
+ ...singletonObjectives.map(obj => `scoreboard objectives add ${obj} dummy`),
90
+ ...(enableProfiling && profiledFns.length > 0
91
+ ? [
92
+ 'scoreboard objectives add __time dummy',
93
+ 'scoreboard objectives add __profile dummy',
94
+ ]
95
+ : []),
96
+ ...throttleFns.map(t => `scoreboard objectives add ${throttleObjective(t.name)} dummy`),
97
+ ...retryFns.map(r => `scoreboard objectives add ${retryObjective(r.name)} dummy`),
98
+ ...(memoizeFns.length > 0 ? [`scoreboard objectives add __memo dummy`] : []),
99
+ ]
54
100
  files.push({
55
101
  path: `data/${namespace}/function/load.mcfunction`,
56
102
  content: loadCmds.join('\n') + '\n',
@@ -59,20 +105,40 @@ export function emit(module: LIRModule, options: EmitOptions): DatapackFile[] {
59
105
  // Each LIR function → .mcfunction file
60
106
  for (const fn of module.functions) {
61
107
  const fnPath = fnNameToPath(fn.name, namespace)
108
+ namespaceMapBuilder?.addFunctionMapping(qualifiedFunctionRef(fn.name, namespace), fn.sourceLoc, humanFunctionName(fn))
62
109
  if (genSourceMap) {
63
110
  const builder = new SourceMapBuilder(fnPath)
64
- const lines = emitFunctionWithSourceMap(fn, namespace, objective, builder, mcVersion)
111
+ const lines = emitFunction(fn, namespace, objective, mcVersion, enableProfiling && profiledFns.includes(fn.name), builder)
65
112
  files.push({ path: fnPath, content: lines.join('\n') + '\n' })
66
113
  const map = builder.build()
67
114
  if (map) {
68
115
  files.push({ path: sourceMapPath(fnPath), content: serializeSourceMap(map) })
69
116
  }
70
117
  } else {
71
- const lines = emitFunction(fn, namespace, objective, mcVersion)
118
+ const lines = emitFunction(fn, namespace, objective, mcVersion, enableProfiling && profiledFns.includes(fn.name))
72
119
  files.push({ path: fnPath, content: lines.join('\n') + '\n' })
73
120
  }
74
121
  }
75
122
 
123
+ const namespaceMap = namespaceMapBuilder?.build()
124
+ if (namespaceMap) {
125
+ files.push({
126
+ path: namespaceSourceMapPath(namespace),
127
+ content: serializeSourceMap(namespaceMap),
128
+ })
129
+ }
130
+
131
+ if (enableProfiling && profiledFns.length > 0) {
132
+ files.push({
133
+ path: `data/${namespace}/function/__profiler_reset.mcfunction`,
134
+ content: emitProfilerReset(profiledFns).join('\n') + '\n',
135
+ })
136
+ files.push({
137
+ path: `data/${namespace}/function/__profiler_report.mcfunction`,
138
+ content: emitProfilerReport(profiledFns).join('\n') + '\n',
139
+ })
140
+ }
141
+
76
142
  // @schedule wrapper functions: _schedule_xxx → schedule function ns:xxx Nt
77
143
  for (const { name, ticks } of scheduleFns) {
78
144
  files.push({
@@ -81,6 +147,122 @@ export function emit(module: LIRModule, options: EmitOptions): DatapackFile[] {
81
147
  })
82
148
  }
83
149
 
150
+ for (const watch of watchFns) {
151
+ const dispatcher = watchDispatcherName(watch.name)
152
+ const prevObjective = watchPrevObjective(watch.name)
153
+ const changedCondition = `unless score @s ${watch.objective} = @s ${prevObjective}`
154
+ files.push({
155
+ path: fnNameToPath(dispatcher, namespace),
156
+ content: [
157
+ `execute as @a unless score @s ${prevObjective} = @s ${prevObjective} run scoreboard players operation @s ${prevObjective} = @s ${watch.objective}`,
158
+ `execute as @a ${changedCondition} run function ${namespace}:${watch.name}`,
159
+ `execute as @a ${changedCondition} run scoreboard players operation @s ${prevObjective} = @s ${watch.objective}`,
160
+ ].join('\n') + '\n',
161
+ })
162
+ }
163
+
164
+ // @throttle wrapper functions
165
+ for (const { name, ticks } of throttleFns) {
166
+ const obj = throttleObjective(name)
167
+ const inner = `${name}_inner`
168
+ files.push({
169
+ path: fnNameToPath(throttleDispatcherName(name), namespace),
170
+ content: [
171
+ `scoreboard players add __throttle_${name} ${obj} 1`,
172
+ `execute if score __throttle_${name} ${obj} matches ${ticks}.. run function ${namespace}:${inner}`,
173
+ `execute if score __throttle_${name} ${obj} matches ${ticks}.. run scoreboard players set __throttle_${name} ${obj} 0`,
174
+ ].join('\n') + '\n',
175
+ })
176
+ // Rename the original function to _inner by emitting a redirect wrapper:
177
+ // The original LIR function keeps its original name; the dispatcher wraps it.
178
+ // We just need the dispatcher to call the real function as <name>_inner.
179
+ // Actually: the original compiled function stays as <name>. We generate
180
+ // a wrapper at <name>_inner that simply calls <name>.
181
+ files.push({
182
+ path: fnNameToPath(inner, namespace),
183
+ content: `function ${namespace}:${name}\n`,
184
+ })
185
+ }
186
+
187
+ // @retry wrapper functions
188
+ for (const { name, max } of retryFns) {
189
+ const obj = retryObjective(name)
190
+ const dispatcherName = retryDispatcherName(name)
191
+ // Dispatcher: if retries remaining > 0, call the function; if it returns 0, decrement counter
192
+ // We use a two-file approach:
193
+ // __retry_<name>: decrements counter then calls the real function
194
+ // __retry_<name>_init: sets the counter to max and schedules the first attempt
195
+ // Runtime logic:
196
+ // - On success (fn returns nonzero): reset counter to 0
197
+ // - On failure (fn returns 0): counter -= 1, schedule next tick
198
+ // Since we can't read a function return value in mcfunction directly,
199
+ // we use a storage-based approach: the function itself sets a "success" flag.
200
+ // Simpler scoreboard approach (matching task spec):
201
+ // __retry_<name> obj tracks remaining attempts
202
+ // Each tick, if counter > 0: call fn, if fn "failed" (set counter to 0 from outside) schedule retry
203
+ // Simplest correct approach:
204
+ // generate a tick-registered dispatcher that:
205
+ // 1. if counter > 0, call the function
206
+ // 2. function sets __retry_<name>_result to 1 on success (convention)
207
+ // 3. if result == 0, decrement counter; else reset counter
208
+ // For simplicity, use the same pattern as @throttle but inverted:
209
+ // The user's function sets a score $ret to signal success/failure.
210
+ // We wrap it: if counter > 0, run the function.
211
+ // After running, check $ret: if 0, keep counter; else reset to 0.
212
+ // Next tick the dispatcher will retry if counter > 0.
213
+ //
214
+ // Minimal correct implementation (matching task spec — fn returns 0 = failure):
215
+ // __retry_<name>_tick: registered as @tick
216
+ // execute if score __retry_<name> <obj> matches 1.. run function ns:<name>
217
+ // execute if score __retry_<name> <obj> matches 1.. if score $ret <obj> matches 0 run scoreboard players remove __retry_<name> <obj> 1
218
+ // execute if score __retry_<name> <obj> matches 1.. unless score $ret <obj> matches 0 run scoreboard players set __retry_<name> <obj> 0
219
+ // To start a retry sequence, something must set __retry_<name> <obj> to max.
220
+ // We generate __retry_<name>_start: scoreboard players set __retry_<name> <obj> <max>
221
+ files.push({
222
+ path: fnNameToPath(dispatcherName, namespace),
223
+ content: [
224
+ `execute if score __retry_${name} ${obj} matches 1.. run function ${namespace}:${name}`,
225
+ `execute if score __retry_${name} ${obj} matches 1.. if score $ret ${obj} matches 0 run scoreboard players remove __retry_${name} ${obj} 1`,
226
+ `execute if score __retry_${name} ${obj} matches 1.. unless score $ret ${obj} matches 0 run scoreboard players set __retry_${name} ${obj} 0`,
227
+ ].join('\n') + '\n',
228
+ })
229
+ files.push({
230
+ path: fnNameToPath(`${name}_start`, namespace),
231
+ content: `scoreboard players set __retry_${name} ${obj} ${max}\n`,
232
+ })
233
+ }
234
+
235
+ // @memoize wrapper functions (LRU-1 cache: last call arg/result)
236
+ // The original compiled function has been renamed to <name>_impl.
237
+ // We generate <name>.mcfunction as the public entry point with cache logic:
238
+ // Players in __memo objective:
239
+ // __memo_<name>_key — cached argument value
240
+ // __memo_<name>_val — cached return value
241
+ // __memo_<name>_hit — 1 if a cached result is available
242
+ // On call ($p0 = argument):
243
+ // 1. If __memo_<name>_hit == 1 AND __memo_<name>_key == $p0 → copy cached val to $ret, return
244
+ // 2. Otherwise: call <name>_impl, store $p0 → key, $ret → val, set hit=1
245
+ for (const name of memoizeFns) {
246
+ const keyPlayer = `__memo_${name}_key`
247
+ const valPlayer = `__memo_${name}_val`
248
+ const hitPlayer = `__memo_${name}_hit`
249
+ const implName = `${name}_impl`
250
+ files.push({
251
+ path: fnNameToPath(name, namespace),
252
+ content: [
253
+ `# @memoize wrapper for ${name} (LRU-1 cache)`,
254
+ `# Cache hit: valid flag set AND key matches current arg`,
255
+ `execute if score ${hitPlayer} __memo matches 1 if score ${keyPlayer} __memo = $p0 ${objective} run scoreboard players operation $ret ${objective} = ${valPlayer} __memo`,
256
+ `execute if score ${hitPlayer} __memo matches 1 if score ${keyPlayer} __memo = $p0 ${objective} run return 0`,
257
+ `# Cache miss: call implementation, store result`,
258
+ `function ${namespace}:${implName}`,
259
+ `scoreboard players operation ${keyPlayer} __memo = $p0 ${objective}`,
260
+ `scoreboard players operation ${valPlayer} __memo = $ret ${objective}`,
261
+ `scoreboard players set ${hitPlayer} __memo 1`,
262
+ ].join('\n') + '\n',
263
+ })
264
+ }
265
+
84
266
  // Tag files for tick/load
85
267
  if (loadFns.length > 0 || true) {
86
268
  // Always include load.json — it must reference the load.mcfunction
@@ -91,8 +273,14 @@ export function emit(module: LIRModule, options: EmitOptions): DatapackFile[] {
91
273
  })
92
274
  }
93
275
 
94
- if (tickFns.length > 0) {
95
- const tickValues = tickFns.map(fn => `${namespace}:${fn}`)
276
+ const allTickFns = [
277
+ ...tickFns,
278
+ ...watchFns.map(watch => watchDispatcherName(watch.name)),
279
+ ...throttleFns.map(t => throttleDispatcherName(t.name)),
280
+ ...retryFns.map(r => retryDispatcherName(r.name)),
281
+ ]
282
+ if (allTickFns.length > 0) {
283
+ const tickValues = allTickFns.map(fn => `${namespace}:${fn}`)
96
284
  files.push({
97
285
  path: 'data/minecraft/tags/function/tick.json',
98
286
  content: JSON.stringify({ values: tickValues }, null, 2) + '\n',
@@ -127,25 +315,36 @@ export function emit(module: LIRModule, options: EmitOptions): DatapackFile[] {
127
315
  // Function emission
128
316
  // ---------------------------------------------------------------------------
129
317
 
130
- function emitFunction(fn: LIRFunction, namespace: string, objective: string, mcVersion: McVersion): string[] {
131
- const lines: string[] = []
132
- for (const instr of fn.instructions) {
133
- lines.push(emitInstr(instr, namespace, objective, mcVersion))
134
- }
135
- return lines
136
- }
137
-
138
- function emitFunctionWithSourceMap(
318
+ function emitFunction(
139
319
  fn: LIRFunction,
140
320
  namespace: string,
141
321
  objective: string,
142
- builder: SourceMapBuilder,
143
322
  mcVersion: McVersion,
323
+ isProfiled = false,
324
+ builder?: SourceMapBuilder,
144
325
  ): string[] {
145
326
  const lines: string[] = []
327
+ const pushLine = (line: string, sourceLoc?: LIRFunction['sourceLoc']): void => {
328
+ lines.push(line)
329
+ builder?.addLine(sourceLoc)
330
+ }
331
+
332
+ for (const line of emitFunctionHeader(fn)) pushLine(line)
333
+ if (isProfiled) {
334
+ for (const line of profilerStartLines(fn.name)) pushLine(line)
335
+ }
336
+
337
+ let lastSourceMarker: string | undefined
146
338
  for (const instr of fn.instructions) {
147
- lines.push(emitInstr(instr, namespace, objective, mcVersion))
148
- builder.addLine(instr.sourceLoc)
339
+ const marker = instr.sourceLoc ? formatSourceMarker(instr.sourceLoc) : undefined
340
+ if (marker && marker !== lastSourceMarker) {
341
+ pushLine(`# src: ${marker}`)
342
+ lastSourceMarker = marker
343
+ }
344
+ pushLine(flattenExecute(emitInstr(instr, namespace, objective, mcVersion)), instr.sourceLoc)
345
+ }
346
+ if (isProfiled) {
347
+ for (const line of profilerEndLines(fn.name)) pushLine(line)
149
348
  }
150
349
  return lines
151
350
  }
@@ -156,6 +355,105 @@ function fnNameToPath(name: string, namespace: string): string {
156
355
  return `data/${namespace}/function/${mcName}.mcfunction`
157
356
  }
158
357
 
358
+ function qualifiedFunctionRef(name: string, namespace: string): string {
359
+ return `${namespace}:${name.replace(/::/g, '/').toLowerCase()}`
360
+ }
361
+
362
+ function humanFunctionName(fn: LIRFunction): string {
363
+ const match = fn.sourceSnippet?.match(/^fn\s+([^(]+)/)
364
+ return match?.[1] ?? fn.name.split('::').pop() ?? fn.name
365
+ }
366
+
367
+ function emitFunctionHeader(fn: LIRFunction): string[] {
368
+ if (!fn.sourceLoc) return []
369
+ const lines: string[] = []
370
+ lines.push(`# Generated from: ${fn.sourceLoc.file}:${fn.sourceLoc.line} (fn ${humanFunctionName(fn)})`)
371
+ if (fn.sourceSnippet) {
372
+ lines.push(`# Source: ${fn.sourceSnippet}`)
373
+ }
374
+ return lines
375
+ }
376
+
377
+ function formatSourceMarker(sourceLoc: NonNullable<LIRInstr['sourceLoc']>): string {
378
+ return `${sourceLoc.file}:${sourceLoc.line}`
379
+ }
380
+
381
+ function watchDispatcherName(name: string): string {
382
+ return `__watch_${name}`
383
+ }
384
+
385
+ function watchPrevObjective(name: string): string {
386
+ return `__watch_${name}_prev`
387
+ }
388
+
389
+ function throttleDispatcherName(name: string): string {
390
+ return `__throttle_${name}`
391
+ }
392
+
393
+ function throttleObjective(name: string): string {
394
+ return `__throttle`
395
+ }
396
+
397
+ function retryDispatcherName(name: string): string {
398
+ return `__retry_${name}`
399
+ }
400
+
401
+ function retryObjective(name: string): string {
402
+ return `__retry`
403
+ }
404
+
405
+ function profilerSafeName(name: string): string {
406
+ return name.replace(/[^A-Za-z0-9_]/g, '_')
407
+ }
408
+
409
+ function profilerStartPlayer(name: string): string {
410
+ return `#prof_start_${profilerSafeName(name)}`
411
+ }
412
+
413
+ function profilerDeltaPlayer(name: string): string {
414
+ return `#prof_delta_${profilerSafeName(name)}`
415
+ }
416
+
417
+ function profilerTotalPlayer(name: string): string {
418
+ return `#prof_total_${profilerSafeName(name)}`
419
+ }
420
+
421
+ function profilerCountPlayer(name: string): string {
422
+ return `#prof_count_${profilerSafeName(name)}`
423
+ }
424
+
425
+ function profilerStartLines(name: string): string[] {
426
+ return [
427
+ `# __profiler_start_${name}`,
428
+ `scoreboard players set ${profilerStartPlayer(name)} __time 0`,
429
+ `execute store result score ${profilerStartPlayer(name)} __time run time query gametime`,
430
+ ]
431
+ }
432
+
433
+ function profilerEndLines(name: string): string[] {
434
+ return [
435
+ `# __profiler_end_${name}`,
436
+ `scoreboard players set ${profilerDeltaPlayer(name)} __time 0`,
437
+ `execute store result score ${profilerDeltaPlayer(name)} __time run time query gametime`,
438
+ `scoreboard players operation ${profilerDeltaPlayer(name)} __time -= ${profilerStartPlayer(name)} __time`,
439
+ `scoreboard players operation ${profilerTotalPlayer(name)} __profile += ${profilerDeltaPlayer(name)} __time`,
440
+ `scoreboard players add ${profilerCountPlayer(name)} __profile 1`,
441
+ ]
442
+ }
443
+
444
+ function emitProfilerReset(profiledFns: string[]): string[] {
445
+ return profiledFns.flatMap(name => [
446
+ `scoreboard players set ${profilerTotalPlayer(name)} __profile 0`,
447
+ `scoreboard players set ${profilerCountPlayer(name)} __profile 0`,
448
+ ])
449
+ }
450
+
451
+ function emitProfilerReport(profiledFns: string[]): string[] {
452
+ return profiledFns.map(name => (
453
+ `tellraw @a [{"text":"[profile] ${name}: total="},{"score":{"name":"${profilerTotalPlayer(name)}","objective":"__profile"}},{"text":" ticks count="},{"score":{"name":"${profilerCountPlayer(name)}","objective":"__profile"}}]`
454
+ ))
455
+ }
456
+
159
457
  // ---------------------------------------------------------------------------
160
458
  // Instruction emission
161
459
  // ---------------------------------------------------------------------------
@@ -283,6 +581,56 @@ function macroLineCompat(template: string): string {
283
581
  return template.replace(/\$\((\w+)\)/g, (_m, p) => `{storage:rs:macro_args,path:${p}}`)
284
582
  }
285
583
 
584
+ // ---------------------------------------------------------------------------
585
+ // Execute Chain Optimization
586
+ // ---------------------------------------------------------------------------
587
+
588
+ /**
589
+ * Flatten nested execute-if chains into a single execute with multiple conditions.
590
+ *
591
+ * MC allows chaining conditions:
592
+ * execute if A run execute if B run X
593
+ * can be written as:
594
+ * execute if A if B run X
595
+ *
596
+ * This reduces command-parsing overhead and improves TPS.
597
+ *
598
+ * Rules:
599
+ * - Only merges when the inner `run` clause is itself `execute if ...`
600
+ * - Does NOT merge `if ... run execute unless ...` — semantics differ
601
+ * (unless negates, changing behavior in chain context)
602
+ * - Recursively flattens deeper nesting (3+ levels)
603
+ */
604
+ export function flattenExecute(cmd: string): string {
605
+ // Match: execute <conditions> run execute if <rest>
606
+ // We only flatten when the inner execute starts with "if" (not "unless", "as", "at", etc.)
607
+ // Pattern: "execute <prefix> run execute if <suffix>"
608
+ const RUN_EXECUTE_IF = / run execute if /
609
+ if (!RUN_EXECUTE_IF.test(cmd)) {
610
+ return cmd
611
+ }
612
+
613
+ // Find the " run execute if " boundary
614
+ const idx = cmd.indexOf(' run execute if ')
615
+ if (idx === -1) return cmd
616
+
617
+ const outer = cmd.slice(0, idx) // "execute if A"
618
+ const inner = cmd.slice(idx + ' run '.length) // "execute if B run X"
619
+
620
+ // The outer must start with "execute"
621
+ if (!outer.startsWith('execute ')) return cmd
622
+
623
+ // Inner starts with "execute if ..."
624
+ // Strip the "execute" prefix from inner to get the conditions + run tail
625
+ // Result: outer + " " + inner_conditions_and_tail
626
+ const innerWithoutExecute = inner.slice('execute '.length) // "if B run X"
627
+
628
+ const merged = `${outer} ${innerWithoutExecute}`
629
+
630
+ // Recurse to handle 3+ levels
631
+ return flattenExecute(merged)
632
+ }
633
+
286
634
  function emitSubcmd(sub: ExecuteSubcmd): string {
287
635
  switch (sub.kind) {
288
636
  case 'as':
@@ -69,6 +69,9 @@ export function compileModules(
69
69
  const tokens = lexer.tokenize()
70
70
  const parser = new Parser(tokens, mod.source, mod.filePath)
71
71
  const ast = parser.parse(namespace)
72
+ if (parser.parseErrors.length > 0) {
73
+ throw parser.parseErrors[0]
74
+ }
72
75
 
73
76
  // Verify declared module name matches provided name
74
77
  const declaredName = ast.moduleName
@@ -122,7 +125,12 @@ export function compileModules(
122
125
  )
123
126
  }
124
127
 
125
- if (imp.symbol === '*') {
128
+ if (imp.symbol === undefined) {
129
+ // Whole-module file import (`import player_utils;`) — not a symbol import;
130
+ // this is resolved by the file-level compile() function, not compileModules.
131
+ // Skip here to avoid treating it as a cross-module symbol reference.
132
+ continue
133
+ } else if (imp.symbol === '*') {
126
134
  // Wildcard: import all exports
127
135
  for (const sym of sourceExports) {
128
136
  resolved.set(sym, `${imp.moduleName}/${sym}`)
@@ -153,6 +161,7 @@ export function compileModules(
153
161
 
154
162
  for (const ast of parsedModules.values()) {
155
163
  for (const imp of ast.imports) {
164
+ if (imp.symbol === undefined) continue // whole-module file import, skip
156
165
  const used = usedExports.get(imp.moduleName)
157
166
  if (!used) continue
158
167
  if (imp.symbol === '*') {
@@ -346,12 +355,16 @@ function compileSingleModule(
346
355
  // Extract decorator metadata
347
356
  const tickFunctions: string[] = []
348
357
  const loadFunctions: string[] = []
358
+ const watchFunctions: Array<{ name: string; objective: string }> = []
349
359
  const coroutineInfos: CoroutineInfo[] = []
350
360
  const scheduleFunctions: Array<{ name: string; ticks: number }> = []
351
361
  for (const fn of hir.functions) {
352
362
  for (const dec of fn.decorators) {
353
363
  if (dec.name === 'tick') tickFunctions.push(fn.name)
354
364
  if (dec.name === 'load') loadFunctions.push(fn.name)
365
+ if (dec.name === 'watch' && dec.args?.objective) {
366
+ watchFunctions.push({ name: fn.name, objective: dec.args.objective })
367
+ }
355
368
  if (dec.name === 'coroutine') {
356
369
  coroutineInfos.push({ fnName: fn.name, batch: dec.args?.batch ?? 10, onDone: dec.args?.onDone })
357
370
  }
@@ -374,7 +387,7 @@ function compileSingleModule(
374
387
  lir.objective = objective
375
388
  const lirOpt = lirOptimizeModule(lir)
376
389
 
377
- const files = emit(lirOpt, { namespace, tickFunctions, loadFunctions, scheduleFunctions })
390
+ const files = emit(lirOpt, { namespace, tickFunctions, loadFunctions, watchFunctions, scheduleFunctions })
378
391
 
379
392
  // For named modules: rename the load.mcfunction to avoid path collision.
380
393
  // Rename `data/${ns}/function/load.mcfunction` → `data/${ns}/function/${modName}/_load.mcfunction`
@@ -525,7 +538,10 @@ function rewriteStmt(stmt: Stmt, symbolMap: Map<string, string>): void {
525
538
  case 'let_destruct':
526
539
  rewriteExpr(stmt.init, symbolMap)
527
540
  break
528
- // break, continue, raw: nothing to rewrite
541
+ case 'labeled_loop':
542
+ rewriteStmt(stmt.body, symbolMap)
543
+ break
544
+ // break, continue, break_label, continue_label, raw: nothing to rewrite
529
545
  }
530
546
  }
531
547