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,322 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MCCommandValidator = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const FUNCTION_ID_RE = /^[0-9a-z_.-]+:[0-9a-z_./-]+$/i;
39
+ const INTEGER_RE = /^-?\d+$/;
40
+ const SCORE_RANGE_RE = /^-?\d+\.\.$|^\.\.-?\d+$|^-?\d+\.\.-?\d+$|^-?\d+$/;
41
+ const COMMENT_PREFIXES = [
42
+ '# RedScript runtime init',
43
+ '# block:',
44
+ '# RedScript tick dispatcher',
45
+ ];
46
+ const SCOREBOARD_PLAYER_ACTIONS = new Set(['set', 'add', 'remove', 'get', 'operation', 'enable']);
47
+ const SCOREBOARD_OPERATIONS = new Set(['=', '+=', '-=', '*=', '/=', '%=', '<', '>', '><']);
48
+ class MCCommandValidator {
49
+ constructor(commandsPath) {
50
+ const parsed = JSON.parse(fs.readFileSync(commandsPath, 'utf-8'));
51
+ this.root = parsed.root;
52
+ this.rootChildren = parsed.root.children ?? [];
53
+ }
54
+ validate(line) {
55
+ const trimmed = line.trim();
56
+ if (!trimmed || trimmed.startsWith('#') || COMMENT_PREFIXES.some(prefix => trimmed.startsWith(prefix))) {
57
+ return { valid: true };
58
+ }
59
+ const tokens = tokenize(trimmed);
60
+ if (tokens.length === 0) {
61
+ return { valid: true };
62
+ }
63
+ if (!this.hasRootCommand(tokens[0])) {
64
+ return { valid: false, error: `Unknown root command: ${tokens[0]}` };
65
+ }
66
+ switch (tokens[0]) {
67
+ case 'execute':
68
+ return this.validateExecute(tokens);
69
+ case 'scoreboard':
70
+ return this.validateScoreboard(tokens);
71
+ case 'function':
72
+ return this.validateFunction(tokens);
73
+ case 'data':
74
+ return this.validateData(tokens);
75
+ case 'return':
76
+ return this.validateReturn(tokens);
77
+ default:
78
+ return this.validateAgainstTree(tokens);
79
+ }
80
+ }
81
+ hasRootCommand(command) {
82
+ return this.rootChildren.some(child => child.type === 'literal' && child.name === command);
83
+ }
84
+ validateExecute(tokens) {
85
+ const runIndex = tokens.indexOf('run');
86
+ if (runIndex === 1 || runIndex === tokens.length - 1) {
87
+ return { valid: false, error: 'Malformed execute run clause' };
88
+ }
89
+ if (runIndex !== -1) {
90
+ const chainResult = this.validateAgainstTree(tokens.slice(0, runIndex));
91
+ if (!chainResult.valid) {
92
+ return chainResult;
93
+ }
94
+ return this.validate(tokens.slice(runIndex + 1).join(' '));
95
+ }
96
+ return this.validateAgainstTree(tokens);
97
+ }
98
+ validateScoreboard(tokens) {
99
+ if (tokens[1] === 'objectives' && tokens[2] === 'add') {
100
+ if (tokens.length < 5) {
101
+ return { valid: false, error: 'scoreboard objectives add requires name and criteria' };
102
+ }
103
+ return this.validateAgainstTree(tokens);
104
+ }
105
+ if (tokens[1] !== 'players' || !SCOREBOARD_PLAYER_ACTIONS.has(tokens[2] ?? '')) {
106
+ return this.validateAgainstTree(tokens);
107
+ }
108
+ const action = tokens[2];
109
+ if (action === 'enable') {
110
+ if (tokens.length !== 5) {
111
+ return { valid: false, error: 'scoreboard players enable requires target and objective' };
112
+ }
113
+ return this.validateAgainstTree(tokens);
114
+ }
115
+ if (action === 'get') {
116
+ if (tokens.length !== 5) {
117
+ return { valid: false, error: 'scoreboard players get requires target and objective' };
118
+ }
119
+ return this.validateAgainstTree(tokens);
120
+ }
121
+ if (action === 'operation') {
122
+ if (tokens.length !== 8) {
123
+ return { valid: false, error: 'scoreboard players operation requires 5 operands' };
124
+ }
125
+ if (!SCOREBOARD_OPERATIONS.has(tokens[5])) {
126
+ return { valid: false, error: `Unknown scoreboard operation: ${tokens[5]}` };
127
+ }
128
+ return this.validateAgainstTree(tokens);
129
+ }
130
+ if (tokens.length !== 6) {
131
+ return { valid: false, error: `scoreboard players ${action} requires target, objective, and value` };
132
+ }
133
+ if (!INTEGER_RE.test(tokens[5])) {
134
+ return { valid: false, error: `Expected integer value, got: ${tokens[5]}` };
135
+ }
136
+ return this.validateAgainstTree(tokens);
137
+ }
138
+ validateFunction(tokens) {
139
+ if (tokens.length !== 2 || !FUNCTION_ID_RE.test(tokens[1])) {
140
+ return { valid: false, error: 'function requires a namespaced function id' };
141
+ }
142
+ return this.validateAgainstTree(tokens);
143
+ }
144
+ validateData(tokens) {
145
+ if (tokens.length < 5) {
146
+ return { valid: false, error: 'data command is incomplete' };
147
+ }
148
+ const action = tokens[1];
149
+ if (!['get', 'modify', 'merge', 'remove'].includes(action)) {
150
+ return this.validateAgainstTree(tokens);
151
+ }
152
+ const targetType = tokens[2];
153
+ if (!['storage', 'entity', 'block'].includes(targetType)) {
154
+ return { valid: false, error: `Unsupported data target: ${targetType}` };
155
+ }
156
+ if (action === 'get') {
157
+ if (tokens.length < 5) {
158
+ return { valid: false, error: 'data get requires target and path' };
159
+ }
160
+ if (tokens[5] && !isNumberish(tokens[5])) {
161
+ return { valid: false, error: `Invalid data get scale: ${tokens[5]}` };
162
+ }
163
+ return this.validateAgainstTree(tokens);
164
+ }
165
+ if (action === 'modify') {
166
+ if (tokens.length < 7) {
167
+ return { valid: false, error: 'data modify is incomplete' };
168
+ }
169
+ if (!['set', 'append', 'prepend', 'insert', 'merge'].includes(tokens[5])) {
170
+ return { valid: false, error: `Unsupported data modify mode: ${tokens[5]}` };
171
+ }
172
+ return this.validateAgainstTree(tokens);
173
+ }
174
+ return this.validateAgainstTree(tokens);
175
+ }
176
+ validateReturn(tokens) {
177
+ if (tokens.length < 2) {
178
+ return { valid: false, error: 'return requires a value or run clause' };
179
+ }
180
+ if (tokens[1] === 'run') {
181
+ if (tokens.length < 3) {
182
+ return { valid: false, error: 'return run requires an inner command' };
183
+ }
184
+ return this.validate(tokens.slice(2).join(' '));
185
+ }
186
+ if (!INTEGER_RE.test(tokens[1])) {
187
+ return { valid: false, error: `Invalid return value: ${tokens[1]}` };
188
+ }
189
+ return this.validateAgainstTree(tokens);
190
+ }
191
+ validateAgainstTree(tokens) {
192
+ const memo = new Map();
193
+ const isValid = walk(this.root, tokens, 0, memo, this.rootChildren);
194
+ return isValid
195
+ ? { valid: true }
196
+ : { valid: false, error: `Command does not match Brigadier tree: ${tokens.join(' ')}` };
197
+ }
198
+ }
199
+ exports.MCCommandValidator = MCCommandValidator;
200
+ function walk(node, tokens, index, memo, rootChildren) {
201
+ const key = `${node.name ?? '<root>'}:${index}`;
202
+ const cached = memo.get(key);
203
+ if (cached !== undefined) {
204
+ return cached;
205
+ }
206
+ if (index === tokens.length) {
207
+ const done = node.executable === true || (node.children ?? []).length === 0;
208
+ memo.set(key, done);
209
+ return done;
210
+ }
211
+ const children = node.children ?? [];
212
+ for (const child of children) {
213
+ if (child.type === 'literal') {
214
+ if (child.name === tokens[index] && walk(child, tokens, index + 1, memo, rootChildren)) {
215
+ memo.set(key, true);
216
+ return true;
217
+ }
218
+ continue;
219
+ }
220
+ if (child.type !== 'argument') {
221
+ continue;
222
+ }
223
+ const parser = child.parser?.parser;
224
+ const modifier = child.parser?.modifier?.type;
225
+ if (parserConsumesRest(parser, modifier)) {
226
+ const done = child.executable === true || (child.children ?? []).length === 0;
227
+ if (done) {
228
+ memo.set(key, true);
229
+ return true;
230
+ }
231
+ }
232
+ const width = parserTokenWidth(parser, tokens, index);
233
+ if (width === null) {
234
+ continue;
235
+ }
236
+ const nextIndex = index + width;
237
+ if (walk(child, tokens, nextIndex, memo, rootChildren)) {
238
+ memo.set(key, true);
239
+ return true;
240
+ }
241
+ for (const redirect of child.redirects ?? []) {
242
+ const target = rootChildren.find(candidate => candidate.name === redirect);
243
+ if (target && walk(target, tokens, nextIndex, memo, rootChildren)) {
244
+ memo.set(key, true);
245
+ return true;
246
+ }
247
+ }
248
+ }
249
+ memo.set(key, false);
250
+ return false;
251
+ }
252
+ function parserConsumesRest(parser, modifier) {
253
+ return ((parser === 'brigadier:string' && modifier === 'greedy') ||
254
+ parser === 'minecraft:message');
255
+ }
256
+ function parserTokenWidth(parser, tokens, index) {
257
+ switch (parser) {
258
+ case 'minecraft:vec3':
259
+ case 'minecraft:block_pos':
260
+ return index + 3 <= tokens.length ? 3 : null;
261
+ case 'minecraft:vec2':
262
+ case 'minecraft:column_pos':
263
+ case 'minecraft:rotation':
264
+ return index + 2 <= tokens.length ? 2 : null;
265
+ default:
266
+ return index < tokens.length ? 1 : null;
267
+ }
268
+ }
269
+ function tokenize(line) {
270
+ const tokens = [];
271
+ let current = '';
272
+ let quote = null;
273
+ let escape = false;
274
+ let bracketDepth = 0;
275
+ let braceDepth = 0;
276
+ for (const char of line) {
277
+ if (escape) {
278
+ current += char;
279
+ escape = false;
280
+ continue;
281
+ }
282
+ if (quote) {
283
+ current += char;
284
+ if (char === '\\') {
285
+ escape = true;
286
+ }
287
+ else if (char === quote) {
288
+ quote = null;
289
+ }
290
+ continue;
291
+ }
292
+ if (char === '"' || char === '\'') {
293
+ quote = char;
294
+ current += char;
295
+ continue;
296
+ }
297
+ if (char === '[')
298
+ bracketDepth += 1;
299
+ if (char === ']')
300
+ bracketDepth = Math.max(0, bracketDepth - 1);
301
+ if (char === '{')
302
+ braceDepth += 1;
303
+ if (char === '}')
304
+ braceDepth = Math.max(0, braceDepth - 1);
305
+ if (/\s/.test(char) && bracketDepth === 0 && braceDepth === 0) {
306
+ if (current) {
307
+ tokens.push(current);
308
+ current = '';
309
+ }
310
+ continue;
311
+ }
312
+ current += char;
313
+ }
314
+ if (current) {
315
+ tokens.push(current);
316
+ }
317
+ return tokens;
318
+ }
319
+ function isNumberish(value) {
320
+ return /^-?\d+(\.\d+)?$/.test(value) || SCORE_RANGE_RE.test(value);
321
+ }
322
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,86 @@
1
+ export declare const enum TagType {
2
+ End = 0,
3
+ Byte = 1,
4
+ Short = 2,
5
+ Int = 3,
6
+ Long = 4,
7
+ Float = 5,
8
+ Double = 6,
9
+ ByteArray = 7,
10
+ String = 8,
11
+ List = 9,
12
+ Compound = 10,
13
+ IntArray = 11,
14
+ LongArray = 12
15
+ }
16
+ export type EndTag = {
17
+ type: TagType.End;
18
+ };
19
+ export type ByteTag = {
20
+ type: TagType.Byte;
21
+ value: number;
22
+ };
23
+ export type ShortTag = {
24
+ type: TagType.Short;
25
+ value: number;
26
+ };
27
+ export type IntTag = {
28
+ type: TagType.Int;
29
+ value: number;
30
+ };
31
+ export type LongTag = {
32
+ type: TagType.Long;
33
+ value: bigint;
34
+ };
35
+ export type FloatTag = {
36
+ type: TagType.Float;
37
+ value: number;
38
+ };
39
+ export type DoubleTag = {
40
+ type: TagType.Double;
41
+ value: number;
42
+ };
43
+ export type ByteArrayTag = {
44
+ type: TagType.ByteArray;
45
+ value: Int8Array;
46
+ };
47
+ export type StringTag = {
48
+ type: TagType.String;
49
+ value: string;
50
+ };
51
+ export type ListTag = {
52
+ type: TagType.List;
53
+ elementType: TagType;
54
+ items: NbtTag[];
55
+ };
56
+ export type CompoundTag = {
57
+ type: TagType.Compound;
58
+ entries: Map<string, NbtTag>;
59
+ };
60
+ export type IntArrayTag = {
61
+ type: TagType.IntArray;
62
+ value: Int32Array;
63
+ };
64
+ export type LongArrayTag = {
65
+ type: TagType.LongArray;
66
+ value: BigInt64Array;
67
+ };
68
+ export type NbtTag = EndTag | ByteTag | ShortTag | IntTag | LongTag | FloatTag | DoubleTag | ByteArrayTag | StringTag | ListTag | CompoundTag | IntArrayTag | LongArrayTag;
69
+ export declare function writeNbt(tag: NbtTag, name: string): Buffer;
70
+ export declare function readNbt(buffer: Buffer): {
71
+ name: string;
72
+ tag: NbtTag;
73
+ };
74
+ export declare const nbt: {
75
+ byte: (value: number) => ByteTag;
76
+ short: (value: number) => ShortTag;
77
+ int: (value: number) => IntTag;
78
+ long: (value: bigint) => LongTag;
79
+ float: (value: number) => FloatTag;
80
+ double: (value: number) => DoubleTag;
81
+ string: (value: string) => StringTag;
82
+ list: (elementType: TagType, items: NbtTag[]) => ListTag;
83
+ compound: (entries: Record<string, NbtTag>) => CompoundTag;
84
+ intArray: (values: number[]) => IntArrayTag;
85
+ byteArray: (values: number[]) => ByteArrayTag;
86
+ };
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.nbt = void 0;
4
+ exports.writeNbt = writeNbt;
5
+ exports.readNbt = readNbt;
6
+ function encodeModifiedUtf8(value) {
7
+ const bytes = [];
8
+ for (let i = 0; i < value.length; i++) {
9
+ const codeUnit = value.charCodeAt(i);
10
+ if (codeUnit !== 0 && codeUnit <= 0x7f) {
11
+ bytes.push(codeUnit);
12
+ continue;
13
+ }
14
+ if (codeUnit <= 0x07ff) {
15
+ bytes.push(0xc0 | ((codeUnit >> 6) & 0x1f), 0x80 | (codeUnit & 0x3f));
16
+ continue;
17
+ }
18
+ bytes.push(0xe0 | ((codeUnit >> 12) & 0x0f), 0x80 | ((codeUnit >> 6) & 0x3f), 0x80 | (codeUnit & 0x3f));
19
+ }
20
+ if (bytes.length > 0xffff) {
21
+ throw new Error(`NBT string is too long: ${bytes.length} bytes`);
22
+ }
23
+ const buffer = Buffer.allocUnsafe(2 + bytes.length);
24
+ buffer.writeUInt16BE(bytes.length, 0);
25
+ for (let i = 0; i < bytes.length; i++) {
26
+ buffer[2 + i] = bytes[i];
27
+ }
28
+ return buffer;
29
+ }
30
+ function decodeModifiedUtf8(buffer, offset) {
31
+ const byteLength = buffer.readUInt16BE(offset);
32
+ offset += 2;
33
+ const codeUnits = [];
34
+ const end = offset + byteLength;
35
+ while (offset < end) {
36
+ const first = buffer[offset++];
37
+ if ((first & 0x80) === 0) {
38
+ codeUnits.push(first);
39
+ continue;
40
+ }
41
+ if ((first & 0xe0) === 0xc0) {
42
+ const second = buffer[offset++];
43
+ codeUnits.push(((first & 0x1f) << 6) | (second & 0x3f));
44
+ continue;
45
+ }
46
+ const second = buffer[offset++];
47
+ const third = buffer[offset++];
48
+ codeUnits.push(((first & 0x0f) << 12) |
49
+ ((second & 0x3f) << 6) |
50
+ (third & 0x3f));
51
+ }
52
+ return {
53
+ value: String.fromCharCode(...codeUnits),
54
+ offset,
55
+ };
56
+ }
57
+ function writePayload(tag) {
58
+ switch (tag.type) {
59
+ case 0 /* TagType.End */:
60
+ return Buffer.alloc(0);
61
+ case 1 /* TagType.Byte */: {
62
+ const buffer = Buffer.allocUnsafe(1);
63
+ buffer.writeInt8(tag.value, 0);
64
+ return buffer;
65
+ }
66
+ case 2 /* TagType.Short */: {
67
+ const buffer = Buffer.allocUnsafe(2);
68
+ buffer.writeInt16BE(tag.value, 0);
69
+ return buffer;
70
+ }
71
+ case 3 /* TagType.Int */: {
72
+ const buffer = Buffer.allocUnsafe(4);
73
+ buffer.writeInt32BE(tag.value, 0);
74
+ return buffer;
75
+ }
76
+ case 4 /* TagType.Long */: {
77
+ const buffer = Buffer.allocUnsafe(8);
78
+ buffer.writeBigInt64BE(tag.value, 0);
79
+ return buffer;
80
+ }
81
+ case 5 /* TagType.Float */: {
82
+ const buffer = Buffer.allocUnsafe(4);
83
+ buffer.writeFloatBE(tag.value, 0);
84
+ return buffer;
85
+ }
86
+ case 6 /* TagType.Double */: {
87
+ const buffer = Buffer.allocUnsafe(8);
88
+ buffer.writeDoubleBE(tag.value, 0);
89
+ return buffer;
90
+ }
91
+ case 7 /* TagType.ByteArray */: {
92
+ const header = Buffer.allocUnsafe(4);
93
+ header.writeInt32BE(tag.value.length, 0);
94
+ return Buffer.concat([header, Buffer.from(tag.value)]);
95
+ }
96
+ case 8 /* TagType.String */:
97
+ return encodeModifiedUtf8(tag.value);
98
+ case 9 /* TagType.List */: {
99
+ const header = Buffer.allocUnsafe(5);
100
+ header.writeUInt8(tag.elementType, 0);
101
+ header.writeInt32BE(tag.items.length, 1);
102
+ return Buffer.concat([header, ...tag.items.map(writePayload)]);
103
+ }
104
+ case 10 /* TagType.Compound */: {
105
+ const parts = [];
106
+ for (const [name, entry] of tag.entries) {
107
+ parts.push(writeNamedTag(entry, name));
108
+ }
109
+ parts.push(Buffer.from([0 /* TagType.End */]));
110
+ return Buffer.concat(parts);
111
+ }
112
+ case 11 /* TagType.IntArray */: {
113
+ const header = Buffer.allocUnsafe(4 + tag.value.length * 4);
114
+ header.writeInt32BE(tag.value.length, 0);
115
+ for (let i = 0; i < tag.value.length; i++) {
116
+ header.writeInt32BE(tag.value[i], 4 + i * 4);
117
+ }
118
+ return header;
119
+ }
120
+ case 12 /* TagType.LongArray */: {
121
+ const header = Buffer.allocUnsafe(4 + tag.value.length * 8);
122
+ header.writeInt32BE(tag.value.length, 0);
123
+ for (let i = 0; i < tag.value.length; i++) {
124
+ header.writeBigInt64BE(tag.value[i], 4 + i * 8);
125
+ }
126
+ return header;
127
+ }
128
+ }
129
+ }
130
+ function writeNamedTag(tag, name) {
131
+ if (tag.type === 0 /* TagType.End */) {
132
+ throw new Error('TAG_End cannot be written as a named tag');
133
+ }
134
+ const nameBuffer = encodeModifiedUtf8(name);
135
+ return Buffer.concat([
136
+ Buffer.from([tag.type]),
137
+ nameBuffer,
138
+ writePayload(tag),
139
+ ]);
140
+ }
141
+ function readPayload(type, buffer, offset) {
142
+ switch (type) {
143
+ case 0 /* TagType.End */:
144
+ return { tag: { type: 0 /* TagType.End */ }, offset };
145
+ case 1 /* TagType.Byte */:
146
+ return { tag: { type: type, value: buffer.readInt8(offset) }, offset: offset + 1 };
147
+ case 2 /* TagType.Short */:
148
+ return { tag: { type: type, value: buffer.readInt16BE(offset) }, offset: offset + 2 };
149
+ case 3 /* TagType.Int */:
150
+ return { tag: { type: type, value: buffer.readInt32BE(offset) }, offset: offset + 4 };
151
+ case 4 /* TagType.Long */:
152
+ return { tag: { type: type, value: buffer.readBigInt64BE(offset) }, offset: offset + 8 };
153
+ case 5 /* TagType.Float */:
154
+ return { tag: { type: type, value: buffer.readFloatBE(offset) }, offset: offset + 4 };
155
+ case 6 /* TagType.Double */:
156
+ return { tag: { type: type, value: buffer.readDoubleBE(offset) }, offset: offset + 8 };
157
+ case 7 /* TagType.ByteArray */: {
158
+ const length = buffer.readInt32BE(offset);
159
+ offset += 4;
160
+ const value = new Int8Array(length);
161
+ for (let i = 0; i < length; i++) {
162
+ value[i] = buffer.readInt8(offset + i);
163
+ }
164
+ return { tag: { type, value }, offset: offset + length };
165
+ }
166
+ case 8 /* TagType.String */: {
167
+ const decoded = decodeModifiedUtf8(buffer, offset);
168
+ return { tag: { type, value: decoded.value }, offset: decoded.offset };
169
+ }
170
+ case 9 /* TagType.List */: {
171
+ const elementType = buffer.readUInt8(offset);
172
+ const length = buffer.readInt32BE(offset + 1);
173
+ offset += 5;
174
+ const items = [];
175
+ for (let i = 0; i < length; i++) {
176
+ const parsed = readPayload(elementType, buffer, offset);
177
+ items.push(parsed.tag);
178
+ offset = parsed.offset;
179
+ }
180
+ return { tag: { type, elementType, items }, offset };
181
+ }
182
+ case 10 /* TagType.Compound */: {
183
+ const entries = new Map();
184
+ while (true) {
185
+ const entryType = buffer.readUInt8(offset);
186
+ offset += 1;
187
+ if (entryType === 0 /* TagType.End */)
188
+ break;
189
+ const name = decodeModifiedUtf8(buffer, offset);
190
+ offset = name.offset;
191
+ const parsed = readPayload(entryType, buffer, offset);
192
+ entries.set(name.value, parsed.tag);
193
+ offset = parsed.offset;
194
+ }
195
+ return { tag: { type, entries }, offset };
196
+ }
197
+ case 11 /* TagType.IntArray */: {
198
+ const length = buffer.readInt32BE(offset);
199
+ offset += 4;
200
+ const value = new Int32Array(length);
201
+ for (let i = 0; i < length; i++) {
202
+ value[i] = buffer.readInt32BE(offset + i * 4);
203
+ }
204
+ return { tag: { type, value }, offset: offset + length * 4 };
205
+ }
206
+ case 12 /* TagType.LongArray */: {
207
+ const length = buffer.readInt32BE(offset);
208
+ offset += 4;
209
+ const value = new BigInt64Array(length);
210
+ for (let i = 0; i < length; i++) {
211
+ value[i] = buffer.readBigInt64BE(offset + i * 8);
212
+ }
213
+ return { tag: { type, value }, offset: offset + length * 8 };
214
+ }
215
+ default:
216
+ throw new Error(`Unsupported NBT tag type: ${type}`);
217
+ }
218
+ }
219
+ function writeNbt(tag, name) {
220
+ return writeNamedTag(tag, name);
221
+ }
222
+ function readNbt(buffer) {
223
+ let offset = 0;
224
+ const type = buffer.readUInt8(offset);
225
+ offset += 1;
226
+ if (type === 0 /* TagType.End */) {
227
+ throw new Error('Invalid root tag: TAG_End');
228
+ }
229
+ const decodedName = decodeModifiedUtf8(buffer, offset);
230
+ offset = decodedName.offset;
231
+ const parsed = readPayload(type, buffer, offset);
232
+ return {
233
+ name: decodedName.value,
234
+ tag: parsed.tag,
235
+ };
236
+ }
237
+ exports.nbt = {
238
+ byte: (value) => ({ type: 1 /* TagType.Byte */, value }),
239
+ short: (value) => ({ type: 2 /* TagType.Short */, value }),
240
+ int: (value) => ({ type: 3 /* TagType.Int */, value }),
241
+ long: (value) => ({ type: 4 /* TagType.Long */, value }),
242
+ float: (value) => ({ type: 5 /* TagType.Float */, value }),
243
+ double: (value) => ({ type: 6 /* TagType.Double */, value }),
244
+ string: (value) => ({ type: 8 /* TagType.String */, value }),
245
+ list: (elementType, items) => ({ type: 9 /* TagType.List */, elementType, items }),
246
+ compound: (entries) => ({ type: 10 /* TagType.Compound */, entries: new Map(Object.entries(entries)) }),
247
+ intArray: (values) => ({ type: 11 /* TagType.IntArray */, value: Int32Array.from(values) }),
248
+ byteArray: (values) => ({ type: 7 /* TagType.ByteArray */, value: Int8Array.from(values) }),
249
+ };
250
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,38 @@
1
+ import type { IRCommand } from '../ir/types';
2
+ export interface OptimizationStats {
3
+ licmHoists: number;
4
+ licmLoopBodies: number;
5
+ cseRedundantReads: number;
6
+ cseArithmetic: number;
7
+ setblockMergedCommands: number;
8
+ setblockFillCommands: number;
9
+ setblockSavedCommands: number;
10
+ deadCodeRemoved: number;
11
+ constantFolds: number;
12
+ inlinedTrivialFunctions: number;
13
+ totalCommandsBefore: number;
14
+ totalCommandsAfter: number;
15
+ }
16
+ export interface CommandFunction {
17
+ name: string;
18
+ commands: IRCommand[];
19
+ }
20
+ export declare function setOptimizerObjective(obj: string): void;
21
+ export declare function createEmptyOptimizationStats(): OptimizationStats;
22
+ export declare function mergeOptimizationStats(base: OptimizationStats, delta: Partial<OptimizationStats>): void;
23
+ export declare function applyLICM(functions: CommandFunction[]): {
24
+ functions: CommandFunction[];
25
+ stats: OptimizationStats;
26
+ };
27
+ export declare function applyCSE(functions: CommandFunction[]): {
28
+ functions: CommandFunction[];
29
+ stats: OptimizationStats;
30
+ };
31
+ export declare function batchSetblocks(functions: CommandFunction[]): {
32
+ functions: CommandFunction[];
33
+ stats: OptimizationStats;
34
+ };
35
+ export declare function optimizeCommandFunctions(functions: CommandFunction[]): {
36
+ functions: CommandFunction[];
37
+ stats: OptimizationStats;
38
+ };