redscript-mc 1.2.30 → 2.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 (269) hide show
  1. package/.claude/commands/build-test.md +10 -0
  2. package/.claude/commands/deploy-demo.md +12 -0
  3. package/.claude/commands/stage-status.md +13 -0
  4. package/.claude/settings.json +12 -0
  5. package/.github/workflows/ci.yml +1 -0
  6. package/CLAUDE.md +231 -0
  7. package/demo.gif +0 -0
  8. package/dist/cli.js +2 -554
  9. package/dist/compile.js +2 -266
  10. package/dist/index.js +2 -159
  11. package/dist/lowering/index.js +5 -3
  12. package/dist/src/__tests__/cli.test.d.ts +1 -0
  13. package/dist/src/__tests__/cli.test.js +104 -0
  14. package/dist/src/__tests__/codegen.test.d.ts +1 -0
  15. package/dist/src/__tests__/codegen.test.js +152 -0
  16. package/dist/src/__tests__/compile-all.test.d.ts +10 -0
  17. package/dist/src/__tests__/compile-all.test.js +108 -0
  18. package/dist/src/__tests__/dce.test.d.ts +1 -0
  19. package/dist/src/__tests__/dce.test.js +102 -0
  20. package/dist/src/__tests__/diagnostics.test.d.ts +4 -0
  21. package/dist/src/__tests__/diagnostics.test.js +177 -0
  22. package/dist/src/__tests__/e2e.test.d.ts +6 -0
  23. package/dist/src/__tests__/e2e.test.js +1789 -0
  24. package/dist/src/__tests__/entity-types.test.d.ts +1 -0
  25. package/dist/src/__tests__/entity-types.test.js +203 -0
  26. package/dist/src/__tests__/formatter.test.d.ts +1 -0
  27. package/dist/src/__tests__/formatter.test.js +40 -0
  28. package/dist/src/__tests__/lexer.test.d.ts +1 -0
  29. package/dist/src/__tests__/lexer.test.js +343 -0
  30. package/dist/src/__tests__/lowering.test.d.ts +1 -0
  31. package/dist/src/__tests__/lowering.test.js +1015 -0
  32. package/dist/src/__tests__/macro.test.d.ts +8 -0
  33. package/dist/src/__tests__/macro.test.js +306 -0
  34. package/dist/src/__tests__/mc-integration.test.d.ts +12 -0
  35. package/dist/src/__tests__/mc-integration.test.js +817 -0
  36. package/dist/src/__tests__/mc-syntax.test.d.ts +1 -0
  37. package/dist/src/__tests__/mc-syntax.test.js +124 -0
  38. package/dist/src/__tests__/nbt.test.d.ts +1 -0
  39. package/dist/src/__tests__/nbt.test.js +82 -0
  40. package/dist/src/__tests__/optimizer-advanced.test.d.ts +1 -0
  41. package/dist/src/__tests__/optimizer-advanced.test.js +124 -0
  42. package/dist/src/__tests__/optimizer.test.d.ts +1 -0
  43. package/dist/src/__tests__/optimizer.test.js +149 -0
  44. package/dist/src/__tests__/parser.test.d.ts +1 -0
  45. package/dist/src/__tests__/parser.test.js +807 -0
  46. package/dist/src/__tests__/repl.test.d.ts +1 -0
  47. package/dist/src/__tests__/repl.test.js +27 -0
  48. package/dist/src/__tests__/runtime.test.d.ts +1 -0
  49. package/dist/src/__tests__/runtime.test.js +289 -0
  50. package/dist/src/__tests__/stdlib-advanced.test.d.ts +4 -0
  51. package/dist/src/__tests__/stdlib-advanced.test.js +374 -0
  52. package/dist/src/__tests__/stdlib-bigint.test.d.ts +7 -0
  53. package/dist/src/__tests__/stdlib-bigint.test.js +426 -0
  54. package/dist/src/__tests__/stdlib-math.test.d.ts +7 -0
  55. package/dist/src/__tests__/stdlib-math.test.js +351 -0
  56. package/dist/src/__tests__/stdlib-vec.test.d.ts +4 -0
  57. package/dist/src/__tests__/stdlib-vec.test.js +263 -0
  58. package/dist/src/__tests__/structure-optimizer.test.d.ts +1 -0
  59. package/dist/src/__tests__/structure-optimizer.test.js +33 -0
  60. package/dist/src/__tests__/typechecker.test.d.ts +1 -0
  61. package/dist/src/__tests__/typechecker.test.js +552 -0
  62. package/dist/src/__tests__/var-allocator.test.d.ts +1 -0
  63. package/dist/src/__tests__/var-allocator.test.js +69 -0
  64. package/dist/src/ast/types.d.ts +515 -0
  65. package/dist/src/ast/types.js +9 -0
  66. package/dist/src/builtins/metadata.d.ts +36 -0
  67. package/dist/src/builtins/metadata.js +1014 -0
  68. package/dist/src/cli.d.ts +11 -0
  69. package/dist/src/cli.js +443 -0
  70. package/dist/src/codegen/cmdblock/index.d.ts +26 -0
  71. package/dist/src/codegen/cmdblock/index.js +45 -0
  72. package/dist/src/codegen/mcfunction/index.d.ts +40 -0
  73. package/dist/src/codegen/mcfunction/index.js +606 -0
  74. package/dist/src/codegen/structure/index.d.ts +24 -0
  75. package/dist/src/codegen/structure/index.js +279 -0
  76. package/dist/src/codegen/var-allocator.d.ts +45 -0
  77. package/dist/src/codegen/var-allocator.js +104 -0
  78. package/dist/src/compile.d.ts +37 -0
  79. package/dist/src/compile.js +165 -0
  80. package/dist/src/diagnostics/index.d.ts +44 -0
  81. package/dist/src/diagnostics/index.js +140 -0
  82. package/dist/src/events/types.d.ts +35 -0
  83. package/dist/src/events/types.js +59 -0
  84. package/dist/src/formatter/index.d.ts +1 -0
  85. package/dist/src/formatter/index.js +26 -0
  86. package/dist/src/index.d.ts +22 -0
  87. package/dist/src/index.js +45 -0
  88. package/dist/src/ir/builder.d.ts +33 -0
  89. package/dist/src/ir/builder.js +99 -0
  90. package/dist/src/ir/types.d.ts +132 -0
  91. package/dist/src/ir/types.js +15 -0
  92. package/dist/src/lexer/index.d.ts +37 -0
  93. package/dist/src/lexer/index.js +569 -0
  94. package/dist/src/lowering/index.d.ts +188 -0
  95. package/dist/src/lowering/index.js +3405 -0
  96. package/dist/src/mc-test/client.d.ts +128 -0
  97. package/dist/src/mc-test/client.js +174 -0
  98. package/dist/src/mc-test/runner.d.ts +28 -0
  99. package/dist/src/mc-test/runner.js +151 -0
  100. package/dist/src/mc-test/setup.d.ts +11 -0
  101. package/dist/src/mc-test/setup.js +98 -0
  102. package/dist/src/mc-validator/index.d.ts +17 -0
  103. package/dist/src/mc-validator/index.js +322 -0
  104. package/dist/src/nbt/index.d.ts +86 -0
  105. package/dist/src/nbt/index.js +250 -0
  106. package/dist/src/optimizer/commands.d.ts +38 -0
  107. package/dist/src/optimizer/commands.js +451 -0
  108. package/dist/src/optimizer/dce.d.ts +34 -0
  109. package/dist/src/optimizer/dce.js +639 -0
  110. package/dist/src/optimizer/passes.d.ts +34 -0
  111. package/dist/src/optimizer/passes.js +243 -0
  112. package/dist/src/optimizer/structure.d.ts +9 -0
  113. package/dist/src/optimizer/structure.js +356 -0
  114. package/dist/src/parser/index.d.ts +93 -0
  115. package/dist/src/parser/index.js +1687 -0
  116. package/dist/src/repl.d.ts +16 -0
  117. package/dist/src/repl.js +165 -0
  118. package/dist/src/runtime/index.d.ts +107 -0
  119. package/dist/src/runtime/index.js +1409 -0
  120. package/dist/src/typechecker/index.d.ts +61 -0
  121. package/dist/src/typechecker/index.js +1034 -0
  122. package/dist/src/types/entity-hierarchy.d.ts +29 -0
  123. package/dist/src/types/entity-hierarchy.js +107 -0
  124. package/dist/src2/__tests__/e2e/basic.test.d.ts +8 -0
  125. package/dist/src2/__tests__/e2e/basic.test.js +140 -0
  126. package/dist/src2/__tests__/e2e/macros.test.d.ts +9 -0
  127. package/dist/src2/__tests__/e2e/macros.test.js +182 -0
  128. package/dist/src2/__tests__/e2e/migrate.test.d.ts +13 -0
  129. package/dist/src2/__tests__/e2e/migrate.test.js +2739 -0
  130. package/dist/src2/__tests__/hir/desugar.test.d.ts +1 -0
  131. package/dist/src2/__tests__/hir/desugar.test.js +234 -0
  132. package/dist/src2/__tests__/lir/lower.test.d.ts +1 -0
  133. package/dist/src2/__tests__/lir/lower.test.js +559 -0
  134. package/dist/src2/__tests__/lir/types.test.d.ts +1 -0
  135. package/dist/src2/__tests__/lir/types.test.js +185 -0
  136. package/dist/src2/__tests__/lir/verify.test.d.ts +1 -0
  137. package/dist/src2/__tests__/lir/verify.test.js +221 -0
  138. package/dist/src2/__tests__/mir/arithmetic.test.d.ts +1 -0
  139. package/dist/src2/__tests__/mir/arithmetic.test.js +130 -0
  140. package/dist/src2/__tests__/mir/control-flow.test.d.ts +1 -0
  141. package/dist/src2/__tests__/mir/control-flow.test.js +205 -0
  142. package/dist/src2/__tests__/mir/verify.test.d.ts +1 -0
  143. package/dist/src2/__tests__/mir/verify.test.js +223 -0
  144. package/dist/src2/__tests__/optimizer/block_merge.test.d.ts +1 -0
  145. package/dist/src2/__tests__/optimizer/block_merge.test.js +78 -0
  146. package/dist/src2/__tests__/optimizer/branch_simplify.test.d.ts +1 -0
  147. package/dist/src2/__tests__/optimizer/branch_simplify.test.js +58 -0
  148. package/dist/src2/__tests__/optimizer/constant_fold.test.d.ts +1 -0
  149. package/dist/src2/__tests__/optimizer/constant_fold.test.js +131 -0
  150. package/dist/src2/__tests__/optimizer/copy_prop.test.d.ts +1 -0
  151. package/dist/src2/__tests__/optimizer/copy_prop.test.js +91 -0
  152. package/dist/src2/__tests__/optimizer/dce.test.d.ts +1 -0
  153. package/dist/src2/__tests__/optimizer/dce.test.js +76 -0
  154. package/dist/src2/__tests__/optimizer/pipeline.test.d.ts +1 -0
  155. package/dist/src2/__tests__/optimizer/pipeline.test.js +102 -0
  156. package/dist/src2/emit/compile.d.ts +19 -0
  157. package/dist/src2/emit/compile.js +80 -0
  158. package/dist/src2/emit/index.d.ts +17 -0
  159. package/dist/src2/emit/index.js +172 -0
  160. package/dist/src2/hir/lower.d.ts +15 -0
  161. package/dist/src2/hir/lower.js +378 -0
  162. package/dist/src2/hir/types.d.ts +373 -0
  163. package/dist/src2/hir/types.js +16 -0
  164. package/dist/src2/lir/lower.d.ts +15 -0
  165. package/dist/src2/lir/lower.js +453 -0
  166. package/dist/src2/lir/types.d.ts +136 -0
  167. package/dist/src2/lir/types.js +11 -0
  168. package/dist/src2/lir/verify.d.ts +14 -0
  169. package/dist/src2/lir/verify.js +113 -0
  170. package/dist/src2/mir/lower.d.ts +9 -0
  171. package/dist/src2/mir/lower.js +1030 -0
  172. package/dist/src2/mir/macro.d.ts +22 -0
  173. package/dist/src2/mir/macro.js +168 -0
  174. package/dist/src2/mir/types.d.ts +183 -0
  175. package/dist/src2/mir/types.js +11 -0
  176. package/dist/src2/mir/verify.d.ts +16 -0
  177. package/dist/src2/mir/verify.js +216 -0
  178. package/dist/src2/optimizer/block_merge.d.ts +12 -0
  179. package/dist/src2/optimizer/block_merge.js +84 -0
  180. package/dist/src2/optimizer/branch_simplify.d.ts +9 -0
  181. package/dist/src2/optimizer/branch_simplify.js +28 -0
  182. package/dist/src2/optimizer/constant_fold.d.ts +10 -0
  183. package/dist/src2/optimizer/constant_fold.js +85 -0
  184. package/dist/src2/optimizer/copy_prop.d.ts +9 -0
  185. package/dist/src2/optimizer/copy_prop.js +113 -0
  186. package/dist/src2/optimizer/dce.d.ts +8 -0
  187. package/dist/src2/optimizer/dce.js +155 -0
  188. package/dist/src2/optimizer/pipeline.d.ts +10 -0
  189. package/dist/src2/optimizer/pipeline.js +42 -0
  190. package/dist/tsconfig.tsbuildinfo +1 -0
  191. package/docs/compiler-pipeline-redesign.md +2243 -0
  192. package/docs/optimization-ideas.md +1076 -0
  193. package/editors/vscode/package-lock.json +3 -3
  194. package/editors/vscode/package.json +1 -1
  195. package/jest.config.js +1 -1
  196. package/package.json +6 -5
  197. package/scripts/postbuild.js +15 -0
  198. package/src/__tests__/cli.test.ts +8 -220
  199. package/src/__tests__/dce.test.ts +11 -56
  200. package/src/__tests__/diagnostics.test.ts +59 -38
  201. package/src/__tests__/mc-integration.test.ts +1 -2
  202. package/src/ast/types.ts +6 -1
  203. package/src/cli.ts +29 -156
  204. package/src/compile.ts +6 -162
  205. package/src/index.ts +14 -178
  206. package/src/mc-test/runner.ts +4 -3
  207. package/src/parser/index.ts +1 -1
  208. package/src/repl.ts +1 -1
  209. package/src/runtime/index.ts +1 -1
  210. package/src2/__tests__/e2e/basic.test.ts +154 -0
  211. package/src2/__tests__/e2e/macros.test.ts +199 -0
  212. package/src2/__tests__/e2e/migrate.test.ts +3008 -0
  213. package/src2/__tests__/hir/desugar.test.ts +263 -0
  214. package/src2/__tests__/lir/lower.test.ts +619 -0
  215. package/src2/__tests__/lir/types.test.ts +207 -0
  216. package/src2/__tests__/lir/verify.test.ts +249 -0
  217. package/src2/__tests__/mir/arithmetic.test.ts +156 -0
  218. package/src2/__tests__/mir/control-flow.test.ts +242 -0
  219. package/src2/__tests__/mir/verify.test.ts +254 -0
  220. package/src2/__tests__/optimizer/block_merge.test.ts +84 -0
  221. package/src2/__tests__/optimizer/branch_simplify.test.ts +64 -0
  222. package/src2/__tests__/optimizer/constant_fold.test.ts +145 -0
  223. package/src2/__tests__/optimizer/copy_prop.test.ts +99 -0
  224. package/src2/__tests__/optimizer/dce.test.ts +83 -0
  225. package/src2/__tests__/optimizer/pipeline.test.ts +116 -0
  226. package/src2/emit/compile.ts +99 -0
  227. package/src2/emit/index.ts +222 -0
  228. package/src2/hir/lower.ts +428 -0
  229. package/src2/hir/types.ts +216 -0
  230. package/src2/lir/lower.ts +556 -0
  231. package/src2/lir/types.ts +109 -0
  232. package/src2/lir/verify.ts +129 -0
  233. package/src2/mir/lower.ts +1160 -0
  234. package/src2/mir/macro.ts +167 -0
  235. package/src2/mir/types.ts +106 -0
  236. package/src2/mir/verify.ts +218 -0
  237. package/src2/optimizer/block_merge.ts +93 -0
  238. package/src2/optimizer/branch_simplify.ts +27 -0
  239. package/src2/optimizer/constant_fold.ts +88 -0
  240. package/src2/optimizer/copy_prop.ts +106 -0
  241. package/src2/optimizer/dce.ts +133 -0
  242. package/src2/optimizer/pipeline.ts +44 -0
  243. package/tsconfig.json +2 -2
  244. package/src/__tests__/codegen.test.ts +0 -161
  245. package/src/__tests__/e2e.test.ts +0 -2039
  246. package/src/__tests__/entity-types.test.ts +0 -236
  247. package/src/__tests__/lowering.test.ts +0 -1185
  248. package/src/__tests__/macro.test.ts +0 -343
  249. package/src/__tests__/nbt.test.ts +0 -58
  250. package/src/__tests__/optimizer-advanced.test.ts +0 -144
  251. package/src/__tests__/optimizer.test.ts +0 -162
  252. package/src/__tests__/runtime.test.ts +0 -305
  253. package/src/__tests__/stdlib-advanced.test.ts +0 -379
  254. package/src/__tests__/stdlib-bigint.test.ts +0 -427
  255. package/src/__tests__/stdlib-math.test.ts +0 -374
  256. package/src/__tests__/stdlib-vec.test.ts +0 -259
  257. package/src/__tests__/structure-optimizer.test.ts +0 -38
  258. package/src/__tests__/var-allocator.test.ts +0 -75
  259. package/src/codegen/cmdblock/index.ts +0 -63
  260. package/src/codegen/mcfunction/index.ts +0 -662
  261. package/src/codegen/structure/index.ts +0 -346
  262. package/src/codegen/var-allocator.ts +0 -104
  263. package/src/ir/builder.ts +0 -116
  264. package/src/ir/types.ts +0 -134
  265. package/src/lowering/index.ts +0 -3876
  266. package/src/optimizer/commands.ts +0 -534
  267. package/src/optimizer/dce.ts +0 -679
  268. package/src/optimizer/passes.ts +0 -250
  269. package/src/optimizer/structure.ts +0 -450
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tests for MC 1.20.2+ macro function support
3
+ *
4
+ * When a function uses runtime parameters in positions that require literal
5
+ * values in MC commands (coordinates, entity types, etc.), RedScript should
6
+ * automatically compile it as a macro function using $-prefixed syntax.
7
+ */
8
+ export {};
@@ -0,0 +1,306 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for MC 1.20.2+ macro function support
4
+ *
5
+ * When a function uses runtime parameters in positions that require literal
6
+ * values in MC commands (coordinates, entity types, etc.), RedScript should
7
+ * automatically compile it as a macro function using $-prefixed syntax.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const lexer_1 = require("../lexer");
11
+ const parser_1 = require("../parser");
12
+ const lowering_1 = require("../lowering");
13
+ const mcfunction_1 = require("../codegen/mcfunction");
14
+ function compile(source, namespace = 'test') {
15
+ const tokens = new lexer_1.Lexer(source).tokenize();
16
+ const ast = new parser_1.Parser(tokens).parse(namespace);
17
+ const lowering = new lowering_1.Lowering(namespace);
18
+ return lowering.lower(ast);
19
+ }
20
+ function getFunction(module, name) {
21
+ return module.functions.find(f => f.name === name);
22
+ }
23
+ function getRawCommands(fn) {
24
+ return fn.blocks
25
+ .flatMap(b => b.instrs)
26
+ .filter((i) => i.op === 'raw')
27
+ // \x01 is the sentinel for the MC macro line-start '$'; normalize for test assertions
28
+ .map(i => i.cmd.replace(/^\x01/, '$'));
29
+ }
30
+ function getGeneratedContent(module, fnName) {
31
+ const files = (0, mcfunction_1.generateDatapack)(module);
32
+ const file = files.find(f => f.path.includes(`/${fnName}.mcfunction`));
33
+ return file?.content;
34
+ }
35
+ // ---------------------------------------------------------------------------
36
+ // Macro function detection
37
+ // ---------------------------------------------------------------------------
38
+ describe('MC macro function detection', () => {
39
+ it('marks function as macro when int param used in summon coordinates', () => {
40
+ const ir = compile(`
41
+ fn spawn_zombie(x: int, y: int, z: int) {
42
+ summon("minecraft:zombie", x, y, z);
43
+ }
44
+ `);
45
+ const fn = getFunction(ir, 'spawn_zombie');
46
+ expect(fn).toBeDefined();
47
+ expect(fn.isMacroFunction).toBe(true);
48
+ expect(fn.macroParamNames).toEqual(expect.arrayContaining(['x', 'y', 'z']));
49
+ });
50
+ it('does NOT mark function as macro when all summon args are constants', () => {
51
+ const ir = compile(`
52
+ fn spawn_fixed() {
53
+ summon("minecraft:zombie", 100, 64, 200);
54
+ }
55
+ `);
56
+ const fn = getFunction(ir, 'spawn_fixed');
57
+ expect(fn).toBeDefined();
58
+ expect(fn.isMacroFunction).toBeFalsy();
59
+ });
60
+ it('marks function as macro when int param used in particle coordinates', () => {
61
+ const ir = compile(`
62
+ fn show_particle(x: int, y: int, z: int) {
63
+ particle("minecraft:flame", x, y, z);
64
+ }
65
+ `);
66
+ const fn = getFunction(ir, 'show_particle');
67
+ expect(fn).toBeDefined();
68
+ expect(fn.isMacroFunction).toBe(true);
69
+ });
70
+ it('marks function as macro when int param used in setblock coordinates', () => {
71
+ const ir = compile(`
72
+ fn place_block(x: int, y: int, z: int) {
73
+ setblock(x, y, z, "minecraft:stone");
74
+ }
75
+ `);
76
+ const fn = getFunction(ir, 'place_block');
77
+ expect(fn).toBeDefined();
78
+ expect(fn.isMacroFunction).toBe(true);
79
+ expect(fn.macroParamNames).toEqual(expect.arrayContaining(['x', 'y', 'z']));
80
+ });
81
+ it('identifies only the params used in macro positions', () => {
82
+ const ir = compile(`
83
+ fn do_stuff(count: int, x: int, y: int, z: int) {
84
+ summon("minecraft:zombie", x, y, z);
85
+ // count is not used in a macro position
86
+ }
87
+ `);
88
+ const fn = getFunction(ir, 'do_stuff');
89
+ expect(fn).toBeDefined();
90
+ expect(fn.isMacroFunction).toBe(true);
91
+ // x, y, z should be macro params; count should NOT be
92
+ expect(fn.macroParamNames).toEqual(expect.arrayContaining(['x', 'y', 'z']));
93
+ expect(fn.macroParamNames).not.toContain('count');
94
+ });
95
+ });
96
+ // ---------------------------------------------------------------------------
97
+ // Macro command generation in function body
98
+ // ---------------------------------------------------------------------------
99
+ describe('MC macro command generation', () => {
100
+ it('generates $-prefixed summon command with $(param) for macro params', () => {
101
+ const ir = compile(`
102
+ fn spawn_zombie(x: int, y: int, z: int) {
103
+ summon("minecraft:zombie", x, y, z);
104
+ }
105
+ `);
106
+ const fn = getFunction(ir, 'spawn_zombie');
107
+ const cmds = getRawCommands(fn);
108
+ // Should have a macro command for summon
109
+ const macroCmd = cmds.find(c => c.startsWith('$summon'));
110
+ expect(macroCmd).toBeDefined();
111
+ expect(macroCmd).toContain('$(x)');
112
+ expect(macroCmd).toContain('$(y)');
113
+ expect(macroCmd).toContain('$(z)');
114
+ expect(macroCmd).toBe('$summon minecraft:zombie $(x) $(y) $(z)');
115
+ });
116
+ it('generates non-prefixed command when args are literals', () => {
117
+ const ir = compile(`
118
+ fn spawn_fixed() {
119
+ summon("minecraft:zombie", 100, 64, 200);
120
+ }
121
+ `);
122
+ const fn = getFunction(ir, 'spawn_fixed');
123
+ const cmds = getRawCommands(fn);
124
+ const summonCmd = cmds.find(c => c.includes('summon'));
125
+ expect(summonCmd).toBeDefined();
126
+ expect(summonCmd.startsWith('$')).toBe(false);
127
+ expect(summonCmd).toContain('100');
128
+ expect(summonCmd).toContain('64');
129
+ expect(summonCmd).toContain('200');
130
+ });
131
+ it('generates $-prefixed particle command with $(param)', () => {
132
+ const ir = compile(`
133
+ fn show_particle(x: int, y: int, z: int) {
134
+ particle("minecraft:flame", x, y, z);
135
+ }
136
+ `);
137
+ const fn = getFunction(ir, 'show_particle');
138
+ const cmds = getRawCommands(fn);
139
+ const macroCmd = cmds.find(c => c.startsWith('$particle'));
140
+ expect(macroCmd).toBeDefined();
141
+ expect(macroCmd).toContain('$(x)');
142
+ });
143
+ it('generates $-prefixed setblock command with $(param)', () => {
144
+ const ir = compile(`
145
+ fn place_block(x: int, y: int, z: int) {
146
+ setblock(x, y, z, "minecraft:stone");
147
+ }
148
+ `);
149
+ const fn = getFunction(ir, 'place_block');
150
+ const cmds = getRawCommands(fn);
151
+ const macroCmd = cmds.find(c => c.startsWith('$setblock'));
152
+ expect(macroCmd).toBeDefined();
153
+ expect(macroCmd).toContain('$(x)');
154
+ expect(macroCmd).toContain('$(y)');
155
+ expect(macroCmd).toContain('$(z)');
156
+ expect(macroCmd).toContain('minecraft:stone');
157
+ });
158
+ });
159
+ // ---------------------------------------------------------------------------
160
+ // Call site code generation
161
+ // ---------------------------------------------------------------------------
162
+ describe('MC macro call site generation', () => {
163
+ it('emits NBT setup + with-storage call for variable args', () => {
164
+ const ir = compile(`
165
+ fn spawn_zombie(x: int, y: int, z: int) {
166
+ summon("minecraft:zombie", x, y, z);
167
+ }
168
+
169
+ fn caller(px: int, pz: int) {
170
+ spawn_zombie(px, 64, pz);
171
+ }
172
+ `);
173
+ const callerFn = getFunction(ir, 'caller');
174
+ const cmds = getRawCommands(callerFn);
175
+ // Should have NBT setup for variable params (px → x, pz → z)
176
+ const xSetup = cmds.find(c => c.includes('macro_args') && c.includes(' x '));
177
+ const zSetup = cmds.find(c => c.includes('macro_args') && c.includes(' z '));
178
+ expect(xSetup).toBeDefined();
179
+ expect(zSetup).toBeDefined();
180
+ // Should have 'function test:spawn_zombie with storage rs:macro_args'
181
+ const callCmd = cmds.find(c => c.includes('spawn_zombie') && c.includes('with storage'));
182
+ expect(callCmd).toBeDefined();
183
+ expect(callCmd).toContain('rs:macro_args');
184
+ });
185
+ it('emits NBT setup for constant args too', () => {
186
+ const ir = compile(`
187
+ fn spawn_zombie(x: int, y: int, z: int) {
188
+ summon("minecraft:zombie", x, y, z);
189
+ }
190
+
191
+ fn caller_const() {
192
+ spawn_zombie(100, 64, 200);
193
+ }
194
+ `);
195
+ const callerFn = getFunction(ir, 'caller_const');
196
+ const cmds = getRawCommands(callerFn);
197
+ // Should have NBT setup for all macro params
198
+ const nbtCmds = cmds.filter(c => c.includes('macro_args'));
199
+ expect(nbtCmds.length).toBeGreaterThan(0);
200
+ // Should call with storage
201
+ const callCmd = cmds.find(c => c.includes('spawn_zombie') && c.includes('with storage'));
202
+ expect(callCmd).toBeDefined();
203
+ });
204
+ it('correctly sets up int variable args into NBT storage', () => {
205
+ const ir = compile(`
206
+ fn spawn_zombie(x: int, y: int, z: int) {
207
+ summon("minecraft:zombie", x, y, z);
208
+ }
209
+
210
+ fn caller(my_x: int) {
211
+ spawn_zombie(my_x, 64, 0);
212
+ }
213
+ `);
214
+ const callerFn = getFunction(ir, 'caller');
215
+ const cmds = getRawCommands(callerFn);
216
+ // For variable arg my_x → x: should use execute store result
217
+ const varSetup = cmds.find(c => c.includes('execute store result storage rs:macro_args x') &&
218
+ c.includes('scoreboard players get'));
219
+ expect(varSetup).toBeDefined();
220
+ // For constant 64 → y: should use data modify ... set value
221
+ const constSetup = cmds.find(c => c.includes('data modify storage rs:macro_args y set value 64'));
222
+ expect(constSetup).toBeDefined();
223
+ });
224
+ });
225
+ // ---------------------------------------------------------------------------
226
+ // Codegen output (mcfunction file content)
227
+ // ---------------------------------------------------------------------------
228
+ describe('MC macro function codegen output', () => {
229
+ it('generates $-prefixed lines in the macro function mcfunction file', () => {
230
+ const ir = compile(`
231
+ fn spawn_zombie(x: int, y: int, z: int) {
232
+ summon("minecraft:zombie", x, y, z);
233
+ }
234
+ `);
235
+ const content = getGeneratedContent(ir, 'spawn_zombie');
236
+ expect(content).toBeDefined();
237
+ expect(content).toContain('$summon minecraft:zombie $(x) $(y) $(z)');
238
+ });
239
+ it('generates correct call site in caller mcfunction file', () => {
240
+ const ir = compile(`
241
+ fn spawn_zombie(x: int, y: int, z: int) {
242
+ summon("minecraft:zombie", x, y, z);
243
+ }
244
+
245
+ fn caller(px: int, pz: int) {
246
+ spawn_zombie(px, 64, pz);
247
+ }
248
+ `);
249
+ const content = getGeneratedContent(ir, 'caller');
250
+ expect(content).toBeDefined();
251
+ expect(content).toContain('with storage rs:macro_args');
252
+ expect(content).toContain('spawn_zombie');
253
+ });
254
+ });
255
+ // ---------------------------------------------------------------------------
256
+ // Edge cases
257
+ // ---------------------------------------------------------------------------
258
+ describe('MC macro edge cases', () => {
259
+ it('handles mixed literal and variable args correctly', () => {
260
+ const ir = compile(`
261
+ fn teleport_y(y: int) {
262
+ summon("minecraft:zombie", 100, y, 200);
263
+ }
264
+ `);
265
+ const fn = getFunction(ir, 'teleport_y');
266
+ expect(fn.isMacroFunction).toBe(true);
267
+ expect(fn.macroParamNames).toContain('y');
268
+ expect(fn.macroParamNames).not.toContain('x');
269
+ const cmds = getRawCommands(fn);
270
+ const macroCmd = cmds.find(c => c.startsWith('$summon'));
271
+ expect(macroCmd).toBeDefined();
272
+ // x and z are literals, y is macro
273
+ expect(macroCmd).toContain('100');
274
+ expect(macroCmd).toContain('$(y)');
275
+ expect(macroCmd).toContain('200');
276
+ });
277
+ it('non-macro functions still work normally', () => {
278
+ const ir = compile(`
279
+ fn greet() {
280
+ say("hello world");
281
+ }
282
+ `);
283
+ const fn = getFunction(ir, 'greet');
284
+ expect(fn.isMacroFunction).toBeFalsy();
285
+ const cmds = getRawCommands(fn);
286
+ const sayCmd = cmds.find(c => c.includes('say') || c.includes('tellraw'));
287
+ expect(sayCmd).toBeDefined();
288
+ expect(sayCmd.startsWith('$')).toBe(false);
289
+ });
290
+ it('macro function with params used in arithmetic still works', () => {
291
+ const ir = compile(`
292
+ fn spawn_offset(x: int, y: int, z: int) {
293
+ summon("minecraft:zombie", x, y, z);
294
+ // params are also used in the macro commands
295
+ }
296
+ `);
297
+ const fn = getFunction(ir, 'spawn_offset');
298
+ expect(fn.isMacroFunction).toBe(true);
299
+ // The macro commands should use $(param) syntax
300
+ const cmds = getRawCommands(fn);
301
+ const macroCmd = cmds.find(c => c.startsWith('$summon'));
302
+ expect(macroCmd).toBeDefined();
303
+ expect(macroCmd).toContain('$(x)');
304
+ });
305
+ });
306
+ //# sourceMappingURL=macro.test.js.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * RedScript MC Integration Tests
3
+ *
4
+ * Tests compiled datapacks against a real Paper 1.21.4 server.
5
+ *
6
+ * Prerequisites:
7
+ * - Paper server running with TestHarnessPlugin on port 25561
8
+ * - MC_SERVER_DIR env var pointing to server directory
9
+ *
10
+ * Run: MC_SERVER_DIR=~/mc-test-server npx jest mc-integration --testTimeout=120000
11
+ */
12
+ export {};