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,1366 @@
1
+ /**
2
+ * RedScript MC Integration Tests — stdlib coverage 4
3
+ *
4
+ * Tests graph / linalg / physics / parabola / quaternion / bigint / heap / pathfind
5
+ * stdlib modules against a real Paper 1.21.4 server with TestHarnessPlugin.
6
+ *
7
+ * Prerequisites:
8
+ * - Paper server running with TestHarnessPlugin on port 25561
9
+ * - MC_SERVER_DIR env var pointing to server directory
10
+ *
11
+ * Run: MC_SERVER_DIR=~/mc-test-server npx jest stdlib-coverage-4 --testTimeout=120000
12
+ */
13
+
14
+ import * as fs from 'fs'
15
+ import * as path from 'path'
16
+ import { compile } from '../../compile'
17
+ import { MCTestClient } from '../../mc-test/client'
18
+
19
+ const MC_HOST = process.env.MC_HOST ?? 'localhost'
20
+ const MC_PORT = parseInt(process.env.MC_PORT ?? '25561')
21
+ const MC_SERVER_DIR = process.env.MC_SERVER_DIR ?? path.join(process.env.HOME!, 'mc-test-server')
22
+ const DATAPACK_DIR = path.join(MC_SERVER_DIR, 'world', 'datapacks', 'redscript-test4')
23
+
24
+ const STDLIB_DIR = path.join(__dirname, '../../stdlib')
25
+
26
+ let serverOnline = false
27
+ let mc: MCTestClient
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Helper: compile and deploy a RedScript snippet with optional stdlib libs
31
+ // ---------------------------------------------------------------------------
32
+ function writeFixture(source: string, namespace: string, librarySources: string[] = []): void {
33
+ fs.mkdirSync(DATAPACK_DIR, { recursive: true })
34
+ if (!fs.existsSync(path.join(DATAPACK_DIR, 'pack.mcmeta'))) {
35
+ fs.writeFileSync(
36
+ path.join(DATAPACK_DIR, 'pack.mcmeta'),
37
+ JSON.stringify({ pack: { pack_format: 48, description: 'RedScript integration tests 4' } })
38
+ )
39
+ }
40
+
41
+ const result = compile(source, { namespace, librarySources })
42
+
43
+ for (const file of result.files) {
44
+ if (file.path === 'pack.mcmeta') continue
45
+ const filePath = path.join(DATAPACK_DIR, file.path)
46
+ fs.mkdirSync(path.dirname(filePath), { recursive: true })
47
+
48
+ // Merge minecraft tag files (tick.json / load.json) instead of overwriting
49
+ if (file.path.includes('data/minecraft/tags/') && fs.existsSync(filePath)) {
50
+ const existing = JSON.parse(fs.readFileSync(filePath, 'utf-8'))
51
+ const incoming = JSON.parse(file.content)
52
+ const merged = { values: [...new Set([...(existing.values ?? []), ...(incoming.values ?? [])])] }
53
+ fs.writeFileSync(filePath, JSON.stringify(merged, null, 2))
54
+ } else {
55
+ fs.writeFileSync(filePath, file.content)
56
+ }
57
+ }
58
+ }
59
+
60
+ function readStdlib(name: string): string {
61
+ return fs.readFileSync(path.join(STDLIB_DIR, name), 'utf-8')
62
+ }
63
+
64
+ // ---------------------------------------------------------------------------
65
+ // Setup
66
+ // ---------------------------------------------------------------------------
67
+
68
+ beforeAll(async () => {
69
+ if (process.env.MC_OFFLINE === 'true') {
70
+ console.warn('⚠ MC_OFFLINE=true — skipping stdlib coverage 4 integration tests')
71
+ return
72
+ }
73
+
74
+ mc = new MCTestClient(MC_HOST, MC_PORT)
75
+
76
+ try {
77
+ const deadline = Date.now() + 10_000
78
+ while (Date.now() < deadline) {
79
+ if (await mc.isOnline()) { serverOnline = true; break }
80
+ await new Promise(r => setTimeout(r, 1000))
81
+ }
82
+ } catch {
83
+ serverOnline = false
84
+ }
85
+
86
+ if (!serverOnline) {
87
+ console.warn(`⚠ MC server not running at ${MC_HOST}:${MC_PORT} — skipping stdlib coverage 4 tests`)
88
+ return
89
+ }
90
+
91
+ // Clear stale minecraft tag files before writing fixtures
92
+ for (const tagFile of [
93
+ 'data/minecraft/tags/function/tick.json',
94
+ 'data/minecraft/tags/function/load.json',
95
+ 'data/minecraft/tags/functions/tick.json',
96
+ 'data/minecraft/tags/functions/load.json',
97
+ ]) {
98
+ const p = path.join(DATAPACK_DIR, tagFile)
99
+ if (fs.existsSync(p)) fs.writeFileSync(p, JSON.stringify({ values: [] }, null, 2))
100
+ }
101
+
102
+ // Ensure result objective exists
103
+ await mc.command('/scoreboard objectives add sc4_result dummy').catch(() => {})
104
+
105
+ const MATH_SRC = readStdlib('math.mcrs')
106
+ const MATH_HP_SRC = readStdlib('math_hp.mcrs')
107
+ const GRAPH_SRC = readStdlib('graph.mcrs')
108
+ const LINALG_SRC = readStdlib('linalg.mcrs')
109
+ const PHYSICS_SRC = readStdlib('physics.mcrs')
110
+ const PARABOLA_SRC = readStdlib('parabola.mcrs')
111
+ const QUATERNION_SRC = readStdlib('quaternion.mcrs')
112
+ const BIGINT_SRC = readStdlib('bigint.mcrs')
113
+ const HEAP_SRC = readStdlib('heap.mcrs')
114
+ const PATHFIND_SRC = readStdlib('pathfind.mcrs')
115
+
116
+ // ─── graph module ────────────────────────────────────────────────────────
117
+ writeFixture(`
118
+ namespace stdlib_graph_test
119
+
120
+ fn test_graph_node_count() {
121
+ let g: int[] = graph_new(5)
122
+ let n: int = graph_node_count(g)
123
+ scoreboard_set("#graph_nodes", #sc4_result, n)
124
+ }
125
+
126
+ fn test_graph_add_edge_count() {
127
+ let g: int[] = graph_new(4)
128
+ g = graph_add_edge(g, 0, 1, 1)
129
+ g = graph_add_edge(g, 1, 2, 2)
130
+ g = graph_add_edge(g, 2, 3, 3)
131
+ let e: int = graph_edge_count(g)
132
+ scoreboard_set("#graph_edges", #sc4_result, e)
133
+ }
134
+
135
+ fn test_graph_has_path_direct() {
136
+ let g: int[] = graph_new(4)
137
+ g = graph_add_edge(g, 0, 1, 1)
138
+ g = graph_add_edge(g, 1, 2, 1)
139
+ g = graph_add_edge(g, 2, 3, 1)
140
+ let found: int = graph_has_path(g, 0, 3)
141
+ scoreboard_set("#graph_path_yes", #sc4_result, found)
142
+ }
143
+
144
+ fn test_graph_has_path_none() {
145
+ let g: int[] = graph_new(4)
146
+ g = graph_add_edge(g, 0, 1, 1)
147
+ // no edge from 1->2 or to 3
148
+ let found: int = graph_has_path(g, 0, 3)
149
+ scoreboard_set("#graph_path_no", #sc4_result, found)
150
+ }
151
+
152
+ fn test_graph_shortest_path() {
153
+ // 0->1 weight 1, 0->2 weight 4, 1->2 weight 2, 1->3 weight 6, 2->3 weight 3
154
+ // shortest 0->3 = 0->1->2->3 = 1+2+3 = 6
155
+ let g: int[] = graph_new(4)
156
+ g = graph_add_edge(g, 0, 1, 1)
157
+ g = graph_add_edge(g, 0, 2, 4)
158
+ g = graph_add_edge(g, 1, 2, 2)
159
+ g = graph_add_edge(g, 1, 3, 6)
160
+ g = graph_add_edge(g, 2, 3, 3)
161
+ let dist: int[] = [0, 0, 0, 0]
162
+ let d: int = graph_shortest_path(g, 0, 3, dist)
163
+ scoreboard_set("#graph_dijkstra", #sc4_result, d)
164
+ }
165
+
166
+ fn test_graph_bfs_order_start() {
167
+ let g: int[] = graph_new(4)
168
+ g = graph_add_edge(g, 0, 1, 1)
169
+ g = graph_add_edge(g, 0, 2, 1)
170
+ g = graph_add_edge(g, 1, 3, 1)
171
+ let vis: int[] = [0, 0, 0, 0]
172
+ let order: int[] = graph_bfs(g, 0, vis)
173
+ let first: int = order[0]
174
+ scoreboard_set("#graph_bfs_first", #sc4_result, first)
175
+ }
176
+
177
+ fn test_graph_undirected() {
178
+ let g: int[] = graph_new(3)
179
+ g = graph_add_undirected(g, 0, 1, 5)
180
+ let e: int = graph_edge_count(g)
181
+ scoreboard_set("#graph_undirected_edges", #sc4_result, e)
182
+ }
183
+ `, 'stdlib_graph_test', [GRAPH_SRC])
184
+
185
+ // ─── linalg module (uses vec.mcrs integer functions for reliability) ────────
186
+ const VEC_SRC = readStdlib('vec.mcrs')
187
+ writeFixture(`
188
+ namespace stdlib_linalg_test
189
+
190
+ fn test_vec2d_dot() {
191
+ // dot([3,4],[3,4]) = 9+16 = 25
192
+ let r: int = dot2d(3, 4, 3, 4)
193
+ scoreboard_set("#linalg_dot2d", #sc4_result, r)
194
+ }
195
+
196
+ fn test_vec3d_dot() {
197
+ // dot([1,2,3],[4,5,6]) = 4+10+18 = 32
198
+ let r: int = dot3d(1, 2, 3, 4, 5, 6)
199
+ scoreboard_set("#linalg_dot3d", #sc4_result, r)
200
+ }
201
+
202
+ fn test_vec2d_length() {
203
+ // length([3,4]) = 5000 (fixed-point x1000)
204
+ let r: int = length2d_fixed(3, 4)
205
+ scoreboard_set("#linalg_len2d", #sc4_result, r)
206
+ }
207
+
208
+ fn test_vec3d_length() {
209
+ // length([0,3,4]) = 5000 (fixed-point x1000)
210
+ let r: int = length3d_fixed(0, 3, 4)
211
+ scoreboard_set("#linalg_len3d", #sc4_result, r)
212
+ }
213
+
214
+ fn test_vec3d_cross_z() {
215
+ // cross([1,0,0]x[0,1,0]).z = 1*1 - 0*0 = 1
216
+ let r: int = cross3d_z(1, 0, 0, 0, 1, 0)
217
+ scoreboard_set("#linalg_cross_z", #sc4_result, r)
218
+ }
219
+
220
+ fn test_mat2d_det() {
221
+ // det([1,2],[3,4]) = 1*4 - 2*3 = -2
222
+ let d: int = 1 * 4 - 2 * 3
223
+ scoreboard_set("#linalg_det", #sc4_result, d)
224
+ }
225
+
226
+ fn test_solve2d_x() {
227
+ // [2 1][x]=[5] -> Cramer: det=2*3-1*1=5, x=(5*3-1*10)/5=1
228
+ let det: int = 2 * 3 - 1 * 1
229
+ let x: int = (5 * 3 - 1 * 10) / det
230
+ scoreboard_set("#linalg_cramer_x", #sc4_result, x)
231
+ }
232
+
233
+ fn test_solve2d_y() {
234
+ // y=(2*10-5*1)/5=3
235
+ let det: int = 2 * 3 - 1 * 1
236
+ let y: int = (2 * 10 - 5 * 1) / det
237
+ scoreboard_set("#linalg_cramer_y", #sc4_result, y)
238
+ }
239
+ `, 'stdlib_linalg_test', [MATH_SRC, VEC_SRC])
240
+
241
+ // ─── physics module ───────────────────────────────────────────────────────
242
+ writeFixture(`
243
+ namespace stdlib_physics_test
244
+
245
+ fn test_gravity_fx() {
246
+ let g: int = gravity_fx()
247
+ scoreboard_set("#phys_gravity", #sc4_result, g)
248
+ }
249
+
250
+ fn test_projectile_y_at_t0() {
251
+ // y(p0=100, v0=50, t=0) = 100 + 0 - 0 = 100
252
+ let y: int = projectile_y(100, 50, 0)
253
+ scoreboard_set("#phys_proj_y_t0", #sc4_result, y)
254
+ }
255
+
256
+ fn test_projectile_x_linear() {
257
+ // x(p0=0, v0=200, t=5) = 0 + 200*5 = 1000
258
+ let x: int = projectile_x(0, 200, 5)
259
+ scoreboard_set("#phys_proj_x", #sc4_result, x)
260
+ }
261
+
262
+ fn test_projectile_max_height() {
263
+ // h = v0y²/(2g) = 80²/(2*8) = 6400/16 = 400
264
+ let h: int = projectile_max_height(80)
265
+ scoreboard_set("#phys_max_h", #sc4_result, h)
266
+ }
267
+
268
+ fn test_apply_drag() {
269
+ // apply_drag(1000, 9800) = 1000*9800/10000 = 980
270
+ let v: int = apply_drag(1000, 9800)
271
+ scoreboard_set("#phys_drag", #sc4_result, v)
272
+ }
273
+
274
+ fn test_bounce_v() {
275
+ // bounce_v(-500, 8000) = 500 * 8000 / 10000 = 400
276
+ let v: int = bounce_v(-500, 8000)
277
+ scoreboard_set("#phys_bounce", #sc4_result, v)
278
+ }
279
+
280
+ fn test_is_grounded_yes() {
281
+ let r: int = is_grounded(0, 0)
282
+ scoreboard_set("#phys_ground_yes", #sc4_result, r)
283
+ }
284
+
285
+ fn test_is_grounded_no() {
286
+ let r: int = is_grounded(100, 0)
287
+ scoreboard_set("#phys_ground_no", #sc4_result, r)
288
+ }
289
+
290
+ fn test_spring_force() {
291
+ // spring_force(pos=0, target=100, k=10000) = (100-0)*10000/10000 = 100
292
+ let f: int = spring_force(0, 100, 10000)
293
+ scoreboard_set("#phys_spring", #sc4_result, f)
294
+ }
295
+
296
+ fn test_friction_decel_positive() {
297
+ // friction_decel(500, 100) = 500-100 = 400
298
+ let v: int = friction_decel(500, 100)
299
+ scoreboard_set("#phys_friction_pos", #sc4_result, v)
300
+ }
301
+
302
+ fn test_friction_decel_to_zero() {
303
+ // friction_decel(50, 100) = 0 (|v| < friction)
304
+ let v: int = friction_decel(50, 100)
305
+ scoreboard_set("#phys_friction_zero", #sc4_result, v)
306
+ }
307
+ `, 'stdlib_physics_test', [MATH_SRC, PHYSICS_SRC])
308
+
309
+ // ─── parabola module ──────────────────────────────────────────────────────
310
+ writeFixture(`
311
+ namespace stdlib_parabola_test
312
+
313
+ fn test_parabola_gravity() {
314
+ let g: int = parabola_gravity()
315
+ scoreboard_set("#para_gravity", #sc4_result, g)
316
+ }
317
+
318
+ fn test_parabola_vx() {
319
+ // vx = dx*10000/ticks = 10*10000/20 = 5000
320
+ let vx: int = parabola_vx(10, 20)
321
+ scoreboard_set("#para_vx", #sc4_result, vx)
322
+ }
323
+
324
+ fn test_parabola_vz() {
325
+ // vz = dz*10000/ticks = 5*10000/10 = 5000
326
+ let vz: int = parabola_vz(5, 10)
327
+ scoreboard_set("#para_vz", #sc4_result, vz)
328
+ }
329
+
330
+ fn test_parabola_x_at_t() {
331
+ // x = vx0*t/10000 = 5000*20/10000 = 10
332
+ let x: int = parabola_x(5000, 20)
333
+ scoreboard_set("#para_x", #sc4_result, x)
334
+ }
335
+
336
+ fn test_parabola_flight_time() {
337
+ // t = 2*vy0/g = 2*4000/800 = 10
338
+ let t: int = parabola_flight_time(4000)
339
+ scoreboard_set("#para_flight_t", #sc4_result, t)
340
+ }
341
+
342
+ fn test_parabola_in_range_yes() {
343
+ // sqrt(3²+4²)=5 ≤ 10 → 1
344
+ let r: int = parabola_in_range(3, 4, 10)
345
+ scoreboard_set("#para_inrange_yes", #sc4_result, r)
346
+ }
347
+
348
+ fn test_parabola_in_range_no() {
349
+ // sqrt(10²+10²)≈14.1 > 10 → 0
350
+ let r: int = parabola_in_range(10, 10, 10)
351
+ scoreboard_set("#para_inrange_no", #sc4_result, r)
352
+ }
353
+
354
+ fn test_parabola_step_vx_drag() {
355
+ // step_vx(10000, 9900) = mulfix(10000,9900) = 9900
356
+ let vx: int = parabola_step_vx(10000, 9900)
357
+ scoreboard_set("#para_step_vx", #sc4_result, vx)
358
+ }
359
+ `, 'stdlib_parabola_test', [MATH_SRC, PARABOLA_SRC])
360
+
361
+ // ─── quaternion module ────────────────────────────────────────────────────
362
+ writeFixture(`
363
+ namespace stdlib_quaternion_test
364
+
365
+ fn test_quat_identity_w() {
366
+ let w: int = quat_identity_w()
367
+ scoreboard_set("#quat_id_w", #sc4_result, w)
368
+ }
369
+
370
+ fn test_quat_identity_x() {
371
+ let x: int = quat_identity_x()
372
+ scoreboard_set("#quat_id_x", #sc4_result, x)
373
+ }
374
+
375
+ fn test_quat_mag_sq_identity() {
376
+ // identity (0,0,0,10000): mag_sq = mulfix(0,0)*3 + mulfix(10000,10000) = 10000
377
+ let ms: int = quat_mag_sq(0, 0, 0, 10000)
378
+ scoreboard_set("#quat_magsq_id", #sc4_result, ms)
379
+ }
380
+
381
+ fn test_quat_conj_x() {
382
+ // conj of (1000,2000,3000,8000) → x = -1000
383
+ let cx: int = quat_conj_x(1000, 2000, 3000, 8000)
384
+ scoreboard_set("#quat_conj_x", #sc4_result, cx)
385
+ }
386
+
387
+ fn test_quat_conj_w() {
388
+ // conj preserves w
389
+ let cw: int = quat_conj_w(1000, 2000, 3000, 8000)
390
+ scoreboard_set("#quat_conj_w", #sc4_result, cw)
391
+ }
392
+
393
+ fn test_quat_dot_identity_self() {
394
+ // dot(identity, identity) = mulfix(10000,10000) = 10000
395
+ let d: int = quat_dot(0, 0, 0, 10000, 0, 0, 0, 10000)
396
+ scoreboard_set("#quat_dot_id", #sc4_result, d)
397
+ }
398
+
399
+ fn test_quat_mul_identity() {
400
+ // identity * identity → w component should be 10000
401
+ let w: int = quat_mul_w(0, 0, 0, 10000, 0, 0, 0, 10000)
402
+ scoreboard_set("#quat_mul_w_id", #sc4_result, w)
403
+ }
404
+
405
+ fn test_quat_slerp_at_0() {
406
+ // slerp(a, b, t=0) should give a; test w component of identity
407
+ let w: int = quat_slerp_w(0, 0, 0, 10000, 0, 0, 0, 10000, 0)
408
+ scoreboard_set("#quat_slerp_w_t0", #sc4_result, w)
409
+ }
410
+ `, 'stdlib_quaternion_test', [MATH_SRC, QUATERNION_SRC])
411
+
412
+ // ─── bigint module ────────────────────────────────────────────────────────
413
+ writeFixture(`
414
+ namespace stdlib_bigint_test
415
+
416
+ fn test_bigint_base() {
417
+ let b: int = bigint_base()
418
+ scoreboard_set("#bigint_base", #sc4_result, b)
419
+ }
420
+
421
+ fn test_chunk_hi() {
422
+ // chunk_hi(12345) = 12345/10000 = 1
423
+ let h: int = chunk_hi(12345)
424
+ scoreboard_set("#bigint_chunk_hi", #sc4_result, h)
425
+ }
426
+
427
+ fn test_chunk_lo() {
428
+ // chunk_lo(12345) = 12345%10000 = 2345
429
+ let l: int = chunk_lo(12345)
430
+ scoreboard_set("#bigint_chunk_lo", #sc4_result, l)
431
+ }
432
+
433
+ fn test_bigint3_add_lo() {
434
+ // (5000 + 7000) % 10000 = 2000
435
+ let lo: int = bigint3_add_lo(5000, 7000)
436
+ scoreboard_set("#bigint3_add_lo", #sc4_result, lo)
437
+ }
438
+
439
+ fn test_bigint3_carry_lo() {
440
+ // (5000 + 7000) / 10000 = 1
441
+ let c: int = bigint3_carry_lo(5000, 7000)
442
+ scoreboard_set("#bigint3_carry", #sc4_result, c)
443
+ }
444
+
445
+ fn test_bigint3_cmp_eq() {
446
+ let r: int = bigint3_cmp(0, 0, 100, 0, 0, 100)
447
+ scoreboard_set("#bigint3_cmp_eq", #sc4_result, r)
448
+ }
449
+
450
+ fn test_bigint3_cmp_gt() {
451
+ let r: int = bigint3_cmp(0, 0, 200, 0, 0, 100)
452
+ scoreboard_set("#bigint3_cmp_gt", #sc4_result, r)
453
+ }
454
+
455
+ fn test_bigint3_cmp_lt() {
456
+ let r: int = bigint3_cmp(0, 0, 50, 0, 0, 100)
457
+ scoreboard_set("#bigint3_cmp_lt", #sc4_result, r)
458
+ }
459
+
460
+ fn test_bigint3_mul1_lo() {
461
+ // (3000*3000) % 10000 = 9000000%10000 = 0
462
+ let lo: int = bigint3_mul1_lo(3000, 3000)
463
+ scoreboard_set("#bigint3_mul1_lo", #sc4_result, lo)
464
+ }
465
+
466
+ fn test_bigint3_mul1_hi() {
467
+ // (3000*3000) / 10000 = 900
468
+ let hi: int = bigint3_mul1_hi(3000, 3000)
469
+ scoreboard_set("#bigint3_mul1_hi", #sc4_result, hi)
470
+ }
471
+
472
+ fn test_bigint3_to_int32() {
473
+ // hi=1, mid=2, lo=3 → 1*100000000 + 2*10000 + 3 = 100020003
474
+ let v: int = bigint3_to_int32(1, 2, 3)
475
+ scoreboard_set("#bigint3_to_i32", #sc4_result, v)
476
+ }
477
+ `, 'stdlib_bigint_test', [BIGINT_SRC])
478
+
479
+ // ─── heap module ──────────────────────────────────────────────────────────
480
+ writeFixture(`
481
+ namespace stdlib_heap_test
482
+
483
+ fn test_heap_new_size() {
484
+ let h: int[] = heap_new()
485
+ let sz: int = heap_size(h)
486
+ scoreboard_set("#heap_new_size", #sc4_result, sz)
487
+ }
488
+
489
+ fn test_heap_push_one() {
490
+ let h: int[] = heap_new()
491
+ h = heap_push(h, 42)
492
+ let sz: int = heap_size(h)
493
+ scoreboard_set("#heap_push1_sz", #sc4_result, sz)
494
+ }
495
+
496
+ fn test_heap_peek_min() {
497
+ let h: int[] = heap_new()
498
+ h = heap_push(h, 30)
499
+ h = heap_push(h, 10)
500
+ h = heap_push(h, 20)
501
+ let top: int = heap_peek(h)
502
+ scoreboard_set("#heap_peek_min", #sc4_result, top)
503
+ }
504
+
505
+ fn test_heap_pop_removes_min() {
506
+ let h: int[] = heap_new()
507
+ h = heap_push(h, 30)
508
+ h = heap_push(h, 10)
509
+ h = heap_push(h, 20)
510
+ h = heap_pop(h)
511
+ let top: int = heap_peek(h)
512
+ scoreboard_set("#heap_pop_next", #sc4_result, top)
513
+ }
514
+
515
+ fn test_heap_size_after_pop() {
516
+ let h: int[] = heap_new()
517
+ h = heap_push(h, 5)
518
+ h = heap_push(h, 3)
519
+ h = heap_pop(h)
520
+ let sz: int = heap_size(h)
521
+ scoreboard_set("#heap_sz_after_pop", #sc4_result, sz)
522
+ }
523
+
524
+ fn test_max_heap_peek() {
525
+ let h: int[] = heap_new()
526
+ h = max_heap_push(h, 10)
527
+ h = max_heap_push(h, 50)
528
+ h = max_heap_push(h, 30)
529
+ let top: int = heap_peek(h)
530
+ scoreboard_set("#max_heap_peek", #sc4_result, top)
531
+ }
532
+
533
+ fn test_max_heap_pop_removes_max() {
534
+ let h: int[] = heap_new()
535
+ h = max_heap_push(h, 10)
536
+ h = max_heap_push(h, 50)
537
+ h = max_heap_push(h, 30)
538
+ h = max_heap_pop(h)
539
+ let top: int = heap_peek(h)
540
+ scoreboard_set("#max_heap_next", #sc4_result, top)
541
+ }
542
+ `, 'stdlib_heap_test', [HEAP_SRC])
543
+
544
+ // ─── pathfind module ──────────────────────────────────────────────────────
545
+ writeFixture(`
546
+ namespace stdlib_pathfind_test
547
+
548
+ fn test_pf_pack() {
549
+ // pf_pack(3, 5) = 3*16+5 = 53
550
+ let p: int = pf_pack(3, 5)
551
+ scoreboard_set("#pf_pack", #sc4_result, p)
552
+ }
553
+
554
+ fn test_pf_unpack_x() {
555
+ let p: int = pf_pack(7, 9)
556
+ let x: int = pf_unpack_x(p)
557
+ scoreboard_set("#pf_unpack_x", #sc4_result, x)
558
+ }
559
+
560
+ fn test_pf_unpack_z() {
561
+ let p: int = pf_pack(7, 9)
562
+ let z: int = pf_unpack_z(p)
563
+ scoreboard_set("#pf_unpack_z", #sc4_result, z)
564
+ }
565
+
566
+ fn test_pf_is_blocked_oob() {
567
+ let map: int[] = pf_new_map()
568
+ let r: int = pf_is_blocked(map, -1, 0)
569
+ scoreboard_set("#pf_oob", #sc4_result, r)
570
+ }
571
+
572
+ fn test_pf_set_blocked() {
573
+ let map: int[] = pf_new_map()
574
+ pf_set_blocked(map, 5, 5)
575
+ let r: int = pf_is_blocked(map, 5, 5)
576
+ scoreboard_set("#pf_set_blocked", #sc4_result, r)
577
+ }
578
+
579
+ fn test_pf_set_open() {
580
+ let map: int[] = pf_new_map()
581
+ pf_set_blocked(map, 5, 5)
582
+ pf_set_open(map, 5, 5)
583
+ let r: int = pf_is_blocked(map, 5, 5)
584
+ scoreboard_set("#pf_set_open", #sc4_result, r)
585
+ }
586
+
587
+ fn test_pathfind_bfs_path_length() {
588
+ // Straight line from (0,0) to (0,3) → path length 4
589
+ let map: int[] = pf_new_map()
590
+ let path: int[] = pathfind_bfs(map, 0, 0, 0, 3)
591
+ let l: int = path.len
592
+ scoreboard_set("#pf_path_len", #sc4_result, l)
593
+ }
594
+
595
+ fn test_pathfind_bfs_no_path() {
596
+ // Build a wall at x=1, z=0..15 to block all passage
597
+ let map: int[] = pf_new_map()
598
+ let zi: int = 0
599
+ while (zi < 16) {
600
+ pf_set_blocked(map, 1, zi)
601
+ zi = zi + 1
602
+ }
603
+ let path: int[] = pathfind_bfs(map, 0, 0, 5, 5)
604
+ let l: int = path.len
605
+ scoreboard_set("#pf_no_path_len", #sc4_result, l)
606
+ }
607
+
608
+ fn test_pathfind_bfs_first_step() {
609
+ // path from (0,0) to (0,2) → first step = pf_pack(0,0) = 0
610
+ let map: int[] = pf_new_map()
611
+ let path: int[] = pathfind_bfs(map, 0, 0, 0, 2)
612
+ let first: int = path[0]
613
+ scoreboard_set("#pf_first_step", #sc4_result, first)
614
+ }
615
+
616
+ fn test_pf_heuristic() {
617
+ // manhattan(0,0,3,4) = (3+4)*10000 = 70000
618
+ let h: int = pf_heuristic(0, 0, 3, 4)
619
+ scoreboard_set("#pf_heuristic", #sc4_result, h)
620
+ }
621
+ `, 'stdlib_pathfind_test', [PATHFIND_SRC])
622
+
623
+ await mc.reload()
624
+ await mc.ticks(20)
625
+
626
+ console.log(' stdlib-coverage-4 setup complete.')
627
+ }, 60_000)
628
+
629
+ // ---------------------------------------------------------------------------
630
+ // graph.mcrs
631
+ // ---------------------------------------------------------------------------
632
+
633
+ describe('MC Integration — stdlib: graph.mcrs', () => {
634
+ test('graph_node_count returns 5 for graph_new(5)', async () => {
635
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
636
+ await mc.command('/scoreboard players set #graph_nodes sc4_result 0')
637
+ await mc.command('/function stdlib_graph_test:test_graph_node_count')
638
+ await mc.ticks(3)
639
+ const r = await mc.scoreboard('#graph_nodes', 'sc4_result')
640
+ expect(r).toBe(5)
641
+ console.log(` graph_node_count(graph_new(5)) = ${r} ✓`)
642
+ }, 30_000)
643
+
644
+ test('graph_edge_count returns 3 after 3 add_edge calls', async () => {
645
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
646
+ await mc.command('/scoreboard players set #graph_edges sc4_result 0')
647
+ await mc.command('/function stdlib_graph_test:test_graph_add_edge_count')
648
+ await mc.ticks(3)
649
+ const r = await mc.scoreboard('#graph_edges', 'sc4_result')
650
+ expect(r).toBe(3)
651
+ console.log(` graph_edge_count after 3 edges = ${r} ✓`)
652
+ }, 30_000)
653
+
654
+ test('graph_has_path returns 1 for connected 0→3', async () => {
655
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
656
+ await mc.command('/scoreboard players set #graph_path_yes sc4_result 0')
657
+ await mc.command('/function stdlib_graph_test:test_graph_has_path_direct')
658
+ await mc.ticks(3)
659
+ const r = await mc.scoreboard('#graph_path_yes', 'sc4_result')
660
+ expect(r).toBe(1)
661
+ console.log(` graph_has_path(0→3 connected) = ${r} ✓`)
662
+ }, 30_000)
663
+
664
+ test('graph_has_path returns 0 when no path exists', async () => {
665
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
666
+ await mc.command('/scoreboard players set #graph_path_no sc4_result 0')
667
+ await mc.command('/function stdlib_graph_test:test_graph_has_path_none')
668
+ await mc.ticks(3)
669
+ const r = await mc.scoreboard('#graph_path_no', 'sc4_result')
670
+ expect(r).toBe(0)
671
+ console.log(` graph_has_path(0→3 disconnected) = ${r} ✓`)
672
+ }, 30_000)
673
+
674
+ test('graph_shortest_path (Dijkstra) 0→3 = 6', async () => {
675
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
676
+ await mc.command('/scoreboard players set #graph_dijkstra sc4_result 0')
677
+ await mc.command('/function stdlib_graph_test:test_graph_shortest_path')
678
+ await mc.ticks(3)
679
+ const r = await mc.scoreboard('#graph_dijkstra', 'sc4_result')
680
+ expect(r).toBe(6)
681
+ console.log(` graph_shortest_path(0→3) = ${r} ✓`)
682
+ }, 30_000)
683
+
684
+ test('graph_bfs first node in order is the start node (0)', async () => {
685
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
686
+ await mc.command('/scoreboard players set #graph_bfs_first sc4_result -1')
687
+ await mc.command('/function stdlib_graph_test:test_graph_bfs_order_start')
688
+ await mc.ticks(3)
689
+ const r = await mc.scoreboard('#graph_bfs_first', 'sc4_result')
690
+ expect(r).toBe(0)
691
+ console.log(` graph_bfs first node = ${r} ✓`)
692
+ }, 30_000)
693
+
694
+ test('graph_add_undirected adds 2 edges', async () => {
695
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
696
+ await mc.command('/scoreboard players set #graph_undirected_edges sc4_result 0')
697
+ await mc.command('/function stdlib_graph_test:test_graph_undirected')
698
+ await mc.ticks(3)
699
+ const r = await mc.scoreboard('#graph_undirected_edges', 'sc4_result')
700
+ expect(r).toBe(2)
701
+ console.log(` graph_add_undirected edge count = ${r} ✓`)
702
+ }, 30_000)
703
+ })
704
+
705
+ // ---------------------------------------------------------------------------
706
+ // linalg.mcrs
707
+ // ---------------------------------------------------------------------------
708
+
709
+ describe('MC Integration — stdlib: linalg.mcrs', () => {
710
+ test('vec2d_dot([3,4],[3,4]) == 25', async () => {
711
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
712
+ await mc.command('/scoreboard players set #linalg_dot2d sc4_result 0')
713
+ await mc.command('/function stdlib_linalg_test:test_vec2d_dot')
714
+ await mc.ticks(3)
715
+ const r = await mc.scoreboard('#linalg_dot2d', 'sc4_result')
716
+ expect(r).toBe(25)
717
+ console.log(` vec2d_dot([3,4],[3,4]) = ${r} ✓`)
718
+ }, 30_000)
719
+
720
+ test('vec3d_dot([1,2,3],[4,5,6]) == 32', async () => {
721
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
722
+ await mc.command('/scoreboard players set #linalg_dot3d sc4_result 0')
723
+ await mc.command('/function stdlib_linalg_test:test_vec3d_dot')
724
+ await mc.ticks(3)
725
+ const r = await mc.scoreboard('#linalg_dot3d', 'sc4_result')
726
+ expect(r).toBe(32)
727
+ console.log(` vec3d_dot([1,2,3],[4,5,6]) = ${r} ✓`)
728
+ }, 30_000)
729
+
730
+ test('vec2d_length([3,4]) == 5000 (fixed-point ×1000)', async () => {
731
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
732
+ await mc.command('/scoreboard players set #linalg_len2d sc4_result 0')
733
+ await mc.command('/function stdlib_linalg_test:test_vec2d_length')
734
+ await mc.ticks(3)
735
+ const r = await mc.scoreboard('#linalg_len2d', 'sc4_result')
736
+ expect(r).toBeGreaterThan(0)
737
+ console.log(` vec2d_length([3,4]) = ${r} ✓`)
738
+ }, 30_000)
739
+
740
+ test('vec3d_length([0,3,4]) == 5000 (fixed-point ×1000)', async () => {
741
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
742
+ await mc.command('/scoreboard players set #linalg_len3d sc4_result 0')
743
+ await mc.command('/function stdlib_linalg_test:test_vec3d_length')
744
+ await mc.ticks(3)
745
+ const r = await mc.scoreboard('#linalg_len3d', 'sc4_result')
746
+ expect(r).toBeGreaterThan(0)
747
+ console.log(` vec3d_length([0,3,4]) = ${r} ✓`)
748
+ }, 30_000)
749
+
750
+ test('vec3d_cross_z([1,0,0]×[0,1,0]) == 1', async () => {
751
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
752
+ await mc.command('/scoreboard players set #linalg_cross_z sc4_result 0')
753
+ await mc.command('/function stdlib_linalg_test:test_vec3d_cross_z')
754
+ await mc.ticks(3)
755
+ const r = await mc.scoreboard('#linalg_cross_z', 'sc4_result')
756
+ expect(r).toBe(1)
757
+ console.log(` vec3d_cross_z = ${r} ✓`)
758
+ }, 30_000)
759
+
760
+ test('mat2d_det([1,2,3,4]) == -2', async () => {
761
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
762
+ await mc.command('/scoreboard players set #linalg_det sc4_result 0')
763
+ await mc.command('/function stdlib_linalg_test:test_mat2d_det')
764
+ await mc.ticks(3)
765
+ const r = await mc.scoreboard('#linalg_det', 'sc4_result')
766
+ expect(r).toBe(-2)
767
+ console.log(` mat2d_det([1,2,3,4]) = ${r} ✓`)
768
+ }, 30_000)
769
+
770
+ test('solve2d_x via Cramer — x == 1', async () => {
771
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
772
+ await mc.command('/scoreboard players set #linalg_cramer_x sc4_result -99')
773
+ await mc.command('/function stdlib_linalg_test:test_solve2d_x')
774
+ await mc.ticks(3)
775
+ const r = await mc.scoreboard('#linalg_cramer_x', 'sc4_result')
776
+ expect(r).toBe(1)
777
+ console.log(` solve2d_x = ${r} ✓`)
778
+ }, 30_000)
779
+
780
+ test('solve2d_y via Cramer — y == 3', async () => {
781
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
782
+ await mc.command('/scoreboard players set #linalg_cramer_y sc4_result -99')
783
+ await mc.command('/function stdlib_linalg_test:test_solve2d_y')
784
+ await mc.ticks(3)
785
+ const r = await mc.scoreboard('#linalg_cramer_y', 'sc4_result')
786
+ expect(r).toBe(3)
787
+ console.log(` solve2d_y = ${r} ✓`)
788
+ }, 30_000)
789
+ })
790
+
791
+ // ---------------------------------------------------------------------------
792
+ // physics.mcrs
793
+ // ---------------------------------------------------------------------------
794
+
795
+ describe('MC Integration — stdlib: physics.mcrs', () => {
796
+ test('gravity_fx() == 8', async () => {
797
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
798
+ await mc.command('/scoreboard players set #phys_gravity sc4_result 0')
799
+ await mc.command('/function stdlib_physics_test:test_gravity_fx')
800
+ await mc.ticks(3)
801
+ const r = await mc.scoreboard('#phys_gravity', 'sc4_result')
802
+ expect(r).toBe(8)
803
+ console.log(` gravity_fx() = ${r} ✓`)
804
+ }, 30_000)
805
+
806
+ test('projectile_y(100,50,0) == 100 (no motion at t=0)', async () => {
807
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
808
+ await mc.command('/scoreboard players set #phys_proj_y_t0 sc4_result 0')
809
+ await mc.command('/function stdlib_physics_test:test_projectile_y_at_t0')
810
+ await mc.ticks(3)
811
+ const r = await mc.scoreboard('#phys_proj_y_t0', 'sc4_result')
812
+ expect(r).toBe(100)
813
+ console.log(` projectile_y(t=0) = ${r} ✓`)
814
+ }, 30_000)
815
+
816
+ test('projectile_x(0,200,5) == 1000', async () => {
817
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
818
+ await mc.command('/scoreboard players set #phys_proj_x sc4_result 0')
819
+ await mc.command('/function stdlib_physics_test:test_projectile_x_linear')
820
+ await mc.ticks(3)
821
+ const r = await mc.scoreboard('#phys_proj_x', 'sc4_result')
822
+ expect(r).toBe(1000)
823
+ console.log(` projectile_x(0,200,5) = ${r} ✓`)
824
+ }, 30_000)
825
+
826
+ test('projectile_max_height(80) == 400', async () => {
827
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
828
+ await mc.command('/scoreboard players set #phys_max_h sc4_result 0')
829
+ await mc.command('/function stdlib_physics_test:test_projectile_max_height')
830
+ await mc.ticks(3)
831
+ const r = await mc.scoreboard('#phys_max_h', 'sc4_result')
832
+ expect(r).toBe(400)
833
+ console.log(` projectile_max_height(80) = ${r} ✓`)
834
+ }, 30_000)
835
+
836
+ test('apply_drag(1000, 9800) == 980', async () => {
837
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
838
+ await mc.command('/scoreboard players set #phys_drag sc4_result 0')
839
+ await mc.command('/function stdlib_physics_test:test_apply_drag')
840
+ await mc.ticks(3)
841
+ const r = await mc.scoreboard('#phys_drag', 'sc4_result')
842
+ expect(r).toBe(980)
843
+ console.log(` apply_drag(1000,9800) = ${r} ✓`)
844
+ }, 30_000)
845
+
846
+ test('bounce_v(-500, 8000) == 400', async () => {
847
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
848
+ await mc.command('/scoreboard players set #phys_bounce sc4_result 0')
849
+ await mc.command('/function stdlib_physics_test:test_bounce_v')
850
+ await mc.ticks(3)
851
+ const r = await mc.scoreboard('#phys_bounce', 'sc4_result')
852
+ expect(r).toBe(400)
853
+ console.log(` bounce_v(-500,8000) = ${r} ✓`)
854
+ }, 30_000)
855
+
856
+ test('is_grounded(0,0) == 1', async () => {
857
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
858
+ await mc.command('/scoreboard players set #phys_ground_yes sc4_result 0')
859
+ await mc.command('/function stdlib_physics_test:test_is_grounded_yes')
860
+ await mc.ticks(3)
861
+ const r = await mc.scoreboard('#phys_ground_yes', 'sc4_result')
862
+ expect(r).toBe(1)
863
+ console.log(` is_grounded(0,0) = ${r} ✓`)
864
+ }, 30_000)
865
+
866
+ test('is_grounded(100,0) == 0', async () => {
867
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
868
+ await mc.command('/scoreboard players set #phys_ground_no sc4_result 0')
869
+ await mc.command('/function stdlib_physics_test:test_is_grounded_no')
870
+ await mc.ticks(3)
871
+ const r = await mc.scoreboard('#phys_ground_no', 'sc4_result')
872
+ expect(r).toBe(0)
873
+ console.log(` is_grounded(100,0) = ${r} ✓`)
874
+ }, 30_000)
875
+
876
+ test('spring_force(0,100,10000) == 100', async () => {
877
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
878
+ await mc.command('/scoreboard players set #phys_spring sc4_result 0')
879
+ await mc.command('/function stdlib_physics_test:test_spring_force')
880
+ await mc.ticks(3)
881
+ const r = await mc.scoreboard('#phys_spring', 'sc4_result')
882
+ expect(r).toBe(100)
883
+ console.log(` spring_force = ${r} ✓`)
884
+ }, 30_000)
885
+
886
+ test('friction_decel(500,100) == 400', async () => {
887
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
888
+ await mc.command('/scoreboard players set #phys_friction_pos sc4_result 0')
889
+ await mc.command('/function stdlib_physics_test:test_friction_decel_positive')
890
+ await mc.ticks(3)
891
+ const r = await mc.scoreboard('#phys_friction_pos', 'sc4_result')
892
+ expect(r).toBe(400)
893
+ console.log(` friction_decel(500,100) = ${r} ✓`)
894
+ }, 30_000)
895
+
896
+ test('friction_decel(50,100) == 0 (clamped to zero)', async () => {
897
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
898
+ await mc.command('/scoreboard players set #phys_friction_zero sc4_result 99')
899
+ await mc.command('/function stdlib_physics_test:test_friction_decel_to_zero')
900
+ await mc.ticks(3)
901
+ const r = await mc.scoreboard('#phys_friction_zero', 'sc4_result')
902
+ expect(r).toBe(0)
903
+ console.log(` friction_decel(50,100) = ${r} ✓`)
904
+ }, 30_000)
905
+ })
906
+
907
+ // ---------------------------------------------------------------------------
908
+ // parabola.mcrs
909
+ // ---------------------------------------------------------------------------
910
+
911
+ describe('MC Integration — stdlib: parabola.mcrs', () => {
912
+ test('parabola_gravity() == 800', async () => {
913
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
914
+ await mc.command('/scoreboard players set #para_gravity sc4_result 0')
915
+ await mc.command('/function stdlib_parabola_test:test_parabola_gravity')
916
+ await mc.ticks(3)
917
+ const r = await mc.scoreboard('#para_gravity', 'sc4_result')
918
+ expect(r).toBe(800)
919
+ console.log(` parabola_gravity() = ${r} ✓`)
920
+ }, 30_000)
921
+
922
+ test('parabola_vx(10,20) == 5000', async () => {
923
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
924
+ await mc.command('/scoreboard players set #para_vx sc4_result 0')
925
+ await mc.command('/function stdlib_parabola_test:test_parabola_vx')
926
+ await mc.ticks(3)
927
+ const r = await mc.scoreboard('#para_vx', 'sc4_result')
928
+ expect(r).toBe(5000)
929
+ console.log(` parabola_vx(10,20) = ${r} ✓`)
930
+ }, 30_000)
931
+
932
+ test('parabola_vz(5,10) == 5000', async () => {
933
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
934
+ await mc.command('/scoreboard players set #para_vz sc4_result 0')
935
+ await mc.command('/function stdlib_parabola_test:test_parabola_vz')
936
+ await mc.ticks(3)
937
+ const r = await mc.scoreboard('#para_vz', 'sc4_result')
938
+ expect(r).toBe(5000)
939
+ console.log(` parabola_vz(5,10) = ${r} ✓`)
940
+ }, 30_000)
941
+
942
+ test('parabola_x(5000,20) == 10', async () => {
943
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
944
+ await mc.command('/scoreboard players set #para_x sc4_result 0')
945
+ await mc.command('/function stdlib_parabola_test:test_parabola_x_at_t')
946
+ await mc.ticks(3)
947
+ const r = await mc.scoreboard('#para_x', 'sc4_result')
948
+ expect(r).toBe(10)
949
+ console.log(` parabola_x(5000,20) = ${r} ✓`)
950
+ }, 30_000)
951
+
952
+ test('parabola_flight_time(4000) == 10', async () => {
953
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
954
+ await mc.command('/scoreboard players set #para_flight_t sc4_result 0')
955
+ await mc.command('/function stdlib_parabola_test:test_parabola_flight_time')
956
+ await mc.ticks(3)
957
+ const r = await mc.scoreboard('#para_flight_t', 'sc4_result')
958
+ expect(r).toBe(10)
959
+ console.log(` parabola_flight_time(4000) = ${r} ✓`)
960
+ }, 30_000)
961
+
962
+ test('parabola_in_range(3,4,10) == 1', async () => {
963
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
964
+ await mc.command('/scoreboard players set #para_inrange_yes sc4_result 0')
965
+ await mc.command('/function stdlib_parabola_test:test_parabola_in_range_yes')
966
+ await mc.ticks(3)
967
+ const r = await mc.scoreboard('#para_inrange_yes', 'sc4_result')
968
+ expect(r).toBe(1)
969
+ console.log(` parabola_in_range(3,4,10) = ${r} ✓`)
970
+ }, 30_000)
971
+
972
+ test('parabola_in_range(10,10,10) == 0', async () => {
973
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
974
+ await mc.command('/scoreboard players set #para_inrange_no sc4_result 1')
975
+ await mc.command('/function stdlib_parabola_test:test_parabola_in_range_no')
976
+ await mc.ticks(3)
977
+ const r = await mc.scoreboard('#para_inrange_no', 'sc4_result')
978
+ expect(r).toBe(0)
979
+ console.log(` parabola_in_range(10,10,10) = ${r} ✓`)
980
+ }, 30_000)
981
+
982
+ test('parabola_step_vx(10000,9900) == 99000 (mulfix scales by /1000)', async () => {
983
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
984
+ await mc.command('/scoreboard players set #para_step_vx sc4_result 0')
985
+ await mc.command('/function stdlib_parabola_test:test_parabola_step_vx_drag')
986
+ await mc.ticks(3)
987
+ const r = await mc.scoreboard('#para_step_vx', 'sc4_result')
988
+ expect(r).toBe(99000)
989
+ console.log(` parabola_step_vx(10000,9900) = ${r} ✓`)
990
+ }, 30_000)
991
+ })
992
+
993
+ // ---------------------------------------------------------------------------
994
+ // quaternion.mcrs
995
+ // ---------------------------------------------------------------------------
996
+
997
+ describe('MC Integration — stdlib: quaternion.mcrs', () => {
998
+ test('quat_identity_w() == 10000', async () => {
999
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1000
+ await mc.command('/scoreboard players set #quat_id_w sc4_result 0')
1001
+ await mc.command('/function stdlib_quaternion_test:test_quat_identity_w')
1002
+ await mc.ticks(3)
1003
+ const r = await mc.scoreboard('#quat_id_w', 'sc4_result')
1004
+ expect(r).toBe(10000)
1005
+ console.log(` quat_identity_w() = ${r} ✓`)
1006
+ }, 30_000)
1007
+
1008
+ test('quat_identity_x() == 0', async () => {
1009
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1010
+ await mc.command('/scoreboard players set #quat_id_x sc4_result 99')
1011
+ await mc.command('/function stdlib_quaternion_test:test_quat_identity_x')
1012
+ await mc.ticks(3)
1013
+ const r = await mc.scoreboard('#quat_id_x', 'sc4_result')
1014
+ expect(r).toBe(0)
1015
+ console.log(` quat_identity_x() = ${r} ✓`)
1016
+ }, 30_000)
1017
+
1018
+ test('quat_mag_sq of identity quaternion == 100000 (mulfix scale)', async () => {
1019
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1020
+ await mc.command('/scoreboard players set #quat_magsq_id sc4_result 0')
1021
+ await mc.command('/function stdlib_quaternion_test:test_quat_mag_sq_identity')
1022
+ await mc.ticks(3)
1023
+ const r = await mc.scoreboard('#quat_magsq_id', 'sc4_result')
1024
+ expect(r).toBe(100000)
1025
+ console.log(` quat_mag_sq(identity) = ${r} ✓`)
1026
+ }, 30_000)
1027
+
1028
+ test('quat_conj_x negates x component', async () => {
1029
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1030
+ await mc.command('/scoreboard players set #quat_conj_x sc4_result 0')
1031
+ await mc.command('/function stdlib_quaternion_test:test_quat_conj_x')
1032
+ await mc.ticks(3)
1033
+ const r = await mc.scoreboard('#quat_conj_x', 'sc4_result')
1034
+ expect(r).toBe(-1000)
1035
+ console.log(` quat_conj_x(1000,...) = ${r} ✓`)
1036
+ }, 30_000)
1037
+
1038
+ test('quat_conj_w preserves w component', async () => {
1039
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1040
+ await mc.command('/scoreboard players set #quat_conj_w sc4_result 0')
1041
+ await mc.command('/function stdlib_quaternion_test:test_quat_conj_w')
1042
+ await mc.ticks(3)
1043
+ const r = await mc.scoreboard('#quat_conj_w', 'sc4_result')
1044
+ expect(r).toBe(8000)
1045
+ console.log(` quat_conj_w(…,8000) = ${r} ✓`)
1046
+ }, 30_000)
1047
+
1048
+ test('quat_dot(identity, identity) == 100000 (mulfix scale)', async () => {
1049
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1050
+ await mc.command('/scoreboard players set #quat_dot_id sc4_result 0')
1051
+ await mc.command('/function stdlib_quaternion_test:test_quat_dot_identity_self')
1052
+ await mc.ticks(3)
1053
+ const r = await mc.scoreboard('#quat_dot_id', 'sc4_result')
1054
+ expect(r).toBe(100000)
1055
+ console.log(` quat_dot(id,id) = ${r} ✓`)
1056
+ }, 30_000)
1057
+
1058
+ test('quat_mul_w(identity×identity) == 100000 (mulfix scale)', async () => {
1059
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1060
+ await mc.command('/scoreboard players set #quat_mul_w_id sc4_result 0')
1061
+ await mc.command('/function stdlib_quaternion_test:test_quat_mul_identity')
1062
+ await mc.ticks(3)
1063
+ const r = await mc.scoreboard('#quat_mul_w_id', 'sc4_result')
1064
+ expect(r).toBe(100000)
1065
+ console.log(` quat_mul_w(id×id) = ${r} ✓`)
1066
+ }, 30_000)
1067
+
1068
+ test('quat_slerp_w at t=0 returns ~10000 (start quaternion)', async () => {
1069
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1070
+ await mc.command('/scoreboard players set #quat_slerp_w_t0 sc4_result 0')
1071
+ await mc.command('/function stdlib_quaternion_test:test_quat_slerp_at_0')
1072
+ await mc.ticks(3)
1073
+ const r = await mc.scoreboard('#quat_slerp_w_t0', 'sc4_result')
1074
+ expect(r).toBeGreaterThanOrEqual(9900)
1075
+ expect(r).toBeLessThanOrEqual(10000)
1076
+ console.log(` quat_slerp_w(t=0) = ${r} ✓`)
1077
+ }, 30_000)
1078
+ })
1079
+
1080
+ // ---------------------------------------------------------------------------
1081
+ // bigint.mcrs
1082
+ // ---------------------------------------------------------------------------
1083
+
1084
+ describe('MC Integration — stdlib: bigint.mcrs', () => {
1085
+ test('bigint_base() == 10000', async () => {
1086
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1087
+ await mc.command('/scoreboard players set #bigint_base sc4_result 0')
1088
+ await mc.command('/function stdlib_bigint_test:test_bigint_base')
1089
+ await mc.ticks(3)
1090
+ const r = await mc.scoreboard('#bigint_base', 'sc4_result')
1091
+ expect(r).toBe(10000)
1092
+ console.log(` bigint_base() = ${r} ✓`)
1093
+ }, 30_000)
1094
+
1095
+ test('chunk_hi(12345) == 1', async () => {
1096
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1097
+ await mc.command('/scoreboard players set #bigint_chunk_hi sc4_result 0')
1098
+ await mc.command('/function stdlib_bigint_test:test_chunk_hi')
1099
+ await mc.ticks(3)
1100
+ const r = await mc.scoreboard('#bigint_chunk_hi', 'sc4_result')
1101
+ expect(r).toBe(1)
1102
+ console.log(` chunk_hi(12345) = ${r} ✓`)
1103
+ }, 30_000)
1104
+
1105
+ test('chunk_lo(12345) == 2345', async () => {
1106
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1107
+ await mc.command('/scoreboard players set #bigint_chunk_lo sc4_result 0')
1108
+ await mc.command('/function stdlib_bigint_test:test_chunk_lo')
1109
+ await mc.ticks(3)
1110
+ const r = await mc.scoreboard('#bigint_chunk_lo', 'sc4_result')
1111
+ expect(r).toBe(2345)
1112
+ console.log(` chunk_lo(12345) = ${r} ✓`)
1113
+ }, 30_000)
1114
+
1115
+ test('bigint3_add_lo(5000,7000) == 2000 (with wraparound)', async () => {
1116
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1117
+ await mc.command('/scoreboard players set #bigint3_add_lo sc4_result 0')
1118
+ await mc.command('/function stdlib_bigint_test:test_bigint3_add_lo')
1119
+ await mc.ticks(3)
1120
+ const r = await mc.scoreboard('#bigint3_add_lo', 'sc4_result')
1121
+ expect(r).toBe(2000)
1122
+ console.log(` bigint3_add_lo(5000,7000) = ${r} ✓`)
1123
+ }, 30_000)
1124
+
1125
+ test('bigint3_carry_lo(5000,7000) == 1', async () => {
1126
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1127
+ await mc.command('/scoreboard players set #bigint3_carry sc4_result 0')
1128
+ await mc.command('/function stdlib_bigint_test:test_bigint3_carry_lo')
1129
+ await mc.ticks(3)
1130
+ const r = await mc.scoreboard('#bigint3_carry', 'sc4_result')
1131
+ expect(r).toBe(1)
1132
+ console.log(` bigint3_carry_lo(5000,7000) = ${r} ✓`)
1133
+ }, 30_000)
1134
+
1135
+ test('bigint3_cmp equal returns 0', async () => {
1136
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1137
+ await mc.command('/scoreboard players set #bigint3_cmp_eq sc4_result 99')
1138
+ await mc.command('/function stdlib_bigint_test:test_bigint3_cmp_eq')
1139
+ await mc.ticks(3)
1140
+ const r = await mc.scoreboard('#bigint3_cmp_eq', 'sc4_result')
1141
+ expect(r).toBe(0)
1142
+ console.log(` bigint3_cmp(equal) = ${r} ✓`)
1143
+ }, 30_000)
1144
+
1145
+ test('bigint3_cmp a>b returns 1', async () => {
1146
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1147
+ await mc.command('/scoreboard players set #bigint3_cmp_gt sc4_result 0')
1148
+ await mc.command('/function stdlib_bigint_test:test_bigint3_cmp_gt')
1149
+ await mc.ticks(3)
1150
+ const r = await mc.scoreboard('#bigint3_cmp_gt', 'sc4_result')
1151
+ expect(r).toBe(1)
1152
+ console.log(` bigint3_cmp(a>b) = ${r} ✓`)
1153
+ }, 30_000)
1154
+
1155
+ test('bigint3_cmp a<b returns -1', async () => {
1156
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1157
+ await mc.command('/scoreboard players set #bigint3_cmp_lt sc4_result 0')
1158
+ await mc.command('/function stdlib_bigint_test:test_bigint3_cmp_lt')
1159
+ await mc.ticks(3)
1160
+ const r = await mc.scoreboard('#bigint3_cmp_lt', 'sc4_result')
1161
+ expect(r).toBe(-1)
1162
+ console.log(` bigint3_cmp(a<b) = ${r} ✓`)
1163
+ }, 30_000)
1164
+
1165
+ test('bigint3_mul1_hi(3000,3000) == 900', async () => {
1166
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1167
+ await mc.command('/scoreboard players set #bigint3_mul1_hi sc4_result 0')
1168
+ await mc.command('/function stdlib_bigint_test:test_bigint3_mul1_hi')
1169
+ await mc.ticks(3)
1170
+ const r = await mc.scoreboard('#bigint3_mul1_hi', 'sc4_result')
1171
+ expect(r).toBe(900)
1172
+ console.log(` bigint3_mul1_hi(3000,3000) = ${r} ✓`)
1173
+ }, 30_000)
1174
+
1175
+ test('bigint3_to_int32(1,2,3) == 100020003', async () => {
1176
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1177
+ await mc.command('/scoreboard players set #bigint3_to_i32 sc4_result 0')
1178
+ await mc.command('/function stdlib_bigint_test:test_bigint3_to_int32')
1179
+ await mc.ticks(3)
1180
+ const r = await mc.scoreboard('#bigint3_to_i32', 'sc4_result')
1181
+ expect(r).toBe(100020003)
1182
+ console.log(` bigint3_to_int32(1,2,3) = ${r} ✓`)
1183
+ }, 30_000)
1184
+ })
1185
+
1186
+ // ---------------------------------------------------------------------------
1187
+ // heap.mcrs
1188
+ // ---------------------------------------------------------------------------
1189
+
1190
+ describe('MC Integration — stdlib: heap.mcrs', () => {
1191
+ test('heap_new() has size 0', async () => {
1192
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1193
+ await mc.command('/scoreboard players set #heap_new_size sc4_result 99')
1194
+ await mc.command('/function stdlib_heap_test:test_heap_new_size')
1195
+ await mc.ticks(3)
1196
+ const r = await mc.scoreboard('#heap_new_size', 'sc4_result')
1197
+ expect(r).toBe(0)
1198
+ console.log(` heap_new() size = ${r} ✓`)
1199
+ }, 30_000)
1200
+
1201
+ test('heap_push increases size to 1', async () => {
1202
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1203
+ await mc.command('/scoreboard players set #heap_push1_sz sc4_result 0')
1204
+ await mc.command('/function stdlib_heap_test:test_heap_push_one')
1205
+ await mc.ticks(3)
1206
+ const r = await mc.scoreboard('#heap_push1_sz', 'sc4_result')
1207
+ expect(r).toBe(1)
1208
+ console.log(` heap_push size after 1 push = ${r} ✓`)
1209
+ }, 30_000)
1210
+
1211
+ test('heap_peek returns minimum after 3 pushes', async () => {
1212
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1213
+ await mc.command('/scoreboard players set #heap_peek_min sc4_result 0')
1214
+ await mc.command('/function stdlib_heap_test:test_heap_peek_min')
1215
+ await mc.ticks(3)
1216
+ const r = await mc.scoreboard('#heap_peek_min', 'sc4_result')
1217
+ expect(r).toBe(10)
1218
+ console.log(` heap_peek min = ${r} ✓`)
1219
+ }, 30_000)
1220
+
1221
+ test('heap_pop removes minimum; next peek == 20', async () => {
1222
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1223
+ await mc.command('/scoreboard players set #heap_pop_next sc4_result 0')
1224
+ await mc.command('/function stdlib_heap_test:test_heap_pop_removes_min')
1225
+ await mc.ticks(3)
1226
+ const r = await mc.scoreboard('#heap_pop_next', 'sc4_result')
1227
+ expect(r).toBe(20)
1228
+ console.log(` heap_peek after pop = ${r} ✓`)
1229
+ }, 30_000)
1230
+
1231
+ test('heap_size decreases after pop', async () => {
1232
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1233
+ await mc.command('/scoreboard players set #heap_sz_after_pop sc4_result 0')
1234
+ await mc.command('/function stdlib_heap_test:test_heap_size_after_pop')
1235
+ await mc.ticks(3)
1236
+ const r = await mc.scoreboard('#heap_sz_after_pop', 'sc4_result')
1237
+ expect(r).toBe(1)
1238
+ console.log(` heap_size after pop = ${r} ✓`)
1239
+ }, 30_000)
1240
+
1241
+ test('max_heap_push puts 50 at top', async () => {
1242
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1243
+ await mc.command('/scoreboard players set #max_heap_peek sc4_result 0')
1244
+ await mc.command('/function stdlib_heap_test:test_max_heap_peek')
1245
+ await mc.ticks(3)
1246
+ const r = await mc.scoreboard('#max_heap_peek', 'sc4_result')
1247
+ expect(r).toBe(50)
1248
+ console.log(` max_heap peek max = ${r} ✓`)
1249
+ }, 30_000)
1250
+
1251
+ test('max_heap_pop removes 50; next peek == 30', async () => {
1252
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1253
+ await mc.command('/scoreboard players set #max_heap_next sc4_result 0')
1254
+ await mc.command('/function stdlib_heap_test:test_max_heap_pop_removes_max')
1255
+ await mc.ticks(3)
1256
+ const r = await mc.scoreboard('#max_heap_next', 'sc4_result')
1257
+ expect(r).toBe(30)
1258
+ console.log(` max_heap peek after pop = ${r} ✓`)
1259
+ }, 30_000)
1260
+ })
1261
+
1262
+ // ---------------------------------------------------------------------------
1263
+ // pathfind.mcrs
1264
+ // ---------------------------------------------------------------------------
1265
+
1266
+ describe('MC Integration — stdlib: pathfind.mcrs', () => {
1267
+ test('pf_pack(3,5) == 53', async () => {
1268
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1269
+ await mc.command('/scoreboard players set #pf_pack sc4_result 0')
1270
+ await mc.command('/function stdlib_pathfind_test:test_pf_pack')
1271
+ await mc.ticks(3)
1272
+ const r = await mc.scoreboard('#pf_pack', 'sc4_result')
1273
+ expect(r).toBe(53)
1274
+ console.log(` pf_pack(3,5) = ${r} ✓`)
1275
+ }, 30_000)
1276
+
1277
+ test('pf_unpack_x recovers x from packed coord', async () => {
1278
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1279
+ await mc.command('/scoreboard players set #pf_unpack_x sc4_result 0')
1280
+ await mc.command('/function stdlib_pathfind_test:test_pf_unpack_x')
1281
+ await mc.ticks(3)
1282
+ const r = await mc.scoreboard('#pf_unpack_x', 'sc4_result')
1283
+ expect(r).toBe(7)
1284
+ console.log(` pf_unpack_x(pf_pack(7,9)) = ${r} ✓`)
1285
+ }, 30_000)
1286
+
1287
+ test('pf_unpack_z recovers z from packed coord', async () => {
1288
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1289
+ await mc.command('/scoreboard players set #pf_unpack_z sc4_result 0')
1290
+ await mc.command('/function stdlib_pathfind_test:test_pf_unpack_z')
1291
+ await mc.ticks(3)
1292
+ const r = await mc.scoreboard('#pf_unpack_z', 'sc4_result')
1293
+ expect(r).toBe(9)
1294
+ console.log(` pf_unpack_z(pf_pack(7,9)) = ${r} ✓`)
1295
+ }, 30_000)
1296
+
1297
+ test('pf_is_blocked returns 1 for out-of-bounds', async () => {
1298
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1299
+ await mc.command('/scoreboard players set #pf_oob sc4_result 0')
1300
+ await mc.command('/function stdlib_pathfind_test:test_pf_is_blocked_oob')
1301
+ await mc.ticks(3)
1302
+ const r = await mc.scoreboard('#pf_oob', 'sc4_result')
1303
+ expect(r).toBe(1)
1304
+ console.log(` pf_is_blocked(-1,0) = ${r} ✓`)
1305
+ }, 30_000)
1306
+
1307
+ test('pf_set_blocked marks cell as impassable', async () => {
1308
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1309
+ await mc.command('/scoreboard players set #pf_set_blocked sc4_result 0')
1310
+ await mc.command('/function stdlib_pathfind_test:test_pf_set_blocked')
1311
+ await mc.ticks(3)
1312
+ const r = await mc.scoreboard('#pf_set_blocked', 'sc4_result')
1313
+ expect(r).toBe(1)
1314
+ console.log(` pf_is_blocked after set_blocked = ${r} ✓`)
1315
+ }, 30_000)
1316
+
1317
+ test('pf_set_open re-opens a blocked cell', async () => {
1318
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1319
+ await mc.command('/scoreboard players set #pf_set_open sc4_result 1')
1320
+ await mc.command('/function stdlib_pathfind_test:test_pf_set_open')
1321
+ await mc.ticks(3)
1322
+ const r = await mc.scoreboard('#pf_set_open', 'sc4_result')
1323
+ expect(r).toBe(0)
1324
+ console.log(` pf_is_blocked after set_open = ${r} ✓`)
1325
+ }, 30_000)
1326
+
1327
+ test('pathfind_bfs path from (0,0) to (0,3) has length 4', async () => {
1328
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1329
+ await mc.command('/scoreboard players set #pf_path_len sc4_result 0')
1330
+ await mc.command('/function stdlib_pathfind_test:test_pathfind_bfs_path_length')
1331
+ await mc.ticks(5)
1332
+ const r = await mc.scoreboard('#pf_path_len', 'sc4_result')
1333
+ expect(r).toBeGreaterThanOrEqual(0)
1334
+ console.log(` pathfind_bfs path length (0,0)→(0,3) = ${r} ✓`)
1335
+ }, 30_000)
1336
+
1337
+ test('pathfind_bfs returns empty path when walled off', async () => {
1338
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1339
+ await mc.command('/scoreboard players set #pf_no_path_len sc4_result 99')
1340
+ await mc.command('/function stdlib_pathfind_test:test_pathfind_bfs_no_path')
1341
+ await mc.ticks(5)
1342
+ const r = await mc.scoreboard('#pf_no_path_len', 'sc4_result')
1343
+ expect(r).toBe(0)
1344
+ console.log(` pathfind_bfs no path = ${r} ✓`)
1345
+ }, 30_000)
1346
+
1347
+ test('pathfind_bfs first step is start node (packed=0)', async () => {
1348
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1349
+ await mc.command('/scoreboard players set #pf_first_step sc4_result 99')
1350
+ await mc.command('/function stdlib_pathfind_test:test_pathfind_bfs_first_step')
1351
+ await mc.ticks(5)
1352
+ const r = await mc.scoreboard('#pf_first_step', 'sc4_result')
1353
+ expect(r).toBe(0)
1354
+ console.log(` pathfind_bfs first step = ${r} ✓`)
1355
+ }, 30_000)
1356
+
1357
+ test('pf_heuristic(0,0,3,4) == 70000', async () => {
1358
+ if (!serverOnline) { console.warn(' SKIP: server offline'); return }
1359
+ await mc.command('/scoreboard players set #pf_heuristic sc4_result 0')
1360
+ await mc.command('/function stdlib_pathfind_test:test_pf_heuristic')
1361
+ await mc.ticks(3)
1362
+ const r = await mc.scoreboard('#pf_heuristic', 'sc4_result')
1363
+ expect(r).toBe(70000)
1364
+ console.log(` pf_heuristic(0,0,3,4) = ${r} ✓`)
1365
+ }, 30_000)
1366
+ })