redscript-mc 1.2.29 → 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 (274) 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/README.md +29 -28
  8. package/README.zh.md +28 -28
  9. package/demo.gif +0 -0
  10. package/dist/cli.js +2 -554
  11. package/dist/compile.js +2 -266
  12. package/dist/index.js +2 -159
  13. package/dist/lexer/index.js +9 -1
  14. package/dist/lowering/index.js +22 -5
  15. package/dist/src/__tests__/cli.test.d.ts +1 -0
  16. package/dist/src/__tests__/cli.test.js +104 -0
  17. package/dist/src/__tests__/codegen.test.d.ts +1 -0
  18. package/dist/src/__tests__/codegen.test.js +152 -0
  19. package/dist/src/__tests__/compile-all.test.d.ts +10 -0
  20. package/dist/src/__tests__/compile-all.test.js +108 -0
  21. package/dist/src/__tests__/dce.test.d.ts +1 -0
  22. package/dist/src/__tests__/dce.test.js +102 -0
  23. package/dist/src/__tests__/diagnostics.test.d.ts +4 -0
  24. package/dist/src/__tests__/diagnostics.test.js +177 -0
  25. package/dist/src/__tests__/e2e.test.d.ts +6 -0
  26. package/dist/src/__tests__/e2e.test.js +1789 -0
  27. package/dist/src/__tests__/entity-types.test.d.ts +1 -0
  28. package/dist/src/__tests__/entity-types.test.js +203 -0
  29. package/dist/src/__tests__/formatter.test.d.ts +1 -0
  30. package/dist/src/__tests__/formatter.test.js +40 -0
  31. package/dist/src/__tests__/lexer.test.d.ts +1 -0
  32. package/dist/src/__tests__/lexer.test.js +343 -0
  33. package/dist/src/__tests__/lowering.test.d.ts +1 -0
  34. package/dist/src/__tests__/lowering.test.js +1015 -0
  35. package/dist/src/__tests__/macro.test.d.ts +8 -0
  36. package/dist/src/__tests__/macro.test.js +306 -0
  37. package/dist/src/__tests__/mc-integration.test.d.ts +12 -0
  38. package/dist/src/__tests__/mc-integration.test.js +817 -0
  39. package/dist/src/__tests__/mc-syntax.test.d.ts +1 -0
  40. package/dist/src/__tests__/mc-syntax.test.js +124 -0
  41. package/dist/src/__tests__/nbt.test.d.ts +1 -0
  42. package/dist/src/__tests__/nbt.test.js +82 -0
  43. package/dist/src/__tests__/optimizer-advanced.test.d.ts +1 -0
  44. package/dist/src/__tests__/optimizer-advanced.test.js +124 -0
  45. package/dist/src/__tests__/optimizer.test.d.ts +1 -0
  46. package/dist/src/__tests__/optimizer.test.js +149 -0
  47. package/dist/src/__tests__/parser.test.d.ts +1 -0
  48. package/dist/src/__tests__/parser.test.js +807 -0
  49. package/dist/src/__tests__/repl.test.d.ts +1 -0
  50. package/dist/src/__tests__/repl.test.js +27 -0
  51. package/dist/src/__tests__/runtime.test.d.ts +1 -0
  52. package/dist/src/__tests__/runtime.test.js +289 -0
  53. package/dist/src/__tests__/stdlib-advanced.test.d.ts +4 -0
  54. package/dist/src/__tests__/stdlib-advanced.test.js +374 -0
  55. package/dist/src/__tests__/stdlib-bigint.test.d.ts +7 -0
  56. package/dist/src/__tests__/stdlib-bigint.test.js +426 -0
  57. package/dist/src/__tests__/stdlib-math.test.d.ts +7 -0
  58. package/dist/src/__tests__/stdlib-math.test.js +351 -0
  59. package/dist/src/__tests__/stdlib-vec.test.d.ts +4 -0
  60. package/dist/src/__tests__/stdlib-vec.test.js +263 -0
  61. package/dist/src/__tests__/structure-optimizer.test.d.ts +1 -0
  62. package/dist/src/__tests__/structure-optimizer.test.js +33 -0
  63. package/dist/src/__tests__/typechecker.test.d.ts +1 -0
  64. package/dist/src/__tests__/typechecker.test.js +552 -0
  65. package/dist/src/__tests__/var-allocator.test.d.ts +1 -0
  66. package/dist/src/__tests__/var-allocator.test.js +69 -0
  67. package/dist/src/ast/types.d.ts +515 -0
  68. package/dist/src/ast/types.js +9 -0
  69. package/dist/src/builtins/metadata.d.ts +36 -0
  70. package/dist/src/builtins/metadata.js +1014 -0
  71. package/dist/src/cli.d.ts +11 -0
  72. package/dist/src/cli.js +443 -0
  73. package/dist/src/codegen/cmdblock/index.d.ts +26 -0
  74. package/dist/src/codegen/cmdblock/index.js +45 -0
  75. package/dist/src/codegen/mcfunction/index.d.ts +40 -0
  76. package/dist/src/codegen/mcfunction/index.js +606 -0
  77. package/dist/src/codegen/structure/index.d.ts +24 -0
  78. package/dist/src/codegen/structure/index.js +279 -0
  79. package/dist/src/codegen/var-allocator.d.ts +45 -0
  80. package/dist/src/codegen/var-allocator.js +104 -0
  81. package/dist/src/compile.d.ts +37 -0
  82. package/dist/src/compile.js +165 -0
  83. package/dist/src/diagnostics/index.d.ts +44 -0
  84. package/dist/src/diagnostics/index.js +140 -0
  85. package/dist/src/events/types.d.ts +35 -0
  86. package/dist/src/events/types.js +59 -0
  87. package/dist/src/formatter/index.d.ts +1 -0
  88. package/dist/src/formatter/index.js +26 -0
  89. package/dist/src/index.d.ts +22 -0
  90. package/dist/src/index.js +45 -0
  91. package/dist/src/ir/builder.d.ts +33 -0
  92. package/dist/src/ir/builder.js +99 -0
  93. package/dist/src/ir/types.d.ts +132 -0
  94. package/dist/src/ir/types.js +15 -0
  95. package/dist/src/lexer/index.d.ts +37 -0
  96. package/dist/src/lexer/index.js +569 -0
  97. package/dist/src/lowering/index.d.ts +188 -0
  98. package/dist/src/lowering/index.js +3405 -0
  99. package/dist/src/mc-test/client.d.ts +128 -0
  100. package/dist/src/mc-test/client.js +174 -0
  101. package/dist/src/mc-test/runner.d.ts +28 -0
  102. package/dist/src/mc-test/runner.js +151 -0
  103. package/dist/src/mc-test/setup.d.ts +11 -0
  104. package/dist/src/mc-test/setup.js +98 -0
  105. package/dist/src/mc-validator/index.d.ts +17 -0
  106. package/dist/src/mc-validator/index.js +322 -0
  107. package/dist/src/nbt/index.d.ts +86 -0
  108. package/dist/src/nbt/index.js +250 -0
  109. package/dist/src/optimizer/commands.d.ts +38 -0
  110. package/dist/src/optimizer/commands.js +451 -0
  111. package/dist/src/optimizer/dce.d.ts +34 -0
  112. package/dist/src/optimizer/dce.js +639 -0
  113. package/dist/src/optimizer/passes.d.ts +34 -0
  114. package/dist/src/optimizer/passes.js +243 -0
  115. package/dist/src/optimizer/structure.d.ts +9 -0
  116. package/dist/src/optimizer/structure.js +356 -0
  117. package/dist/src/parser/index.d.ts +93 -0
  118. package/dist/src/parser/index.js +1687 -0
  119. package/dist/src/repl.d.ts +16 -0
  120. package/dist/src/repl.js +165 -0
  121. package/dist/src/runtime/index.d.ts +107 -0
  122. package/dist/src/runtime/index.js +1409 -0
  123. package/dist/src/typechecker/index.d.ts +61 -0
  124. package/dist/src/typechecker/index.js +1034 -0
  125. package/dist/src/types/entity-hierarchy.d.ts +29 -0
  126. package/dist/src/types/entity-hierarchy.js +107 -0
  127. package/dist/src2/__tests__/e2e/basic.test.d.ts +8 -0
  128. package/dist/src2/__tests__/e2e/basic.test.js +140 -0
  129. package/dist/src2/__tests__/e2e/macros.test.d.ts +9 -0
  130. package/dist/src2/__tests__/e2e/macros.test.js +182 -0
  131. package/dist/src2/__tests__/e2e/migrate.test.d.ts +13 -0
  132. package/dist/src2/__tests__/e2e/migrate.test.js +2739 -0
  133. package/dist/src2/__tests__/hir/desugar.test.d.ts +1 -0
  134. package/dist/src2/__tests__/hir/desugar.test.js +234 -0
  135. package/dist/src2/__tests__/lir/lower.test.d.ts +1 -0
  136. package/dist/src2/__tests__/lir/lower.test.js +559 -0
  137. package/dist/src2/__tests__/lir/types.test.d.ts +1 -0
  138. package/dist/src2/__tests__/lir/types.test.js +185 -0
  139. package/dist/src2/__tests__/lir/verify.test.d.ts +1 -0
  140. package/dist/src2/__tests__/lir/verify.test.js +221 -0
  141. package/dist/src2/__tests__/mir/arithmetic.test.d.ts +1 -0
  142. package/dist/src2/__tests__/mir/arithmetic.test.js +130 -0
  143. package/dist/src2/__tests__/mir/control-flow.test.d.ts +1 -0
  144. package/dist/src2/__tests__/mir/control-flow.test.js +205 -0
  145. package/dist/src2/__tests__/mir/verify.test.d.ts +1 -0
  146. package/dist/src2/__tests__/mir/verify.test.js +223 -0
  147. package/dist/src2/__tests__/optimizer/block_merge.test.d.ts +1 -0
  148. package/dist/src2/__tests__/optimizer/block_merge.test.js +78 -0
  149. package/dist/src2/__tests__/optimizer/branch_simplify.test.d.ts +1 -0
  150. package/dist/src2/__tests__/optimizer/branch_simplify.test.js +58 -0
  151. package/dist/src2/__tests__/optimizer/constant_fold.test.d.ts +1 -0
  152. package/dist/src2/__tests__/optimizer/constant_fold.test.js +131 -0
  153. package/dist/src2/__tests__/optimizer/copy_prop.test.d.ts +1 -0
  154. package/dist/src2/__tests__/optimizer/copy_prop.test.js +91 -0
  155. package/dist/src2/__tests__/optimizer/dce.test.d.ts +1 -0
  156. package/dist/src2/__tests__/optimizer/dce.test.js +76 -0
  157. package/dist/src2/__tests__/optimizer/pipeline.test.d.ts +1 -0
  158. package/dist/src2/__tests__/optimizer/pipeline.test.js +102 -0
  159. package/dist/src2/emit/compile.d.ts +19 -0
  160. package/dist/src2/emit/compile.js +80 -0
  161. package/dist/src2/emit/index.d.ts +17 -0
  162. package/dist/src2/emit/index.js +172 -0
  163. package/dist/src2/hir/lower.d.ts +15 -0
  164. package/dist/src2/hir/lower.js +378 -0
  165. package/dist/src2/hir/types.d.ts +373 -0
  166. package/dist/src2/hir/types.js +16 -0
  167. package/dist/src2/lir/lower.d.ts +15 -0
  168. package/dist/src2/lir/lower.js +453 -0
  169. package/dist/src2/lir/types.d.ts +136 -0
  170. package/dist/src2/lir/types.js +11 -0
  171. package/dist/src2/lir/verify.d.ts +14 -0
  172. package/dist/src2/lir/verify.js +113 -0
  173. package/dist/src2/mir/lower.d.ts +9 -0
  174. package/dist/src2/mir/lower.js +1030 -0
  175. package/dist/src2/mir/macro.d.ts +22 -0
  176. package/dist/src2/mir/macro.js +168 -0
  177. package/dist/src2/mir/types.d.ts +183 -0
  178. package/dist/src2/mir/types.js +11 -0
  179. package/dist/src2/mir/verify.d.ts +16 -0
  180. package/dist/src2/mir/verify.js +216 -0
  181. package/dist/src2/optimizer/block_merge.d.ts +12 -0
  182. package/dist/src2/optimizer/block_merge.js +84 -0
  183. package/dist/src2/optimizer/branch_simplify.d.ts +9 -0
  184. package/dist/src2/optimizer/branch_simplify.js +28 -0
  185. package/dist/src2/optimizer/constant_fold.d.ts +10 -0
  186. package/dist/src2/optimizer/constant_fold.js +85 -0
  187. package/dist/src2/optimizer/copy_prop.d.ts +9 -0
  188. package/dist/src2/optimizer/copy_prop.js +113 -0
  189. package/dist/src2/optimizer/dce.d.ts +8 -0
  190. package/dist/src2/optimizer/dce.js +155 -0
  191. package/dist/src2/optimizer/pipeline.d.ts +10 -0
  192. package/dist/src2/optimizer/pipeline.js +42 -0
  193. package/dist/tsconfig.tsbuildinfo +1 -0
  194. package/docs/compiler-pipeline-redesign.md +2243 -0
  195. package/docs/optimization-ideas.md +1076 -0
  196. package/editors/vscode/package-lock.json +3 -3
  197. package/editors/vscode/package.json +1 -1
  198. package/examples/readme-demo.mcrs +44 -66
  199. package/jest.config.js +1 -1
  200. package/package.json +6 -5
  201. package/scripts/postbuild.js +15 -0
  202. package/src/__tests__/cli.test.ts +8 -220
  203. package/src/__tests__/dce.test.ts +11 -56
  204. package/src/__tests__/diagnostics.test.ts +59 -38
  205. package/src/__tests__/mc-integration.test.ts +1 -2
  206. package/src/ast/types.ts +6 -1
  207. package/src/cli.ts +29 -156
  208. package/src/compile.ts +6 -162
  209. package/src/index.ts +14 -178
  210. package/src/lexer/index.ts +9 -1
  211. package/src/mc-test/runner.ts +4 -3
  212. package/src/parser/index.ts +1 -1
  213. package/src/repl.ts +1 -1
  214. package/src/runtime/index.ts +1 -1
  215. package/src2/__tests__/e2e/basic.test.ts +154 -0
  216. package/src2/__tests__/e2e/macros.test.ts +199 -0
  217. package/src2/__tests__/e2e/migrate.test.ts +3008 -0
  218. package/src2/__tests__/hir/desugar.test.ts +263 -0
  219. package/src2/__tests__/lir/lower.test.ts +619 -0
  220. package/src2/__tests__/lir/types.test.ts +207 -0
  221. package/src2/__tests__/lir/verify.test.ts +249 -0
  222. package/src2/__tests__/mir/arithmetic.test.ts +156 -0
  223. package/src2/__tests__/mir/control-flow.test.ts +242 -0
  224. package/src2/__tests__/mir/verify.test.ts +254 -0
  225. package/src2/__tests__/optimizer/block_merge.test.ts +84 -0
  226. package/src2/__tests__/optimizer/branch_simplify.test.ts +64 -0
  227. package/src2/__tests__/optimizer/constant_fold.test.ts +145 -0
  228. package/src2/__tests__/optimizer/copy_prop.test.ts +99 -0
  229. package/src2/__tests__/optimizer/dce.test.ts +83 -0
  230. package/src2/__tests__/optimizer/pipeline.test.ts +116 -0
  231. package/src2/emit/compile.ts +99 -0
  232. package/src2/emit/index.ts +222 -0
  233. package/src2/hir/lower.ts +428 -0
  234. package/src2/hir/types.ts +216 -0
  235. package/src2/lir/lower.ts +556 -0
  236. package/src2/lir/types.ts +109 -0
  237. package/src2/lir/verify.ts +129 -0
  238. package/src2/mir/lower.ts +1160 -0
  239. package/src2/mir/macro.ts +167 -0
  240. package/src2/mir/types.ts +106 -0
  241. package/src2/mir/verify.ts +218 -0
  242. package/src2/optimizer/block_merge.ts +93 -0
  243. package/src2/optimizer/branch_simplify.ts +27 -0
  244. package/src2/optimizer/constant_fold.ts +88 -0
  245. package/src2/optimizer/copy_prop.ts +106 -0
  246. package/src2/optimizer/dce.ts +133 -0
  247. package/src2/optimizer/pipeline.ts +44 -0
  248. package/tsconfig.json +2 -2
  249. package/src/__tests__/codegen.test.ts +0 -161
  250. package/src/__tests__/e2e.test.ts +0 -2039
  251. package/src/__tests__/entity-types.test.ts +0 -236
  252. package/src/__tests__/lowering.test.ts +0 -1185
  253. package/src/__tests__/macro.test.ts +0 -343
  254. package/src/__tests__/nbt.test.ts +0 -58
  255. package/src/__tests__/optimizer-advanced.test.ts +0 -144
  256. package/src/__tests__/optimizer.test.ts +0 -162
  257. package/src/__tests__/runtime.test.ts +0 -305
  258. package/src/__tests__/stdlib-advanced.test.ts +0 -379
  259. package/src/__tests__/stdlib-bigint.test.ts +0 -427
  260. package/src/__tests__/stdlib-math.test.ts +0 -374
  261. package/src/__tests__/stdlib-vec.test.ts +0 -259
  262. package/src/__tests__/structure-optimizer.test.ts +0 -38
  263. package/src/__tests__/var-allocator.test.ts +0 -75
  264. package/src/codegen/cmdblock/index.ts +0 -63
  265. package/src/codegen/mcfunction/index.ts +0 -662
  266. package/src/codegen/structure/index.ts +0 -346
  267. package/src/codegen/var-allocator.ts +0 -104
  268. package/src/ir/builder.ts +0 -116
  269. package/src/ir/types.ts +0 -134
  270. package/src/lowering/index.ts +0 -3860
  271. package/src/optimizer/commands.ts +0 -534
  272. package/src/optimizer/dce.ts +0 -679
  273. package/src/optimizer/passes.ts +0 -250
  274. package/src/optimizer/structure.ts +0 -450
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ /**
3
+ * Stage 7 — LIR → .mcfunction Emission
4
+ *
5
+ * Converts a LIRModule into DatapackFile[] representing a Minecraft datapack.
6
+ * Each LIRFunction becomes a .mcfunction file under data/<ns>/function/.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.emit = emit;
10
+ // ---------------------------------------------------------------------------
11
+ // Public API
12
+ // ---------------------------------------------------------------------------
13
+ function emit(module, options) {
14
+ const { namespace } = options;
15
+ const tickFns = options.tickFunctions ?? [];
16
+ const loadFns = options.loadFunctions ?? [];
17
+ const objective = module.objective;
18
+ const files = [];
19
+ // pack.mcmeta
20
+ files.push({
21
+ path: 'pack.mcmeta',
22
+ content: JSON.stringify({
23
+ pack: { pack_format: 26, description: `RedScript datapack: ${namespace}` },
24
+ }, null, 2) + '\n',
25
+ });
26
+ // load.mcfunction — creates the scoreboard objective
27
+ const loadCmds = [`scoreboard objectives add ${objective} dummy`];
28
+ files.push({
29
+ path: `data/${namespace}/function/load.mcfunction`,
30
+ content: loadCmds.join('\n') + '\n',
31
+ });
32
+ // Each LIR function → .mcfunction file
33
+ for (const fn of module.functions) {
34
+ const lines = emitFunction(fn, namespace, objective);
35
+ const fnPath = fnNameToPath(fn.name, namespace);
36
+ files.push({ path: fnPath, content: lines.join('\n') + '\n' });
37
+ }
38
+ // Tag files for tick/load
39
+ if (loadFns.length > 0 || true) {
40
+ // Always include load.json — it must reference the load.mcfunction
41
+ const loadValues = [`${namespace}:load`, ...loadFns.map(fn => `${namespace}:${fn}`)];
42
+ files.push({
43
+ path: 'data/minecraft/tags/function/load.json',
44
+ content: JSON.stringify({ values: loadValues }, null, 2) + '\n',
45
+ });
46
+ }
47
+ if (tickFns.length > 0) {
48
+ const tickValues = tickFns.map(fn => `${namespace}:${fn}`);
49
+ files.push({
50
+ path: 'data/minecraft/tags/function/tick.json',
51
+ content: JSON.stringify({ values: tickValues }, null, 2) + '\n',
52
+ });
53
+ }
54
+ return files;
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // Function emission
58
+ // ---------------------------------------------------------------------------
59
+ function emitFunction(fn, namespace, objective) {
60
+ const lines = [];
61
+ for (const instr of fn.instructions) {
62
+ lines.push(emitInstr(instr, namespace, objective));
63
+ }
64
+ return lines;
65
+ }
66
+ function fnNameToPath(name, namespace) {
67
+ // LIR function names may contain :: for methods — convert to /
68
+ const mcName = name.replace(/::/g, '/').toLowerCase();
69
+ return `data/${namespace}/function/${mcName}.mcfunction`;
70
+ }
71
+ // ---------------------------------------------------------------------------
72
+ // Instruction emission
73
+ // ---------------------------------------------------------------------------
74
+ function emitInstr(instr, ns, obj) {
75
+ switch (instr.kind) {
76
+ case 'score_set':
77
+ return `scoreboard players set ${slot(instr.dst)} ${instr.value}`;
78
+ case 'score_copy':
79
+ return `scoreboard players operation ${slot(instr.dst)} = ${slot(instr.src)}`;
80
+ case 'score_add':
81
+ return `scoreboard players operation ${slot(instr.dst)} += ${slot(instr.src)}`;
82
+ case 'score_sub':
83
+ return `scoreboard players operation ${slot(instr.dst)} -= ${slot(instr.src)}`;
84
+ case 'score_mul':
85
+ return `scoreboard players operation ${slot(instr.dst)} *= ${slot(instr.src)}`;
86
+ case 'score_div':
87
+ return `scoreboard players operation ${slot(instr.dst)} /= ${slot(instr.src)}`;
88
+ case 'score_mod':
89
+ return `scoreboard players operation ${slot(instr.dst)} %= ${slot(instr.src)}`;
90
+ case 'score_min':
91
+ return `scoreboard players operation ${slot(instr.dst)} < ${slot(instr.src)}`;
92
+ case 'score_max':
93
+ return `scoreboard players operation ${slot(instr.dst)} > ${slot(instr.src)}`;
94
+ case 'score_swap':
95
+ return `scoreboard players operation ${slot(instr.a)} >< ${slot(instr.b)}`;
96
+ case 'store_cmd_to_score':
97
+ return `execute store result score ${slot(instr.dst)} run ${emitInstr(instr.cmd, ns, obj)}`;
98
+ case 'store_score_to_nbt':
99
+ return `execute store result storage ${instr.ns} ${instr.path} ${instr.type} ${instr.scale} run scoreboard players get ${slot(instr.src)}`;
100
+ case 'store_nbt_to_score':
101
+ return `execute store result score ${slot(instr.dst)} run data get storage ${instr.ns} ${instr.path} ${instr.scale}`;
102
+ case 'nbt_set_literal':
103
+ return `data modify storage ${instr.ns} ${instr.path} set value ${instr.value}`;
104
+ case 'nbt_copy':
105
+ return `data modify storage ${instr.dstNs} ${instr.dstPath} set from storage ${instr.srcNs} ${instr.srcPath}`;
106
+ case 'call':
107
+ return `function ${instr.fn}`;
108
+ case 'call_macro':
109
+ return `function ${instr.fn} with storage ${instr.storage}`;
110
+ case 'call_if_matches':
111
+ return `execute if score ${slot(instr.slot)} matches ${instr.range} run function ${instr.fn}`;
112
+ case 'call_unless_matches':
113
+ return `execute unless score ${slot(instr.slot)} matches ${instr.range} run function ${instr.fn}`;
114
+ case 'call_if_score':
115
+ return `execute if score ${slot(instr.a)} ${cmpToMC(instr.op)} ${slot(instr.b)} run function ${instr.fn}`;
116
+ case 'call_unless_score':
117
+ return `execute unless score ${slot(instr.a)} ${cmpToMC(instr.op)} ${slot(instr.b)} run function ${instr.fn}`;
118
+ case 'call_context': {
119
+ const subcmds = instr.subcommands.map(emitSubcmd).join(' ');
120
+ return `execute ${subcmds} run function ${instr.fn}`;
121
+ }
122
+ case 'return_value':
123
+ return `scoreboard players operation $ret ${instr.slot.obj} = ${slot(instr.slot)}`;
124
+ case 'macro_line':
125
+ return `$${instr.template}`;
126
+ case 'raw':
127
+ return instr.cmd;
128
+ }
129
+ }
130
+ // ---------------------------------------------------------------------------
131
+ // Helpers
132
+ // ---------------------------------------------------------------------------
133
+ function slot(s) {
134
+ return `${s.player} ${s.obj}`;
135
+ }
136
+ function cmpToMC(op) {
137
+ switch (op) {
138
+ case 'eq': return '=';
139
+ case 'ne': return '='; // ne uses "unless" form, but when used in if score context
140
+ case 'lt': return '<';
141
+ case 'le': return '<=';
142
+ case 'gt': return '>';
143
+ case 'ge': return '>=';
144
+ }
145
+ }
146
+ function emitSubcmd(sub) {
147
+ switch (sub.kind) {
148
+ case 'as':
149
+ return `as ${sub.selector}`;
150
+ case 'at':
151
+ return `at ${sub.selector}`;
152
+ case 'at_self':
153
+ return 'at @s';
154
+ case 'positioned':
155
+ return `positioned ${sub.x} ${sub.y} ${sub.z}`;
156
+ case 'rotated':
157
+ return `rotated ${sub.yaw} ${sub.pitch}`;
158
+ case 'in':
159
+ return `in ${sub.dimension}`;
160
+ case 'anchored':
161
+ return `anchored ${sub.anchor}`;
162
+ case 'if_score':
163
+ return `if score ${sub.a} ${cmpToMC(sub.op)} ${sub.b}`;
164
+ case 'unless_score':
165
+ return `unless score ${sub.a} ${cmpToMC(sub.op)} ${sub.b}`;
166
+ case 'if_matches':
167
+ return `if score ${sub.score} matches ${sub.range}`;
168
+ case 'unless_matches':
169
+ return `unless score ${sub.score} matches ${sub.range}`;
170
+ }
171
+ }
172
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * AST → HIR Lowering — Stage 2 of the RedScript compiler pipeline.
3
+ *
4
+ * Desugaring transforms:
5
+ * - for(init;cond;step) → block { init; while(cond) { body; step } }
6
+ * - for_range(v,start,end) → block { let v = start; while(v < end) { body; v = v + 1 } }
7
+ * - a += b / -= / *= / /= / %= → a = a OP b
8
+ * - a && b → if(a) { b } else { false }
9
+ * - a || b → if(a) { true } else { b }
10
+ * - as_block / at_block / as_at → unified execute with subcommands
11
+ * - All other nodes pass through with field-wise recursion
12
+ */
13
+ import type { Program } from '../../src/ast/types';
14
+ import type { HIRModule } from './types';
15
+ export declare function lowerToHIR(program: Program): HIRModule;
@@ -0,0 +1,378 @@
1
+ "use strict";
2
+ /**
3
+ * AST → HIR Lowering — Stage 2 of the RedScript compiler pipeline.
4
+ *
5
+ * Desugaring transforms:
6
+ * - for(init;cond;step) → block { init; while(cond) { body; step } }
7
+ * - for_range(v,start,end) → block { let v = start; while(v < end) { body; v = v + 1 } }
8
+ * - a += b / -= / *= / /= / %= → a = a OP b
9
+ * - a && b → if(a) { b } else { false }
10
+ * - a || b → if(a) { true } else { b }
11
+ * - as_block / at_block / as_at → unified execute with subcommands
12
+ * - All other nodes pass through with field-wise recursion
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.lowerToHIR = lowerToHIR;
16
+ // ---------------------------------------------------------------------------
17
+ // Public API
18
+ // ---------------------------------------------------------------------------
19
+ function lowerToHIR(program) {
20
+ return {
21
+ namespace: program.namespace,
22
+ globals: program.globals.map(lowerGlobal),
23
+ functions: program.declarations.map(lowerFunction),
24
+ structs: program.structs.map((s) => ({
25
+ name: s.name,
26
+ fields: s.fields.map(f => ({ name: f.name, type: f.type })),
27
+ span: s.span,
28
+ })),
29
+ implBlocks: program.implBlocks.map((ib) => ({
30
+ typeName: ib.typeName,
31
+ methods: ib.methods.map(lowerFunction),
32
+ span: ib.span,
33
+ })),
34
+ enums: program.enums.map((e) => ({
35
+ name: e.name,
36
+ variants: e.variants.map(v => ({ name: v.name, value: v.value })),
37
+ span: e.span,
38
+ })),
39
+ consts: program.consts.map((c) => ({
40
+ name: c.name,
41
+ type: c.type,
42
+ value: lowerExpr(c.value),
43
+ span: c.span,
44
+ })),
45
+ isLibrary: program.isLibrary,
46
+ };
47
+ }
48
+ // ---------------------------------------------------------------------------
49
+ // Functions & globals
50
+ // ---------------------------------------------------------------------------
51
+ function lowerGlobal(g) {
52
+ return {
53
+ name: g.name,
54
+ type: g.type,
55
+ init: lowerExpr(g.init),
56
+ mutable: g.mutable,
57
+ span: g.span,
58
+ };
59
+ }
60
+ function lowerFunction(fn) {
61
+ return {
62
+ name: fn.name,
63
+ params: fn.params.map(lowerParam),
64
+ returnType: fn.returnType,
65
+ decorators: fn.decorators,
66
+ body: lowerBlock(fn.body),
67
+ isLibraryFn: fn.isLibraryFn,
68
+ span: fn.span,
69
+ };
70
+ }
71
+ function lowerParam(p) {
72
+ return {
73
+ name: p.name,
74
+ type: p.type,
75
+ default: p.default ? lowerExpr(p.default) : undefined,
76
+ };
77
+ }
78
+ // ---------------------------------------------------------------------------
79
+ // Blocks & statements
80
+ // ---------------------------------------------------------------------------
81
+ function lowerBlock(block) {
82
+ const result = [];
83
+ for (const stmt of block) {
84
+ const lowered = lowerStmt(stmt);
85
+ // lowerStmt may return an array (e.g. for → [init, while])
86
+ if (Array.isArray(lowered)) {
87
+ result.push(...lowered);
88
+ }
89
+ else {
90
+ result.push(lowered);
91
+ }
92
+ }
93
+ return result;
94
+ }
95
+ function lowerStmt(stmt) {
96
+ switch (stmt.kind) {
97
+ case 'let':
98
+ return { kind: 'let', name: stmt.name, type: stmt.type, init: lowerExpr(stmt.init), span: stmt.span };
99
+ case 'expr':
100
+ return { kind: 'expr', expr: lowerExpr(stmt.expr), span: stmt.span };
101
+ case 'return':
102
+ return { kind: 'return', value: stmt.value ? lowerExpr(stmt.value) : undefined, span: stmt.span };
103
+ case 'break':
104
+ return { kind: 'break', span: stmt.span };
105
+ case 'continue':
106
+ return { kind: 'continue', span: stmt.span };
107
+ case 'if':
108
+ return {
109
+ kind: 'if',
110
+ cond: lowerExpr(stmt.cond),
111
+ then: lowerBlock(stmt.then),
112
+ else_: stmt.else_ ? lowerBlock(stmt.else_) : undefined,
113
+ span: stmt.span,
114
+ };
115
+ case 'while':
116
+ return { kind: 'while', cond: lowerExpr(stmt.cond), body: lowerBlock(stmt.body), span: stmt.span };
117
+ // --- Desugaring: for → while ---
118
+ case 'for': {
119
+ const stmts = [];
120
+ // Init
121
+ if (stmt.init) {
122
+ const init = lowerStmt(stmt.init);
123
+ if (Array.isArray(init))
124
+ stmts.push(...init);
125
+ else
126
+ stmts.push(init);
127
+ }
128
+ // while(cond) { body } step { step_expr }
129
+ const body = lowerBlock(stmt.body);
130
+ const step = [{ kind: 'expr', expr: lowerExpr(stmt.step), span: stmt.span }];
131
+ stmts.push({ kind: 'while', cond: lowerExpr(stmt.cond), body, step, span: stmt.span });
132
+ return stmts;
133
+ }
134
+ // --- Desugaring: for_range → let + while(cond) { body } step { v++ } ---
135
+ case 'for_range': {
136
+ const varName = stmt.varName;
137
+ const initStmt = {
138
+ kind: 'let',
139
+ name: varName,
140
+ type: { kind: 'named', name: 'int' },
141
+ init: lowerExpr(stmt.start),
142
+ span: stmt.span,
143
+ };
144
+ const body = lowerBlock(stmt.body);
145
+ // step: v = v + 1 (in separate step block so continue still increments)
146
+ const step = [{
147
+ kind: 'expr',
148
+ expr: {
149
+ kind: 'assign',
150
+ target: varName,
151
+ value: {
152
+ kind: 'binary',
153
+ op: '+',
154
+ left: { kind: 'ident', name: varName },
155
+ right: { kind: 'int_lit', value: 1 },
156
+ },
157
+ },
158
+ }];
159
+ const whileStmt = {
160
+ kind: 'while',
161
+ cond: {
162
+ kind: 'binary',
163
+ op: '<',
164
+ left: { kind: 'ident', name: varName },
165
+ right: lowerExpr(stmt.end),
166
+ },
167
+ body,
168
+ step,
169
+ span: stmt.span,
170
+ };
171
+ return [initStmt, whileStmt];
172
+ }
173
+ case 'foreach':
174
+ return {
175
+ kind: 'foreach',
176
+ binding: stmt.binding,
177
+ iterable: lowerExpr(stmt.iterable),
178
+ body: lowerBlock(stmt.body),
179
+ executeContext: stmt.executeContext,
180
+ span: stmt.span,
181
+ };
182
+ case 'match':
183
+ return {
184
+ kind: 'match',
185
+ expr: lowerExpr(stmt.expr),
186
+ arms: stmt.arms.map(arm => ({
187
+ pattern: arm.pattern ? lowerExpr(arm.pattern) : null,
188
+ body: lowerBlock(arm.body),
189
+ })),
190
+ span: stmt.span,
191
+ };
192
+ // --- Desugaring: as_block → execute [as] ---
193
+ case 'as_block':
194
+ return {
195
+ kind: 'execute',
196
+ subcommands: [{ kind: 'as', selector: stmt.selector }],
197
+ body: lowerBlock(stmt.body),
198
+ span: stmt.span,
199
+ };
200
+ // --- Desugaring: at_block → execute [at] ---
201
+ case 'at_block':
202
+ return {
203
+ kind: 'execute',
204
+ subcommands: [{ kind: 'at', selector: stmt.selector }],
205
+ body: lowerBlock(stmt.body),
206
+ span: stmt.span,
207
+ };
208
+ // --- Desugaring: as_at → execute [as, at] ---
209
+ case 'as_at':
210
+ return {
211
+ kind: 'execute',
212
+ subcommands: [
213
+ { kind: 'as', selector: stmt.as_sel },
214
+ { kind: 'at', selector: stmt.at_sel },
215
+ ],
216
+ body: lowerBlock(stmt.body),
217
+ span: stmt.span,
218
+ };
219
+ case 'execute':
220
+ return {
221
+ kind: 'execute',
222
+ subcommands: stmt.subcommands.map(lowerExecuteSubcommand),
223
+ body: lowerBlock(stmt.body),
224
+ span: stmt.span,
225
+ };
226
+ case 'raw':
227
+ return { kind: 'raw', cmd: stmt.cmd, span: stmt.span };
228
+ default: {
229
+ const _exhaustive = stmt;
230
+ throw new Error(`Unknown statement kind: ${_exhaustive.kind}`);
231
+ }
232
+ }
233
+ }
234
+ // ---------------------------------------------------------------------------
235
+ // Execute subcommands (pass-through — same shape)
236
+ // ---------------------------------------------------------------------------
237
+ function lowerExecuteSubcommand(sub) {
238
+ // All subcommand types share the same shape between AST and HIR
239
+ return sub;
240
+ }
241
+ // ---------------------------------------------------------------------------
242
+ // Expressions
243
+ // ---------------------------------------------------------------------------
244
+ /** Map compound assignment operator to its base binary op */
245
+ const COMPOUND_TO_BINOP = {
246
+ '+=': '+',
247
+ '-=': '-',
248
+ '*=': '*',
249
+ '/=': '/',
250
+ '%=': '%',
251
+ };
252
+ function lowerExpr(expr) {
253
+ switch (expr.kind) {
254
+ // --- Pass-through literals ---
255
+ case 'int_lit':
256
+ case 'float_lit':
257
+ case 'byte_lit':
258
+ case 'short_lit':
259
+ case 'long_lit':
260
+ case 'double_lit':
261
+ case 'bool_lit':
262
+ case 'str_lit':
263
+ case 'range_lit':
264
+ case 'rel_coord':
265
+ case 'local_coord':
266
+ case 'mc_name':
267
+ case 'blockpos':
268
+ return expr;
269
+ case 'ident':
270
+ return { kind: 'ident', name: expr.name, span: expr.span };
271
+ case 'selector':
272
+ return { kind: 'selector', raw: expr.raw, isSingle: expr.isSingle, sel: expr.sel, span: expr.span };
273
+ case 'array_lit':
274
+ return { kind: 'array_lit', elements: expr.elements.map(lowerExpr), span: expr.span };
275
+ case 'struct_lit':
276
+ return {
277
+ kind: 'struct_lit',
278
+ fields: expr.fields.map(f => ({ name: f.name, value: lowerExpr(f.value) })),
279
+ span: expr.span,
280
+ };
281
+ case 'str_interp':
282
+ return {
283
+ kind: 'str_interp',
284
+ parts: expr.parts.map(p => typeof p === 'string' ? p : lowerExpr(p)),
285
+ span: expr.span,
286
+ };
287
+ case 'f_string':
288
+ return { kind: 'f_string', parts: expr.parts, span: expr.span };
289
+ // Binary ops — && and || preserved as-is (short-circuit → control flow in MIR)
290
+ case 'binary':
291
+ return {
292
+ kind: 'binary',
293
+ op: expr.op,
294
+ left: lowerExpr(expr.left),
295
+ right: lowerExpr(expr.right),
296
+ span: expr.span,
297
+ };
298
+ case 'unary':
299
+ return { kind: 'unary', op: expr.op, operand: lowerExpr(expr.operand), span: expr.span };
300
+ case 'is_check':
301
+ return { kind: 'is_check', expr: lowerExpr(expr.expr), entityType: expr.entityType, span: expr.span };
302
+ // --- Desugaring: compound assignment → plain assign ---
303
+ case 'assign':
304
+ if (expr.op !== '=') {
305
+ const binOp = COMPOUND_TO_BINOP[expr.op];
306
+ return {
307
+ kind: 'assign',
308
+ target: expr.target,
309
+ value: {
310
+ kind: 'binary',
311
+ op: binOp,
312
+ left: { kind: 'ident', name: expr.target },
313
+ right: lowerExpr(expr.value),
314
+ span: expr.span,
315
+ },
316
+ span: expr.span,
317
+ };
318
+ }
319
+ return { kind: 'assign', target: expr.target, value: lowerExpr(expr.value), span: expr.span };
320
+ // --- Desugaring: compound member_assign → plain member_assign ---
321
+ case 'member_assign':
322
+ if (expr.op !== '=') {
323
+ const binOp = COMPOUND_TO_BINOP[expr.op];
324
+ const obj = lowerExpr(expr.obj);
325
+ return {
326
+ kind: 'member_assign',
327
+ obj,
328
+ field: expr.field,
329
+ value: {
330
+ kind: 'binary',
331
+ op: binOp,
332
+ left: { kind: 'member', obj, field: expr.field },
333
+ right: lowerExpr(expr.value),
334
+ span: expr.span,
335
+ },
336
+ span: expr.span,
337
+ };
338
+ }
339
+ return {
340
+ kind: 'member_assign',
341
+ obj: lowerExpr(expr.obj),
342
+ field: expr.field,
343
+ value: lowerExpr(expr.value),
344
+ span: expr.span,
345
+ };
346
+ case 'member':
347
+ return { kind: 'member', obj: lowerExpr(expr.obj), field: expr.field, span: expr.span };
348
+ case 'index':
349
+ return { kind: 'index', obj: lowerExpr(expr.obj), index: lowerExpr(expr.index), span: expr.span };
350
+ case 'call':
351
+ return { kind: 'call', fn: expr.fn, args: expr.args.map(lowerExpr), span: expr.span };
352
+ case 'invoke':
353
+ return { kind: 'invoke', callee: lowerExpr(expr.callee), args: expr.args.map(lowerExpr), span: expr.span };
354
+ case 'static_call':
355
+ return {
356
+ kind: 'static_call',
357
+ type: expr.type,
358
+ method: expr.method,
359
+ args: expr.args.map(lowerExpr),
360
+ span: expr.span,
361
+ };
362
+ case 'lambda': {
363
+ const body = Array.isArray(expr.body) ? lowerBlock(expr.body) : lowerExpr(expr.body);
364
+ return {
365
+ kind: 'lambda',
366
+ params: expr.params,
367
+ returnType: expr.returnType,
368
+ body,
369
+ span: expr.span,
370
+ };
371
+ }
372
+ default: {
373
+ const _exhaustive = expr;
374
+ throw new Error(`Unknown expression kind: ${_exhaustive.kind}`);
375
+ }
376
+ }
377
+ }
378
+ //# sourceMappingURL=lower.js.map