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
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Tests for tuple types and destructuring.
3
+ *
4
+ * RedScript supports:
5
+ * - Tuple type annotations: (int, int)
6
+ * - Tuple literal expressions: (a, b)
7
+ * - Destructuring let-bindings: let (lo, hi) = expr
8
+ * - Functions that return tuples: fn foo(): (int, int) { return (a, b) }
9
+ */
10
+
11
+ import { Lexer } from '../../lexer'
12
+ import { Parser } from '../../parser'
13
+ import { lowerToHIR } from '../../hir/lower'
14
+ import { lowerToMIR } from '../../mir/lower'
15
+ import { verifyMIR } from '../../mir/verify'
16
+ import { compile } from '../../emit/compile'
17
+ import type { MIRFunction } from '../../mir/types'
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Helpers
21
+ // ---------------------------------------------------------------------------
22
+
23
+ function parse(source: string) {
24
+ const tokens = new Lexer(source).tokenize()
25
+ return new Parser(tokens, source).parse('test')
26
+ }
27
+
28
+ function lowerFn(source: string, fnName: string): MIRFunction {
29
+ const ast = parse(source)
30
+ const hir = lowerToHIR(ast)
31
+ const mir = lowerToMIR(hir)
32
+ expect(verifyMIR(mir)).toEqual([])
33
+ const fn = mir.functions.find(f => f.name === fnName)
34
+ expect(fn).toBeDefined()
35
+ return fn!
36
+ }
37
+
38
+ // ---------------------------------------------------------------------------
39
+ // 1. Parser: tuple type annotation (int, int)
40
+ // ---------------------------------------------------------------------------
41
+
42
+ const TUPLE_TYPE_SRC = `
43
+ fn min_max(arr: int[]): (int, int) {
44
+ let min: int = arr[0]
45
+ let max: int = arr[0]
46
+ return (min, max)
47
+ }
48
+ `
49
+
50
+ describe('tuple type — parser', () => {
51
+ test('parses function return type as tuple', () => {
52
+ const ast = parse(TUPLE_TYPE_SRC)
53
+ const fn = ast.declarations[0]
54
+ expect(fn.returnType).toMatchObject({ kind: 'tuple', elements: [
55
+ { kind: 'named', name: 'int' },
56
+ { kind: 'named', name: 'int' },
57
+ ] })
58
+ })
59
+
60
+ test('return statement contains a tuple_lit expression', () => {
61
+ const ast = parse(TUPLE_TYPE_SRC)
62
+ const fn = ast.declarations[0]
63
+ const ret = fn.body[fn.body.length - 1]
64
+ expect(ret.kind).toBe('return')
65
+ if (ret.kind !== 'return') throw new Error()
66
+ expect(ret.value).toMatchObject({ kind: 'tuple_lit', elements: [
67
+ { kind: 'ident', name: 'min' },
68
+ { kind: 'ident', name: 'max' },
69
+ ] })
70
+ })
71
+ })
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // 2. Parser: let destructuring let (a, b) = expr
75
+ // ---------------------------------------------------------------------------
76
+
77
+ const DESTRUCT_SRC = `
78
+ fn test() {
79
+ let (lo, hi) = (1, 2)
80
+ }
81
+ `
82
+
83
+ describe('tuple destructuring — parser', () => {
84
+ test('parses let_destruct with two bindings', () => {
85
+ const ast = parse(DESTRUCT_SRC)
86
+ const fn = ast.declarations[0]
87
+ const stmt = fn.body[0]
88
+ expect(stmt).toMatchObject({
89
+ kind: 'let_destruct',
90
+ names: ['lo', 'hi'],
91
+ })
92
+ })
93
+
94
+ test('initializer is a tuple_lit', () => {
95
+ const ast = parse(DESTRUCT_SRC)
96
+ const fn = ast.declarations[0]
97
+ const stmt = fn.body[0] as any
98
+ expect(stmt.init).toMatchObject({ kind: 'tuple_lit', elements: [
99
+ { kind: 'int_lit', value: 1 },
100
+ { kind: 'int_lit', value: 2 },
101
+ ] })
102
+ })
103
+ })
104
+
105
+ // ---------------------------------------------------------------------------
106
+ // 3. Parser: three-element tuple
107
+ // ---------------------------------------------------------------------------
108
+
109
+ // Note: (1, 2, 3) with three int literals is ambiguous with BlockPos literal in the parser.
110
+ // Use variable names to force tuple interpretation.
111
+ const THREE_TUPLE_SRC = `
112
+ fn triple(): (int, int, int) {
113
+ let x: int = 1
114
+ let y: int = 2
115
+ let z: int = 3
116
+ return (x, y, z)
117
+ }
118
+
119
+ fn caller() {
120
+ let (a, b, c) = triple()
121
+ }
122
+ `
123
+
124
+ describe('three-element tuple', () => {
125
+ test('return type has three elements', () => {
126
+ const ast = parse(THREE_TUPLE_SRC)
127
+ const fn = ast.declarations[0]
128
+ expect(fn.returnType).toMatchObject({
129
+ kind: 'tuple',
130
+ elements: [
131
+ { kind: 'named', name: 'int' },
132
+ { kind: 'named', name: 'int' },
133
+ { kind: 'named', name: 'int' },
134
+ ],
135
+ })
136
+ })
137
+
138
+ test('destructuring binds three names', () => {
139
+ const ast = parse(THREE_TUPLE_SRC)
140
+ const caller = ast.declarations[1]
141
+ const stmt = caller.body[0] as any
142
+ expect(stmt.kind).toBe('let_destruct')
143
+ expect(stmt.names).toEqual(['a', 'b', 'c'])
144
+ })
145
+ })
146
+
147
+ // ---------------------------------------------------------------------------
148
+ // 4. MIR: tuple return emits __rf_0 / __rf_1 copies
149
+ // ---------------------------------------------------------------------------
150
+
151
+ describe('tuple return — MIR', () => {
152
+ test('MIR for return (a, b) emits copies to __rf_0 and __rf_1', () => {
153
+ const fn = lowerFn(TUPLE_TYPE_SRC, 'min_max')
154
+
155
+ const allInstrs = fn.blocks.flatMap(b => b.instrs)
156
+ const rf0 = allInstrs.find(i => i.kind === 'copy' && (i as any).dst === '__rf_0')
157
+ const rf1 = allInstrs.find(i => i.kind === 'copy' && (i as any).dst === '__rf_1')
158
+ expect(rf0).toBeDefined()
159
+ expect(rf1).toBeDefined()
160
+ })
161
+ })
162
+
163
+ // ---------------------------------------------------------------------------
164
+ // 5. MIR: destructuring a tuple call — reads __rf_0, __rf_1
165
+ // ---------------------------------------------------------------------------
166
+
167
+ const CALLER_SRC = `
168
+ fn min_max(arr: int[]): (int, int) {
169
+ let min: int = arr[0]
170
+ let max: int = arr[0]
171
+ return (min, max)
172
+ }
173
+
174
+ fn test() {
175
+ let arr = [3, 1, 4, 1, 5, 9]
176
+ let (lo, hi) = min_max(arr)
177
+ }
178
+ `
179
+
180
+ describe('tuple destructuring call — MIR', () => {
181
+ test('MIR for let (lo, hi) = call() reads __rf_0 and __rf_1', () => {
182
+ const fn = lowerFn(CALLER_SRC, 'test')
183
+
184
+ const allInstrs = fn.blocks.flatMap(b => b.instrs)
185
+ // There must be copies from __rf_0 and __rf_1 temps
186
+ const readRf = allInstrs.filter(i =>
187
+ i.kind === 'copy' && (i as any).src?.name?.startsWith('__rf_')
188
+ )
189
+ expect(readRf.length).toBeGreaterThanOrEqual(2)
190
+ })
191
+ })
192
+
193
+ // ---------------------------------------------------------------------------
194
+ // 6. MIR: direct tuple literal destructuring let (a, b) = (10, 20)
195
+ // ---------------------------------------------------------------------------
196
+
197
+ const DIRECT_DESTRUCT_SRC = `
198
+ fn test() {
199
+ let (a, b) = (10, 20)
200
+ }
201
+ `
202
+
203
+ describe('direct tuple literal destructuring — MIR', () => {
204
+ test('MIR evaluates each element into separate temps', () => {
205
+ const fn = lowerFn(DIRECT_DESTRUCT_SRC, 'test')
206
+ const allInstrs = fn.blocks.flatMap(b => b.instrs)
207
+ // Constants 10 and 20 should appear in the instr stream
208
+ const constVals = allInstrs
209
+ .filter(i => i.kind === 'copy' && (i as any).src?.kind === 'const')
210
+ .map(i => (i as any).src.value as number)
211
+ expect(constVals).toContain(10)
212
+ expect(constVals).toContain(20)
213
+ })
214
+ })
215
+
216
+ // ---------------------------------------------------------------------------
217
+ // Helpers for compile output
218
+ // ---------------------------------------------------------------------------
219
+
220
+ function compileOutput(source: string): string {
221
+ const result = compile(source, { namespace: 'test' })
222
+ // compile() returns { files: Array<{path, content}>, warnings, success }
223
+ const files = (result as any).files as Array<{ path: string; content: string }>
224
+ return files.map((f: { path: string; content: string }) => f.content).join('\n')
225
+ }
226
+
227
+ // ---------------------------------------------------------------------------
228
+ // 7. End-to-end compile: does not throw
229
+ // ---------------------------------------------------------------------------
230
+
231
+ describe('tuple type — end-to-end compile', () => {
232
+ test('min_max function compiles without error', () => {
233
+ expect(() => compile(TUPLE_TYPE_SRC, { namespace: 'test' })).not.toThrow()
234
+ })
235
+
236
+ test('full min_max + caller compiles without error', () => {
237
+ expect(() => compile(CALLER_SRC, { namespace: 'test' })).not.toThrow()
238
+ })
239
+
240
+ test('three-element tuple compiles without error', () => {
241
+ expect(() => compile(THREE_TUPLE_SRC, { namespace: 'test' })).not.toThrow()
242
+ })
243
+ })
244
+
245
+ // ---------------------------------------------------------------------------
246
+ // 8. Compile output: tuple return generates scoreboard operations
247
+ // ---------------------------------------------------------------------------
248
+
249
+ describe('tuple return — compiled output', () => {
250
+ test('compiled output contains scoreboard operations for both return slots', () => {
251
+ const allOutput = compileOutput(TUPLE_TYPE_SRC)
252
+ // Tuple return compiles to scoreboard operations for ret_0 and ret_1 slots
253
+ expect(allOutput).toMatch(/\$ret_0/)
254
+ expect(allOutput).toMatch(/\$ret_1/)
255
+ })
256
+
257
+ test('compiled caller output references both return slots', () => {
258
+ const allOutput = compileOutput(CALLER_SRC)
259
+ // Caller reads from ret_0 / ret_1 (scoreboard-based return convention)
260
+ expect(allOutput).toMatch(/\$ret_0/)
261
+ expect(allOutput).toMatch(/\$ret_1/)
262
+ })
263
+ })
@@ -0,0 +1,72 @@
1
+ import { compile } from '../../emit/compile'
2
+ import { Lexer } from '../../lexer'
3
+ import { Parser } from '../../parser'
4
+ import { TypeChecker } from '../../typechecker'
5
+ import type { DiagnosticError } from '../../diagnostics'
6
+
7
+ function getFile(files: Array<{ path: string; content: string }>, path: string): string {
8
+ const file = files.find(entry => entry.path === path)
9
+ if (!file) {
10
+ throw new Error(`Missing file: ${path}\nFiles:\n${files.map(entry => entry.path).join('\n')}`)
11
+ }
12
+ return file.content
13
+ }
14
+
15
+ function parseWatchObjective(source: string): string | undefined {
16
+ const tokens = new Lexer(source).tokenize()
17
+ const ast = new Parser(tokens).parse('test')
18
+ return ast.declarations[0]?.watchObjective
19
+ }
20
+
21
+ function typeCheck(source: string): DiagnosticError[] {
22
+ const tokens = new Lexer(source).tokenize()
23
+ const ast = new Parser(tokens).parse('test')
24
+ return new TypeChecker(source).check(ast)
25
+ }
26
+
27
+ describe('@watch decorator', () => {
28
+ test('parser records the watched objective on the function', () => {
29
+ expect(parseWatchObjective(`
30
+ @watch("rs.kills")
31
+ fn on_kill() {}
32
+ `)).toBe('rs.kills')
33
+ })
34
+
35
+ test('typechecker accepts parameterless handlers and rejects parameters', () => {
36
+ expect(typeCheck(`
37
+ @watch("rs.kills")
38
+ fn on_kill() {
39
+ say("kill");
40
+ }
41
+ `)).toHaveLength(0)
42
+
43
+ const errors = typeCheck(`
44
+ @watch("rs.kills")
45
+ fn on_kill(player: Player) {}
46
+ `)
47
+ expect(errors.length).toBeGreaterThan(0)
48
+ expect(errors[0].message).toContain('cannot declare parameters')
49
+ })
50
+
51
+ test('emits watcher objective, dispatcher, and tick registration', () => {
52
+ const result = compile(`
53
+ @watch("rs.kills")
54
+ fn on_kill() {
55
+ let k: int = scoreboard_get("@s", "rs.kills");
56
+ if (k >= 10) {
57
+ title("@s", "Achievement Unlocked!");
58
+ }
59
+ }
60
+ `, { namespace: 'watch_test' })
61
+
62
+ const load = getFile(result.files, 'data/watch_test/function/load.mcfunction')
63
+ const tick = JSON.parse(getFile(result.files, 'data/minecraft/tags/function/tick.json'))
64
+ const watch = getFile(result.files, 'data/watch_test/function/__watch_on_kill.mcfunction')
65
+
66
+ expect(load).toContain('scoreboard objectives add __watch_on_kill_prev dummy')
67
+ expect(tick.values).toContain('watch_test:__watch_on_kill')
68
+ expect(watch).toContain('execute as @a unless score @s __watch_on_kill_prev = @s __watch_on_kill_prev run scoreboard players operation @s __watch_on_kill_prev = @s rs.kills')
69
+ expect(watch).toContain('execute as @a unless score @s rs.kills = @s __watch_on_kill_prev run function watch_test:on_kill')
70
+ expect(watch).toContain('execute as @a unless score @s rs.kills = @s __watch_on_kill_prev run scoreboard players operation @s __watch_on_kill_prev = @s rs.kills')
71
+ })
72
+ })
@@ -0,0 +1,181 @@
1
+ import * as fs from 'fs'
2
+ import * as os from 'os'
3
+ import * as path from 'path'
4
+ import { loadProjectConfig, buildTomlTemplate, ProjectConfig } from '../../config/project-config'
5
+
6
+ // Helper: create a temp directory tree and write files
7
+ function makeTmpDir(): string {
8
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'redscript-config-test-'))
9
+ }
10
+
11
+ function writeToml(dir: string, content: string): void {
12
+ fs.writeFileSync(path.join(dir, 'redscript.toml'), content, 'utf-8')
13
+ }
14
+
15
+ afterAll(() => {
16
+ // Cleanup is handled per-test via individual tmpdir removal
17
+ })
18
+
19
+ // ──────────────────────────────────────────────────────────────────────────────
20
+ // Test 1: Returns null when no redscript.toml exists
21
+ // ──────────────────────────────────────────────────────────────────────────────
22
+ test('returns null when no redscript.toml is found', () => {
23
+ const dir = makeTmpDir()
24
+ const result = loadProjectConfig(dir)
25
+ expect(result).toBeNull()
26
+ fs.rmSync(dir, { recursive: true })
27
+ })
28
+
29
+ // ──────────────────────────────────────────────────────────────────────────────
30
+ // Test 2: Parses [project] section correctly
31
+ // ──────────────────────────────────────────────────────────────────────────────
32
+ test('parses [project] section fields correctly', () => {
33
+ const dir = makeTmpDir()
34
+ writeToml(dir, `
35
+ [project]
36
+ name = "my-datapack"
37
+ namespace = "my_pack"
38
+ mc-version = "1.21.4"
39
+ description = "My awesome datapack"
40
+ `)
41
+ const config = loadProjectConfig(dir)
42
+ expect(config).not.toBeNull()
43
+ expect(config!.project?.name).toBe('my-datapack')
44
+ expect(config!.project?.namespace).toBe('my_pack')
45
+ expect(config!.project?.['mc-version']).toBe('1.21.4')
46
+ expect(config!.project?.description).toBe('My awesome datapack')
47
+ fs.rmSync(dir, { recursive: true })
48
+ })
49
+
50
+ // ──────────────────────────────────────────────────────────────────────────────
51
+ // Test 3: Parses [compiler] section correctly
52
+ // ──────────────────────────────────────────────────────────────────────────────
53
+ test('parses [compiler] section fields correctly', () => {
54
+ const dir = makeTmpDir()
55
+ writeToml(dir, `
56
+ [compiler]
57
+ optimization = 2
58
+ include-dirs = ["src/shared", "src/stdlib"]
59
+ no-dce = false
60
+ `)
61
+ const config = loadProjectConfig(dir)
62
+ expect(config).not.toBeNull()
63
+ expect(config!.compiler?.optimization).toBe(2)
64
+ expect(config!.compiler?.['include-dirs']).toEqual(['src/shared', 'src/stdlib'])
65
+ expect(config!.compiler?.['no-dce']).toBe(false)
66
+ fs.rmSync(dir, { recursive: true })
67
+ })
68
+
69
+ // ──────────────────────────────────────────────────────────────────────────────
70
+ // Test 4: Parses [output] section correctly
71
+ // ──────────────────────────────────────────────────────────────────────────────
72
+ test('parses [output] section fields correctly', () => {
73
+ const dir = makeTmpDir()
74
+ writeToml(dir, `
75
+ [output]
76
+ dir = "dist/"
77
+ `)
78
+ const config = loadProjectConfig(dir)
79
+ expect(config).not.toBeNull()
80
+ expect(config!.output?.dir).toBe('dist/')
81
+ fs.rmSync(dir, { recursive: true })
82
+ })
83
+
84
+ // ──────────────────────────────────────────────────────────────────────────────
85
+ // Test 5: Full config — all sections together
86
+ // ──────────────────────────────────────────────────────────────────────────────
87
+ test('parses all sections in a full redscript.toml', () => {
88
+ const dir = makeTmpDir()
89
+ writeToml(dir, `
90
+ [project]
91
+ name = "my-datapack"
92
+ namespace = "my_pack"
93
+ mc-version = "1.21.4"
94
+ description = "My awesome datapack"
95
+
96
+ [compiler]
97
+ optimization = 2
98
+ include-dirs = ["src/shared", "src/stdlib"]
99
+ no-dce = false
100
+
101
+ [output]
102
+ dir = "dist/"
103
+ `)
104
+ const config = loadProjectConfig(dir)
105
+ expect(config).not.toBeNull()
106
+ expect(config!.project?.namespace).toBe('my_pack')
107
+ expect(config!.compiler?.optimization).toBe(2)
108
+ expect(config!.output?.dir).toBe('dist/')
109
+ fs.rmSync(dir, { recursive: true })
110
+ })
111
+
112
+ // ──────────────────────────────────────────────────────────────────────────────
113
+ // Test 6: Walks up the directory tree (sub-directory can find parent toml)
114
+ // ──────────────────────────────────────────────────────────────────────────────
115
+ test('finds redscript.toml by walking up the directory tree', () => {
116
+ const rootDir = makeTmpDir()
117
+ writeToml(rootDir, `
118
+ [project]
119
+ namespace = "parent_pack"
120
+ `)
121
+ // Create a nested sub-directory (simulating src/nested)
122
+ const subDir = path.join(rootDir, 'src', 'nested')
123
+ fs.mkdirSync(subDir, { recursive: true })
124
+
125
+ // loadProjectConfig called from subDir should find the toml in rootDir
126
+ const config = loadProjectConfig(subDir)
127
+ expect(config).not.toBeNull()
128
+ expect(config!.project?.namespace).toBe('parent_pack')
129
+ fs.rmSync(rootDir, { recursive: true })
130
+ })
131
+
132
+ // ──────────────────────────────────────────────────────────────────────────────
133
+ // Test 7: CLI flags take priority over toml values (simulated merge)
134
+ // ──────────────────────────────────────────────────────────────────────────────
135
+ test('CLI flags override toml values when merged', () => {
136
+ const dir = makeTmpDir()
137
+ writeToml(dir, `
138
+ [project]
139
+ namespace = "toml_namespace"
140
+ mc-version = "1.21.0"
141
+ description = "From TOML"
142
+
143
+ [output]
144
+ dir = "dist/"
145
+ `)
146
+ const tomlConfig = loadProjectConfig(dir)
147
+ expect(tomlConfig).not.toBeNull()
148
+
149
+ // Simulate CLI merge logic: CLI args take priority
150
+ const cliNamespace = 'cli_namespace' // provided by CLI
151
+ const cliMcVersion: string | undefined = undefined // not provided by CLI
152
+ const cliOutput: string | undefined = undefined // not provided by CLI
153
+
154
+ const namespace = cliNamespace ?? tomlConfig!.project?.namespace ?? 'default'
155
+ const mcVersion = cliMcVersion ?? tomlConfig!.project?.['mc-version'] ?? '1.21'
156
+ const outputDir = cliOutput ?? tomlConfig!.output?.dir ?? './dist'
157
+
158
+ expect(namespace).toBe('cli_namespace') // CLI wins
159
+ expect(mcVersion).toBe('1.21.0') // falls back to toml
160
+ expect(outputDir).toBe('dist/') // falls back to toml
161
+
162
+ fs.rmSync(dir, { recursive: true })
163
+ })
164
+
165
+ // ──────────────────────────────────────────────────────────────────────────────
166
+ // Test 8: buildTomlTemplate generates valid parseable content
167
+ // ──────────────────────────────────────────────────────────────────────────────
168
+ test('buildTomlTemplate generates a parseable template', () => {
169
+ const dir = makeTmpDir()
170
+ const template = buildTomlTemplate('test_pack')
171
+ fs.writeFileSync(path.join(dir, 'redscript.toml'), template, 'utf-8')
172
+
173
+ const config = loadProjectConfig(dir)
174
+ expect(config).not.toBeNull()
175
+ expect(config!.project?.name).toBe('test_pack')
176
+ expect(config!.project?.namespace).toBe('test_pack')
177
+ expect(config!.project?.['mc-version']).toBe('1.21.4')
178
+ expect(config!.output?.dir).toBe('dist/')
179
+
180
+ fs.rmSync(dir, { recursive: true })
181
+ })
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Tests for the @config decorator — compile-time configuration injection.
3
+ *
4
+ * @config("key", default: value) on a global let variable allows values to be
5
+ * injected at compile time via CompileOptions.config, enabling customizable
6
+ * build-time constants.
7
+ */
8
+
9
+ import { compile } from '../emit/compile'
10
+
11
+ function getFile(files: { path: string; content: string }[], pathSubstr: string): string | undefined {
12
+ const f = files.find(f => f.path.includes(pathSubstr))
13
+ return f?.content
14
+ }
15
+
16
+ describe('@config decorator — compile-time configuration injection', () => {
17
+ test('uses default value when no config is provided', () => {
18
+ const source = `
19
+ @config("max_players", default: 20)
20
+ let MAX_PLAYERS: int
21
+
22
+ fn get_max(): int {
23
+ return MAX_PLAYERS;
24
+ }
25
+ `
26
+ const result = compile(source, { namespace: 'test' })
27
+ const fn = getFile(result.files, 'get_max.mcfunction')
28
+ expect(fn).toBeDefined()
29
+ // Default value 20 should be used
30
+ expect(fn).toContain('20')
31
+ })
32
+
33
+ test('overrides default value with provided config', () => {
34
+ const source = `
35
+ @config("max_players", default: 20)
36
+ let MAX_PLAYERS: int
37
+
38
+ fn get_max(): int {
39
+ return MAX_PLAYERS;
40
+ }
41
+ `
42
+ const result = compile(source, { namespace: 'test', config: { max_players: 10 } })
43
+ const fn = getFile(result.files, 'get_max.mcfunction')
44
+ expect(fn).toBeDefined()
45
+ // Config value 10 should be used, not default 20
46
+ expect(fn).toContain('10')
47
+ })
48
+
49
+ test('different config values produce different outputs', () => {
50
+ const source = `
51
+ @config("difficulty", default: 1)
52
+ let DIFFICULTY: int
53
+
54
+ fn get_difficulty(): int {
55
+ return DIFFICULTY;
56
+ }
57
+ `
58
+
59
+ const resultEasy = compile(source, { namespace: 'test', config: { difficulty: 1 } })
60
+ const resultHard = compile(source, { namespace: 'test', config: { difficulty: 5 } })
61
+
62
+ const fnEasy = getFile(resultEasy.files, 'get_difficulty.mcfunction')
63
+ const fnHard = getFile(resultHard.files, 'get_difficulty.mcfunction')
64
+
65
+ expect(fnEasy).toBeDefined()
66
+ expect(fnHard).toBeDefined()
67
+
68
+ // Hard difficulty (5) vs easy (1) — outputs differ
69
+ expect(fnEasy).not.toEqual(fnHard)
70
+ expect(fnEasy).toContain('1')
71
+ expect(fnHard).toContain('5')
72
+ })
73
+
74
+ test('multiple @config variables', () => {
75
+ const source = `
76
+ @config("max_players", default: 20)
77
+ let MAX_PLAYERS: int
78
+
79
+ @config("difficulty", default: 1)
80
+ let DIFFICULTY: int
81
+
82
+ fn get_max(): int {
83
+ return MAX_PLAYERS;
84
+ }
85
+
86
+ fn get_diff(): int {
87
+ return DIFFICULTY;
88
+ }
89
+ `
90
+ const result = compile(source, {
91
+ namespace: 'test',
92
+ config: { max_players: 10, difficulty: 3 },
93
+ })
94
+
95
+ const maxFn = getFile(result.files, 'get_max.mcfunction')
96
+ const diffFn = getFile(result.files, 'get_diff.mcfunction')
97
+
98
+ expect(maxFn).toBeDefined()
99
+ expect(diffFn).toBeDefined()
100
+
101
+ // max_players=10 used
102
+ expect(maxFn).toContain('10')
103
+ // difficulty=3 used
104
+ expect(diffFn).toContain('3')
105
+ })
106
+
107
+ test('config without default falls back to 0', () => {
108
+ const source = `
109
+ @config("some_value")
110
+ let SOME_VALUE: int
111
+
112
+ fn get_val(): int {
113
+ return SOME_VALUE;
114
+ }
115
+ `
116
+ // No config provided, no default — should fall back to 0
117
+ const result = compile(source, { namespace: 'test' })
118
+ const fn = getFile(result.files, 'get_val.mcfunction')
119
+ expect(fn).toBeDefined()
120
+ expect(fn).toContain('0')
121
+ })
122
+
123
+ test('config value overrides even when default is provided', () => {
124
+ const source = `
125
+ @config("boost", default: 100)
126
+ let BOOST: int
127
+
128
+ fn get_boost(): int {
129
+ return BOOST;
130
+ }
131
+ `
132
+ const result = compile(source, { namespace: 'test', config: { boost: 999 } })
133
+ const fn = getFile(result.files, 'get_boost.mcfunction')
134
+ expect(fn).toBeDefined()
135
+ expect(fn).toContain('999')
136
+ // Default 100 should NOT appear
137
+ expect(fn).not.toContain('100')
138
+ })
139
+
140
+ test('compilation succeeds without errors for @config globals', () => {
141
+ const source = `
142
+ @config("max_players", default: 20)
143
+ let MAX_PLAYERS: int
144
+
145
+ @config("difficulty", default: 1)
146
+ let DIFFICULTY: int
147
+
148
+ fn spawn_enemies(): void {
149
+ let count: int = 3 * DIFFICULTY;
150
+ }
151
+ `
152
+ // Should compile cleanly with config values
153
+ expect(() =>
154
+ compile(source, { namespace: 'test', config: { max_players: 10, difficulty: 3 } })
155
+ ).not.toThrow()
156
+ })
157
+ })