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,22 @@
1
+ /**
2
+ * Macro function detection — pre-scans HIR to find parameters used in
3
+ * builtin call positions (coordinates, entity types, etc.)
4
+ *
5
+ * A function becomes a "macro function" when one of its params appears
6
+ * in a position that requires literal substitution in the MC command
7
+ * (e.g. summon coords, particle coords, setblock coords, local/relative
8
+ * coords like ^px or ~height).
9
+ */
10
+ import type { HIRModule } from '../hir/types';
11
+ /** Builtins whose arguments appear literally in MC commands */
12
+ export declare const BUILTIN_SET: Set<string>;
13
+ export interface MacroFunctionInfo {
14
+ macroParams: Set<string>;
15
+ /** param name → param type name (for NBT scale inference) */
16
+ paramTypes: Map<string, string>;
17
+ }
18
+ /**
19
+ * Pre-scan HIR functions to detect which params need macro treatment.
20
+ * Returns a map: function name → MacroFunctionInfo.
21
+ */
22
+ export declare function detectMacroFunctions(hir: HIRModule): Map<string, MacroFunctionInfo>;
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ /**
3
+ * Macro function detection — pre-scans HIR to find parameters used in
4
+ * builtin call positions (coordinates, entity types, etc.)
5
+ *
6
+ * A function becomes a "macro function" when one of its params appears
7
+ * in a position that requires literal substitution in the MC command
8
+ * (e.g. summon coords, particle coords, setblock coords, local/relative
9
+ * coords like ^px or ~height).
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.BUILTIN_SET = void 0;
13
+ exports.detectMacroFunctions = detectMacroFunctions;
14
+ // ---------------------------------------------------------------------------
15
+ // Known builtins that emit MC commands with inline arguments
16
+ // ---------------------------------------------------------------------------
17
+ /** Builtins whose arguments appear literally in MC commands */
18
+ exports.BUILTIN_SET = new Set([
19
+ 'say', 'tell', 'tellraw', 'title', 'actionbar', 'subtitle', 'title_times',
20
+ 'announce', 'give', 'kill', 'effect', 'effect_clear',
21
+ 'summon', 'particle', 'playsound', 'clear', 'weather',
22
+ 'time_set', 'time_add', 'gamerule', 'tag_add', 'tag_remove',
23
+ 'kick', 'setblock', 'fill', 'clone', 'difficulty', 'xp_add', 'xp_set',
24
+ ]);
25
+ /**
26
+ * Pre-scan HIR functions to detect which params need macro treatment.
27
+ * Returns a map: function name → MacroFunctionInfo.
28
+ */
29
+ function detectMacroFunctions(hir) {
30
+ const result = new Map();
31
+ for (const fn of hir.functions) {
32
+ const paramNames = new Set(fn.params.map(p => p.name));
33
+ const macroParams = new Set();
34
+ scanBlock(fn.body, paramNames, macroParams);
35
+ if (macroParams.size > 0) {
36
+ const paramTypes = new Map();
37
+ for (const p of fn.params) {
38
+ const typeName = p.type?.kind === 'named' ? p.type.name : 'int';
39
+ paramTypes.set(p.name, typeName);
40
+ }
41
+ result.set(fn.name, { macroParams, paramTypes });
42
+ }
43
+ }
44
+ for (const ib of hir.implBlocks) {
45
+ for (const m of ib.methods) {
46
+ const paramNames = new Set(m.params.map(p => p.name));
47
+ const macroParams = new Set();
48
+ scanBlock(m.body, paramNames, macroParams);
49
+ if (macroParams.size > 0) {
50
+ const paramTypes = new Map();
51
+ for (const p of m.params) {
52
+ const typeName = p.type?.kind === 'named' ? p.type.name : 'int';
53
+ paramTypes.set(p.name, typeName);
54
+ }
55
+ result.set(`${ib.typeName}::${m.name}`, { macroParams, paramTypes });
56
+ }
57
+ }
58
+ }
59
+ return result;
60
+ }
61
+ // ---------------------------------------------------------------------------
62
+ // HIR scanning
63
+ // ---------------------------------------------------------------------------
64
+ function scanBlock(stmts, paramNames, macroParams) {
65
+ for (const stmt of stmts)
66
+ scanStmt(stmt, paramNames, macroParams);
67
+ }
68
+ function scanStmt(stmt, paramNames, macroParams) {
69
+ switch (stmt.kind) {
70
+ case 'expr':
71
+ scanExpr(stmt.expr, paramNames, macroParams);
72
+ break;
73
+ case 'let':
74
+ scanExpr(stmt.init, paramNames, macroParams);
75
+ break;
76
+ case 'return':
77
+ if (stmt.value)
78
+ scanExpr(stmt.value, paramNames, macroParams);
79
+ break;
80
+ case 'if':
81
+ scanExpr(stmt.cond, paramNames, macroParams);
82
+ scanBlock(stmt.then, paramNames, macroParams);
83
+ if (stmt.else_)
84
+ scanBlock(stmt.else_, paramNames, macroParams);
85
+ break;
86
+ case 'while':
87
+ scanExpr(stmt.cond, paramNames, macroParams);
88
+ scanBlock(stmt.body, paramNames, macroParams);
89
+ if (stmt.step)
90
+ scanBlock(stmt.step, paramNames, macroParams);
91
+ break;
92
+ case 'foreach':
93
+ scanBlock(stmt.body, paramNames, macroParams);
94
+ break;
95
+ case 'match':
96
+ scanExpr(stmt.expr, paramNames, macroParams);
97
+ for (const arm of stmt.arms)
98
+ scanBlock(arm.body, paramNames, macroParams);
99
+ break;
100
+ case 'execute':
101
+ scanBlock(stmt.body, paramNames, macroParams);
102
+ break;
103
+ case 'raw': break;
104
+ }
105
+ }
106
+ function scanExpr(expr, paramNames, macroParams) {
107
+ if (expr.kind === 'call' && exports.BUILTIN_SET.has(expr.fn)) {
108
+ // Check if any argument is a param identifier or a coord with a param variable
109
+ for (const arg of expr.args) {
110
+ checkMacroArg(arg, paramNames, macroParams);
111
+ }
112
+ // Recurse into args for nested expressions
113
+ for (const arg of expr.args)
114
+ scanExpr(arg, paramNames, macroParams);
115
+ return;
116
+ }
117
+ // Recurse into sub-expressions
118
+ switch (expr.kind) {
119
+ case 'call':
120
+ for (const arg of expr.args)
121
+ scanExpr(arg, paramNames, macroParams);
122
+ break;
123
+ case 'invoke':
124
+ scanExpr(expr.callee, paramNames, macroParams);
125
+ for (const arg of expr.args)
126
+ scanExpr(arg, paramNames, macroParams);
127
+ break;
128
+ case 'binary':
129
+ scanExpr(expr.left, paramNames, macroParams);
130
+ scanExpr(expr.right, paramNames, macroParams);
131
+ break;
132
+ case 'unary':
133
+ scanExpr(expr.operand, paramNames, macroParams);
134
+ break;
135
+ case 'assign':
136
+ scanExpr(expr.value, paramNames, macroParams);
137
+ break;
138
+ case 'member_assign':
139
+ scanExpr(expr.obj, paramNames, macroParams);
140
+ scanExpr(expr.value, paramNames, macroParams);
141
+ break;
142
+ case 'member':
143
+ scanExpr(expr.obj, paramNames, macroParams);
144
+ break;
145
+ case 'index':
146
+ scanExpr(expr.obj, paramNames, macroParams);
147
+ scanExpr(expr.index, paramNames, macroParams);
148
+ break;
149
+ case 'static_call':
150
+ for (const arg of expr.args)
151
+ scanExpr(arg, paramNames, macroParams);
152
+ break;
153
+ }
154
+ }
155
+ /** Check if a single argument expression references a function parameter in a macro position */
156
+ function checkMacroArg(expr, paramNames, macroParams) {
157
+ if (expr.kind === 'ident' && paramNames.has(expr.name)) {
158
+ macroParams.add(expr.name);
159
+ }
160
+ else if (expr.kind === 'local_coord' || expr.kind === 'rel_coord') {
161
+ // ^varname or ~varname — extract the variable part
162
+ const rest = expr.value.slice(1);
163
+ if (rest && /^[a-zA-Z_]\w*$/.test(rest) && paramNames.has(rest)) {
164
+ macroParams.add(rest);
165
+ }
166
+ }
167
+ }
168
+ //# sourceMappingURL=macro.js.map
@@ -0,0 +1,183 @@
1
+ /**
2
+ * MIR (Mid-level IR) Types — Stage 3 of the RedScript compiler pipeline.
3
+ *
4
+ * MIR is a 3-address, explicit-CFG representation with versioned temporaries.
5
+ * Every instruction produces at most one result into a fresh temporary.
6
+ *
7
+ * Spec: docs/compiler-pipeline-redesign.md § "MIR Instruction Set"
8
+ */
9
+ export type Temp = string;
10
+ export type Operand = {
11
+ kind: 'temp';
12
+ name: Temp;
13
+ } | {
14
+ kind: 'const';
15
+ value: number;
16
+ };
17
+ export type BlockId = string;
18
+ export type CmpOp = 'eq' | 'ne' | 'lt' | 'le' | 'gt' | 'ge';
19
+ export type NBTType = 'int' | 'double' | 'float' | 'long' | 'short' | 'byte';
20
+ export type ExecuteSubcmd = {
21
+ kind: 'as';
22
+ selector: string;
23
+ } | {
24
+ kind: 'at';
25
+ selector: string;
26
+ } | {
27
+ kind: 'at_self';
28
+ } | {
29
+ kind: 'positioned';
30
+ x: string;
31
+ y: string;
32
+ z: string;
33
+ } | {
34
+ kind: 'rotated';
35
+ yaw: string;
36
+ pitch: string;
37
+ } | {
38
+ kind: 'in';
39
+ dimension: string;
40
+ } | {
41
+ kind: 'anchored';
42
+ anchor: 'eyes' | 'feet';
43
+ } | {
44
+ kind: 'if_score';
45
+ a: string;
46
+ op: CmpOp;
47
+ b: string;
48
+ } | {
49
+ kind: 'unless_score';
50
+ a: string;
51
+ op: CmpOp;
52
+ b: string;
53
+ } | {
54
+ kind: 'if_matches';
55
+ score: string;
56
+ range: string;
57
+ } | {
58
+ kind: 'unless_matches';
59
+ score: string;
60
+ range: string;
61
+ };
62
+ export type MIRInstr = {
63
+ kind: 'const';
64
+ dst: Temp;
65
+ value: number;
66
+ } | {
67
+ kind: 'copy';
68
+ dst: Temp;
69
+ src: Operand;
70
+ } | {
71
+ kind: 'add';
72
+ dst: Temp;
73
+ a: Operand;
74
+ b: Operand;
75
+ } | {
76
+ kind: 'sub';
77
+ dst: Temp;
78
+ a: Operand;
79
+ b: Operand;
80
+ } | {
81
+ kind: 'mul';
82
+ dst: Temp;
83
+ a: Operand;
84
+ b: Operand;
85
+ } | {
86
+ kind: 'div';
87
+ dst: Temp;
88
+ a: Operand;
89
+ b: Operand;
90
+ } | {
91
+ kind: 'mod';
92
+ dst: Temp;
93
+ a: Operand;
94
+ b: Operand;
95
+ } | {
96
+ kind: 'neg';
97
+ dst: Temp;
98
+ src: Operand;
99
+ } | {
100
+ kind: 'cmp';
101
+ dst: Temp;
102
+ op: CmpOp;
103
+ a: Operand;
104
+ b: Operand;
105
+ } | {
106
+ kind: 'and';
107
+ dst: Temp;
108
+ a: Operand;
109
+ b: Operand;
110
+ } | {
111
+ kind: 'or';
112
+ dst: Temp;
113
+ a: Operand;
114
+ b: Operand;
115
+ } | {
116
+ kind: 'not';
117
+ dst: Temp;
118
+ src: Operand;
119
+ } | {
120
+ kind: 'nbt_read';
121
+ dst: Temp;
122
+ ns: string;
123
+ path: string;
124
+ scale: number;
125
+ } | {
126
+ kind: 'nbt_write';
127
+ ns: string;
128
+ path: string;
129
+ type: NBTType;
130
+ scale: number;
131
+ src: Operand;
132
+ } | {
133
+ kind: 'call';
134
+ dst: Temp | null;
135
+ fn: string;
136
+ args: Operand[];
137
+ } | {
138
+ kind: 'call_macro';
139
+ dst: Temp | null;
140
+ fn: string;
141
+ args: {
142
+ name: string;
143
+ value: Operand;
144
+ type: NBTType;
145
+ scale: number;
146
+ }[];
147
+ } | {
148
+ kind: 'call_context';
149
+ fn: string;
150
+ subcommands: ExecuteSubcmd[];
151
+ } | {
152
+ kind: 'jump';
153
+ target: BlockId;
154
+ } | {
155
+ kind: 'branch';
156
+ cond: Operand;
157
+ then: BlockId;
158
+ else: BlockId;
159
+ } | {
160
+ kind: 'return';
161
+ value: Operand | null;
162
+ };
163
+ export interface MIRBlock {
164
+ id: BlockId;
165
+ instrs: MIRInstr[];
166
+ term: MIRInstr;
167
+ preds: BlockId[];
168
+ }
169
+ export interface MIRFunction {
170
+ name: string;
171
+ params: {
172
+ name: Temp;
173
+ isMacroParam: boolean;
174
+ }[];
175
+ blocks: MIRBlock[];
176
+ entry: BlockId;
177
+ isMacro: boolean;
178
+ }
179
+ export interface MIRModule {
180
+ functions: MIRFunction[];
181
+ namespace: string;
182
+ objective: string;
183
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ /**
3
+ * MIR (Mid-level IR) Types — Stage 3 of the RedScript compiler pipeline.
4
+ *
5
+ * MIR is a 3-address, explicit-CFG representation with versioned temporaries.
6
+ * Every instruction produces at most one result into a fresh temporary.
7
+ *
8
+ * Spec: docs/compiler-pipeline-redesign.md § "MIR Instruction Set"
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * MIR Verifier — validates structural invariants of MIR modules.
3
+ *
4
+ * Checks:
5
+ * 1. Every block ends with exactly one terminator (jump | branch | return)
6
+ * 2. Every temp used is defined before use (in the block or as a param)
7
+ * 3. No unreachable blocks (all blocks reachable from entry)
8
+ * 4. Branch/jump targets must exist in the function
9
+ */
10
+ import type { MIRModule } from './types';
11
+ export interface VerifyError {
12
+ fn: string;
13
+ block?: string;
14
+ message: string;
15
+ }
16
+ export declare function verifyMIR(module: MIRModule): VerifyError[];
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ /**
3
+ * MIR Verifier — validates structural invariants of MIR modules.
4
+ *
5
+ * Checks:
6
+ * 1. Every block ends with exactly one terminator (jump | branch | return)
7
+ * 2. Every temp used is defined before use (in the block or as a param)
8
+ * 3. No unreachable blocks (all blocks reachable from entry)
9
+ * 4. Branch/jump targets must exist in the function
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.verifyMIR = verifyMIR;
13
+ function verifyMIR(module) {
14
+ const errors = [];
15
+ for (const fn of module.functions) {
16
+ errors.push(...verifyFunction(fn));
17
+ }
18
+ return errors;
19
+ }
20
+ function verifyFunction(fn) {
21
+ const errors = [];
22
+ const blockIds = new Set(fn.blocks.map(b => b.id));
23
+ // 1. Check terminators
24
+ for (const block of fn.blocks) {
25
+ if (!isTerminator(block.term)) {
26
+ errors.push({
27
+ fn: fn.name,
28
+ block: block.id,
29
+ message: `block '${block.id}' does not end with a terminator (found '${block.term.kind}')`,
30
+ });
31
+ }
32
+ // Check that no non-terminator instruction is a terminator
33
+ for (const instr of block.instrs) {
34
+ if (isTerminator(instr)) {
35
+ errors.push({
36
+ fn: fn.name,
37
+ block: block.id,
38
+ message: `block '${block.id}' has terminator '${instr.kind}' in non-terminal position`,
39
+ });
40
+ }
41
+ }
42
+ }
43
+ // 2. Check that branch/jump targets exist
44
+ for (const block of fn.blocks) {
45
+ const targets = getTermTargets(block.term);
46
+ for (const target of targets) {
47
+ if (!blockIds.has(target)) {
48
+ errors.push({
49
+ fn: fn.name,
50
+ block: block.id,
51
+ message: `block '${block.id}' references non-existent target '${target}'`,
52
+ });
53
+ }
54
+ }
55
+ }
56
+ // 3. Check reachability from entry
57
+ const reachable = new Set();
58
+ const entryBlock = fn.blocks.find(b => b.id === fn.entry);
59
+ if (!entryBlock) {
60
+ errors.push({
61
+ fn: fn.name,
62
+ message: `entry block '${fn.entry}' not found`,
63
+ });
64
+ }
65
+ else {
66
+ // BFS from entry
67
+ const queue = [fn.entry];
68
+ while (queue.length > 0) {
69
+ const id = queue.shift();
70
+ if (reachable.has(id))
71
+ continue;
72
+ reachable.add(id);
73
+ const block = fn.blocks.find(b => b.id === id);
74
+ if (block) {
75
+ for (const target of getTermTargets(block.term)) {
76
+ if (!reachable.has(target)) {
77
+ queue.push(target);
78
+ }
79
+ }
80
+ }
81
+ }
82
+ for (const block of fn.blocks) {
83
+ if (!reachable.has(block.id)) {
84
+ errors.push({
85
+ fn: fn.name,
86
+ block: block.id,
87
+ message: `block '${block.id}' is unreachable from entry`,
88
+ });
89
+ }
90
+ }
91
+ }
92
+ // 4. Check use-before-def for temporaries
93
+ // Collect all defined temps: params + all dst fields in instructions
94
+ const allDefs = new Set();
95
+ for (const p of fn.params)
96
+ allDefs.add(p.name);
97
+ for (const block of fn.blocks) {
98
+ for (const instr of block.instrs) {
99
+ const dst = getDst(instr);
100
+ if (dst)
101
+ allDefs.add(dst);
102
+ }
103
+ const termDst = getDst(block.term);
104
+ if (termDst)
105
+ allDefs.add(termDst);
106
+ }
107
+ // Check that every temp used in an operand is in allDefs
108
+ for (const block of fn.blocks) {
109
+ for (const instr of block.instrs) {
110
+ for (const used of getUsedTemps(instr)) {
111
+ if (!allDefs.has(used)) {
112
+ errors.push({
113
+ fn: fn.name,
114
+ block: block.id,
115
+ message: `temp '${used}' used but never defined`,
116
+ });
117
+ }
118
+ }
119
+ }
120
+ for (const used of getUsedTemps(block.term)) {
121
+ if (!allDefs.has(used)) {
122
+ errors.push({
123
+ fn: fn.name,
124
+ block: block.id,
125
+ message: `temp '${used}' used in terminator but never defined`,
126
+ });
127
+ }
128
+ }
129
+ }
130
+ return errors;
131
+ }
132
+ function isTerminator(instr) {
133
+ return instr.kind === 'jump' || instr.kind === 'branch' || instr.kind === 'return';
134
+ }
135
+ function getTermTargets(term) {
136
+ switch (term.kind) {
137
+ case 'jump': return [term.target];
138
+ case 'branch': return [term.then, term.else];
139
+ case 'return': return [];
140
+ default: return [];
141
+ }
142
+ }
143
+ function getDst(instr) {
144
+ switch (instr.kind) {
145
+ case 'const':
146
+ case 'copy':
147
+ case 'add':
148
+ case 'sub':
149
+ case 'mul':
150
+ case 'div':
151
+ case 'mod':
152
+ case 'neg':
153
+ case 'cmp':
154
+ case 'and':
155
+ case 'or':
156
+ case 'not':
157
+ case 'nbt_read':
158
+ return instr.dst;
159
+ case 'call':
160
+ case 'call_macro':
161
+ return instr.dst;
162
+ default:
163
+ return null;
164
+ }
165
+ }
166
+ function getOperandTemps(op) {
167
+ return op.kind === 'temp' ? [op.name] : [];
168
+ }
169
+ function getUsedTemps(instr) {
170
+ const temps = [];
171
+ switch (instr.kind) {
172
+ case 'const':
173
+ break;
174
+ case 'copy':
175
+ case 'neg':
176
+ case 'not':
177
+ temps.push(...getOperandTemps(instr.src));
178
+ break;
179
+ case 'add':
180
+ case 'sub':
181
+ case 'mul':
182
+ case 'div':
183
+ case 'mod':
184
+ case 'cmp':
185
+ case 'and':
186
+ case 'or':
187
+ temps.push(...getOperandTemps(instr.a), ...getOperandTemps(instr.b));
188
+ break;
189
+ case 'nbt_read':
190
+ break;
191
+ case 'nbt_write':
192
+ temps.push(...getOperandTemps(instr.src));
193
+ break;
194
+ case 'call':
195
+ for (const arg of instr.args)
196
+ temps.push(...getOperandTemps(arg));
197
+ break;
198
+ case 'call_macro':
199
+ for (const arg of instr.args)
200
+ temps.push(...getOperandTemps(arg.value));
201
+ break;
202
+ case 'call_context':
203
+ break;
204
+ case 'jump':
205
+ break;
206
+ case 'branch':
207
+ temps.push(...getOperandTemps(instr.cond));
208
+ break;
209
+ case 'return':
210
+ if (instr.value)
211
+ temps.push(...getOperandTemps(instr.value));
212
+ break;
213
+ }
214
+ return temps;
215
+ }
216
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Block Merging — MIR optimization pass.
3
+ *
4
+ * Merges a block B into its sole predecessor A when:
5
+ * - A ends with an unconditional jump to B
6
+ * - B has exactly one predecessor (A)
7
+ * - B is not the entry block
8
+ *
9
+ * The merged block keeps A's id and combines A's instrs + B's instrs + B's terminator.
10
+ */
11
+ import type { MIRFunction } from '../mir/types';
12
+ export declare function blockMerge(fn: MIRFunction): MIRFunction;