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
@@ -18107,7 +18107,7 @@ var require_diagnostics = __commonJS({
18107
18107
  "../../dist/src/diagnostics/index.js"(exports2) {
18108
18108
  "use strict";
18109
18109
  Object.defineProperty(exports2, "__esModule", { value: true });
18110
- exports2.DiagnosticCollector = exports2.DiagnosticError = void 0;
18110
+ exports2.DiagnosticCollector = exports2.CheckFailedError = exports2.DiagnosticBundleError = exports2.DiagnosticError = void 0;
18111
18111
  exports2.parseErrorMessage = parseErrorMessage;
18112
18112
  exports2.formatError = formatError;
18113
18113
  function formatSourcePointer(sourceLines, line, col) {
@@ -18164,6 +18164,23 @@ var require_diagnostics = __commonJS({
18164
18164
  }
18165
18165
  };
18166
18166
  exports2.DiagnosticError = DiagnosticError;
18167
+ var DiagnosticBundleError = class extends Error {
18168
+ constructor(diagnostics) {
18169
+ super(diagnostics[0]?.message ?? "Multiple diagnostics");
18170
+ this.name = "DiagnosticBundleError";
18171
+ this.diagnostics = diagnostics;
18172
+ }
18173
+ };
18174
+ exports2.DiagnosticBundleError = DiagnosticBundleError;
18175
+ var CheckFailedError = class extends Error {
18176
+ constructor(diagnostics, warnings) {
18177
+ super(diagnostics[0]?.message ?? "Check failed");
18178
+ this.name = "CheckFailedError";
18179
+ this.diagnostics = diagnostics;
18180
+ this.warnings = warnings;
18181
+ }
18182
+ };
18183
+ exports2.CheckFailedError = CheckFailedError;
18167
18184
  var DiagnosticCollector = class {
18168
18185
  constructor(source, filePath) {
18169
18186
  this.diagnostics = [];
@@ -18241,6 +18258,8 @@ var require_lexer = __commonJS({
18241
18258
  while: "while",
18242
18259
  for: "for",
18243
18260
  foreach: "foreach",
18261
+ do: "do",
18262
+ repeat: "repeat",
18244
18263
  match: "match",
18245
18264
  return: "return",
18246
18265
  break: "break",
@@ -18260,6 +18279,8 @@ var require_lexer = __commonJS({
18260
18279
  unless: "unless",
18261
18280
  declare: "declare",
18262
18281
  export: "export",
18282
+ import: "import",
18283
+ interface: "interface",
18263
18284
  int: "int",
18264
18285
  bool: "bool",
18265
18286
  float: "float",
@@ -18502,7 +18523,13 @@ var require_lexer = __commonJS({
18502
18523
  return;
18503
18524
  }
18504
18525
  if (char === '"') {
18505
- this.scanString(startLine, startCol);
18526
+ if (this.peek() === '"' && this.peek(1) === '"') {
18527
+ this.advance();
18528
+ this.advance();
18529
+ this.scanMultiLineString(startLine, startCol);
18530
+ } else {
18531
+ this.scanString(startLine, startCol);
18532
+ }
18506
18533
  return;
18507
18534
  }
18508
18535
  if (char === "#") {
@@ -18576,6 +18603,28 @@ var require_lexer = __commonJS({
18576
18603
  }
18577
18604
  return result;
18578
18605
  }
18606
+ scanMultiLineString(startLine, startCol) {
18607
+ let value = "";
18608
+ while (!this.isAtEnd()) {
18609
+ if (this.peek() === '"' && this.peek(1) === '"' && this.peek(2) === '"') {
18610
+ this.advance();
18611
+ this.advance();
18612
+ this.advance();
18613
+ break;
18614
+ }
18615
+ if (this.peek() === "\\" && this.peek(1) === '"') {
18616
+ this.advance();
18617
+ value += this.advance();
18618
+ continue;
18619
+ }
18620
+ value += this.advance();
18621
+ }
18622
+ if (value.startsWith("\n"))
18623
+ value = value.slice(1);
18624
+ if (value.endsWith("\n"))
18625
+ value = value.slice(0, -1);
18626
+ this.addToken("string_lit", value, startLine, startCol);
18627
+ }
18579
18628
  scanString(startLine, startCol) {
18580
18629
  let value = "";
18581
18630
  let interpolationDepth = 0;
@@ -18834,6 +18883,7 @@ var require_parser = __commonJS({
18834
18883
  this.pos = 0;
18835
18884
  this.inLibraryMode = false;
18836
18885
  this.warnings = [];
18886
+ this.parseErrors = [];
18837
18887
  this.tokens = tokens;
18838
18888
  this.sourceLines = source?.split("\n") ?? [];
18839
18889
  this.filePath = filePath;
@@ -18895,6 +18945,60 @@ var require_parser = __commonJS({
18895
18945
  return { kind: "eof", value: "", line: span.line, col: span.col };
18896
18946
  }
18897
18947
  // -------------------------------------------------------------------------
18948
+ // Error Recovery
18949
+ // -------------------------------------------------------------------------
18950
+ /**
18951
+ * Synchronize to the next top-level declaration boundary after a parse error.
18952
+ * Skips tokens until we find a keyword that starts a top-level declaration,
18953
+ * or a `}` (end of a block), or EOF.
18954
+ */
18955
+ syncToNextDecl() {
18956
+ const TOP_LEVEL_KEYWORDS = /* @__PURE__ */ new Set([
18957
+ "fn",
18958
+ "struct",
18959
+ "impl",
18960
+ "enum",
18961
+ "const",
18962
+ "let",
18963
+ "export",
18964
+ "declare",
18965
+ "import",
18966
+ "namespace",
18967
+ "module"
18968
+ ]);
18969
+ while (!this.check("eof")) {
18970
+ const kind = this.peek().kind;
18971
+ if (kind === "}") {
18972
+ this.advance();
18973
+ return;
18974
+ }
18975
+ if (TOP_LEVEL_KEYWORDS.has(kind)) {
18976
+ return;
18977
+ }
18978
+ if (kind === "ident" && this.peek().value === "import") {
18979
+ return;
18980
+ }
18981
+ this.advance();
18982
+ }
18983
+ }
18984
+ /**
18985
+ * Synchronize to the next statement boundary inside a block after a parse error.
18986
+ * Skips tokens until we reach `;`, `}`, or EOF.
18987
+ */
18988
+ syncToNextStmt() {
18989
+ while (!this.check("eof")) {
18990
+ const kind = this.peek().kind;
18991
+ if (kind === ";") {
18992
+ this.advance();
18993
+ return;
18994
+ }
18995
+ if (kind === "}") {
18996
+ return;
18997
+ }
18998
+ this.advance();
18999
+ }
19000
+ }
19001
+ // -------------------------------------------------------------------------
18898
19002
  // Program
18899
19003
  // -------------------------------------------------------------------------
18900
19004
  parse(defaultNamespace = "redscript") {
@@ -18906,6 +19010,7 @@ var require_parser = __commonJS({
18906
19010
  const enums = [];
18907
19011
  const consts = [];
18908
19012
  const imports = [];
19013
+ const interfaces = [];
18909
19014
  let isLibrary = false;
18910
19015
  let moduleName;
18911
19016
  if (this.check("namespace")) {
@@ -18926,40 +19031,74 @@ var require_parser = __commonJS({
18926
19031
  this.match(";");
18927
19032
  }
18928
19033
  while (!this.check("eof")) {
18929
- if (this.check("let")) {
18930
- globals.push(this.parseGlobalDecl(true));
18931
- } else if (this.check("struct")) {
18932
- structs.push(this.parseStructDecl());
18933
- } else if (this.check("impl")) {
18934
- implBlocks.push(this.parseImplBlock());
18935
- } else if (this.check("enum")) {
18936
- enums.push(this.parseEnumDecl());
18937
- } else if (this.check("const")) {
18938
- consts.push(this.parseConstDecl());
18939
- } else if (this.check("declare")) {
18940
- this.advance();
18941
- this.parseDeclareStub();
18942
- } else if (this.check("export")) {
18943
- declarations.push(this.parseExportedFnDecl());
18944
- } else if (this.check("ident") && this.peek().value === "import") {
18945
- this.advance();
18946
- const importToken = this.peek();
18947
- const modName = this.expect("ident").value;
18948
- this.expect("::");
18949
- let symbol;
18950
- if (this.check("*")) {
19034
+ try {
19035
+ if (this.check("decorator") && this.peek().value.startsWith("@config")) {
19036
+ const decorToken = this.advance();
19037
+ const decorator = this.parseDecoratorValue(decorToken.value);
19038
+ if (!this.check("let")) {
19039
+ this.error("@config decorator must be followed by a let declaration");
19040
+ }
19041
+ const g = this.parseGlobalDecl(true);
19042
+ g.configKey = decorator.args?.configKey;
19043
+ g.configDefault = decorator.args?.configDefault;
19044
+ globals.push(g);
19045
+ } else if (this.check("let")) {
19046
+ globals.push(this.parseGlobalDecl(true));
19047
+ } else if (this.check("decorator") && this.peek().value === "@singleton") {
19048
+ this.advance();
19049
+ if (!this.check("struct")) {
19050
+ this.error("@singleton decorator must be followed by a struct declaration");
19051
+ }
19052
+ const s = this.parseStructDecl();
19053
+ s.isSingleton = true;
19054
+ structs.push(s);
19055
+ } else if (this.check("struct")) {
19056
+ structs.push(this.parseStructDecl());
19057
+ } else if (this.check("impl")) {
19058
+ implBlocks.push(this.parseImplBlock());
19059
+ } else if (this.check("interface")) {
19060
+ interfaces.push(this.parseInterfaceDecl());
19061
+ } else if (this.check("enum")) {
19062
+ enums.push(this.parseEnumDecl());
19063
+ } else if (this.check("const")) {
19064
+ consts.push(this.parseConstDecl());
19065
+ } else if (this.check("declare")) {
19066
+ this.advance();
19067
+ this.parseDeclareStub();
19068
+ } else if (this.check("export")) {
19069
+ declarations.push(this.parseExportedFnDecl());
19070
+ } else if (this.check("import") || this.check("ident") && this.peek().value === "import") {
18951
19071
  this.advance();
18952
- symbol = "*";
19072
+ const importToken = this.peek();
19073
+ const modName = this.expect("ident").value;
19074
+ if (this.check("::")) {
19075
+ this.advance();
19076
+ let symbol;
19077
+ if (this.check("*")) {
19078
+ this.advance();
19079
+ symbol = "*";
19080
+ } else {
19081
+ symbol = this.expect("ident").value;
19082
+ }
19083
+ this.match(";");
19084
+ imports.push(this.withLoc({ moduleName: modName, symbol }, importToken));
19085
+ } else {
19086
+ this.match(";");
19087
+ imports.push(this.withLoc({ moduleName: modName, symbol: void 0 }, importToken));
19088
+ }
18953
19089
  } else {
18954
- symbol = this.expect("ident").value;
19090
+ declarations.push(this.parseFnDecl());
19091
+ }
19092
+ } catch (err) {
19093
+ if (err instanceof diagnostics_1.DiagnosticError) {
19094
+ this.parseErrors.push(err);
19095
+ this.syncToNextDecl();
19096
+ } else {
19097
+ throw err;
18955
19098
  }
18956
- this.match(";");
18957
- imports.push(this.withLoc({ moduleName: modName, symbol }, importToken));
18958
- } else {
18959
- declarations.push(this.parseFnDecl());
18960
19099
  }
18961
19100
  }
18962
- return { namespace, moduleName, globals, declarations, structs, implBlocks, enums, consts, imports, isLibrary };
19101
+ return { namespace, moduleName, globals, declarations, structs, implBlocks, enums, consts, imports, interfaces, isLibrary };
18963
19102
  }
18964
19103
  // -------------------------------------------------------------------------
18965
19104
  // Struct Declaration
@@ -18988,6 +19127,20 @@ var require_parser = __commonJS({
18988
19127
  while (!this.check("}") && !this.check("eof")) {
18989
19128
  const variantToken = this.expect("ident");
18990
19129
  const variant = { name: variantToken.value };
19130
+ if (this.check("(")) {
19131
+ this.advance();
19132
+ const fields = [];
19133
+ while (!this.check(")") && !this.check("eof")) {
19134
+ const fieldName = this.expect("ident").value;
19135
+ this.expect(":");
19136
+ const fieldType = this.parseType();
19137
+ fields.push({ name: fieldName, type: fieldType });
19138
+ if (!this.match(","))
19139
+ break;
19140
+ }
19141
+ this.expect(")");
19142
+ variant.fields = fields;
19143
+ }
18991
19144
  if (this.match("=")) {
18992
19145
  const valueToken = this.expect("int_lit");
18993
19146
  variant.value = parseInt(valueToken.value, 10);
@@ -19005,14 +19158,72 @@ var require_parser = __commonJS({
19005
19158
  }
19006
19159
  parseImplBlock() {
19007
19160
  const implToken = this.expect("impl");
19008
- const typeName = this.expect("ident").value;
19161
+ let traitName;
19162
+ let typeName;
19163
+ const firstName = this.expect("ident").value;
19164
+ if (this.match("for")) {
19165
+ traitName = firstName;
19166
+ typeName = this.expect("ident").value;
19167
+ } else {
19168
+ typeName = firstName;
19169
+ }
19009
19170
  this.expect("{");
19010
19171
  const methods = [];
19011
19172
  while (!this.check("}") && !this.check("eof")) {
19012
19173
  methods.push(this.parseFnDecl(typeName));
19013
19174
  }
19014
19175
  this.expect("}");
19015
- return this.withLoc({ kind: "impl_block", typeName, methods }, implToken);
19176
+ return this.withLoc({ kind: "impl_block", traitName, typeName, methods }, implToken);
19177
+ }
19178
+ /**
19179
+ * Parse an interface declaration:
19180
+ * interface <Name> {
19181
+ * fn <method>(<params>): <retType>
19182
+ * ...
19183
+ * }
19184
+ * Method signatures have no body — they are prototype-only.
19185
+ */
19186
+ parseInterfaceDecl() {
19187
+ const ifaceToken = this.expect("interface");
19188
+ const name = this.expect("ident").value;
19189
+ this.expect("{");
19190
+ const methods = [];
19191
+ while (!this.check("}") && !this.check("eof")) {
19192
+ const fnToken = this.expect("fn");
19193
+ const methodName = this.expect("ident").value;
19194
+ this.expect("(");
19195
+ const params = this.parseInterfaceParams();
19196
+ this.expect(")");
19197
+ let returnType;
19198
+ if (this.match(":")) {
19199
+ returnType = this.parseType();
19200
+ }
19201
+ methods.push(this.withLoc({ name: methodName, params, returnType }, fnToken));
19202
+ }
19203
+ this.expect("}");
19204
+ return this.withLoc({ name, methods }, ifaceToken);
19205
+ }
19206
+ /**
19207
+ * Parse interface method params — like parseParams but allows bare `self`
19208
+ * (no `:` required for the first param named 'self').
19209
+ */
19210
+ parseInterfaceParams() {
19211
+ const params = [];
19212
+ if (!this.check(")")) {
19213
+ do {
19214
+ const paramToken = this.expect("ident");
19215
+ const paramName = paramToken.value;
19216
+ let type;
19217
+ if (params.length === 0 && paramName === "self" && !this.check(":")) {
19218
+ type = { kind: "named", name: "void" };
19219
+ } else {
19220
+ this.expect(":");
19221
+ type = this.parseType();
19222
+ }
19223
+ params.push(this.withLoc({ name: paramName, type }, paramToken));
19224
+ } while (this.match(","));
19225
+ }
19226
+ return params;
19016
19227
  }
19017
19228
  parseConstDecl() {
19018
19229
  const constToken = this.expect("const");
@@ -19032,8 +19243,12 @@ var require_parser = __commonJS({
19032
19243
  const name = this.expect("ident").value;
19033
19244
  this.expect(":");
19034
19245
  const type = this.parseType();
19035
- this.expect("=");
19036
- const init = this.parseExpr();
19246
+ let init;
19247
+ if (this.match("=")) {
19248
+ init = this.parseExpr();
19249
+ } else {
19250
+ init = { kind: "int_lit", value: 0 };
19251
+ }
19037
19252
  this.match(";");
19038
19253
  return this.withLoc({ kind: "global", name, type, init, mutable }, token);
19039
19254
  }
@@ -19049,6 +19264,7 @@ var require_parser = __commonJS({
19049
19264
  }
19050
19265
  parseFnDecl(implTypeName) {
19051
19266
  const decorators = this.parseDecorators();
19267
+ const watchObjective = decorators.find((decorator) => decorator.name === "watch")?.args?.objective;
19052
19268
  let isExported;
19053
19269
  const filteredDecorators = decorators.filter((d) => {
19054
19270
  if (d.name === "keep") {
@@ -19085,7 +19301,8 @@ var require_parser = __commonJS({
19085
19301
  decorators: filteredDecorators,
19086
19302
  body,
19087
19303
  isLibraryFn: this.inLibraryMode || void 0,
19088
- isExported
19304
+ isExported,
19305
+ watchObjective
19089
19306
  }, fnToken);
19090
19307
  if (fn.span && closingBraceLine)
19091
19308
  fn.span.endLine = closingBraceLine;
@@ -19119,7 +19336,7 @@ var require_parser = __commonJS({
19119
19336
  return decorators;
19120
19337
  }
19121
19338
  parseDecoratorValue(value) {
19122
- const match = value.match(/^@(\w+)(?:\(([^)]*)\))?$/);
19339
+ const match = value.match(/^@(\w+)(?:\((.*)\))?$/s);
19123
19340
  if (!match) {
19124
19341
  this.error(`Invalid decorator: ${value}`);
19125
19342
  }
@@ -19128,6 +19345,9 @@ var require_parser = __commonJS({
19128
19345
  if (!argsStr) {
19129
19346
  return { name };
19130
19347
  }
19348
+ if (name === "profile") {
19349
+ this.error("@profile decorator does not accept arguments");
19350
+ }
19131
19351
  const args = {};
19132
19352
  if (name === "on") {
19133
19353
  const eventTypeMatch = argsStr.match(/^([A-Za-z_][A-Za-z0-9_]*)$/);
@@ -19136,10 +19356,12 @@ var require_parser = __commonJS({
19136
19356
  return { name, args };
19137
19357
  }
19138
19358
  }
19139
- if (name === "on_trigger" || name === "on_advancement" || name === "on_craft" || name === "on_join_team") {
19359
+ if (name === "watch" || name === "on_trigger" || name === "on_advancement" || name === "on_craft" || name === "on_join_team") {
19140
19360
  const strMatch = argsStr.match(/^"([^"]*)"$/);
19141
19361
  if (strMatch) {
19142
- if (name === "on_trigger") {
19362
+ if (name === "watch") {
19363
+ args.objective = strMatch[1];
19364
+ } else if (name === "on_trigger") {
19143
19365
  args.trigger = strMatch[1];
19144
19366
  } else if (name === "on_advancement") {
19145
19367
  args.advancement = strMatch[1];
@@ -19151,6 +19373,24 @@ var require_parser = __commonJS({
19151
19373
  return { name, args };
19152
19374
  }
19153
19375
  }
19376
+ if (name === "config") {
19377
+ const configMatch = argsStr.match(/^"([^"]+)"\s*,\s*default\s*:\s*(-?\d+(?:\.\d+)?)$/);
19378
+ if (configMatch) {
19379
+ return { name, args: { configKey: configMatch[1], configDefault: parseFloat(configMatch[2]) } };
19380
+ }
19381
+ const keyOnlyMatch = argsStr.match(/^"([^"]+)"$/);
19382
+ if (keyOnlyMatch) {
19383
+ return { name, args: { configKey: keyOnlyMatch[1] } };
19384
+ }
19385
+ this.error(`Invalid @config syntax. Expected: @config("key", default: value) or @config("key")`);
19386
+ }
19387
+ if (name === "deprecated") {
19388
+ const strMatch = argsStr.match(/^"([^"]*)"$/);
19389
+ if (strMatch) {
19390
+ return { name, args: { message: strMatch[1] } };
19391
+ }
19392
+ return { name, args: {} };
19393
+ }
19154
19394
  if (name === "require_on_load") {
19155
19395
  const rawArgs = [];
19156
19396
  for (const part of argsStr.split(",")) {
@@ -19286,7 +19526,16 @@ var require_parser = __commonJS({
19286
19526
  this.expect("{");
19287
19527
  const stmts = [];
19288
19528
  while (!this.check("}") && !this.check("eof")) {
19289
- stmts.push(this.parseStmt());
19529
+ try {
19530
+ stmts.push(this.parseStmt());
19531
+ } catch (err) {
19532
+ if (err instanceof diagnostics_1.DiagnosticError) {
19533
+ this.parseErrors.push(err);
19534
+ this.syncToNextStmt();
19535
+ } else {
19536
+ throw err;
19537
+ }
19538
+ }
19290
19539
  }
19291
19540
  this.expect("}");
19292
19541
  return stmts;
@@ -19295,6 +19544,9 @@ var require_parser = __commonJS({
19295
19544
  if (this.check("let")) {
19296
19545
  return this.parseLetStmt();
19297
19546
  }
19547
+ if (this.check("const")) {
19548
+ return this.parseLocalConstDecl();
19549
+ }
19298
19550
  if (this.check("return")) {
19299
19551
  return this.parseReturnStmt();
19300
19552
  }
@@ -19314,6 +19566,12 @@ var require_parser = __commonJS({
19314
19566
  if (this.check("while")) {
19315
19567
  return this.parseWhileStmt();
19316
19568
  }
19569
+ if (this.check("do")) {
19570
+ return this.parseDoWhileStmt();
19571
+ }
19572
+ if (this.check("repeat")) {
19573
+ return this.parseRepeatStmt();
19574
+ }
19317
19575
  if (this.check("for")) {
19318
19576
  return this.parseForStmt();
19319
19577
  }
@@ -19368,6 +19626,16 @@ var require_parser = __commonJS({
19368
19626
  this.match(";");
19369
19627
  return this.withLoc({ kind: "let", name, type, init }, letToken);
19370
19628
  }
19629
+ parseLocalConstDecl() {
19630
+ const constToken = this.expect("const");
19631
+ const name = this.expect("ident").value;
19632
+ this.expect(":");
19633
+ const type = this.parseType();
19634
+ this.expect("=");
19635
+ const value = this.parseExpr();
19636
+ this.match(";");
19637
+ return this.withLoc({ kind: "const_decl", name, type, value }, constToken);
19638
+ }
19371
19639
  parseReturnStmt() {
19372
19640
  const returnToken = this.expect("return");
19373
19641
  let value;
@@ -19398,9 +19666,7 @@ var require_parser = __commonJS({
19398
19666
  }
19399
19667
  return this.withLoc({ kind: "if_let_some", binding, init, then: then2, else_: else_2 }, ifToken);
19400
19668
  }
19401
- this.expect("(");
19402
- const cond = this.parseExpr();
19403
- this.expect(")");
19669
+ const cond = this.parseParenOptionalCond();
19404
19670
  const then = this.parseBlock();
19405
19671
  let else_;
19406
19672
  if (this.match("else")) {
@@ -19414,12 +19680,44 @@ var require_parser = __commonJS({
19414
19680
  }
19415
19681
  parseWhileStmt() {
19416
19682
  const whileToken = this.expect("while");
19417
- this.expect("(");
19418
- const cond = this.parseExpr();
19419
- this.expect(")");
19683
+ if (this.check("let") && this.peek(1).kind === "ident" && this.peek(1).value === "Some") {
19684
+ this.advance();
19685
+ this.advance();
19686
+ this.expect("(");
19687
+ const binding = this.expect("ident").value;
19688
+ this.expect(")");
19689
+ this.expect("=");
19690
+ const init = this.parseExpr();
19691
+ const body2 = this.parseBlock();
19692
+ return this.withLoc({ kind: "while_let_some", binding, init, body: body2 }, whileToken);
19693
+ }
19694
+ const cond = this.parseParenOptionalCond();
19420
19695
  const body = this.parseBlock();
19421
19696
  return this.withLoc({ kind: "while", cond, body }, whileToken);
19422
19697
  }
19698
+ parseDoWhileStmt() {
19699
+ const doToken = this.expect("do");
19700
+ const body = this.parseBlock();
19701
+ this.expect("while");
19702
+ const cond = this.parseParenOptionalCond();
19703
+ this.match(";");
19704
+ return this.withLoc({ kind: "do_while", cond, body }, doToken);
19705
+ }
19706
+ parseRepeatStmt() {
19707
+ const repeatToken = this.expect("repeat");
19708
+ const countToken = this.expect("int_lit");
19709
+ const count = parseInt(countToken.value, 10);
19710
+ const body = this.parseBlock();
19711
+ return this.withLoc({ kind: "repeat", count, body }, repeatToken);
19712
+ }
19713
+ parseParenOptionalCond() {
19714
+ if (this.match("(")) {
19715
+ const cond = this.parseExpr();
19716
+ this.expect(")");
19717
+ return cond;
19718
+ }
19719
+ return this.parseExpr();
19720
+ }
19423
19721
  parseForStmt() {
19424
19722
  const forToken = this.expect("for");
19425
19723
  if (this.check("ident") && this.peek(1).kind === "in") {
@@ -19536,6 +19834,22 @@ var require_parser = __commonJS({
19536
19834
  this.expect(")");
19537
19835
  return { kind: "PatSome", binding };
19538
19836
  }
19837
+ if (this.check("ident") && this.peek(1).kind === "::") {
19838
+ const enumName = this.advance().value;
19839
+ this.expect("::");
19840
+ const variant = this.expect("ident").value;
19841
+ const bindings = [];
19842
+ if (this.check("(")) {
19843
+ this.advance();
19844
+ while (!this.check(")") && !this.check("eof")) {
19845
+ bindings.push(this.expect("ident").value);
19846
+ if (!this.match(","))
19847
+ break;
19848
+ }
19849
+ this.expect(")");
19850
+ }
19851
+ return { kind: "PatEnum", enumName, variant, bindings };
19852
+ }
19539
19853
  if (this.check("int_lit")) {
19540
19854
  const tok = this.advance();
19541
19855
  return { kind: "PatInt", value: parseInt(tok.value, 10) };
@@ -19868,6 +20182,12 @@ var require_parser = __commonJS({
19868
20182
  continue;
19869
20183
  }
19870
20184
  if (expr.kind === "member") {
20185
+ if (expr.field === "unwrap_or") {
20186
+ const defaultExpr = this.parseExpr();
20187
+ this.expect(")");
20188
+ expr = this.withLoc({ kind: "unwrap_or", opt: expr.obj, default_: defaultExpr }, this.getLocToken(expr) ?? openParenToken);
20189
+ continue;
20190
+ }
19871
20191
  const methodMap = {
19872
20192
  "tag": "__entity_tag",
19873
20193
  "untag": "__entity_untag",
@@ -19945,6 +20265,21 @@ var require_parser = __commonJS({
19945
20265
  this.expect("::");
19946
20266
  const memberToken = this.expect("ident");
19947
20267
  if (this.check("(")) {
20268
+ const isNamedArgs = this.peek(1).kind === "ident" && this.peek(2).kind === ":";
20269
+ if (isNamedArgs) {
20270
+ this.advance();
20271
+ const args2 = [];
20272
+ while (!this.check(")") && !this.check("eof")) {
20273
+ const fieldName = this.expect("ident").value;
20274
+ this.expect(":");
20275
+ const value = this.parseExpr();
20276
+ args2.push({ name: fieldName, value });
20277
+ if (!this.match(","))
20278
+ break;
20279
+ }
20280
+ this.expect(")");
20281
+ return this.withLoc({ kind: "enum_construct", enumName: typeToken.value, variant: memberToken.value, args: args2 }, typeToken);
20282
+ }
19948
20283
  this.advance();
19949
20284
  const args = this.parseArgs();
19950
20285
  this.expect(")");
@@ -20773,16 +21108,18 @@ var require_lower = __commonJS({
20773
21108
  structs: program.structs.map((s) => ({
20774
21109
  name: s.name,
20775
21110
  fields: s.fields.map((f) => ({ name: f.name, type: f.type })),
21111
+ isSingleton: s.isSingleton,
20776
21112
  span: s.span
20777
21113
  })),
20778
21114
  implBlocks: program.implBlocks.map((ib) => ({
20779
21115
  typeName: ib.typeName,
21116
+ traitName: ib.traitName,
20780
21117
  methods: ib.methods.map(lowerFunction),
20781
21118
  span: ib.span
20782
21119
  })),
20783
21120
  enums: program.enums.map((e) => ({
20784
21121
  name: e.name,
20785
- variants: e.variants.map((v) => ({ name: v.name, value: v.value })),
21122
+ variants: e.variants.map((v) => ({ name: v.name, value: v.value, fields: v.fields })),
20786
21123
  span: e.span
20787
21124
  })),
20788
21125
  consts: program.consts.map((c) => ({
@@ -20806,6 +21143,8 @@ var require_lower = __commonJS({
20806
21143
  return pat;
20807
21144
  case "PatExpr":
20808
21145
  return { kind: "PatExpr", expr: lowerExpr(pat.expr) };
21146
+ case "PatEnum":
21147
+ return { kind: "PatEnum", enumName: pat.enumName, variant: pat.variant, bindings: pat.bindings };
20809
21148
  }
20810
21149
  }
20811
21150
  function lowerGlobal(g) {
@@ -20827,7 +21166,8 @@ var require_lower = __commonJS({
20827
21166
  body: lowerBlock(fn.body),
20828
21167
  isLibraryFn: fn.isLibraryFn,
20829
21168
  isExported: fn.isExported,
20830
- span: fn.span
21169
+ span: fn.span,
21170
+ watchObjective: fn.watchObjective
20831
21171
  };
20832
21172
  }
20833
21173
  function lowerParam(p) {
@@ -20855,6 +21195,8 @@ var require_lower = __commonJS({
20855
21195
  return { kind: "let", name: stmt.name, type: stmt.type, init: lowerExpr(stmt.init), span: stmt.span };
20856
21196
  case "let_destruct":
20857
21197
  return { kind: "let_destruct", names: stmt.names, type: stmt.type, init: lowerExpr(stmt.init), span: stmt.span };
21198
+ case "const_decl":
21199
+ return { kind: "const_decl", name: stmt.name, type: stmt.type, value: lowerExpr(stmt.value), span: stmt.span };
20858
21200
  case "expr":
20859
21201
  return { kind: "expr", expr: lowerExpr(stmt.expr), span: stmt.span };
20860
21202
  case "return":
@@ -21106,6 +21448,68 @@ var require_lower = __commonJS({
21106
21448
  else_: stmt.else_ ? lowerBlock(stmt.else_) : void 0,
21107
21449
  span: stmt.span
21108
21450
  };
21451
+ // --- Desugaring: do_while → body + while(cond) { body } ---
21452
+ // Emits the body once unconditionally, then a while loop:
21453
+ // <body>
21454
+ // while (cond) { <body> }
21455
+ case "do_while": {
21456
+ const firstBody = lowerBlock(stmt.body);
21457
+ const loopBody = lowerBlock(stmt.body);
21458
+ const whileStmt = {
21459
+ kind: "while",
21460
+ cond: lowerExpr(stmt.cond),
21461
+ body: loopBody,
21462
+ span: stmt.span
21463
+ };
21464
+ return [...firstBody, whileStmt];
21465
+ }
21466
+ // --- Desugaring: repeat N → let __repeat_i = 0; while(__repeat_i < N) { body; __repeat_i = __repeat_i + 1 } ---
21467
+ case "repeat": {
21468
+ const id = repeatCounter++;
21469
+ const idxName = `__repeat_i_${id}`;
21470
+ const initStmt = {
21471
+ kind: "let",
21472
+ name: idxName,
21473
+ type: { kind: "named", name: "int" },
21474
+ init: { kind: "int_lit", value: 0 },
21475
+ span: stmt.span
21476
+ };
21477
+ const body = lowerBlock(stmt.body);
21478
+ const step = [{
21479
+ kind: "expr",
21480
+ expr: {
21481
+ kind: "assign",
21482
+ target: idxName,
21483
+ value: {
21484
+ kind: "binary",
21485
+ op: "+",
21486
+ left: { kind: "ident", name: idxName },
21487
+ right: { kind: "int_lit", value: 1 }
21488
+ }
21489
+ }
21490
+ }];
21491
+ const whileStmt = {
21492
+ kind: "while",
21493
+ cond: {
21494
+ kind: "binary",
21495
+ op: "<",
21496
+ left: { kind: "ident", name: idxName },
21497
+ right: { kind: "int_lit", value: stmt.count }
21498
+ },
21499
+ body,
21500
+ step,
21501
+ span: stmt.span
21502
+ };
21503
+ return [initStmt, whileStmt];
21504
+ }
21505
+ case "while_let_some":
21506
+ return {
21507
+ kind: "while_let_some",
21508
+ binding: stmt.binding,
21509
+ init: lowerExpr(stmt.init),
21510
+ body: lowerBlock(stmt.body),
21511
+ span: stmt.span
21512
+ };
21109
21513
  default: {
21110
21514
  const _exhaustive = stmt;
21111
21515
  throw new Error(`Unknown statement kind: ${_exhaustive.kind}`);
@@ -21116,6 +21520,7 @@ var require_lower = __commonJS({
21116
21520
  return sub;
21117
21521
  }
21118
21522
  var forEachCounter = 0;
21523
+ var repeatCounter = 0;
21119
21524
  var COMPOUND_TO_BINOP = {
21120
21525
  "+=": "+",
21121
21526
  "-=": "-",
@@ -21158,8 +21563,10 @@ var require_lower = __commonJS({
21158
21563
  parts: expr.parts.map((p) => typeof p === "string" ? p : lowerExpr(p)),
21159
21564
  span: expr.span
21160
21565
  };
21161
- case "f_string":
21162
- return { kind: "f_string", parts: expr.parts, span: expr.span };
21566
+ case "f_string": {
21567
+ const hirParts = expr.parts.map((part) => part.kind === "text" ? { kind: "text", value: part.value } : { kind: "expr", expr: lowerExpr(part.expr) });
21568
+ return { kind: "f_string", parts: hirParts, span: expr.span };
21569
+ }
21163
21570
  // Binary ops — && and || preserved as-is (short-circuit → control flow in MIR)
21164
21571
  case "binary":
21165
21572
  return {
@@ -21264,12 +21671,22 @@ var require_lower = __commonJS({
21264
21671
  };
21265
21672
  case "path_expr":
21266
21673
  return { kind: "path_expr", enumName: expr.enumName, variant: expr.variant, span: expr.span };
21674
+ case "enum_construct":
21675
+ return {
21676
+ kind: "enum_construct",
21677
+ enumName: expr.enumName,
21678
+ variant: expr.variant,
21679
+ args: expr.args.map((a) => ({ name: a.name, value: lowerExpr(a.value) })),
21680
+ span: expr.span
21681
+ };
21267
21682
  case "tuple_lit":
21268
21683
  return { kind: "tuple_lit", elements: expr.elements.map(lowerExpr), span: expr.span };
21269
21684
  case "some_lit":
21270
21685
  return { kind: "some_lit", value: lowerExpr(expr.value), span: expr.span };
21271
21686
  case "none_lit":
21272
21687
  return { kind: "none_lit", span: expr.span };
21688
+ case "unwrap_or":
21689
+ return { kind: "unwrap_or", opt: lowerExpr(expr.opt), default_: lowerExpr(expr.default_), span: expr.span };
21273
21690
  case "type_cast":
21274
21691
  return { kind: "type_cast", expr: lowerExpr(expr.expr), targetType: expr.targetType, span: expr.span };
21275
21692
  case "lambda": {
@@ -21502,6 +21919,14 @@ var require_monomorphize = __commonJS({
21502
21919
  then: this.rewriteBlock(stmt.then, ctx),
21503
21920
  else_: stmt.else_ ? this.rewriteBlock(stmt.else_, ctx) : void 0
21504
21921
  };
21922
+ case "while_let_some":
21923
+ return {
21924
+ ...stmt,
21925
+ init: this.rewriteExpr(stmt.init, ctx),
21926
+ body: this.rewriteBlock(stmt.body, ctx)
21927
+ };
21928
+ case "const_decl":
21929
+ return { ...stmt, value: this.rewriteExpr(stmt.value, ctx) };
21505
21930
  case "break":
21506
21931
  case "continue":
21507
21932
  case "raw":
@@ -21559,11 +21984,16 @@ var require_monomorphize = __commonJS({
21559
21984
  case "str_interp":
21560
21985
  return { ...expr, parts: expr.parts.map((p) => typeof p === "string" ? p : this.rewriteExpr(p, ctx)) };
21561
21986
  case "f_string":
21562
- return expr;
21987
+ return {
21988
+ ...expr,
21989
+ parts: expr.parts.map((p) => p.kind === "text" ? p : { kind: "expr", expr: this.rewriteExpr(p.expr, ctx) })
21990
+ };
21563
21991
  case "some_lit":
21564
21992
  return { ...expr, value: this.rewriteExpr(expr.value, ctx) };
21565
21993
  case "none_lit":
21566
21994
  return expr;
21995
+ case "unwrap_or":
21996
+ return { ...expr, opt: this.rewriteExpr(expr.opt, ctx), default_: this.rewriteExpr(expr.default_, ctx) };
21567
21997
  // Literals / terminals — pass through unchanged
21568
21998
  default:
21569
21999
  return expr;
@@ -21646,35 +22076,241 @@ var require_monomorphize = __commonJS({
21646
22076
  }
21647
22077
  });
21648
22078
 
21649
- // ../../dist/src/mir/macro.js
21650
- var require_macro = __commonJS({
21651
- "../../dist/src/mir/macro.js"(exports2) {
22079
+ // ../../dist/src/hir/deprecated.js
22080
+ var require_deprecated = __commonJS({
22081
+ "../../dist/src/hir/deprecated.js"(exports2) {
21652
22082
  "use strict";
21653
22083
  Object.defineProperty(exports2, "__esModule", { value: true });
21654
- exports2.BUILTIN_SET = void 0;
21655
- exports2.detectMacroFunctions = detectMacroFunctions;
21656
- exports2.BUILTIN_SET = /* @__PURE__ */ new Set([
21657
- "say",
21658
- "tell",
21659
- "tellraw",
21660
- "title",
21661
- "actionbar",
21662
- "subtitle",
21663
- "title_times",
21664
- "announce",
21665
- "give",
21666
- "kill",
21667
- "effect",
21668
- "effect_clear",
21669
- "summon",
21670
- "particle",
21671
- "playsound",
21672
- "clear",
21673
- "weather",
21674
- "time_set",
21675
- "time_add",
21676
- "gamerule",
21677
- "tag_add",
22084
+ exports2.checkDeprecatedCalls = checkDeprecatedCalls;
22085
+ function buildDeprecatedMap(hir) {
22086
+ const deprecated = /* @__PURE__ */ new Map();
22087
+ for (const fn of hir.functions) {
22088
+ const dep = getDeprecatedDecorator(fn.decorators);
22089
+ if (dep !== null) {
22090
+ deprecated.set(fn.name, dep);
22091
+ }
22092
+ }
22093
+ for (const ib of hir.implBlocks) {
22094
+ for (const m of ib.methods) {
22095
+ const dep = getDeprecatedDecorator(m.decorators);
22096
+ if (dep !== null) {
22097
+ deprecated.set(`${ib.typeName}::${m.name}`, dep);
22098
+ }
22099
+ }
22100
+ }
22101
+ return deprecated;
22102
+ }
22103
+ function getDeprecatedDecorator(decorators) {
22104
+ for (const dec of decorators) {
22105
+ if (dec.name === "deprecated") {
22106
+ return dec.args?.message ?? "";
22107
+ }
22108
+ }
22109
+ return null;
22110
+ }
22111
+ function checkDeprecatedCalls(hir) {
22112
+ const deprecated = buildDeprecatedMap(hir);
22113
+ if (deprecated.size === 0)
22114
+ return [];
22115
+ const warnings = [];
22116
+ for (const fn of hir.functions) {
22117
+ walkBlock(fn.body, fn.name, deprecated, warnings);
22118
+ }
22119
+ for (const ib of hir.implBlocks) {
22120
+ for (const m of ib.methods) {
22121
+ walkBlock(m.body, `${ib.typeName}::${m.name}`, deprecated, warnings);
22122
+ }
22123
+ }
22124
+ return warnings;
22125
+ }
22126
+ function walkBlock(block, caller, deprecated, warnings) {
22127
+ for (const stmt of block) {
22128
+ walkStmt(stmt, caller, deprecated, warnings);
22129
+ }
22130
+ }
22131
+ function walkStmt(stmt, caller, deprecated, warnings) {
22132
+ switch (stmt.kind) {
22133
+ case "let":
22134
+ case "let_destruct":
22135
+ walkExpr(stmt.init, caller, deprecated, warnings);
22136
+ break;
22137
+ case "expr":
22138
+ walkExpr(stmt.expr, caller, deprecated, warnings);
22139
+ break;
22140
+ case "return":
22141
+ if (stmt.value)
22142
+ walkExpr(stmt.value, caller, deprecated, warnings);
22143
+ break;
22144
+ case "if":
22145
+ walkExpr(stmt.cond, caller, deprecated, warnings);
22146
+ walkBlock(stmt.then, caller, deprecated, warnings);
22147
+ if (stmt.else_)
22148
+ walkBlock(stmt.else_, caller, deprecated, warnings);
22149
+ break;
22150
+ case "while":
22151
+ walkExpr(stmt.cond, caller, deprecated, warnings);
22152
+ walkBlock(stmt.body, caller, deprecated, warnings);
22153
+ if (stmt.step)
22154
+ walkBlock(stmt.step, caller, deprecated, warnings);
22155
+ break;
22156
+ case "foreach":
22157
+ walkExpr(stmt.iterable, caller, deprecated, warnings);
22158
+ walkBlock(stmt.body, caller, deprecated, warnings);
22159
+ break;
22160
+ case "match":
22161
+ walkExpr(stmt.expr, caller, deprecated, warnings);
22162
+ for (const arm of stmt.arms) {
22163
+ walkBlock(arm.body, caller, deprecated, warnings);
22164
+ }
22165
+ break;
22166
+ // break/continue/raw/execute: no sub-exprs to walk for deprecation purposes
22167
+ default:
22168
+ break;
22169
+ }
22170
+ }
22171
+ function walkExpr(expr, caller, deprecated, warnings) {
22172
+ switch (expr.kind) {
22173
+ case "call": {
22174
+ if (deprecated.has(expr.fn)) {
22175
+ const msg = deprecated.get(expr.fn);
22176
+ const location = expr.span ? `line ${expr.span.line}, col ${expr.span.col}: ` : "";
22177
+ const detail = msg ? `: ${msg}` : "";
22178
+ warnings.push(`[DeprecatedUsage] ${location}'${expr.fn}' is deprecated${detail} (called from '${caller}')`);
22179
+ }
22180
+ for (const arg of expr.args)
22181
+ walkExpr(arg, caller, deprecated, warnings);
22182
+ break;
22183
+ }
22184
+ case "static_call": {
22185
+ const qualName = `${expr.type}::${expr.method}`;
22186
+ if (deprecated.has(qualName)) {
22187
+ const msg = deprecated.get(qualName);
22188
+ const location = expr.span ? `line ${expr.span.line}, col ${expr.span.col}: ` : "";
22189
+ const detail = msg ? `: ${msg}` : "";
22190
+ warnings.push(`[DeprecatedUsage] ${location}'${qualName}' is deprecated${detail} (called from '${caller}')`);
22191
+ }
22192
+ for (const arg of expr.args)
22193
+ walkExpr(arg, caller, deprecated, warnings);
22194
+ break;
22195
+ }
22196
+ case "invoke":
22197
+ walkExpr(expr.callee, caller, deprecated, warnings);
22198
+ for (const arg of expr.args)
22199
+ walkExpr(arg, caller, deprecated, warnings);
22200
+ break;
22201
+ case "binary":
22202
+ walkExpr(expr.left, caller, deprecated, warnings);
22203
+ walkExpr(expr.right, caller, deprecated, warnings);
22204
+ break;
22205
+ case "unary":
22206
+ walkExpr(expr.operand, caller, deprecated, warnings);
22207
+ break;
22208
+ case "is_check":
22209
+ walkExpr(expr.expr, caller, deprecated, warnings);
22210
+ break;
22211
+ case "type_cast":
22212
+ walkExpr(expr.expr, caller, deprecated, warnings);
22213
+ break;
22214
+ case "assign":
22215
+ walkExpr(expr.value, caller, deprecated, warnings);
22216
+ break;
22217
+ case "member_assign":
22218
+ walkExpr(expr.obj, caller, deprecated, warnings);
22219
+ walkExpr(expr.value, caller, deprecated, warnings);
22220
+ break;
22221
+ case "index_assign":
22222
+ walkExpr(expr.obj, caller, deprecated, warnings);
22223
+ walkExpr(expr.index, caller, deprecated, warnings);
22224
+ walkExpr(expr.value, caller, deprecated, warnings);
22225
+ break;
22226
+ case "member":
22227
+ walkExpr(expr.obj, caller, deprecated, warnings);
22228
+ break;
22229
+ case "index":
22230
+ walkExpr(expr.obj, caller, deprecated, warnings);
22231
+ walkExpr(expr.index, caller, deprecated, warnings);
22232
+ break;
22233
+ case "array_lit":
22234
+ for (const el of expr.elements)
22235
+ walkExpr(el, caller, deprecated, warnings);
22236
+ break;
22237
+ case "struct_lit":
22238
+ for (const f of expr.fields)
22239
+ walkExpr(f.value, caller, deprecated, warnings);
22240
+ break;
22241
+ case "str_interp":
22242
+ for (const part of expr.parts) {
22243
+ if (typeof part !== "string")
22244
+ walkExpr(part, caller, deprecated, warnings);
22245
+ }
22246
+ break;
22247
+ case "f_string":
22248
+ for (const part of expr.parts) {
22249
+ if (part.kind === "expr")
22250
+ walkExpr(part.expr, caller, deprecated, warnings);
22251
+ }
22252
+ break;
22253
+ case "some_lit":
22254
+ walkExpr(expr.value, caller, deprecated, warnings);
22255
+ break;
22256
+ case "unwrap_or":
22257
+ walkExpr(expr.opt, caller, deprecated, warnings);
22258
+ walkExpr(expr.default_, caller, deprecated, warnings);
22259
+ break;
22260
+ case "lambda": {
22261
+ const body = expr.body;
22262
+ if (Array.isArray(body)) {
22263
+ walkBlock(body, caller, deprecated, warnings);
22264
+ } else {
22265
+ walkExpr(body, caller, deprecated, warnings);
22266
+ }
22267
+ break;
22268
+ }
22269
+ case "tuple_lit":
22270
+ for (const el of expr.elements)
22271
+ walkExpr(el, caller, deprecated, warnings);
22272
+ break;
22273
+ case "enum_construct":
22274
+ for (const arg of expr.args)
22275
+ walkExpr(arg.value, caller, deprecated, warnings);
22276
+ break;
22277
+ // Terminals: int_lit, float_lit, bool_lit, str_lit, ident, selector, etc.
22278
+ default:
22279
+ break;
22280
+ }
22281
+ }
22282
+ }
22283
+ });
22284
+
22285
+ // ../../dist/src/mir/macro.js
22286
+ var require_macro = __commonJS({
22287
+ "../../dist/src/mir/macro.js"(exports2) {
22288
+ "use strict";
22289
+ Object.defineProperty(exports2, "__esModule", { value: true });
22290
+ exports2.BUILTIN_SET = void 0;
22291
+ exports2.detectMacroFunctions = detectMacroFunctions;
22292
+ exports2.BUILTIN_SET = /* @__PURE__ */ new Set([
22293
+ "say",
22294
+ "tell",
22295
+ "tellraw",
22296
+ "title",
22297
+ "actionbar",
22298
+ "subtitle",
22299
+ "title_times",
22300
+ "announce",
22301
+ "give",
22302
+ "kill",
22303
+ "effect",
22304
+ "effect_clear",
22305
+ "summon",
22306
+ "particle",
22307
+ "playsound",
22308
+ "clear",
22309
+ "weather",
22310
+ "time_set",
22311
+ "time_add",
22312
+ "gamerule",
22313
+ "tag_add",
21678
22314
  "tag_remove",
21679
22315
  "kick",
21680
22316
  "setblock",
@@ -21832,23 +22468,35 @@ var require_lower2 = __commonJS({
21832
22468
  var macro_1 = require_macro();
21833
22469
  function lowerToMIR(hir, sourceFile) {
21834
22470
  const structDefs = /* @__PURE__ */ new Map();
22471
+ const singletonStructs = /* @__PURE__ */ new Set();
21835
22472
  for (const s of hir.structs) {
21836
22473
  structDefs.set(s.name, s.fields.map((f) => f.name));
22474
+ if (s.isSingleton)
22475
+ singletonStructs.add(s.name);
21837
22476
  }
21838
22477
  const enumDefs = /* @__PURE__ */ new Map();
22478
+ const enumPayloads = /* @__PURE__ */ new Map();
21839
22479
  for (const e of hir.enums) {
21840
22480
  const variants = /* @__PURE__ */ new Map();
22481
+ const payloads = /* @__PURE__ */ new Map();
21841
22482
  for (const v of e.variants) {
21842
22483
  variants.set(v.name, v.value ?? 0);
22484
+ if (v.fields && v.fields.length > 0) {
22485
+ payloads.set(v.name, v.fields);
22486
+ }
21843
22487
  }
21844
22488
  enumDefs.set(e.name, variants);
22489
+ if (payloads.size > 0) {
22490
+ enumPayloads.set(e.name, payloads);
22491
+ }
21845
22492
  }
21846
22493
  const implMethods = /* @__PURE__ */ new Map();
21847
22494
  for (const ib of hir.implBlocks) {
21848
22495
  const methods = /* @__PURE__ */ new Map();
21849
22496
  for (const m of ib.methods) {
21850
22497
  const hasSelf = m.params.length > 0 && m.params[0].name === "self";
21851
- methods.set(m.name, { hasSelf });
22498
+ const returnStructName = m.returnType.kind === "struct" ? m.returnType.name : void 0;
22499
+ methods.set(m.name, { hasSelf, returnStructName });
21852
22500
  }
21853
22501
  implMethods.set(ib.typeName, methods);
21854
22502
  }
@@ -21868,14 +22516,23 @@ var require_lower2 = __commonJS({
21868
22516
  hirFnMap.set(f.name, f);
21869
22517
  }
21870
22518
  const specializedFnsRegistry = /* @__PURE__ */ new Map();
22519
+ const constValues = /* @__PURE__ */ new Map();
22520
+ for (const c of hir.consts) {
22521
+ if (c.value.kind === "int_lit")
22522
+ constValues.set(c.name, c.value.value);
22523
+ else if (c.value.kind === "bool_lit")
22524
+ constValues.set(c.name, c.value.value ? 1 : 0);
22525
+ else if (c.value.kind === "float_lit")
22526
+ constValues.set(c.name, Math.round(c.value.value * 1e4));
22527
+ }
21871
22528
  const allFunctions = [];
21872
22529
  for (const f of hir.functions) {
21873
- const { fn, helpers } = lowerFunction(f, hir.namespace, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, sourceFile, timerCounter, void 0, hirFnMap, specializedFnsRegistry);
22530
+ const { fn, helpers } = lowerFunction(f, hir.namespace, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, sourceFile, timerCounter, void 0, hirFnMap, specializedFnsRegistry, void 0, enumPayloads, constValues, singletonStructs);
21874
22531
  allFunctions.push(fn, ...helpers);
21875
22532
  }
21876
22533
  for (const ib of hir.implBlocks) {
21877
22534
  for (const m of ib.methods) {
21878
- const { fn, helpers } = lowerImplMethod(m, ib.typeName, hir.namespace, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, sourceFile, timerCounter);
22535
+ const { fn, helpers } = lowerImplMethod(m, ib.typeName, hir.namespace, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, sourceFile, timerCounter, enumPayloads, constValues);
21879
22536
  allFunctions.push(fn, ...helpers);
21880
22537
  }
21881
22538
  }
@@ -21889,7 +22546,7 @@ var require_lower2 = __commonJS({
21889
22546
  };
21890
22547
  }
21891
22548
  var FnContext = class {
21892
- constructor(namespace, fnName, structDefs = /* @__PURE__ */ new Map(), implMethods = /* @__PURE__ */ new Map(), macroInfo = /* @__PURE__ */ new Map(), fnParamInfo = /* @__PURE__ */ new Map(), enumDefs = /* @__PURE__ */ new Map(), timerCounter = { count: 0, timerId: 0 }) {
22549
+ constructor(namespace, fnName, structDefs = /* @__PURE__ */ new Map(), implMethods = /* @__PURE__ */ new Map(), macroInfo = /* @__PURE__ */ new Map(), fnParamInfo = /* @__PURE__ */ new Map(), enumDefs = /* @__PURE__ */ new Map(), timerCounter = { count: 0, timerId: 0 }, enumPayloads = /* @__PURE__ */ new Map()) {
21893
22550
  this.tempCounter = 0;
21894
22551
  this.blockCounter = 0;
21895
22552
  this.blocks = [];
@@ -21898,14 +22555,18 @@ var require_lower2 = __commonJS({
21898
22555
  this.structVars = /* @__PURE__ */ new Map();
21899
22556
  this.tupleVars = /* @__PURE__ */ new Map();
21900
22557
  this.arrayVars = /* @__PURE__ */ new Map();
22558
+ this.stringVars = /* @__PURE__ */ new Map();
21901
22559
  this.currentSourceLoc = void 0;
21902
22560
  this.sourceFile = void 0;
21903
22561
  this.constTemps = /* @__PURE__ */ new Map();
21904
22562
  this.floatTemps = /* @__PURE__ */ new Set();
21905
22563
  this.doubleVars = /* @__PURE__ */ new Map();
21906
22564
  this.doubleVarCount = 0;
22565
+ this.stringVarCount = 0;
21907
22566
  this.hirFunctions = /* @__PURE__ */ new Map();
21908
22567
  this.specializedFnsRegistry = /* @__PURE__ */ new Map();
22568
+ this.constValues = /* @__PURE__ */ new Map();
22569
+ this.singletonStructs = /* @__PURE__ */ new Set();
21909
22570
  this.namespace = namespace;
21910
22571
  this.fnName = fnName;
21911
22572
  this.structDefs = structDefs;
@@ -21914,6 +22575,7 @@ var require_lower2 = __commonJS({
21914
22575
  this.fnParamInfo = fnParamInfo;
21915
22576
  this.currentMacroParams = macroInfo.get(fnName)?.macroParams ?? /* @__PURE__ */ new Set();
21916
22577
  this.enumDefs = enumDefs;
22578
+ this.enumPayloads = enumPayloads;
21917
22579
  this.timerCounter = timerCounter;
21918
22580
  const entry = this.makeBlock("entry");
21919
22581
  this.currentBlock = entry;
@@ -21974,11 +22636,17 @@ var require_lower2 = __commonJS({
21974
22636
  this.doubleVars.set(varName, path3);
21975
22637
  return path3;
21976
22638
  }
22639
+ /** Allocate a unique NBT storage path for a string value */
22640
+ freshStringVar(varName) {
22641
+ return `${this.namespace}_${this.fnName}_${varName}_${this.stringVarCount++}`;
22642
+ }
21977
22643
  };
21978
- function lowerFunction(fn, namespace, structDefs = /* @__PURE__ */ new Map(), implMethods = /* @__PURE__ */ new Map(), macroInfo = /* @__PURE__ */ new Map(), fnParamInfo = /* @__PURE__ */ new Map(), enumDefs = /* @__PURE__ */ new Map(), sourceFile, timerCounter = { count: 0, timerId: 0 }, arrayArgBindings, hirFnMap, specializedFnsRegistry, overrideName) {
22644
+ function lowerFunction(fn, namespace, structDefs = /* @__PURE__ */ new Map(), implMethods = /* @__PURE__ */ new Map(), macroInfo = /* @__PURE__ */ new Map(), fnParamInfo = /* @__PURE__ */ new Map(), enumDefs = /* @__PURE__ */ new Map(), sourceFile, timerCounter = { count: 0, timerId: 0 }, arrayArgBindings, hirFnMap, specializedFnsRegistry, overrideName, enumPayloads = /* @__PURE__ */ new Map(), constValues = /* @__PURE__ */ new Map(), singletonStructs = /* @__PURE__ */ new Set()) {
21979
22645
  const mirFnName = overrideName ?? fn.name;
21980
- const ctx = new FnContext(namespace, mirFnName, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, timerCounter);
22646
+ const ctx = new FnContext(namespace, mirFnName, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, timerCounter, enumPayloads);
21981
22647
  ctx.sourceFile = sourceFile;
22648
+ ctx.constValues = constValues;
22649
+ ctx.singletonStructs = singletonStructs;
21982
22650
  if (hirFnMap)
21983
22651
  ctx.hirFunctions = hirFnMap;
21984
22652
  if (specializedFnsRegistry)
@@ -21992,6 +22660,7 @@ var require_lower2 = __commonJS({
21992
22660
  const params = [];
21993
22661
  const scope = /* @__PURE__ */ new Map();
21994
22662
  let doubleParamSlot = 0;
22663
+ let stringParamSlot = 0;
21995
22664
  fn.params.forEach((p) => {
21996
22665
  if (p.type.kind === "array" && arrayArgBindings?.has(p.name)) {
21997
22666
  return;
@@ -22001,6 +22670,10 @@ var require_lower2 = __commonJS({
22001
22670
  ctx.doubleVars.set(p.name, path3);
22002
22671
  return;
22003
22672
  }
22673
+ if (p.type.kind === "named" && (p.type.name === "string" || p.type.name === "format_string")) {
22674
+ ctx.stringVars.set(p.name, `__sp${stringParamSlot++}`);
22675
+ return;
22676
+ }
22004
22677
  const t = ctx.freshTemp();
22005
22678
  params.push({ name: t, isMacroParam: fnMacroInfo?.macroParams.has(p.name) ?? false });
22006
22679
  scope.set(p.name, t);
@@ -22022,10 +22695,11 @@ var require_lower2 = __commonJS({
22022
22695
  };
22023
22696
  return { fn: result, helpers: ctx.helperFunctions };
22024
22697
  }
22025
- function lowerImplMethod(method, typeName, namespace, structDefs, implMethods, macroInfo = /* @__PURE__ */ new Map(), fnParamInfo = /* @__PURE__ */ new Map(), enumDefs = /* @__PURE__ */ new Map(), sourceFile, timerCounter = { count: 0, timerId: 0 }) {
22698
+ function lowerImplMethod(method, typeName, namespace, structDefs, implMethods, macroInfo = /* @__PURE__ */ new Map(), fnParamInfo = /* @__PURE__ */ new Map(), enumDefs = /* @__PURE__ */ new Map(), sourceFile, timerCounter = { count: 0, timerId: 0 }, enumPayloads = /* @__PURE__ */ new Map(), constValues = /* @__PURE__ */ new Map()) {
22026
22699
  const fnName = `${typeName}::${method.name}`;
22027
- const ctx = new FnContext(namespace, fnName, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, timerCounter);
22700
+ const ctx = new FnContext(namespace, fnName, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, timerCounter, enumPayloads);
22028
22701
  ctx.sourceFile = sourceFile;
22702
+ ctx.constValues = constValues;
22029
22703
  const fields = structDefs.get(typeName) ?? [];
22030
22704
  const hasSelf = method.params.length > 0 && method.params[0].name === "self";
22031
22705
  const params = [];
@@ -22149,7 +22823,13 @@ var require_lower2 = __commonJS({
22149
22823
  }
22150
22824
  switch (stmt.kind) {
22151
22825
  case "let": {
22152
- if (stmt.init.kind === "some_lit") {
22826
+ if (stmt.type?.kind === "named" && (stmt.type.name === "string" || stmt.type.name === "format_string")) {
22827
+ const path3 = lowerStringExprToPath(stmt.init, ctx, scope, stmt.name) ?? ctx.freshStringVar(stmt.name);
22828
+ ctx.stringVars.set(stmt.name, path3);
22829
+ const t = ctx.freshTemp();
22830
+ ctx.emit({ kind: "const", dst: t, value: 0 });
22831
+ scope.set(stmt.name, t);
22832
+ } else if (stmt.init.kind === "some_lit") {
22153
22833
  const hasTemp = `__opt_${stmt.name}_has`;
22154
22834
  const valTemp = `__opt_${stmt.name}_val`;
22155
22835
  ctx.emit({ kind: "const", dst: hasTemp, value: 1 });
@@ -22198,8 +22878,12 @@ var require_lower2 = __commonJS({
22198
22878
  ctx.emit({ kind: "copy", dst: valTemp, src: { kind: "temp", name: "__rf_val" } });
22199
22879
  const fieldTemps = /* @__PURE__ */ new Map([["has", hasTemp], ["val", valTemp]]);
22200
22880
  ctx.structVars.set(stmt.name, { typeName: "__option", fields: fieldTemps });
22201
- } else if (stmt.type?.kind === "struct") {
22202
- const fields = ctx.structDefs.get(stmt.type.name);
22881
+ } else if (
22882
+ // Struct-typed let: explicit annotation OR inferred from @singleton::get() return
22883
+ stmt.type?.kind === "struct" || stmt.init.kind === "static_call" && ctx.singletonStructs.has(stmt.init.type) && stmt.init.method === "get"
22884
+ ) {
22885
+ const inferredStructName = stmt.type?.kind === "struct" ? stmt.type.name : stmt.init.type;
22886
+ const fields = ctx.structDefs.get(inferredStructName);
22203
22887
  if (fields) {
22204
22888
  lowerExpr(stmt.init, ctx, scope);
22205
22889
  const fieldTemps = /* @__PURE__ */ new Map();
@@ -22213,7 +22897,7 @@ var require_lower2 = __commonJS({
22213
22897
  ctx.constTemps.set(t, constVal);
22214
22898
  }
22215
22899
  }
22216
- ctx.structVars.set(stmt.name, { typeName: stmt.type.name, fields: fieldTemps });
22900
+ ctx.structVars.set(stmt.name, { typeName: inferredStructName, fields: fieldTemps });
22217
22901
  } else {
22218
22902
  const valOp = lowerExpr(stmt.init, ctx, scope);
22219
22903
  const t = ctx.freshTemp();
@@ -22316,6 +23000,12 @@ var require_lower2 = __commonJS({
22316
23000
  }
22317
23001
  break;
22318
23002
  }
23003
+ case "const_decl": {
23004
+ const op = lowerExpr(stmt.value, ctx, scope);
23005
+ const numericValue = op.kind === "const" ? op.value : 0;
23006
+ ctx.constValues.set(stmt.name, numericValue);
23007
+ break;
23008
+ }
22319
23009
  case "expr": {
22320
23010
  lowerExpr(stmt.expr, ctx, scope);
22321
23011
  break;
@@ -22482,6 +23172,45 @@ var require_lower2 = __commonJS({
22482
23172
  break;
22483
23173
  }
22484
23174
  case "match": {
23175
+ const hasStringPats = stmt.arms.some((a) => a.pattern.kind === "PatExpr" && a.pattern.expr.kind === "str_lit");
23176
+ if (hasStringPats) {
23177
+ const matchPath = lowerStringExprToPath(stmt.expr, ctx, scope, "match");
23178
+ if (!matchPath) {
23179
+ throw new Error("String match requires a string literal or tracked string variable");
23180
+ }
23181
+ const mergeBlock2 = ctx.newBlock("match_merge");
23182
+ for (let i = 0; i < stmt.arms.length; i++) {
23183
+ const arm = stmt.arms[i];
23184
+ const pat = arm.pattern;
23185
+ if (pat.kind === "PatWild") {
23186
+ lowerBlock(arm.body, ctx, new Map(scope));
23187
+ if (isPlaceholderTerm(ctx.current().term)) {
23188
+ ctx.terminate({ kind: "jump", target: mergeBlock2.id });
23189
+ }
23190
+ continue;
23191
+ }
23192
+ if (pat.kind === "PatExpr" && pat.expr.kind === "str_lit") {
23193
+ const cmpTemp = ctx.freshTemp();
23194
+ ctx.emit({ kind: "string_match", dst: cmpTemp, ns: "rs:strings", path: matchPath, value: pat.expr.value });
23195
+ const armBody = ctx.newBlock("match_arm");
23196
+ const nextArm = ctx.newBlock("match_next");
23197
+ ctx.terminate({ kind: "branch", cond: { kind: "temp", name: cmpTemp }, then: armBody.id, else: nextArm.id });
23198
+ ctx.switchTo(armBody);
23199
+ lowerBlock(arm.body, ctx, new Map(scope));
23200
+ if (isPlaceholderTerm(ctx.current().term)) {
23201
+ ctx.terminate({ kind: "jump", target: mergeBlock2.id });
23202
+ }
23203
+ ctx.switchTo(nextArm);
23204
+ continue;
23205
+ }
23206
+ throw new Error(`Unsupported string match pattern: ${pat.kind}`);
23207
+ }
23208
+ if (isPlaceholderTerm(ctx.current().term)) {
23209
+ ctx.terminate({ kind: "jump", target: mergeBlock2.id });
23210
+ }
23211
+ ctx.switchTo(mergeBlock2);
23212
+ break;
23213
+ }
22485
23214
  const mergeBlock = ctx.newBlock("match_merge");
22486
23215
  const hasOptionPats = stmt.arms.some((a) => a.pattern.kind === "PatSome" || a.pattern.kind === "PatNone");
22487
23216
  let optHasOp;
@@ -22559,6 +23288,35 @@ var require_lower2 = __commonJS({
22559
23288
  ctx.terminate({ kind: "jump", target: mergeBlock.id });
22560
23289
  }
22561
23290
  ctx.switchTo(nextArm);
23291
+ } else if (pat.kind === "PatEnum") {
23292
+ const tagValue = ctx.enumDefs.get(pat.enumName)?.get(pat.variant) ?? 0;
23293
+ const cmpTemp = ctx.freshTemp();
23294
+ ctx.emit({ kind: "cmp", dst: cmpTemp, op: "eq", a: matchVal, b: { kind: "const", value: tagValue } });
23295
+ const armBody = ctx.newBlock("match_arm");
23296
+ const nextArm = ctx.newBlock("match_next");
23297
+ ctx.terminate({ kind: "branch", cond: { kind: "temp", name: cmpTemp }, then: armBody.id, else: nextArm.id });
23298
+ ctx.switchTo(armBody);
23299
+ const armScope = new Map(scope);
23300
+ const payloadFields = ctx.enumPayloads.get(pat.enumName)?.get(pat.variant) ?? [];
23301
+ for (let bi = 0; bi < pat.bindings.length; bi++) {
23302
+ const binding = pat.bindings[bi];
23303
+ const fieldDef = payloadFields[bi];
23304
+ const fieldName = fieldDef ? fieldDef.name : binding;
23305
+ const bindTemp = ctx.freshTemp();
23306
+ ctx.emit({
23307
+ kind: "nbt_read",
23308
+ dst: bindTemp,
23309
+ ns: "rs:enums",
23310
+ path: `${pat.enumName}_${fieldName}`,
23311
+ scale: 1
23312
+ });
23313
+ armScope.set(binding, bindTemp);
23314
+ }
23315
+ lowerBlock(arm.body, ctx, armScope);
23316
+ if (isPlaceholderTerm(ctx.current().term)) {
23317
+ ctx.terminate({ kind: "jump", target: mergeBlock.id });
23318
+ }
23319
+ ctx.switchTo(nextArm);
22562
23320
  } else if (pat.kind === "PatExpr") {
22563
23321
  const expr = pat.expr;
22564
23322
  if (expr.kind === "range_lit") {
@@ -22661,6 +23419,47 @@ var require_lower2 = __commonJS({
22661
23419
  ctx.switchTo(mergeBlock);
22662
23420
  break;
22663
23421
  }
23422
+ case "while_let_some": {
23423
+ const headerBlock = ctx.newBlock("whl_header");
23424
+ const bodyBlock = ctx.newBlock("whl_body");
23425
+ const exitBlock = ctx.newBlock("whl_exit");
23426
+ ctx.terminate({ kind: "jump", target: headerBlock.id });
23427
+ ctx.switchTo(headerBlock);
23428
+ let hasOp;
23429
+ let valTemp;
23430
+ const sv = (() => {
23431
+ if (stmt.init.kind === "ident")
23432
+ return ctx.structVars.get(stmt.init.name);
23433
+ return void 0;
23434
+ })();
23435
+ if (sv && sv.typeName === "__option") {
23436
+ const hasT = sv.fields.get("has");
23437
+ const valT = sv.fields.get("val");
23438
+ hasOp = { kind: "temp", name: hasT };
23439
+ valTemp = valT;
23440
+ } else {
23441
+ lowerExpr(stmt.init, ctx, scope);
23442
+ const hasT = ctx.freshTemp();
23443
+ const valT = ctx.freshTemp();
23444
+ ctx.emit({ kind: "copy", dst: hasT, src: { kind: "temp", name: "__rf_has" } });
23445
+ ctx.emit({ kind: "copy", dst: valT, src: { kind: "temp", name: "__rf_val" } });
23446
+ hasOp = { kind: "temp", name: hasT };
23447
+ valTemp = valT;
23448
+ }
23449
+ ctx.terminate({ kind: "branch", cond: hasOp, then: bodyBlock.id, else: exitBlock.id });
23450
+ ctx.switchTo(bodyBlock);
23451
+ const bodyScope = new Map(scope);
23452
+ if (valTemp)
23453
+ bodyScope.set(stmt.binding, valTemp);
23454
+ ctx.pushLoop(headerBlock.id, exitBlock.id, headerBlock.id);
23455
+ lowerBlock(stmt.body, ctx, bodyScope);
23456
+ ctx.popLoop();
23457
+ if (isPlaceholderTerm(ctx.current().term)) {
23458
+ ctx.terminate({ kind: "jump", target: headerBlock.id });
23459
+ }
23460
+ ctx.switchTo(exitBlock);
23461
+ break;
23462
+ }
22664
23463
  default: {
22665
23464
  const _exhaustive = stmt;
22666
23465
  throw new Error(`Unknown HIR statement kind: ${_exhaustive.kind}`);
@@ -22723,6 +23522,9 @@ var require_lower2 = __commonJS({
22723
23522
  const temp = scope.get(expr.name);
22724
23523
  if (temp)
22725
23524
  return { kind: "temp", name: temp };
23525
+ if (ctx.constValues.has(expr.name)) {
23526
+ return { kind: "const", value: ctx.constValues.get(expr.name) };
23527
+ }
22726
23528
  const t = ctx.freshTemp();
22727
23529
  ctx.emit({ kind: "copy", dst: t, src: { kind: "const", value: 0 } });
22728
23530
  scope.set(expr.name, t);
@@ -22841,6 +23643,27 @@ var require_lower2 = __commonJS({
22841
23643
  const value = variants?.get(expr.variant) ?? 0;
22842
23644
  return { kind: "const", value };
22843
23645
  }
23646
+ case "enum_construct": {
23647
+ const variants = ctx.enumDefs.get(expr.enumName);
23648
+ const tagValue = variants?.get(expr.variant) ?? 0;
23649
+ const tagTemp = ctx.freshTemp();
23650
+ ctx.emit({ kind: "const", dst: tagTemp, value: tagValue });
23651
+ const payloadFields = ctx.enumPayloads.get(expr.enumName)?.get(expr.variant) ?? [];
23652
+ for (const arg of expr.args) {
23653
+ const fieldDef = payloadFields.find((f) => f.name === arg.name);
23654
+ const argOp = lowerExpr(arg.value, ctx, scope);
23655
+ const nbtType = fieldDef && fieldDef.type.kind === "named" && (fieldDef.type.name === "float" || fieldDef.type.name === "fixed") ? "float" : "int";
23656
+ ctx.emit({
23657
+ kind: "nbt_write",
23658
+ ns: "rs:enums",
23659
+ path: `${expr.enumName}_${arg.name}`,
23660
+ type: nbtType,
23661
+ scale: 1,
23662
+ src: argOp
23663
+ });
23664
+ }
23665
+ return { kind: "temp", name: tagTemp };
23666
+ }
22844
23667
  case "member": {
22845
23668
  if (expr.obj.kind === "ident") {
22846
23669
  const enumVariants = ctx.enumDefs.get(expr.obj.name);
@@ -23101,13 +23924,37 @@ var require_lower2 = __commonJS({
23101
23924
  ctx.emit({ kind: "const", dst: t2, value: 0 });
23102
23925
  return { kind: "temp", name: t2 };
23103
23926
  }
23927
+ if (expr.fn === "int_to_str" || expr.fn === "bool_to_str") {
23928
+ if (expr.args.length === 1) {
23929
+ return lowerExpr(expr.args[0], ctx, scope);
23930
+ }
23931
+ const t2 = ctx.freshTemp();
23932
+ ctx.emit({ kind: "const", dst: t2, value: 0 });
23933
+ return { kind: "temp", name: t2 };
23934
+ }
23104
23935
  if (macro_1.BUILTIN_SET.has(expr.fn)) {
23105
- const cmd = formatBuiltinCall(expr.fn, expr.args, ctx.currentMacroParams, ctx.getNamespace());
23936
+ const TEXT_BUILTINS_SET = /* @__PURE__ */ new Set(["tell", "tellraw", "title", "subtitle", "actionbar", "announce"]);
23937
+ let resolvedArgs = expr.args;
23938
+ if (TEXT_BUILTINS_SET.has(expr.fn)) {
23939
+ resolvedArgs = expr.args.map((arg) => arg.kind === "f_string" ? precomputeFStringParts(arg, ctx, scope) : arg);
23940
+ }
23941
+ const cmd = formatBuiltinCall(expr.fn, resolvedArgs, ctx.currentMacroParams, ctx.getNamespace());
23106
23942
  ctx.emit({ kind: "call", dst: null, fn: `__raw:${cmd}`, args: [] });
23107
23943
  const t2 = ctx.freshTemp();
23108
23944
  ctx.emit({ kind: "const", dst: t2, value: 0 });
23109
23945
  return { kind: "temp", name: t2 };
23110
23946
  }
23947
+ const PARSER_METHOD_REMAP = {
23948
+ "set_add": "add",
23949
+ "set_contains": "contains",
23950
+ "set_remove": "remove",
23951
+ "set_clear": "clear",
23952
+ "__array_push": "push",
23953
+ "__array_pop": "pop",
23954
+ "__entity_tag": "tag",
23955
+ "__entity_untag": "untag",
23956
+ "__entity_has_tag": "has_tag"
23957
+ };
23111
23958
  if (expr.args.length > 0 && expr.args[0].kind === "ident") {
23112
23959
  const sv = ctx.structVars.get(expr.args[0].name);
23113
23960
  if (sv) {
@@ -23118,7 +23965,8 @@ var require_lower2 = __commonJS({
23118
23965
  return lowerTimerMethod(expr.fn, timerId, sv, ctx, scope, expr.args.slice(1));
23119
23966
  }
23120
23967
  }
23121
- const methodInfo = ctx.implMethods.get(sv.typeName)?.get(expr.fn);
23968
+ const originalMethodName = PARSER_METHOD_REMAP[expr.fn] ?? expr.fn;
23969
+ const methodInfo = ctx.implMethods.get(sv.typeName)?.get(expr.fn) ?? ctx.implMethods.get(sv.typeName)?.get(originalMethodName);
23122
23970
  if (methodInfo?.hasSelf) {
23123
23971
  const fields = ctx.structDefs.get(sv.typeName) ?? [];
23124
23972
  const selfArgs = fields.map((f) => {
@@ -23142,7 +23990,7 @@ var require_lower2 = __commonJS({
23142
23990
  }
23143
23991
  const allArgs = [...selfArgs, ...explicitArgs];
23144
23992
  const t2 = ctx.freshTemp();
23145
- ctx.emit({ kind: "call", dst: t2, fn: `${sv.typeName}::${expr.fn}`, args: allArgs });
23993
+ ctx.emit({ kind: "call", dst: t2, fn: `${sv.typeName}::${originalMethodName}`, args: allArgs });
23146
23994
  return { kind: "temp", name: t2 };
23147
23995
  }
23148
23996
  }
@@ -23188,7 +24036,7 @@ var require_lower2 = __commonJS({
23188
24036
  const specializedName = `${expr.fn}__arr_${bindingKey}`;
23189
24037
  if (!ctx.specializedFnsRegistry.has(specializedName)) {
23190
24038
  ctx.specializedFnsRegistry.set(specializedName, []);
23191
- const { fn: specFn, helpers: specHelpers } = lowerFunction(targetHirFn, ctx.getNamespace(), ctx.structDefs, ctx.implMethods, ctx.macroInfo, ctx.fnParamInfo, ctx.enumDefs, ctx.sourceFile, ctx.timerCounter, arrayArgBindings, ctx.hirFunctions, ctx.specializedFnsRegistry, specializedName);
24039
+ const { fn: specFn, helpers: specHelpers } = lowerFunction(targetHirFn, ctx.getNamespace(), ctx.structDefs, ctx.implMethods, ctx.macroInfo, ctx.fnParamInfo, ctx.enumDefs, ctx.sourceFile, ctx.timerCounter, arrayArgBindings, ctx.hirFunctions, ctx.specializedFnsRegistry, specializedName, ctx.enumPayloads);
23192
24040
  ctx.specializedFnsRegistry.set(specializedName, [specFn, ...specHelpers]);
23193
24041
  }
23194
24042
  const nonArrayArgs = [];
@@ -23207,6 +24055,34 @@ var require_lower2 = __commonJS({
23207
24055
  {
23208
24056
  const targetParams = ctx.fnParamInfo.get(expr.fn);
23209
24057
  if (targetParams) {
24058
+ const hasStringParam = targetParams.some((p) => p.type.kind === "named" && (p.type.name === "string" || p.type.name === "format_string"));
24059
+ if (hasStringParam) {
24060
+ const nonStringArgs = [];
24061
+ let stringSlot = 0;
24062
+ for (let i = 0; i < targetParams.length && i < expr.args.length; i++) {
24063
+ const p = targetParams[i];
24064
+ if (p.type.kind === "named" && (p.type.name === "string" || p.type.name === "format_string")) {
24065
+ const srcPath = lowerStringExprToPath(expr.args[i], ctx, scope, `arg${stringSlot}`);
24066
+ if (srcPath) {
24067
+ ctx.emit({
24068
+ kind: "call",
24069
+ dst: null,
24070
+ fn: `__raw:data modify storage rs:strings __sp${stringSlot} set from storage rs:strings ${srcPath}`,
24071
+ args: []
24072
+ });
24073
+ }
24074
+ stringSlot++;
24075
+ } else {
24076
+ nonStringArgs.push(lowerExpr(expr.args[i], ctx, scope));
24077
+ }
24078
+ }
24079
+ for (let i = targetParams.length; i < expr.args.length; i++) {
24080
+ nonStringArgs.push(lowerExpr(expr.args[i], ctx, scope));
24081
+ }
24082
+ const t2 = ctx.freshTemp();
24083
+ ctx.emit({ kind: "call", dst: t2, fn: expr.fn, args: nonStringArgs });
24084
+ return { kind: "temp", name: t2 };
24085
+ }
23210
24086
  const hasDoubleParam = targetParams.some((p) => p.type.kind === "named" && p.type.name === "double");
23211
24087
  if (hasDoubleParam) {
23212
24088
  const ns = ctx.getNamespace();
@@ -23287,6 +24163,31 @@ var require_lower2 = __commonJS({
23287
24163
  }
23288
24164
  }
23289
24165
  }
24166
+ if (expr.callee.kind === "member" && expr.callee.obj.kind !== "ident") {
24167
+ const returnedStructType = inferInvokeReturnStructType(expr.callee.obj, ctx);
24168
+ if (returnedStructType) {
24169
+ lowerExpr(expr.callee.obj, ctx, scope);
24170
+ const chainFields = ctx.structDefs.get(returnedStructType) ?? [];
24171
+ const chainFieldTemps = /* @__PURE__ */ new Map();
24172
+ for (const fieldName of chainFields) {
24173
+ const ft = ctx.freshTemp();
24174
+ ctx.emit({ kind: "copy", dst: ft, src: { kind: "temp", name: `__rf_${fieldName}` } });
24175
+ chainFieldTemps.set(fieldName, ft);
24176
+ }
24177
+ const methodInfo = ctx.implMethods.get(returnedStructType)?.get(expr.callee.field);
24178
+ if (methodInfo?.hasSelf) {
24179
+ const selfArgs = chainFields.map((f) => {
24180
+ const temp = chainFieldTemps.get(f);
24181
+ return temp ? { kind: "temp", name: temp } : { kind: "const", value: 0 };
24182
+ });
24183
+ const explicitArgs = expr.args.map((a) => lowerExpr(a, ctx, scope));
24184
+ const allArgs = [...selfArgs, ...explicitArgs];
24185
+ const ct = ctx.freshTemp();
24186
+ ctx.emit({ kind: "call", dst: ct, fn: `${returnedStructType}::${expr.callee.field}`, args: allArgs });
24187
+ return { kind: "temp", name: ct };
24188
+ }
24189
+ }
24190
+ }
23290
24191
  const calleeOp = lowerExpr(expr.callee, ctx, scope);
23291
24192
  const args = expr.args.map((a) => lowerExpr(a, ctx, scope));
23292
24193
  const t = ctx.freshTemp();
@@ -23308,6 +24209,25 @@ var require_lower2 = __commonJS({
23308
24209
  ctx.emit({ kind: "const", dst: t2, value: 0 });
23309
24210
  return { kind: "temp", name: t2 };
23310
24211
  }
24212
+ if (ctx.singletonStructs.has(expr.type)) {
24213
+ if (expr.method === "get") {
24214
+ const t2 = ctx.freshTemp();
24215
+ ctx.emit({ kind: "call", dst: t2, fn: `${expr.type}::${expr.method}`, args: [] });
24216
+ return { kind: "temp", name: t2 };
24217
+ } else if (expr.method === "set" && expr.args.length === 1 && expr.args[0].kind === "ident") {
24218
+ const sv = ctx.structVars.get(expr.args[0].name);
24219
+ if (sv) {
24220
+ const fields = ctx.structDefs.get(sv.typeName) ?? [];
24221
+ const fieldArgs = fields.map((f) => {
24222
+ const temp = sv.fields.get(f);
24223
+ return temp ? { kind: "temp", name: temp } : { kind: "const", value: 0 };
24224
+ });
24225
+ const t2 = ctx.freshTemp();
24226
+ ctx.emit({ kind: "call", dst: t2, fn: `${expr.type}::${expr.method}`, args: fieldArgs });
24227
+ return { kind: "temp", name: t2 };
24228
+ }
24229
+ }
24230
+ }
23311
24231
  const args = expr.args.map((a) => lowerExpr(a, ctx, scope));
23312
24232
  const t = ctx.freshTemp();
23313
24233
  ctx.emit({ kind: "call", dst: t, fn: `${expr.type}::${expr.method}`, args });
@@ -23337,6 +24257,41 @@ var require_lower2 = __commonJS({
23337
24257
  ctx.emit({ kind: "const", dst: t, value: 0 });
23338
24258
  return { kind: "temp", name: t };
23339
24259
  }
24260
+ case "unwrap_or": {
24261
+ const resultTemp = ctx.freshTemp();
24262
+ const defaultOp = lowerExpr(expr.default_, ctx, scope);
24263
+ ctx.emit({ kind: "copy", dst: resultTemp, src: defaultOp });
24264
+ const sv = (() => {
24265
+ if (expr.opt.kind === "ident")
24266
+ return ctx.structVars.get(expr.opt.name);
24267
+ return void 0;
24268
+ })();
24269
+ let hasOp;
24270
+ let valTemp;
24271
+ if (sv && sv.typeName === "__option") {
24272
+ const hasT = sv.fields.get("has");
24273
+ const valT = sv.fields.get("val");
24274
+ hasOp = { kind: "temp", name: hasT };
24275
+ valTemp = valT;
24276
+ } else {
24277
+ lowerExpr(expr.opt, ctx, scope);
24278
+ const hasT = ctx.freshTemp();
24279
+ const valT = ctx.freshTemp();
24280
+ ctx.emit({ kind: "copy", dst: hasT, src: { kind: "temp", name: "__rf_has" } });
24281
+ ctx.emit({ kind: "copy", dst: valT, src: { kind: "temp", name: "__rf_val" } });
24282
+ hasOp = { kind: "temp", name: hasT };
24283
+ valTemp = valT;
24284
+ }
24285
+ const someBlock = ctx.newBlock("unwrap_some");
24286
+ const mergeBlock = ctx.newBlock("unwrap_merge");
24287
+ ctx.terminate({ kind: "branch", cond: hasOp, then: someBlock.id, else: mergeBlock.id });
24288
+ ctx.switchTo(someBlock);
24289
+ if (valTemp)
24290
+ ctx.emit({ kind: "copy", dst: resultTemp, src: { kind: "temp", name: valTemp } });
24291
+ ctx.terminate({ kind: "jump", target: mergeBlock.id });
24292
+ ctx.switchTo(mergeBlock);
24293
+ return { kind: "temp", name: resultTemp };
24294
+ }
23340
24295
  case "type_cast": {
23341
24296
  const ns = ctx.getNamespace();
23342
24297
  const targetName = expr.targetType.kind === "named" ? expr.targetType.name : null;
@@ -23438,6 +24393,23 @@ var require_lower2 = __commonJS({
23438
24393
  ctx.switchTo(merge);
23439
24394
  return { kind: "temp", name: result };
23440
24395
  }
24396
+ function inferInvokeReturnStructType(expr, ctx) {
24397
+ if (expr.kind === "invoke" && expr.callee.kind === "member") {
24398
+ let receiverTypeName;
24399
+ if (expr.callee.obj.kind === "ident") {
24400
+ receiverTypeName = ctx.structVars.get(expr.callee.obj.name)?.typeName;
24401
+ } else {
24402
+ receiverTypeName = inferInvokeReturnStructType(expr.callee.obj, ctx);
24403
+ }
24404
+ if (receiverTypeName) {
24405
+ const methodInfo = ctx.implMethods.get(receiverTypeName)?.get(expr.callee.field);
24406
+ if (methodInfo?.returnStructName) {
24407
+ return methodInfo.returnStructName;
24408
+ }
24409
+ }
24410
+ }
24411
+ return void 0;
24412
+ }
23441
24413
  function lowerTimerMethod(method, timerId, sv, ctx, scope, extraArgs) {
23442
24414
  const ns = ctx.getNamespace();
23443
24415
  const player = `__timer_${timerId}`;
@@ -23557,6 +24529,39 @@ var require_lower2 = __commonJS({
23557
24529
  }
23558
24530
  }
23559
24531
  }
24532
+ function lowerStringExprToPath(expr, ctx, scope, hint = "str") {
24533
+ switch (expr.kind) {
24534
+ case "str_lit": {
24535
+ const path3 = ctx.freshStringVar(hint);
24536
+ ctx.emit({
24537
+ kind: "call",
24538
+ dst: null,
24539
+ fn: `__raw:data modify storage rs:strings ${path3} set value ${JSON.stringify(expr.value)}`,
24540
+ args: []
24541
+ });
24542
+ return path3;
24543
+ }
24544
+ case "ident":
24545
+ return ctx.stringVars.get(expr.name) ?? null;
24546
+ case "assign": {
24547
+ if (!ctx.stringVars.has(expr.target))
24548
+ return null;
24549
+ const dstPath = ctx.stringVars.get(expr.target);
24550
+ const srcPath = lowerStringExprToPath(expr.value, ctx, scope, expr.target);
24551
+ if (!srcPath || srcPath === dstPath)
24552
+ return dstPath;
24553
+ ctx.emit({
24554
+ kind: "call",
24555
+ dst: null,
24556
+ fn: `__raw:data modify storage rs:strings ${dstPath} set from storage rs:strings ${srcPath}`,
24557
+ args: []
24558
+ });
24559
+ return dstPath;
24560
+ }
24561
+ default:
24562
+ return null;
24563
+ }
24564
+ }
23560
24565
  function selectorToString(sel) {
23561
24566
  if (!sel.filters || Object.keys(sel.filters).length === 0) {
23562
24567
  return sel.kind;
@@ -23579,6 +24584,47 @@ var require_lower2 = __commonJS({
23579
24584
  return `${sel.kind}[${parts.join(",")}]`;
23580
24585
  }
23581
24586
  var MACRO_SENTINEL = "";
24587
+ function precomputeFStringParts(expr, ctx, scope) {
24588
+ if (expr.kind !== "f_string")
24589
+ return expr;
24590
+ const newParts = [];
24591
+ for (const part of expr.parts) {
24592
+ if (part.kind === "text") {
24593
+ newParts.push(part);
24594
+ continue;
24595
+ }
24596
+ const inner = part.expr;
24597
+ if (inner.kind === "ident" || inner.kind === "int_lit" || inner.kind === "bool_lit") {
24598
+ newParts.push({ kind: "expr", expr: inner });
24599
+ continue;
24600
+ }
24601
+ if (inner.kind === "call" && (inner.fn === "int_to_str" || inner.fn === "bool_to_str") && inner.args.length === 1) {
24602
+ const arg = inner.args[0];
24603
+ if (arg.kind === "ident") {
24604
+ newParts.push({ kind: "expr", expr: arg });
24605
+ continue;
24606
+ }
24607
+ const argOp = lowerExpr(arg, ctx, scope);
24608
+ if (argOp.kind === "temp") {
24609
+ newParts.push({ kind: "expr", expr: { kind: "ident", name: argOp.name } });
24610
+ } else if (argOp.kind === "const") {
24611
+ newParts.push({ kind: "expr", expr: { kind: "int_lit", value: argOp.value } });
24612
+ } else {
24613
+ newParts.push(part);
24614
+ }
24615
+ continue;
24616
+ }
24617
+ const tempOp = lowerExpr(inner, ctx, scope);
24618
+ if (tempOp.kind === "temp") {
24619
+ newParts.push({ kind: "expr", expr: { kind: "ident", name: tempOp.name } });
24620
+ } else if (tempOp.kind === "const") {
24621
+ newParts.push({ kind: "expr", expr: { kind: "int_lit", value: tempOp.value } });
24622
+ } else {
24623
+ newParts.push(part);
24624
+ }
24625
+ }
24626
+ return { kind: "f_string", parts: newParts };
24627
+ }
23582
24628
  function fStringToJsonText(expr, namespace) {
23583
24629
  if (expr.kind !== "f_string")
23584
24630
  return JSON.stringify(expr.kind === "str_lit" ? { text: expr.value } : { text: "~" });
@@ -23594,6 +24640,8 @@ var require_lower2 = __commonJS({
23594
24640
  extra.push({ score: { name: `$${inner.name}`, objective } });
23595
24641
  } else if (inner.kind === "int_lit") {
23596
24642
  extra.push({ text: String(inner.value) });
24643
+ } else if (inner.kind === "bool_lit") {
24644
+ extra.push({ text: inner.value ? "true" : "false" });
23597
24645
  } else {
23598
24646
  extra.push({ text: "?" });
23599
24647
  }
@@ -24789,6 +25837,219 @@ var require_interprocedural = __commonJS({
24789
25837
  }
24790
25838
  });
24791
25839
 
25840
+ // ../../dist/src/optimizer/inline.js
25841
+ var require_inline = __commonJS({
25842
+ "../../dist/src/optimizer/inline.js"(exports2) {
25843
+ "use strict";
25844
+ Object.defineProperty(exports2, "__esModule", { value: true });
25845
+ exports2.inlinePass = inlinePass;
25846
+ var _inlineCounter = 0;
25847
+ function freshInlineId() {
25848
+ return `__inline_${_inlineCounter++}`;
25849
+ }
25850
+ function inlinePass(mod) {
25851
+ const inlineSet = mod.inlineFunctions;
25852
+ if (!inlineSet || inlineSet.size === 0)
25853
+ return mod;
25854
+ const fnMap = new Map(mod.functions.map((f) => [f.name, f]));
25855
+ const updatedFunctions = mod.functions.map((fn) => inlineCallsInFunction(fn, fnMap, inlineSet));
25856
+ return { ...mod, functions: updatedFunctions };
25857
+ }
25858
+ function inlineCallsInFunction(fn, fnMap, inlineSet) {
25859
+ let blocks = fn.blocks.map((b) => ({ ...b, instrs: [...b.instrs] }));
25860
+ let changed = true;
25861
+ while (changed) {
25862
+ changed = false;
25863
+ const nextBlocks = [];
25864
+ for (const block of blocks) {
25865
+ const callIdx = block.instrs.findIndex((instr) => {
25866
+ if (instr.kind !== "call")
25867
+ return false;
25868
+ if (!inlineSet.has(instr.fn))
25869
+ return false;
25870
+ const callee2 = fnMap.get(instr.fn);
25871
+ if (!callee2)
25872
+ return false;
25873
+ if (callee2.isMacro)
25874
+ return false;
25875
+ if (callee2.name === fn.name)
25876
+ return false;
25877
+ if (isSelfRecursive(callee2))
25878
+ return false;
25879
+ if (callee2.params.length !== instr.args.length)
25880
+ return false;
25881
+ return true;
25882
+ });
25883
+ if (callIdx === -1) {
25884
+ nextBlocks.push(block);
25885
+ continue;
25886
+ }
25887
+ changed = true;
25888
+ const callInstr = block.instrs[callIdx];
25889
+ const callee = fnMap.get(callInstr.fn);
25890
+ const inlineId = freshInlineId();
25891
+ const priorInstrs = block.instrs.slice(0, callIdx);
25892
+ const afterInstrs = block.instrs.slice(callIdx + 1);
25893
+ const contBlockId = `${block.id}${inlineId}_cont`;
25894
+ const clonedBlocks = cloneCallee(callee, inlineId, callInstr.args, callInstr.dst, contBlockId);
25895
+ const clonedEntryId = `${callee.entry}${inlineId}`;
25896
+ const patchedCurrentBlock = {
25897
+ ...block,
25898
+ instrs: priorInstrs,
25899
+ term: { kind: "jump", target: clonedEntryId }
25900
+ };
25901
+ const contBlock = {
25902
+ id: contBlockId,
25903
+ instrs: afterInstrs,
25904
+ term: block.term,
25905
+ preds: []
25906
+ };
25907
+ nextBlocks.push(patchedCurrentBlock, ...clonedBlocks, contBlock);
25908
+ }
25909
+ blocks = nextBlocks;
25910
+ }
25911
+ return { ...fn, blocks };
25912
+ }
25913
+ function cloneCallee(callee, inlineId, args, dst, contBlockId) {
25914
+ const sub = /* @__PURE__ */ new Map();
25915
+ for (let i = 0; i < callee.params.length; i++) {
25916
+ sub.set(callee.params[i].name, args[i]);
25917
+ }
25918
+ const calleeTemps = /* @__PURE__ */ new Set();
25919
+ for (const block of callee.blocks) {
25920
+ collectDefinedTemps(block, calleeTemps);
25921
+ }
25922
+ const tempRename = /* @__PURE__ */ new Map();
25923
+ for (const tmp of calleeTemps) {
25924
+ if (!sub.has(tmp)) {
25925
+ tempRename.set(tmp, `${tmp}${inlineId}`);
25926
+ }
25927
+ }
25928
+ const fullSub = new Map([...sub]);
25929
+ for (const [old, renamed] of tempRename) {
25930
+ fullSub.set(old, { kind: "temp", name: renamed });
25931
+ }
25932
+ const blockRename = (id) => `${id}${inlineId}`;
25933
+ return callee.blocks.map((block) => cloneBlock(block, inlineId, fullSub, blockRename, dst, contBlockId));
25934
+ }
25935
+ function collectDefinedTemps(block, out) {
25936
+ const collect = (instr) => {
25937
+ if ("dst" in instr && instr.dst !== null && instr.dst !== void 0) {
25938
+ out.add(instr.dst);
25939
+ }
25940
+ };
25941
+ block.instrs.forEach(collect);
25942
+ collect(block.term);
25943
+ }
25944
+ function cloneBlock(block, inlineId, sub, blockRename, callDst, contBlockId) {
25945
+ const newId = blockRename(block.id);
25946
+ const newInstrs = block.instrs.map((instr) => subAndRenameInstr(instr, sub, blockRename));
25947
+ let newTerm;
25948
+ const term = block.term;
25949
+ if (term.kind === "return") {
25950
+ const retInstrs = [];
25951
+ if (term.value !== null && callDst !== null) {
25952
+ const subbed = substituteOp(term.value, sub);
25953
+ retInstrs.push({ kind: "copy", dst: callDst, src: subbed });
25954
+ }
25955
+ return {
25956
+ id: newId,
25957
+ instrs: [...newInstrs, ...retInstrs],
25958
+ term: { kind: "jump", target: contBlockId },
25959
+ preds: block.preds.map(blockRename)
25960
+ };
25961
+ } else {
25962
+ newTerm = subAndRenameInstr(term, sub, blockRename);
25963
+ }
25964
+ return {
25965
+ id: newId,
25966
+ instrs: newInstrs,
25967
+ term: newTerm,
25968
+ preds: block.preds.map(blockRename)
25969
+ };
25970
+ }
25971
+ function substituteOp(op, sub) {
25972
+ if (op.kind === "temp") {
25973
+ const replacement = sub.get(op.name);
25974
+ if (replacement !== void 0)
25975
+ return replacement;
25976
+ }
25977
+ return op;
25978
+ }
25979
+ function renameBlockId(id, blockRename) {
25980
+ return blockRename(id);
25981
+ }
25982
+ function subAndRenameInstr(instr, sub, blockRename) {
25983
+ const renameDst = (dst) => {
25984
+ if (dst === null)
25985
+ return null;
25986
+ const r = sub.get(dst);
25987
+ if (r && r.kind === "temp")
25988
+ return r.name;
25989
+ return dst;
25990
+ };
25991
+ switch (instr.kind) {
25992
+ case "const":
25993
+ return { ...instr, dst: renameDst(instr.dst) };
25994
+ case "copy":
25995
+ return { ...instr, dst: renameDst(instr.dst), src: substituteOp(instr.src, sub) };
25996
+ case "neg":
25997
+ case "not":
25998
+ return { ...instr, dst: renameDst(instr.dst), src: substituteOp(instr.src, sub) };
25999
+ case "add":
26000
+ case "sub":
26001
+ case "mul":
26002
+ case "div":
26003
+ case "mod":
26004
+ case "and":
26005
+ case "or":
26006
+ return { ...instr, dst: renameDst(instr.dst), a: substituteOp(instr.a, sub), b: substituteOp(instr.b, sub) };
26007
+ case "cmp":
26008
+ return { ...instr, dst: renameDst(instr.dst), a: substituteOp(instr.a, sub), b: substituteOp(instr.b, sub) };
26009
+ case "nbt_read":
26010
+ return { ...instr, dst: renameDst(instr.dst) };
26011
+ case "nbt_read_dynamic":
26012
+ return { ...instr, dst: renameDst(instr.dst), indexSrc: substituteOp(instr.indexSrc, sub) };
26013
+ case "nbt_write":
26014
+ return { ...instr, src: substituteOp(instr.src, sub) };
26015
+ case "nbt_write_dynamic":
26016
+ return { ...instr, indexSrc: substituteOp(instr.indexSrc, sub), valueSrc: substituteOp(instr.valueSrc, sub) };
26017
+ case "nbt_list_len":
26018
+ return { ...instr, dst: renameDst(instr.dst) };
26019
+ case "score_read":
26020
+ return { ...instr, dst: renameDst(instr.dst) };
26021
+ case "score_write":
26022
+ return { ...instr, src: substituteOp(instr.src, sub) };
26023
+ case "call":
26024
+ return { ...instr, dst: renameDst(instr.dst), args: instr.args.map((a) => substituteOp(a, sub)) };
26025
+ case "call_macro":
26026
+ return { ...instr, dst: renameDst(instr.dst), args: instr.args.map((a) => ({ ...a, value: substituteOp(a.value, sub) })) };
26027
+ case "call_context":
26028
+ return instr;
26029
+ case "jump":
26030
+ return { ...instr, target: renameBlockId(instr.target, blockRename) };
26031
+ case "branch":
26032
+ return { ...instr, cond: substituteOp(instr.cond, sub), then: renameBlockId(instr.then, blockRename), else: renameBlockId(instr.else, blockRename) };
26033
+ case "return":
26034
+ return { ...instr, value: instr.value ? substituteOp(instr.value, sub) : null };
26035
+ default:
26036
+ return instr;
26037
+ }
26038
+ }
26039
+ function isSelfRecursive(fn) {
26040
+ for (const block of fn.blocks) {
26041
+ for (const instr of block.instrs) {
26042
+ if (instr.kind === "call" && instr.fn === fn.name)
26043
+ return true;
26044
+ if (instr.kind === "call_macro" && instr.fn === fn.name)
26045
+ return true;
26046
+ }
26047
+ }
26048
+ return false;
26049
+ }
26050
+ }
26051
+ });
26052
+
24792
26053
  // ../../dist/src/optimizer/selector-cache.js
24793
26054
  var require_selector_cache = __commonJS({
24794
26055
  "../../dist/src/optimizer/selector-cache.js"(exports2) {
@@ -24879,6 +26140,7 @@ var require_pipeline = __commonJS({
24879
26140
  var unroll_1 = require_unroll();
24880
26141
  var nbt_batch_1 = require_nbt_batch();
24881
26142
  var interprocedural_1 = require_interprocedural();
26143
+ var inline_1 = require_inline();
24882
26144
  var selector_cache_1 = require_selector_cache();
24883
26145
  Object.defineProperty(exports2, "selectorCache", { enumerable: true, get: function() {
24884
26146
  return selector_cache_1.selectorCache;
@@ -24906,9 +26168,10 @@ var require_pipeline = __commonJS({
24906
26168
  return current;
24907
26169
  }
24908
26170
  function optimizeModule(mod, passes) {
26171
+ const inlined = (0, inline_1.inlinePass)(mod);
24909
26172
  const perFnOptimized = {
24910
- ...mod,
24911
- functions: mod.functions.map((fn) => optimizeFunction(fn, passes))
26173
+ ...inlined,
26174
+ functions: inlined.functions.map((fn) => optimizeFunction(fn, passes))
24912
26175
  };
24913
26176
  return (0, interprocedural_1.interproceduralConstProp)(perFnOptimized);
24914
26177
  }
@@ -25165,6 +26428,17 @@ var require_lower3 = __commonJS({
25165
26428
  });
25166
26429
  break;
25167
26430
  }
26431
+ case "string_match": {
26432
+ const dst = ctx.slot(instr.dst);
26433
+ const dstStr = `${dst.player} ${dst.obj}`;
26434
+ const literal = JSON.stringify(instr.value);
26435
+ instrs.push({ kind: "score_set", dst, value: 0 });
26436
+ instrs.push({
26437
+ kind: "raw",
26438
+ cmd: `execute if data storage ${instr.ns} ${instr.path} matches ${literal} run scoreboard players set ${dstStr} 1`
26439
+ });
26440
+ break;
26441
+ }
25168
26442
  case "and": {
25169
26443
  lowerOperandToSlot(instr.dst, instr.a, ctx, instrs);
25170
26444
  lowerBinOp(instr.dst, instr.b, "score_mul", ctx, instrs);
@@ -25198,8 +26472,13 @@ var require_lower3 = __commonJS({
25198
26472
  }
25199
26473
  case "nbt_list_len": {
25200
26474
  const dst = ctx.slot(instr.dst);
25201
- const ns = ctx.namespace;
25202
- instrs.push({ kind: "raw", cmd: `execute store result score ${dst} __${ns} run data get storage ${instr.ns} ${instr.path}` });
26475
+ instrs.push({
26476
+ kind: "store_nbt_to_score",
26477
+ dst,
26478
+ ns: instr.ns,
26479
+ path: instr.path,
26480
+ scale: 1
26481
+ });
25203
26482
  break;
25204
26483
  }
25205
26484
  case "nbt_read_dynamic": {
@@ -25871,6 +27150,9 @@ var require_emit = __commonJS({
25871
27150
  const tickFns = options.tickFunctions ?? [];
25872
27151
  const loadFns = options.loadFunctions ?? [];
25873
27152
  const scheduleFns = options.scheduleFunctions ?? [];
27153
+ const watchFns = options.watchFunctions ?? [];
27154
+ const profiledFns = options.profiledFunctions ?? [];
27155
+ const enableProfiling = options.enableProfiling ?? false;
25874
27156
  const objective = module3.objective;
25875
27157
  const genSourceMap = options.generateSourceMap ?? false;
25876
27158
  const mcVersion = options.mcVersion ?? mc_version_1.DEFAULT_MC_VERSION;
@@ -25881,7 +27163,16 @@ var require_emit = __commonJS({
25881
27163
  pack: { pack_format: 26, description: `RedScript datapack: ${namespace}` }
25882
27164
  }, null, 2) + "\n"
25883
27165
  });
25884
- const loadCmds = [`scoreboard objectives add ${objective} dummy`];
27166
+ const singletonObjectives = options.singletonObjectives ?? [];
27167
+ const loadCmds = [
27168
+ `scoreboard objectives add ${objective} dummy`,
27169
+ ...watchFns.map((watch) => `scoreboard objectives add ${watchPrevObjective(watch.name)} dummy`),
27170
+ ...singletonObjectives.map((obj) => `scoreboard objectives add ${obj} dummy`),
27171
+ ...enableProfiling && profiledFns.length > 0 ? [
27172
+ "scoreboard objectives add __time dummy",
27173
+ "scoreboard objectives add __profile dummy"
27174
+ ] : []
27175
+ ];
25885
27176
  files.push({
25886
27177
  path: `data/${namespace}/function/load.mcfunction`,
25887
27178
  content: loadCmds.join("\n") + "\n"
@@ -25890,17 +27181,27 @@ var require_emit = __commonJS({
25890
27181
  const fnPath = fnNameToPath(fn.name, namespace);
25891
27182
  if (genSourceMap) {
25892
27183
  const builder = new sourcemap_1.SourceMapBuilder(fnPath);
25893
- const lines = emitFunctionWithSourceMap(fn, namespace, objective, builder, mcVersion);
27184
+ const lines = emitFunctionWithSourceMap(fn, namespace, objective, builder, mcVersion, enableProfiling && profiledFns.includes(fn.name));
25894
27185
  files.push({ path: fnPath, content: lines.join("\n") + "\n" });
25895
27186
  const map = builder.build();
25896
27187
  if (map) {
25897
27188
  files.push({ path: (0, sourcemap_1.sourceMapPath)(fnPath), content: (0, sourcemap_1.serializeSourceMap)(map) });
25898
27189
  }
25899
27190
  } else {
25900
- const lines = emitFunction(fn, namespace, objective, mcVersion);
27191
+ const lines = emitFunction(fn, namespace, objective, mcVersion, enableProfiling && profiledFns.includes(fn.name));
25901
27192
  files.push({ path: fnPath, content: lines.join("\n") + "\n" });
25902
27193
  }
25903
27194
  }
27195
+ if (enableProfiling && profiledFns.length > 0) {
27196
+ files.push({
27197
+ path: `data/${namespace}/function/__profiler_reset.mcfunction`,
27198
+ content: emitProfilerReset(profiledFns).join("\n") + "\n"
27199
+ });
27200
+ files.push({
27201
+ path: `data/${namespace}/function/__profiler_report.mcfunction`,
27202
+ content: emitProfilerReport(profiledFns).join("\n") + "\n"
27203
+ });
27204
+ }
25904
27205
  for (const { name, ticks } of scheduleFns) {
25905
27206
  files.push({
25906
27207
  path: `data/${namespace}/function/_schedule_${name}.mcfunction`,
@@ -25908,6 +27209,19 @@ var require_emit = __commonJS({
25908
27209
  `
25909
27210
  });
25910
27211
  }
27212
+ for (const watch of watchFns) {
27213
+ const dispatcher = watchDispatcherName(watch.name);
27214
+ const prevObjective = watchPrevObjective(watch.name);
27215
+ const changedCondition = `unless score @s ${watch.objective} = @s ${prevObjective}`;
27216
+ files.push({
27217
+ path: fnNameToPath(dispatcher, namespace),
27218
+ content: [
27219
+ `execute as @a unless score @s ${prevObjective} = @s ${prevObjective} run scoreboard players operation @s ${prevObjective} = @s ${watch.objective}`,
27220
+ `execute as @a ${changedCondition} run function ${namespace}:${watch.name}`,
27221
+ `execute as @a ${changedCondition} run scoreboard players operation @s ${prevObjective} = @s ${watch.objective}`
27222
+ ].join("\n") + "\n"
27223
+ });
27224
+ }
25911
27225
  if (loadFns.length > 0 || true) {
25912
27226
  const loadValues = [`${namespace}:load`, ...loadFns.map((fn) => `${namespace}:${fn}`)];
25913
27227
  files.push({
@@ -25915,8 +27229,9 @@ var require_emit = __commonJS({
25915
27229
  content: JSON.stringify({ values: loadValues }, null, 2) + "\n"
25916
27230
  });
25917
27231
  }
25918
- if (tickFns.length > 0) {
25919
- const tickValues = tickFns.map((fn) => `${namespace}:${fn}`);
27232
+ const allTickFns = [...tickFns, ...watchFns.map((watch) => watchDispatcherName(watch.name))];
27233
+ if (allTickFns.length > 0) {
27234
+ const tickValues = allTickFns.map((fn) => `${namespace}:${fn}`);
25920
27235
  files.push({
25921
27236
  path: "data/minecraft/tags/function/tick.json",
25922
27237
  content: JSON.stringify({ values: tickValues }, null, 2) + "\n"
@@ -25942,25 +27257,87 @@ var require_emit = __commonJS({
25942
27257
  }
25943
27258
  return files;
25944
27259
  }
25945
- function emitFunction(fn, namespace, objective, mcVersion) {
25946
- const lines = [];
27260
+ function emitFunction(fn, namespace, objective, mcVersion, isProfiled = false) {
27261
+ const lines = isProfiled ? profilerStartLines(fn.name) : [];
25947
27262
  for (const instr of fn.instructions) {
25948
27263
  lines.push(emitInstr(instr, namespace, objective, mcVersion));
25949
27264
  }
27265
+ if (isProfiled) {
27266
+ lines.push(...profilerEndLines(fn.name));
27267
+ }
25950
27268
  return lines;
25951
27269
  }
25952
- function emitFunctionWithSourceMap(fn, namespace, objective, builder, mcVersion) {
27270
+ function emitFunctionWithSourceMap(fn, namespace, objective, builder, mcVersion, isProfiled = false) {
25953
27271
  const lines = [];
27272
+ if (isProfiled) {
27273
+ for (const line of profilerStartLines(fn.name)) {
27274
+ lines.push(line);
27275
+ builder.addLine(void 0);
27276
+ }
27277
+ }
25954
27278
  for (const instr of fn.instructions) {
25955
27279
  lines.push(emitInstr(instr, namespace, objective, mcVersion));
25956
27280
  builder.addLine(instr.sourceLoc);
25957
27281
  }
27282
+ if (isProfiled) {
27283
+ for (const line of profilerEndLines(fn.name)) {
27284
+ lines.push(line);
27285
+ builder.addLine(void 0);
27286
+ }
27287
+ }
25958
27288
  return lines;
25959
27289
  }
25960
27290
  function fnNameToPath(name, namespace) {
25961
27291
  const mcName = name.replace(/::/g, "/").toLowerCase();
25962
27292
  return `data/${namespace}/function/${mcName}.mcfunction`;
25963
27293
  }
27294
+ function watchDispatcherName(name) {
27295
+ return `__watch_${name}`;
27296
+ }
27297
+ function watchPrevObjective(name) {
27298
+ return `__watch_${name}_prev`;
27299
+ }
27300
+ function profilerSafeName(name) {
27301
+ return name.replace(/[^A-Za-z0-9_]/g, "_");
27302
+ }
27303
+ function profilerStartPlayer(name) {
27304
+ return `#prof_start_${profilerSafeName(name)}`;
27305
+ }
27306
+ function profilerDeltaPlayer(name) {
27307
+ return `#prof_delta_${profilerSafeName(name)}`;
27308
+ }
27309
+ function profilerTotalPlayer(name) {
27310
+ return `#prof_total_${profilerSafeName(name)}`;
27311
+ }
27312
+ function profilerCountPlayer(name) {
27313
+ return `#prof_count_${profilerSafeName(name)}`;
27314
+ }
27315
+ function profilerStartLines(name) {
27316
+ return [
27317
+ `# __profiler_start_${name}`,
27318
+ `scoreboard players set ${profilerStartPlayer(name)} __time 0`,
27319
+ `execute store result score ${profilerStartPlayer(name)} __time run time query gametime`
27320
+ ];
27321
+ }
27322
+ function profilerEndLines(name) {
27323
+ return [
27324
+ `# __profiler_end_${name}`,
27325
+ `scoreboard players set ${profilerDeltaPlayer(name)} __time 0`,
27326
+ `execute store result score ${profilerDeltaPlayer(name)} __time run time query gametime`,
27327
+ `scoreboard players operation ${profilerDeltaPlayer(name)} __time -= ${profilerStartPlayer(name)} __time`,
27328
+ `scoreboard players operation ${profilerTotalPlayer(name)} __profile += ${profilerDeltaPlayer(name)} __time`,
27329
+ `scoreboard players add ${profilerCountPlayer(name)} __profile 1`
27330
+ ];
27331
+ }
27332
+ function emitProfilerReset(profiledFns) {
27333
+ return profiledFns.flatMap((name) => [
27334
+ `scoreboard players set ${profilerTotalPlayer(name)} __profile 0`,
27335
+ `scoreboard players set ${profilerCountPlayer(name)} __profile 0`
27336
+ ]);
27337
+ }
27338
+ function emitProfilerReport(profiledFns) {
27339
+ return profiledFns.map((name) => `tellraw @a [{"text":"[profile] ${name}: total="},{"score":{"name":"${profilerTotalPlayer(name)}","objective":"__profile"}},{"text":" ticks count="},{"score":{"name":"${profilerCountPlayer(name)}","objective":"__profile"}}]`);
27340
+ }
25964
27341
  function emitInstr(instr, ns, obj, mcVersion) {
25965
27342
  switch (instr.kind) {
25966
27343
  case "score_set":
@@ -27147,7 +28524,6 @@ var require_typechecker = __commonJS({
27147
28524
  var VOID_TYPE = { kind: "named", name: "void" };
27148
28525
  var INT_TYPE = { kind: "named", name: "int" };
27149
28526
  var STRING_TYPE = { kind: "named", name: "string" };
27150
- var FORMAT_STRING_TYPE = { kind: "named", name: "format_string" };
27151
28527
  var BUILTIN_SIGNATURES = {
27152
28528
  setTimeout: {
27153
28529
  params: [INT_TYPE, { kind: "function_type", params: [], return: VOID_TYPE }],
@@ -27160,15 +28536,24 @@ var require_typechecker = __commonJS({
27160
28536
  clearInterval: {
27161
28537
  params: [INT_TYPE],
27162
28538
  return: VOID_TYPE
28539
+ },
28540
+ int_to_str: {
28541
+ params: [INT_TYPE],
28542
+ return: STRING_TYPE
28543
+ },
28544
+ bool_to_str: {
28545
+ params: [{ kind: "named", name: "bool" }],
28546
+ return: STRING_TYPE
27163
28547
  }
27164
28548
  };
27165
- var TypeChecker = class {
28549
+ var TypeChecker = class _TypeChecker {
27166
28550
  constructor(source, filePath) {
27167
28551
  this.lintWarnings = [];
27168
28552
  this.functions = /* @__PURE__ */ new Map();
27169
28553
  this.implMethods = /* @__PURE__ */ new Map();
27170
28554
  this.structs = /* @__PURE__ */ new Map();
27171
28555
  this.enums = /* @__PURE__ */ new Map();
28556
+ this.enumPayloads = /* @__PURE__ */ new Map();
27172
28557
  this.consts = /* @__PURE__ */ new Map();
27173
28558
  this.globals = /* @__PURE__ */ new Map();
27174
28559
  this.currentFn = null;
@@ -27177,6 +28562,7 @@ var require_typechecker = __commonJS({
27177
28562
  this.selfTypeStack = ["entity"];
27178
28563
  this.loopDepth = 0;
27179
28564
  this.condDepth = 0;
28565
+ this.interfaces = /* @__PURE__ */ new Map();
27180
28566
  this.richTextBuiltins = /* @__PURE__ */ new Map([
27181
28567
  ["say", { messageIndex: 0 }],
27182
28568
  ["announce", { messageIndex: 0 }],
@@ -27216,6 +28602,9 @@ var require_typechecker = __commonJS({
27216
28602
  for (const fn of program.declarations) {
27217
28603
  this.functions.set(fn.name, fn);
27218
28604
  }
28605
+ for (const iface of program.interfaces ?? []) {
28606
+ this.interfaces.set(iface.name, iface);
28607
+ }
27219
28608
  for (const global of program.globals ?? []) {
27220
28609
  this.globals.set(global.name, this.normalizeType(global.type));
27221
28610
  }
@@ -27245,13 +28634,47 @@ var require_typechecker = __commonJS({
27245
28634
  fields.set(field.name, field.type);
27246
28635
  }
27247
28636
  this.structs.set(struct.name, fields);
28637
+ if (struct.isSingleton) {
28638
+ const structType = { kind: "struct", name: struct.name };
28639
+ let singletonMethods = this.implMethods.get(struct.name);
28640
+ if (!singletonMethods) {
28641
+ singletonMethods = /* @__PURE__ */ new Map();
28642
+ this.implMethods.set(struct.name, singletonMethods);
28643
+ }
28644
+ const voidType = { kind: "named", name: "void" };
28645
+ singletonMethods.set("get", {
28646
+ name: "get",
28647
+ params: [],
28648
+ returnType: structType,
28649
+ decorators: [],
28650
+ body: [],
28651
+ typeParams: void 0,
28652
+ isLibraryFn: true
28653
+ });
28654
+ singletonMethods.set("set", {
28655
+ name: "set",
28656
+ params: [{ name: "gs", type: structType }],
28657
+ returnType: voidType,
28658
+ decorators: [],
28659
+ body: [],
28660
+ typeParams: void 0,
28661
+ isLibraryFn: true
28662
+ });
28663
+ }
27248
28664
  }
27249
28665
  for (const enumDecl of program.enums ?? []) {
27250
28666
  const variants = /* @__PURE__ */ new Map();
28667
+ const payloads = /* @__PURE__ */ new Map();
27251
28668
  for (const variant of enumDecl.variants) {
27252
28669
  variants.set(variant.name, variant.value ?? 0);
28670
+ if (variant.fields && variant.fields.length > 0) {
28671
+ payloads.set(variant.name, variant.fields);
28672
+ }
27253
28673
  }
27254
28674
  this.enums.set(enumDecl.name, variants);
28675
+ if (payloads.size > 0) {
28676
+ this.enumPayloads.set(enumDecl.name, payloads);
28677
+ }
27255
28678
  }
27256
28679
  for (const constDecl of program.consts ?? []) {
27257
28680
  const constType = this.normalizeType(constDecl.type);
@@ -27261,6 +28684,20 @@ var require_typechecker = __commonJS({
27261
28684
  }
27262
28685
  this.consts.set(constDecl.name, constType);
27263
28686
  }
28687
+ for (const implBlock of program.implBlocks ?? []) {
28688
+ if (!implBlock.traitName)
28689
+ continue;
28690
+ const iface = this.interfaces.get(implBlock.traitName);
28691
+ if (!iface)
28692
+ continue;
28693
+ const implementedMethods = new Set(implBlock.methods.map((m) => m.name));
28694
+ for (const required of iface.methods) {
28695
+ if (!implementedMethods.has(required.name)) {
28696
+ const span = implBlock.span ?? required.span;
28697
+ this.report(`Struct '${implBlock.typeName}' does not implement required method '${required.name}' from interface '${implBlock.traitName}'`, span ?? { line: 1, col: 1 });
28698
+ }
28699
+ }
28700
+ }
27264
28701
  for (const fn of program.declarations) {
27265
28702
  this.checkFunction(fn);
27266
28703
  }
@@ -27304,6 +28741,30 @@ var require_typechecker = __commonJS({
27304
28741
  this.currentReturnType = null;
27305
28742
  }
27306
28743
  checkFunctionDecorators(fn) {
28744
+ const watchDecorators = fn.decorators.filter((decorator) => decorator.name === "watch");
28745
+ if (watchDecorators.length > 1) {
28746
+ this.report(`Function '${fn.name}' cannot have multiple @watch decorators`, fn);
28747
+ return;
28748
+ }
28749
+ if (watchDecorators.length === 1) {
28750
+ const objective = watchDecorators[0].args?.objective;
28751
+ if (!objective) {
28752
+ this.report(`Function '${fn.name}' is missing a scoreboard objective in @watch("...")`, fn);
28753
+ return;
28754
+ }
28755
+ if (fn.params.length > 0) {
28756
+ this.report(`@watch handler '${fn.name}' cannot declare parameters`, fn);
28757
+ }
28758
+ }
28759
+ const profileDecorators = fn.decorators.filter((decorator) => decorator.name === "profile");
28760
+ if (profileDecorators.length > 1) {
28761
+ this.report(`Function '${fn.name}' cannot have multiple @profile decorators`, fn);
28762
+ return;
28763
+ }
28764
+ if (profileDecorators.length === 1 && (profileDecorators[0].rawArgs?.length || profileDecorators[0].args && Object.keys(profileDecorators[0].args).length > 0)) {
28765
+ this.report(`@profile decorator on '${fn.name}' does not accept arguments`, fn);
28766
+ return;
28767
+ }
27307
28768
  const eventDecorators = fn.decorators.filter((decorator) => decorator.name === "on");
27308
28769
  if (eventDecorators.length === 0) {
27309
28770
  return;
@@ -27408,8 +28869,21 @@ var require_typechecker = __commonJS({
27408
28869
  if (!isUnknown(subjectType) && !isUnknown(patternType) && !this.typesMatch(subjectType, patternType)) {
27409
28870
  this.report("Match arm pattern type must match subject type", arm.pattern.expr);
27410
28871
  }
28872
+ this.checkBlock(arm.body);
28873
+ } else if (arm.pattern.kind === "PatEnum") {
28874
+ const pat = arm.pattern;
28875
+ const variantPayloads = this.enumPayloads.get(pat.enumName)?.get(pat.variant) ?? [];
28876
+ const savedScope = new Map(this.scope);
28877
+ for (let i = 0; i < pat.bindings.length; i++) {
28878
+ const fieldDef = variantPayloads[i];
28879
+ const bindingType = fieldDef ? fieldDef.type : { kind: "named", name: "int" };
28880
+ this.scope.set(pat.bindings[i], { type: bindingType, mutable: false });
28881
+ }
28882
+ this.checkBlock(arm.body);
28883
+ this.scope = savedScope;
28884
+ } else {
28885
+ this.checkBlock(arm.body);
27411
28886
  }
27412
- this.checkBlock(arm.body);
27413
28887
  }
27414
28888
  break;
27415
28889
  case "as_block": {
@@ -27448,6 +28922,9 @@ var require_typechecker = __commonJS({
27448
28922
  break;
27449
28923
  case "raw":
27450
28924
  break;
28925
+ case "const_decl":
28926
+ this.scope.set(stmt.name, { type: stmt.type, mutable: false });
28927
+ break;
27451
28928
  }
27452
28929
  }
27453
28930
  checkLetDestructStmt(stmt) {
@@ -27645,6 +29122,31 @@ var require_typechecker = __commonJS({
27645
29122
  }
27646
29123
  }
27647
29124
  break;
29125
+ case "enum_construct": {
29126
+ if (!this.enums.has(expr.enumName)) {
29127
+ this.report(`Unknown enum '${expr.enumName}'`, expr);
29128
+ break;
29129
+ }
29130
+ const variants = this.enums.get(expr.enumName);
29131
+ if (!variants.has(expr.variant)) {
29132
+ this.report(`Enum '${expr.enumName}' has no variant '${expr.variant}'`, expr);
29133
+ break;
29134
+ }
29135
+ const variantPayloads = this.enumPayloads.get(expr.enumName)?.get(expr.variant) ?? [];
29136
+ if (variantPayloads.length === 0 && expr.args.length > 0) {
29137
+ this.report(`Enum variant '${expr.enumName}::${expr.variant}' has no payload fields`, expr);
29138
+ break;
29139
+ }
29140
+ for (const arg of expr.args) {
29141
+ const fieldDef = variantPayloads.find((f) => f.name === arg.name);
29142
+ if (!fieldDef) {
29143
+ this.report(`Unknown field '${arg.name}' for enum variant '${expr.enumName}::${expr.variant}'`, expr);
29144
+ } else {
29145
+ this.checkExpr(arg.value, fieldDef.type);
29146
+ }
29147
+ }
29148
+ break;
29149
+ }
27648
29150
  case "blockpos":
27649
29151
  break;
27650
29152
  // Literals don't need checking
@@ -27737,7 +29239,7 @@ var require_typechecker = __commonJS({
27737
29239
  return;
27738
29240
  }
27739
29241
  const messageType = this.inferType(message);
27740
- if (messageType.kind !== "named" || messageType.name !== "string" && messageType.name !== "format_string") {
29242
+ if (messageType.kind !== "named" || messageType.name !== "string") {
27741
29243
  this.report(`Argument ${messageIndex + 1} of '${expr.fn}' expects string or format_string, got ${this.typeToString(messageType)}`, message);
27742
29244
  }
27743
29245
  }
@@ -27933,7 +29435,7 @@ var require_typechecker = __commonJS({
27933
29435
  this.checkExpr(part.expr);
27934
29436
  }
27935
29437
  }
27936
- return FORMAT_STRING_TYPE;
29438
+ return STRING_TYPE;
27937
29439
  case "blockpos":
27938
29440
  return { kind: "named", name: "BlockPos" };
27939
29441
  case "ident":
@@ -27994,6 +29496,11 @@ var require_typechecker = __commonJS({
27994
29496
  return { kind: "enum", name: expr.enumName };
27995
29497
  }
27996
29498
  return { kind: "named", name: "void" };
29499
+ case "enum_construct":
29500
+ if (this.enums.has(expr.enumName)) {
29501
+ return { kind: "enum", name: expr.enumName };
29502
+ }
29503
+ return { kind: "named", name: "void" };
27997
29504
  case "member":
27998
29505
  if (expr.obj.kind === "ident" && this.enums.has(expr.obj.name)) {
27999
29506
  return { kind: "enum", name: expr.obj.name };
@@ -28105,7 +29612,8 @@ var require_typechecker = __commonJS({
28105
29612
  if (receiverType.kind !== "struct") {
28106
29613
  return null;
28107
29614
  }
28108
- const method = this.implMethods.get(receiverType.name)?.get(expr.fn);
29615
+ const methodName = _TypeChecker.PARSER_METHOD_REMAP[expr.fn] ?? expr.fn;
29616
+ const method = this.implMethods.get(receiverType.name)?.get(expr.fn) ?? this.implMethods.get(receiverType.name)?.get(methodName);
28109
29617
  if (!method || method.params[0]?.name !== "self") {
28110
29618
  return null;
28111
29619
  }
@@ -28276,6 +29784,17 @@ var require_typechecker = __commonJS({
28276
29784
  }
28277
29785
  };
28278
29786
  exports2.TypeChecker = TypeChecker;
29787
+ TypeChecker.PARSER_METHOD_REMAP = {
29788
+ "set_add": "add",
29789
+ "set_contains": "contains",
29790
+ "set_remove": "remove",
29791
+ "set_clear": "clear",
29792
+ "__array_push": "push",
29793
+ "__array_pop": "pop",
29794
+ "__entity_tag": "tag",
29795
+ "__entity_untag": "untag",
29796
+ "__entity_has_tag": "has_tag"
29797
+ };
28279
29798
  }
28280
29799
  });
28281
29800
 
@@ -28283,14 +29802,54 @@ var require_typechecker = __commonJS({
28283
29802
  var require_compile2 = __commonJS({
28284
29803
  "../../dist/src/emit/compile.js"(exports2) {
28285
29804
  "use strict";
29805
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
29806
+ if (k2 === void 0) k2 = k;
29807
+ var desc = Object.getOwnPropertyDescriptor(m, k);
29808
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
29809
+ desc = { enumerable: true, get: function() {
29810
+ return m[k];
29811
+ } };
29812
+ }
29813
+ Object.defineProperty(o, k2, desc);
29814
+ }) : (function(o, m, k, k2) {
29815
+ if (k2 === void 0) k2 = k;
29816
+ o[k2] = m[k];
29817
+ }));
29818
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
29819
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29820
+ }) : function(o, v) {
29821
+ o["default"] = v;
29822
+ });
29823
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
29824
+ var ownKeys = function(o) {
29825
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
29826
+ var ar = [];
29827
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
29828
+ return ar;
29829
+ };
29830
+ return ownKeys(o);
29831
+ };
29832
+ return function(mod) {
29833
+ if (mod && mod.__esModule) return mod;
29834
+ var result = {};
29835
+ if (mod != null) {
29836
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
29837
+ }
29838
+ __setModuleDefault(result, mod);
29839
+ return result;
29840
+ };
29841
+ })();
28286
29842
  Object.defineProperty(exports2, "__esModule", { value: true });
28287
29843
  exports2.compile = compile;
29844
+ var fs2 = __importStar(require("fs"));
29845
+ var path3 = __importStar(require("path"));
28288
29846
  var lexer_1 = require_lexer();
28289
29847
  var parser_1 = require_parser();
28290
29848
  var compile_1 = require_compile();
28291
29849
  var diagnostics_1 = require_diagnostics();
28292
29850
  var lower_1 = require_lower();
28293
29851
  var monomorphize_1 = require_monomorphize();
29852
+ var deprecated_1 = require_deprecated();
28294
29853
  var lower_2 = require_lower2();
28295
29854
  var pipeline_1 = require_pipeline();
28296
29855
  var lower_3 = require_lower3();
@@ -28301,35 +29860,136 @@ var require_compile2 = __commonJS({
28301
29860
  var mc_version_1 = require_mc_version();
28302
29861
  var typechecker_1 = require_typechecker();
28303
29862
  var types_1 = require_types();
29863
+ function pruneLibraryFunctionFiles(files, libraryPaths) {
29864
+ if (libraryPaths.size === 0)
29865
+ return files;
29866
+ const fnPathToFilePath = /* @__PURE__ */ new Map();
29867
+ for (const file of files) {
29868
+ const match = file.path.match(/^data\/([^/]+)\/function\/(.+)\.mcfunction$/);
29869
+ if (match) {
29870
+ fnPathToFilePath.set(`${match[1]}:${match[2]}`, file.path);
29871
+ }
29872
+ }
29873
+ const callGraph = /* @__PURE__ */ new Map();
29874
+ const callPattern = /\bfunction\s+([\w\-]+:[\w\-./]+)/g;
29875
+ for (const file of files) {
29876
+ if (!file.path.endsWith(".mcfunction"))
29877
+ continue;
29878
+ const called = /* @__PURE__ */ new Set();
29879
+ let match;
29880
+ callPattern.lastIndex = 0;
29881
+ while ((match = callPattern.exec(file.content)) !== null) {
29882
+ called.add(match[1]);
29883
+ }
29884
+ callGraph.set(file.path, called);
29885
+ }
29886
+ const reachableFiles = /* @__PURE__ */ new Set();
29887
+ const queue = [];
29888
+ for (const file of files) {
29889
+ if (!file.path.endsWith(".mcfunction"))
29890
+ continue;
29891
+ if (libraryPaths.has(file.path))
29892
+ continue;
29893
+ queue.push(file.path);
29894
+ reachableFiles.add(file.path);
29895
+ }
29896
+ while (queue.length > 0) {
29897
+ const current = queue.shift();
29898
+ const called = callGraph.get(current) ?? /* @__PURE__ */ new Set();
29899
+ for (const fnPath of called) {
29900
+ const filePath = fnPathToFilePath.get(fnPath);
29901
+ if (filePath && !reachableFiles.has(filePath)) {
29902
+ reachableFiles.add(filePath);
29903
+ queue.push(filePath);
29904
+ }
29905
+ }
29906
+ }
29907
+ return files.filter((file) => !libraryPaths.has(file.path) || reachableFiles.has(file.path));
29908
+ }
28304
29909
  function compile(source, options = {}) {
28305
- const { namespace = "redscript", filePath, generateSourceMap = false, mcVersion = mc_version_1.DEFAULT_MC_VERSION, lenient = false, includeDirs } = options;
29910
+ const { namespace = "redscript", filePath, generateSourceMap = false, mcVersion = mc_version_1.DEFAULT_MC_VERSION, lenient = false, includeDirs, stopAfterCheck = false, debug = false } = options;
28306
29911
  const warnings = [];
28307
29912
  const preprocessed = (0, compile_1.preprocessSourceWithMetadata)(source, { filePath, includeDirs });
28308
29913
  const processedSource = preprocessed.source;
28309
- const lexer = new lexer_1.Lexer(processedSource);
28310
- const tokens = lexer.tokenize();
28311
- const parser = new parser_1.Parser(tokens, processedSource, filePath);
28312
- const ast = parser.parse(namespace);
28313
- warnings.push(...parser.warnings);
28314
- for (const li of preprocessed.libraryImports ?? []) {
28315
- const libPreprocessed = (0, compile_1.preprocessSourceWithMetadata)(li.source, { filePath: li.filePath });
28316
- const libTokens = new lexer_1.Lexer(libPreprocessed.source, li.filePath).tokenize();
28317
- const libParser = new parser_1.Parser(libTokens, libPreprocessed.source, li.filePath);
28318
- const libAst = libParser.parse(namespace);
28319
- warnings.push(...libParser.warnings);
28320
- for (const fn of libAst.declarations)
28321
- fn.isLibraryFn = true;
28322
- ast.declarations.push(...libAst.declarations);
28323
- ast.structs.push(...libAst.structs);
28324
- ast.implBlocks.push(...libAst.implBlocks);
28325
- ast.enums.push(...libAst.enums);
28326
- ast.consts.push(...libAst.consts);
28327
- ast.globals.push(...libAst.globals);
28328
- }
28329
- if (options.librarySources) {
28330
- for (const libSrc of options.librarySources) {
28331
- const libTokens = new lexer_1.Lexer(libSrc).tokenize();
28332
- const libAst = new parser_1.Parser(libTokens, libSrc).parse(namespace);
29914
+ try {
29915
+ let resolveModuleFilePath = function(modName, fromFile) {
29916
+ const candidates = [`${modName}.mcrs`, modName];
29917
+ const stdlibDir = path3.resolve(__dirname, "..", "src", "stdlib");
29918
+ for (const candidate of candidates) {
29919
+ if (fromFile) {
29920
+ const rel = path3.resolve(path3.dirname(fromFile), candidate);
29921
+ if (fs2.existsSync(rel))
29922
+ return rel;
29923
+ }
29924
+ const stdlib = path3.resolve(stdlibDir, candidate);
29925
+ if (fs2.existsSync(stdlib))
29926
+ return stdlib;
29927
+ for (const dir of includeDirs ?? []) {
29928
+ const extra = path3.resolve(dir, candidate);
29929
+ if (fs2.existsSync(extra))
29930
+ return extra;
29931
+ }
29932
+ }
29933
+ return null;
29934
+ }, mergeWholeModuleImport = function(modFilePath) {
29935
+ if (seenModuleImports.has(modFilePath))
29936
+ return;
29937
+ seenModuleImports.add(modFilePath);
29938
+ const modSource = fs2.readFileSync(modFilePath, "utf-8");
29939
+ const modPreprocessed = (0, compile_1.preprocessSourceWithMetadata)(modSource, { filePath: modFilePath, includeDirs });
29940
+ const modTokens = new lexer_1.Lexer(modPreprocessed.source, modFilePath).tokenize();
29941
+ const modParser = new parser_1.Parser(modTokens, modPreprocessed.source, modFilePath);
29942
+ const modAst = modParser.parse(namespace);
29943
+ warnings.push(...modParser.warnings);
29944
+ if (modParser.parseErrors.length > 0) {
29945
+ throw stopAfterCheck ? new diagnostics_1.DiagnosticBundleError(modParser.parseErrors) : modParser.parseErrors[0];
29946
+ }
29947
+ for (const fn of modAst.declarations)
29948
+ fn.isLibraryFn = true;
29949
+ for (const imp of modAst.imports) {
29950
+ if (imp.symbol !== void 0)
29951
+ continue;
29952
+ const nestedPath = resolveModuleFilePath(imp.moduleName, modFilePath);
29953
+ if (!nestedPath) {
29954
+ warnings.push(`[ImportWarning] Module '${imp.moduleName}' not found (imported in ${modFilePath})`);
29955
+ continue;
29956
+ }
29957
+ mergeWholeModuleImport(nestedPath);
29958
+ }
29959
+ ast.declarations.push(...modAst.declarations);
29960
+ ast.structs.push(...modAst.structs);
29961
+ ast.implBlocks.push(...modAst.implBlocks);
29962
+ ast.enums.push(...modAst.enums);
29963
+ ast.consts.push(...modAst.consts);
29964
+ ast.globals.push(...modAst.globals);
29965
+ };
29966
+ const lexer = new lexer_1.Lexer(processedSource);
29967
+ const tokens = lexer.tokenize();
29968
+ const parser = new parser_1.Parser(tokens, processedSource, filePath);
29969
+ const ast = parser.parse(namespace);
29970
+ warnings.push(...parser.warnings);
29971
+ if (parser.parseErrors.length > 0) {
29972
+ throw stopAfterCheck ? new diagnostics_1.DiagnosticBundleError(parser.parseErrors) : parser.parseErrors[0];
29973
+ }
29974
+ const seenModuleImports = /* @__PURE__ */ new Set();
29975
+ for (const imp of ast.imports) {
29976
+ if (imp.symbol !== void 0)
29977
+ continue;
29978
+ const resolved = resolveModuleFilePath(imp.moduleName, filePath);
29979
+ if (!resolved) {
29980
+ throw new diagnostics_1.DiagnosticError("ParseError", `Module '${imp.moduleName}' not found. Make sure '${imp.moduleName}.mcrs' exists relative to this file or in the stdlib.`, imp.span ?? { line: 1, col: 1 });
29981
+ }
29982
+ mergeWholeModuleImport(resolved);
29983
+ }
29984
+ for (const li of preprocessed.libraryImports ?? []) {
29985
+ const libPreprocessed = (0, compile_1.preprocessSourceWithMetadata)(li.source, { filePath: li.filePath });
29986
+ const libTokens = new lexer_1.Lexer(libPreprocessed.source, li.filePath).tokenize();
29987
+ const libParser = new parser_1.Parser(libTokens, libPreprocessed.source, li.filePath);
29988
+ const libAst = libParser.parse(namespace);
29989
+ warnings.push(...libParser.warnings);
29990
+ if (libParser.parseErrors.length > 0) {
29991
+ throw stopAfterCheck ? new diagnostics_1.DiagnosticBundleError(libParser.parseErrors) : libParser.parseErrors[0];
29992
+ }
28333
29993
  for (const fn of libAst.declarations)
28334
29994
  fn.isLibraryFn = true;
28335
29995
  ast.declarations.push(...libAst.declarations);
@@ -28339,35 +29999,90 @@ var require_compile2 = __commonJS({
28339
29999
  ast.consts.push(...libAst.consts);
28340
30000
  ast.globals.push(...libAst.globals);
28341
30001
  }
28342
- }
28343
- {
28344
- const checker = new typechecker_1.TypeChecker(processedSource, filePath);
28345
- const typeErrors = checker.check(ast);
28346
- warnings.push(...checker.getWarnings());
28347
- if (typeErrors.length > 0) {
28348
- if (lenient) {
28349
- for (const e of typeErrors) {
28350
- warnings.push(`[TypeError] line ${e.location.line}, col ${e.location.col}: ${e.message}`);
30002
+ if (options.librarySources) {
30003
+ for (const libSrc of options.librarySources) {
30004
+ const libTokens = new lexer_1.Lexer(libSrc).tokenize();
30005
+ const libParser = new parser_1.Parser(libTokens, libSrc);
30006
+ const libAst = libParser.parse(namespace);
30007
+ warnings.push(...libParser.warnings);
30008
+ if (libParser.parseErrors.length > 0) {
30009
+ throw stopAfterCheck ? new diagnostics_1.DiagnosticBundleError(libParser.parseErrors) : libParser.parseErrors[0];
30010
+ }
30011
+ for (const fn of libAst.declarations)
30012
+ fn.isLibraryFn = true;
30013
+ ast.declarations.push(...libAst.declarations);
30014
+ ast.structs.push(...libAst.structs);
30015
+ ast.implBlocks.push(...libAst.implBlocks);
30016
+ ast.enums.push(...libAst.enums);
30017
+ ast.consts.push(...libAst.consts);
30018
+ ast.globals.push(...libAst.globals);
30019
+ }
30020
+ }
30021
+ {
30022
+ const configValues = options.config ?? {};
30023
+ const configGlobalNames = /* @__PURE__ */ new Set();
30024
+ for (const g of ast.globals) {
30025
+ if (g.configKey !== void 0) {
30026
+ const resolvedValue = Object.prototype.hasOwnProperty.call(configValues, g.configKey) ? configValues[g.configKey] : g.configDefault ?? 0;
30027
+ const intValue = Math.round(resolvedValue);
30028
+ ast.consts.push({
30029
+ name: g.name,
30030
+ type: { kind: "named", name: "int" },
30031
+ value: { kind: "int_lit", value: intValue },
30032
+ span: g.span
30033
+ });
30034
+ configGlobalNames.add(g.name);
30035
+ }
30036
+ }
30037
+ if (configGlobalNames.size > 0) {
30038
+ ast.globals = ast.globals.filter((g) => !configGlobalNames.has(g.name));
30039
+ }
30040
+ }
30041
+ {
30042
+ const checker = new typechecker_1.TypeChecker(processedSource, filePath);
30043
+ const typeErrors = checker.check(ast);
30044
+ warnings.push(...checker.getWarnings());
30045
+ if (typeErrors.length > 0) {
30046
+ if (lenient) {
30047
+ for (const e of typeErrors) {
30048
+ warnings.push(`[TypeError] line ${e.location.line}, col ${e.location.col}: ${e.message}`);
30049
+ }
30050
+ } else {
30051
+ throw stopAfterCheck ? new diagnostics_1.DiagnosticBundleError(typeErrors) : typeErrors[0];
28351
30052
  }
28352
- } else {
28353
- throw typeErrors[0];
28354
30053
  }
28355
30054
  }
28356
- }
28357
- try {
28358
30055
  const hirRaw = (0, lower_1.lowerToHIR)(ast);
28359
30056
  const hir = (0, monomorphize_1.monomorphize)(hirRaw);
30057
+ const libraryFilePaths = new Set(hir.functions.filter((fn) => fn.isLibraryFn && fn.decorators.length === 0).map((fn) => `data/${namespace}/function/${fn.name}.mcfunction`));
30058
+ warnings.push(...(0, deprecated_1.checkDeprecatedCalls)(hir));
30059
+ if (stopAfterCheck) {
30060
+ return { files: [], warnings, success: true };
30061
+ }
28360
30062
  const tickFunctions = [];
28361
30063
  const loadFunctions = [];
30064
+ const watchFunctions = [];
30065
+ const inlineFunctions = /* @__PURE__ */ new Set();
28362
30066
  const coroutineInfos = [];
28363
30067
  const scheduleFunctions = [];
30068
+ const profiledFunctions = [];
28364
30069
  const eventHandlers = /* @__PURE__ */ new Map();
28365
30070
  for (const fn of hir.functions) {
30071
+ if (fn.watchObjective) {
30072
+ watchFunctions.push({ name: fn.name, objective: fn.watchObjective });
30073
+ } else {
30074
+ const watchDec = fn.decorators?.find((d) => d.name === "watch" && d.args?.objective);
30075
+ if (watchDec?.args?.objective) {
30076
+ watchFunctions.push({ name: fn.name, objective: watchDec.args.objective });
30077
+ }
30078
+ }
28366
30079
  for (const dec of fn.decorators) {
28367
30080
  if (dec.name === "tick")
28368
30081
  tickFunctions.push(fn.name);
28369
30082
  if (dec.name === "load")
28370
30083
  loadFunctions.push(fn.name);
30084
+ if (dec.name === "inline")
30085
+ inlineFunctions.add(fn.name);
28371
30086
  if (dec.name === "coroutine") {
28372
30087
  coroutineInfos.push({
28373
30088
  fnName: fn.name,
@@ -28378,6 +30093,9 @@ var require_compile2 = __commonJS({
28378
30093
  if (dec.name === "schedule") {
28379
30094
  scheduleFunctions.push({ name: fn.name, ticks: dec.args?.ticks ?? 1 });
28380
30095
  }
30096
+ if (dec.name === "profile") {
30097
+ profiledFunctions.push(fn.name);
30098
+ }
28381
30099
  if (dec.name === "on" && dec.args?.eventType) {
28382
30100
  const evType = dec.args.eventType;
28383
30101
  if ((0, types_1.isEventTypeName)(evType)) {
@@ -28389,6 +30107,9 @@ var require_compile2 = __commonJS({
28389
30107
  }
28390
30108
  }
28391
30109
  const mir = (0, lower_2.lowerToMIR)(hir, filePath);
30110
+ if (inlineFunctions.size > 0) {
30111
+ mir.inlineFunctions = inlineFunctions;
30112
+ }
28392
30113
  const mirOpt = (0, pipeline_1.optimizeModule)(mir);
28393
30114
  const coroResult = (0, coroutine_1.coroutineTransform)(mirOpt, coroutineInfos);
28394
30115
  const mirFinal = coroResult.module;
@@ -28413,15 +30134,90 @@ var require_compile2 = __commonJS({
28413
30134
  }
28414
30135
  }
28415
30136
  }
28416
- const files = (0, index_1.emit)(lirOpt, { namespace, tickFunctions, loadFunctions, scheduleFunctions, generateSourceMap, mcVersion, eventHandlers });
28417
- return { files, warnings, success: true };
30137
+ const singletonObjectives = [];
30138
+ for (const s of hir.structs) {
30139
+ if (!s.isSingleton)
30140
+ continue;
30141
+ const structName = s.name;
30142
+ const objective = lirOpt.objective;
30143
+ const getInstrs = [];
30144
+ for (const field of s.fields) {
30145
+ const fieldObj = singletonObjectiveName(structName, field.name);
30146
+ if (!singletonObjectives.includes(fieldObj)) {
30147
+ singletonObjectives.push(fieldObj);
30148
+ }
30149
+ getInstrs.push({
30150
+ kind: "score_copy",
30151
+ dst: { player: `$__rf_${field.name}`, obj: objective },
30152
+ src: { player: `__sng`, obj: fieldObj }
30153
+ });
30154
+ }
30155
+ getInstrs.push({ kind: "score_set", dst: { player: "$ret", obj: objective }, value: 0 });
30156
+ lirOpt.functions.push({
30157
+ name: `${structName}::get`,
30158
+ instructions: getInstrs,
30159
+ isMacro: false,
30160
+ macroParams: []
30161
+ });
30162
+ const setInstrs = [];
30163
+ for (let i = 0; i < s.fields.length; i++) {
30164
+ const field = s.fields[i];
30165
+ const fieldObj = singletonObjectiveName(structName, field.name);
30166
+ setInstrs.push({
30167
+ kind: "score_copy",
30168
+ dst: { player: `__sng`, obj: fieldObj },
30169
+ src: { player: `$p${i}`, obj: objective }
30170
+ });
30171
+ }
30172
+ setInstrs.push({ kind: "score_set", dst: { player: "$ret", obj: objective }, value: 0 });
30173
+ lirOpt.functions.push({
30174
+ name: `${structName}::set`,
30175
+ instructions: setInstrs,
30176
+ isMacro: false,
30177
+ macroParams: []
30178
+ });
30179
+ }
30180
+ const files = (0, index_1.emit)(lirOpt, {
30181
+ namespace,
30182
+ tickFunctions,
30183
+ loadFunctions,
30184
+ watchFunctions,
30185
+ scheduleFunctions,
30186
+ generateSourceMap,
30187
+ mcVersion,
30188
+ eventHandlers,
30189
+ singletonObjectives,
30190
+ profiledFunctions,
30191
+ enableProfiling: debug
30192
+ });
30193
+ const prunedFiles = pruneLibraryFunctionFiles(files, libraryFilePaths);
30194
+ return { files: prunedFiles, warnings, success: true };
28418
30195
  } catch (err) {
30196
+ if (stopAfterCheck) {
30197
+ if (err instanceof diagnostics_1.CheckFailedError)
30198
+ throw err;
30199
+ if (err instanceof diagnostics_1.DiagnosticBundleError) {
30200
+ throw new diagnostics_1.CheckFailedError(err.diagnostics, warnings);
30201
+ }
30202
+ if (err instanceof diagnostics_1.DiagnosticError) {
30203
+ throw new diagnostics_1.CheckFailedError([err], warnings);
30204
+ }
30205
+ const sourceLines2 = processedSource.split("\n");
30206
+ throw new diagnostics_1.CheckFailedError([(0, diagnostics_1.parseErrorMessage)("LoweringError", err.message, sourceLines2, filePath)], warnings);
30207
+ }
28419
30208
  if (err instanceof diagnostics_1.DiagnosticError)
28420
30209
  throw err;
28421
30210
  const sourceLines = processedSource.split("\n");
28422
30211
  throw (0, diagnostics_1.parseErrorMessage)("LoweringError", err.message, sourceLines, filePath);
28423
30212
  }
28424
30213
  }
30214
+ function singletonObjectiveName(structName, fieldName) {
30215
+ const overhead = 5;
30216
+ if (structName.length + fieldName.length <= 12) {
30217
+ return `_s_${structName}_${fieldName}`;
30218
+ }
30219
+ return `_s_${structName.slice(0, 4)}_${fieldName.slice(0, 8)}`;
30220
+ }
28425
30221
  }
28426
30222
  });
28427
30223
 
@@ -28454,6 +30250,9 @@ var require_modules = __commonJS({
28454
30250
  const tokens = lexer.tokenize();
28455
30251
  const parser = new parser_1.Parser(tokens, mod.source, mod.filePath);
28456
30252
  const ast = parser.parse(namespace);
30253
+ if (parser.parseErrors.length > 0) {
30254
+ throw parser.parseErrors[0];
30255
+ }
28457
30256
  const declaredName = ast.moduleName;
28458
30257
  if (declaredName && declaredName !== mod.name) {
28459
30258
  throw new diagnostics_1.DiagnosticError("LoweringError", `Module declares name '${declaredName}' but was registered as '${mod.name}'`, { file: mod.filePath, line: 1, col: 1 });
@@ -28478,7 +30277,9 @@ var require_modules = __commonJS({
28478
30277
  if (!sourceExports) {
28479
30278
  throw new diagnostics_1.DiagnosticError("LoweringError", `Module '${imp.moduleName}' not found (imported in '${modName}')`, { file: ast.namespace, line: 1, col: 1 });
28480
30279
  }
28481
- if (imp.symbol === "*") {
30280
+ if (imp.symbol === void 0) {
30281
+ continue;
30282
+ } else if (imp.symbol === "*") {
28482
30283
  for (const sym of sourceExports) {
28483
30284
  resolved.set(sym, `${imp.moduleName}/${sym}`);
28484
30285
  }
@@ -28497,6 +30298,8 @@ var require_modules = __commonJS({
28497
30298
  }
28498
30299
  for (const ast of parsedModules.values()) {
28499
30300
  for (const imp of ast.imports) {
30301
+ if (imp.symbol === void 0)
30302
+ continue;
28500
30303
  const used = usedExports.get(imp.moduleName);
28501
30304
  if (!used)
28502
30305
  continue;
@@ -28618,6 +30421,7 @@ var require_modules = __commonJS({
28618
30421
  const hir = (0, monomorphize_1.monomorphize)(hirRaw);
28619
30422
  const tickFunctions = [];
28620
30423
  const loadFunctions = [];
30424
+ const watchFunctions = [];
28621
30425
  const coroutineInfos = [];
28622
30426
  const scheduleFunctions = [];
28623
30427
  for (const fn of hir.functions) {
@@ -28626,6 +30430,9 @@ var require_modules = __commonJS({
28626
30430
  tickFunctions.push(fn.name);
28627
30431
  if (dec.name === "load")
28628
30432
  loadFunctions.push(fn.name);
30433
+ if (dec.name === "watch" && dec.args?.objective) {
30434
+ watchFunctions.push({ name: fn.name, objective: dec.args.objective });
30435
+ }
28629
30436
  if (dec.name === "coroutine") {
28630
30437
  coroutineInfos.push({ fnName: fn.name, batch: dec.args?.batch ?? 10, onDone: dec.args?.onDone });
28631
30438
  }
@@ -28643,7 +30450,7 @@ var require_modules = __commonJS({
28643
30450
  const lir = (0, lower_3.lowerToLIR)(mirFinal);
28644
30451
  lir.objective = objective;
28645
30452
  const lirOpt = (0, pipeline_2.lirOptimizeModule)(lir);
28646
- const files = (0, index_1.emit)(lirOpt, { namespace, tickFunctions, loadFunctions, scheduleFunctions });
30453
+ const files = (0, index_1.emit)(lirOpt, { namespace, tickFunctions, loadFunctions, watchFunctions, scheduleFunctions });
28647
30454
  if (moduleName) {
28648
30455
  const loadPath = `data/${namespace}/function/load.mcfunction`;
28649
30456
  const newLoadPath = `data/${namespace}/function/${moduleName}/_load.mcfunction`;
@@ -29279,11 +31086,17 @@ var require_cache = __commonJS({
29279
31086
  save() {
29280
31087
  fs2.mkdirSync(this.cacheDir, { recursive: true });
29281
31088
  const serialized = {
29282
- version: 1,
31089
+ version: 2,
29283
31090
  entries: {}
29284
31091
  };
29285
31092
  for (const [filePath, entry] of this.entries) {
29286
- serialized.entries[filePath] = { hash: entry.hash, mtime: entry.mtime };
31093
+ serialized.entries[filePath] = {
31094
+ hash: entry.hash,
31095
+ mtime: entry.mtime,
31096
+ compiledFunctions: entry.compiledFunctions,
31097
+ outputFiles: entry.outputFiles,
31098
+ dependencies: entry.dependencies
31099
+ };
29287
31100
  }
29288
31101
  const cachePath = path3.join(this.cacheDir, "cache.json");
29289
31102
  fs2.writeFileSync(cachePath, JSON.stringify(serialized, null, 2));
@@ -29293,10 +31106,16 @@ var require_cache = __commonJS({
29293
31106
  const cachePath = path3.join(this.cacheDir, "cache.json");
29294
31107
  try {
29295
31108
  const data = JSON.parse(fs2.readFileSync(cachePath, "utf-8"));
29296
- if (data.version !== 1)
31109
+ if (data.version !== 2)
29297
31110
  return;
29298
31111
  for (const [filePath, entry] of Object.entries(data.entries)) {
29299
- this.entries.set(filePath, { hash: entry.hash, mtime: entry.mtime });
31112
+ this.entries.set(filePath, {
31113
+ hash: entry.hash,
31114
+ mtime: entry.mtime,
31115
+ compiledFunctions: entry.compiledFunctions,
31116
+ outputFiles: entry.outputFiles,
31117
+ dependencies: entry.dependencies
31118
+ });
29300
31119
  }
29301
31120
  } catch {
29302
31121
  }
@@ -29507,101 +31326,137 @@ var require_incremental = __commonJS({
29507
31326
  Object.defineProperty(exports2, "__esModule", { value: true });
29508
31327
  exports2.compileIncremental = compileIncremental;
29509
31328
  exports2.resetCompileCache = resetCompileCache;
31329
+ var fs2 = __importStar(require("fs"));
29510
31330
  var path3 = __importStar(require("path"));
29511
31331
  var compile_1 = require_compile2();
29512
- var fs2 = __importStar(require("fs"));
29513
- var compiledCache = /* @__PURE__ */ new Map();
31332
+ var deps_1 = require_deps();
29514
31333
  function compileIncremental(files, cache, depGraph, options) {
31334
+ const start = Date.now();
31335
+ const normalizedEntries = [...new Set(files.map((file) => path3.resolve(file)))];
29515
31336
  const result = {
29516
31337
  recompiled: 0,
29517
31338
  cached: 0,
29518
31339
  errors: /* @__PURE__ */ new Map(),
29519
- results: /* @__PURE__ */ new Map()
31340
+ results: /* @__PURE__ */ new Map(),
31341
+ skippedFiles: [],
31342
+ rebuiltFiles: [],
31343
+ elapsedMs: 0
29520
31344
  };
29521
- for (const file of files) {
29522
- const absFile = path3.resolve(file);
29523
- try {
29524
- const source = fs2.readFileSync(absFile, "utf-8");
29525
- depGraph.addFile(absFile, source);
29526
- } catch {
29527
- depGraph.removeFile(absFile);
29528
- }
29529
- }
29530
- const changedSourceFiles = /* @__PURE__ */ new Set();
29531
- const allSourceFiles = /* @__PURE__ */ new Set();
29532
- for (const file of files) {
29533
- const absFile = path3.resolve(file);
29534
- const allDeps = depGraph.getTransitiveDeps(absFile);
29535
- allSourceFiles.add(absFile);
29536
- for (const dep of allDeps)
29537
- allSourceFiles.add(dep);
29538
- }
29539
- for (const sourceFile of allSourceFiles) {
29540
- if (cache.hasChanged(sourceFile)) {
29541
- changedSourceFiles.add(sourceFile);
29542
- }
31345
+ if (normalizedEntries.length === 0) {
31346
+ result.elapsedMs = Date.now() - start;
31347
+ return result;
29543
31348
  }
29544
- for (const file of files) {
29545
- const absFile = path3.resolve(file);
29546
- const allDeps = depGraph.getTransitiveDeps(absFile);
29547
- const unitFiles = [absFile, ...allDeps];
29548
- let needsRecompile = false;
29549
- const prevEntry = compiledCache.get(absFile);
29550
- if (!prevEntry) {
29551
- needsRecompile = true;
29552
- } else {
29553
- for (const unitFile of unitFiles) {
29554
- if (changedSourceFiles.has(unitFile)) {
29555
- needsRecompile = true;
29556
- break;
29557
- }
29558
- }
29559
- if (!needsRecompile && prevEntry.depHashes.size !== unitFiles.length) {
29560
- needsRecompile = true;
29561
- }
29562
- }
29563
- if (!needsRecompile) {
29564
- const cached = compiledCache.get(absFile);
29565
- writeBuildOutput(cached.result, options.output);
31349
+ depGraph.clear();
31350
+ const discoveredFiles = discoverDependencyGraph(normalizedEntries, depGraph);
31351
+ const changedFiles = /* @__PURE__ */ new Set();
31352
+ for (const file of discoveredFiles) {
31353
+ if (cache.hasChanged(file))
31354
+ changedFiles.add(file);
31355
+ }
31356
+ const dirtyFiles = depGraph.computeDirtySet(changedFiles);
31357
+ for (const entry of normalizedEntries) {
31358
+ if (!discoveredFiles.has(entry))
31359
+ dirtyFiles.add(entry);
31360
+ }
31361
+ for (const entryFile of normalizedEntries) {
31362
+ const entryDeps = depGraph.getTransitiveDeps(entryFile);
31363
+ const entryUnit = /* @__PURE__ */ new Set([entryFile, ...entryDeps]);
31364
+ const cachedEntry = cache.get(entryFile);
31365
+ const cachedDepList = new Set(cachedEntry?.dependencies ?? []);
31366
+ const hasDependencyDrift = cachedDepList.size !== entryUnit.size || [...entryUnit].some((file) => !cachedDepList.has(file));
31367
+ const canUseCache = !dirtyFiles.has(entryFile) && !hasDependencyDrift && !!cachedEntry?.outputFiles && cachedEntry.outputFiles.length > 0;
31368
+ if (canUseCache) {
31369
+ writeBuildOutput(cachedEntry.outputFiles, options.output);
29566
31370
  result.cached++;
31371
+ result.skippedFiles.push(entryFile);
29567
31372
  continue;
29568
31373
  }
29569
31374
  try {
29570
- const source = fs2.readFileSync(absFile, "utf-8");
29571
- const ns = options.namespace ?? deriveNamespace(absFile);
29572
- const compileResult = (0, compile_1.compile)(source, { namespace: ns, filePath: absFile });
29573
- const depHashes = /* @__PURE__ */ new Map();
29574
- for (const unitFile of unitFiles) {
29575
- cache.update(unitFile);
29576
- const entry = cache.get(unitFile);
29577
- if (entry)
29578
- depHashes.set(unitFile, entry.hash);
29579
- }
29580
- compiledCache.set(absFile, { result: compileResult, depHashes });
29581
- writeBuildOutput(compileResult, options.output);
31375
+ const source = fs2.readFileSync(entryFile, "utf-8");
31376
+ const ns = options.namespace ?? deriveNamespace(entryFile);
31377
+ const compileResult = (0, compile_1.compile)(source, {
31378
+ namespace: ns,
31379
+ filePath: entryFile,
31380
+ generateSourceMap: options.generateSourceMap,
31381
+ mcVersion: options.mcVersion,
31382
+ lenient: options.lenient,
31383
+ includeDirs: options.includeDirs
31384
+ });
31385
+ const outputFiles = cloneFiles(compileResult.files);
31386
+ const compiledFunctions = outputFiles.filter((file) => file.path.endsWith(".mcfunction")).map((file) => file.path);
31387
+ removeStaleOutputs(cachedEntry?.outputFiles ?? [], outputFiles, options.output);
31388
+ for (const file of entryUnit) {
31389
+ cache.update(file);
31390
+ }
31391
+ const entryRecord = cache.get(entryFile);
31392
+ if (entryRecord) {
31393
+ entryRecord.compiledFunctions = compiledFunctions;
31394
+ entryRecord.outputFiles = outputFiles;
31395
+ entryRecord.dependencies = [...entryUnit].sort();
31396
+ }
31397
+ writeBuildOutput(outputFiles, options.output);
29582
31398
  result.recompiled++;
29583
- result.results.set(absFile, compileResult);
31399
+ result.results.set(entryFile, compileResult);
31400
+ result.rebuiltFiles.push(entryFile);
29584
31401
  } catch (err) {
29585
- result.errors.set(absFile, err.message);
31402
+ result.errors.set(entryFile, err.message);
29586
31403
  }
29587
31404
  }
31405
+ cache.save();
31406
+ result.elapsedMs = Date.now() - start;
29588
31407
  return result;
29589
31408
  }
29590
- function writeBuildOutput(compileResult, output) {
31409
+ function discoverDependencyGraph(entries, depGraph) {
31410
+ const visited = /* @__PURE__ */ new Set();
31411
+ const queue = [...entries];
31412
+ while (queue.length > 0) {
31413
+ const current = path3.resolve(queue.shift());
31414
+ if (visited.has(current))
31415
+ continue;
31416
+ visited.add(current);
31417
+ try {
31418
+ const source = fs2.readFileSync(current, "utf-8");
31419
+ depGraph.addFile(current, source);
31420
+ const imports = (0, deps_1.parseImports)(current, source);
31421
+ for (const imported of imports) {
31422
+ if (!visited.has(imported))
31423
+ queue.push(imported);
31424
+ }
31425
+ } catch {
31426
+ depGraph.removeFile(current);
31427
+ }
31428
+ }
31429
+ return visited;
31430
+ }
31431
+ function cloneFiles(files) {
31432
+ return files.map((file) => ({ path: file.path, content: file.content }));
31433
+ }
31434
+ function writeBuildOutput(files, output) {
29591
31435
  fs2.mkdirSync(output, { recursive: true });
29592
- for (const dataFile of compileResult.files) {
31436
+ for (const dataFile of files) {
29593
31437
  const filePath = path3.join(output, dataFile.path);
29594
31438
  const dir = path3.dirname(filePath);
29595
31439
  fs2.mkdirSync(dir, { recursive: true });
29596
31440
  fs2.writeFileSync(filePath, dataFile.content);
29597
31441
  }
29598
31442
  }
31443
+ function removeStaleOutputs(previousFiles, nextFiles, output) {
31444
+ if (previousFiles.length === 0)
31445
+ return;
31446
+ const nextPaths = new Set(nextFiles.map((file) => file.path));
31447
+ for (const oldFile of previousFiles) {
31448
+ if (nextPaths.has(oldFile.path))
31449
+ continue;
31450
+ const targetPath = path3.join(output, oldFile.path);
31451
+ if (fs2.existsSync(targetPath))
31452
+ fs2.rmSync(targetPath, { force: true });
31453
+ }
31454
+ }
29599
31455
  function deriveNamespace(filePath) {
29600
31456
  const basename = path3.basename(filePath, path3.extname(filePath));
29601
31457
  return basename.toLowerCase().replace(/[^a-z0-9]/g, "_");
29602
31458
  }
29603
31459
  function resetCompileCache() {
29604
- compiledCache.clear();
29605
31460
  }
29606
31461
  }
29607
31462
  });
@@ -29614,8 +31469,10 @@ var require_src = __commonJS({
29614
31469
  exports2.resetCompileCache = exports2.compileIncremental = exports2.parseImports = exports2.DependencyGraph = exports2.hashFile = exports2.FileCache = exports2.MCCommandValidator = exports2.preprocessSourceWithMetadata = exports2.preprocessSource = exports2.Parser = exports2.Lexer = exports2.DEFAULT_MC_VERSION = exports2.compareMcVersion = exports2.parseMcVersion = exports2.McVersion = exports2.compileModules = exports2.compile = exports2.version = void 0;
29615
31470
  exports2.check = check;
29616
31471
  exports2.checkWithWarnings = checkWithWarnings;
31472
+ exports2.checkDetailed = checkDetailed;
29617
31473
  exports2.version = "2.0.0";
29618
31474
  var compile_1 = require_compile2();
31475
+ var diagnostics_1 = require_diagnostics();
29619
31476
  var compile_2 = require_compile2();
29620
31477
  Object.defineProperty(exports2, "compile", { enumerable: true, get: function() {
29621
31478
  return compile_2.compile;
@@ -29681,11 +31538,24 @@ var require_src = __commonJS({
29681
31538
  return checkWithWarnings(source, namespace, filePath).error;
29682
31539
  }
29683
31540
  function checkWithWarnings(source, namespace = "redscript", filePath) {
31541
+ const result = checkDetailed(source, namespace, filePath);
31542
+ return { error: result.errors[0] ?? null, warnings: result.warnings };
31543
+ }
31544
+ function checkDetailed(source, namespace = "redscript", filePath) {
29684
31545
  try {
29685
- const result = (0, compile_1.compile)(source, { namespace, filePath });
29686
- return { error: null, warnings: result.warnings };
31546
+ const result = (0, compile_1.compile)(source, { namespace, filePath, stopAfterCheck: true });
31547
+ return { errors: [], warnings: result.warnings };
29687
31548
  } catch (err) {
29688
- return { error: err, warnings: [] };
31549
+ if (err instanceof diagnostics_1.CheckFailedError) {
31550
+ return { errors: err.diagnostics, warnings: err.warnings };
31551
+ }
31552
+ if (err instanceof diagnostics_1.DiagnosticError) {
31553
+ return { errors: [err], warnings: [] };
31554
+ }
31555
+ return {
31556
+ errors: [(0, diagnostics_1.parseErrorMessage)("LoweringError", err.message, source.split("\n"), filePath)],
31557
+ warnings: []
31558
+ };
29689
31559
  }
29690
31560
  }
29691
31561
  }