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
package/dist/compile.js CHANGED
@@ -1,266 +1,2 @@
1
- "use strict";
2
- /**
3
- * RedScript Compile API
4
- *
5
- * Main compile function with proper error handling and diagnostics.
6
- */
7
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
- if (k2 === undefined) k2 = k;
9
- var desc = Object.getOwnPropertyDescriptor(m, k);
10
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
- desc = { enumerable: true, get: function() { return m[k]; } };
12
- }
13
- Object.defineProperty(o, k2, desc);
14
- }) : (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- o[k2] = m[k];
17
- }));
18
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
- Object.defineProperty(o, "default", { enumerable: true, value: v });
20
- }) : function(o, v) {
21
- o["default"] = v;
22
- });
23
- var __importStar = (this && this.__importStar) || (function () {
24
- var ownKeys = function(o) {
25
- ownKeys = Object.getOwnPropertyNames || function (o) {
26
- var ar = [];
27
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
- return ar;
29
- };
30
- return ownKeys(o);
31
- };
32
- return function (mod) {
33
- if (mod && mod.__esModule) return mod;
34
- var result = {};
35
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
- __setModuleDefault(result, mod);
37
- return result;
38
- };
39
- })();
40
- Object.defineProperty(exports, "__esModule", { value: true });
41
- exports.resolveSourceLine = resolveSourceLine;
42
- exports.preprocessSourceWithMetadata = preprocessSourceWithMetadata;
43
- exports.preprocessSource = preprocessSource;
44
- exports.compile = compile;
45
- exports.formatCompileError = formatCompileError;
46
- const fs = __importStar(require("fs"));
47
- const path = __importStar(require("path"));
48
- const lexer_1 = require("./lexer");
49
- const parser_1 = require("./parser");
50
- const lowering_1 = require("./lowering");
51
- const passes_1 = require("./optimizer/passes");
52
- const dce_1 = require("./optimizer/dce");
53
- const mcfunction_1 = require("./codegen/mcfunction");
54
- const diagnostics_1 = require("./diagnostics");
55
- /**
56
- * Resolve a combined-source line number back to the original file and line.
57
- * Returns { filePath, line } if a mapping is found, otherwise returns the input unchanged.
58
- */
59
- function resolveSourceLine(combinedLine, ranges, fallbackFile) {
60
- for (const range of ranges) {
61
- if (combinedLine >= range.startLine && combinedLine <= range.endLine) {
62
- const localLine = combinedLine - range.startLine + 1;
63
- return { filePath: range.filePath, line: localLine };
64
- }
65
- }
66
- return { filePath: fallbackFile, line: combinedLine };
67
- }
68
- const IMPORT_RE = /^\s*import\s+"([^"]+)"\s*;?\s*$/;
69
- /** Returns true if the source file declares `module library;` at its top
70
- * (before any non-comment/non-blank lines). */
71
- function isLibrarySource(source) {
72
- for (const line of source.split('\n')) {
73
- const trimmed = line.trim();
74
- if (!trimmed || trimmed.startsWith('//'))
75
- continue;
76
- return /^module\s+library\s*;/.test(trimmed);
77
- }
78
- return false;
79
- }
80
- function countLines(source) {
81
- return source === '' ? 0 : source.split('\n').length;
82
- }
83
- function offsetRanges(ranges, lineOffset) {
84
- return ranges.map(range => ({
85
- startLine: range.startLine + lineOffset,
86
- endLine: range.endLine + lineOffset,
87
- filePath: range.filePath,
88
- }));
89
- }
90
- function preprocessSourceWithMetadata(source, options = {}) {
91
- const { filePath } = options;
92
- const seen = options.seen ?? new Set();
93
- if (filePath) {
94
- seen.add(path.resolve(filePath));
95
- }
96
- const lines = source.split('\n');
97
- const imports = [];
98
- /** Library imports: `module library;` files routed here instead of concatenated. */
99
- const libraryImports = [];
100
- const bodyLines = [];
101
- let parsingHeader = true;
102
- for (let i = 0; i < lines.length; i++) {
103
- const line = lines[i];
104
- const trimmed = line.trim();
105
- const match = line.match(IMPORT_RE);
106
- if (parsingHeader && match) {
107
- if (!filePath) {
108
- throw new diagnostics_1.DiagnosticError('ParseError', 'Import statements require a file path', { line: i + 1, col: 1 }, lines);
109
- }
110
- const importPath = path.resolve(path.dirname(filePath), match[1]);
111
- if (!seen.has(importPath)) {
112
- seen.add(importPath);
113
- let importedSource;
114
- try {
115
- importedSource = fs.readFileSync(importPath, 'utf-8');
116
- }
117
- catch {
118
- throw new diagnostics_1.DiagnosticError('ParseError', `Cannot import '${match[1]}'`, { file: filePath, line: i + 1, col: 1 }, lines);
119
- }
120
- if (isLibrarySource(importedSource)) {
121
- // Library file: parse separately so its functions are DCE-eligible.
122
- // Also collect any transitive library imports inside it.
123
- const nested = preprocessSourceWithMetadata(importedSource, { filePath: importPath, seen });
124
- libraryImports.push({ source: importedSource, filePath: importPath });
125
- // Propagate transitive library imports (e.g. math.mcrs imports vec.mcrs)
126
- if (nested.libraryImports)
127
- libraryImports.push(...nested.libraryImports);
128
- }
129
- else {
130
- imports.push(preprocessSourceWithMetadata(importedSource, { filePath: importPath, seen }));
131
- }
132
- }
133
- continue;
134
- }
135
- if (parsingHeader && (trimmed === '' || trimmed.startsWith('//'))) {
136
- bodyLines.push(line);
137
- continue;
138
- }
139
- parsingHeader = false;
140
- bodyLines.push(line);
141
- }
142
- const body = bodyLines.join('\n');
143
- const parts = [...imports.map(entry => entry.source), body].filter(Boolean);
144
- const combined = parts.join('\n');
145
- const ranges = [];
146
- let lineOffset = 0;
147
- for (const entry of imports) {
148
- ranges.push(...offsetRanges(entry.ranges, lineOffset));
149
- lineOffset += countLines(entry.source);
150
- }
151
- if (filePath && body) {
152
- ranges.push({
153
- startLine: lineOffset + 1,
154
- endLine: lineOffset + countLines(body),
155
- filePath: path.resolve(filePath),
156
- });
157
- }
158
- return {
159
- source: combined,
160
- ranges,
161
- libraryImports: libraryImports.length > 0 ? libraryImports : undefined,
162
- };
163
- }
164
- function preprocessSource(source, options = {}) {
165
- return preprocessSourceWithMetadata(source, options).source;
166
- }
167
- // ---------------------------------------------------------------------------
168
- // Main Compile Function
169
- // ---------------------------------------------------------------------------
170
- function compile(source, options = {}) {
171
- const { namespace = 'redscript', filePath, optimize: shouldOptimize = true } = options;
172
- const shouldRunDce = options.dce ?? shouldOptimize;
173
- let sourceLines = source.split('\n');
174
- try {
175
- const preprocessed = preprocessSourceWithMetadata(source, { filePath });
176
- const preprocessedSource = preprocessed.source;
177
- sourceLines = preprocessedSource.split('\n');
178
- // Lexing
179
- const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
180
- // Parsing — user source
181
- const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
182
- // Collect all library sources: explicit `librarySources` option +
183
- // auto-detected imports (files with `module library;` pulled out by the
184
- // preprocessor rather than concatenated).
185
- const allLibrarySources = [];
186
- for (const libSrc of options.librarySources ?? []) {
187
- allLibrarySources.push({ src: libSrc });
188
- }
189
- for (const li of preprocessed.libraryImports ?? []) {
190
- allLibrarySources.push({ src: li.source, fp: li.filePath });
191
- }
192
- // Parse library sources independently (fresh Parser per source) so that
193
- // `inLibraryMode` never bleeds into user code. All resulting functions get
194
- // isLibraryFn=true (either via `module library;` in the source, or forced below).
195
- for (const { src, fp } of allLibrarySources) {
196
- const libPreprocessed = preprocessSourceWithMetadata(src, fp ? { filePath: fp } : {});
197
- const libTokens = new lexer_1.Lexer(libPreprocessed.source, fp).tokenize();
198
- const libAst = new parser_1.Parser(libTokens, libPreprocessed.source, fp).parse(namespace);
199
- // Force all functions to library mode (even if source lacks `module library;`)
200
- for (const fn of libAst.declarations)
201
- fn.isLibraryFn = true;
202
- // Merge into main AST
203
- parsedAst.declarations.push(...libAst.declarations);
204
- parsedAst.structs.push(...libAst.structs);
205
- parsedAst.implBlocks.push(...libAst.implBlocks);
206
- parsedAst.enums.push(...libAst.enums);
207
- parsedAst.consts.push(...libAst.consts);
208
- parsedAst.globals.push(...libAst.globals);
209
- }
210
- const dceResult = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : { program: parsedAst, warnings: [] };
211
- const ast = dceResult.program;
212
- // Configure scoreboard objective for this compilation.
213
- // Default: use the datapack namespace so each datapack gets its own objective
214
- // automatically, preventing variable collisions when multiple datapacks coexist.
215
- const scoreboardObj = options.scoreboardObjective ?? `__${namespace}`;
216
- (0, lowering_1.setScoreboardObjective)(scoreboardObj);
217
- // Lowering
218
- const ir = new lowering_1.Lowering(namespace, preprocessed.ranges).lower(ast);
219
- // Optimization
220
- const optimized = shouldOptimize
221
- ? { ...ir, functions: ir.functions.map(fn => (0, passes_1.optimize)(fn)) }
222
- : ir;
223
- // Code generation — mangle=true by default to prevent cross-function
224
- // scoreboard variable collisions in the global MC scoreboard namespace.
225
- const generated = (0, mcfunction_1.generateDatapackWithStats)(optimized, {
226
- mangle: options.mangle ?? true,
227
- scoreboardObjective: scoreboardObj,
228
- });
229
- return {
230
- success: true,
231
- files: [...generated.files, ...generated.advancements],
232
- advancements: generated.advancements,
233
- ast,
234
- ir: optimized,
235
- };
236
- }
237
- catch (err) {
238
- // Already a DiagnosticError
239
- if (err instanceof diagnostics_1.DiagnosticError) {
240
- return { success: false, error: err };
241
- }
242
- // Try to parse the error message for line/col info
243
- if (err instanceof Error) {
244
- const diagnostic = (0, diagnostics_1.parseErrorMessage)('ParseError', err.message, sourceLines, filePath);
245
- return { success: false, error: diagnostic };
246
- }
247
- // Unknown error
248
- return {
249
- success: false,
250
- error: new diagnostics_1.DiagnosticError('ParseError', String(err), { file: filePath, line: 1, col: 1 }, sourceLines)
251
- };
252
- }
253
- }
254
- // ---------------------------------------------------------------------------
255
- // Format Compile Error
256
- // ---------------------------------------------------------------------------
257
- function formatCompileError(result) {
258
- if (result.success) {
259
- return 'Compilation successful';
260
- }
261
- if (result.error) {
262
- return (0, diagnostics_1.formatError)(result.error, result.error.sourceLines?.join('\n'));
263
- }
264
- return 'Unknown error';
265
- }
266
- //# sourceMappingURL=compile.js.map
1
+ // shim — delegates to dist/src/
2
+ module.exports = require('./src/compile');
package/dist/index.js CHANGED
@@ -1,159 +1,2 @@
1
- "use strict";
2
- /**
3
- * RedScript Compiler
4
- *
5
- * Main entry point for programmatic usage.
6
- */
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.MCCommandValidator = exports.generateDatapack = exports.optimize = exports.Lowering = exports.TypeChecker = exports.Parser = exports.Lexer = exports.version = void 0;
9
- exports.compile = compile;
10
- exports.check = check;
11
- // eslint-disable-next-line @typescript-eslint/no-var-requires
12
- exports.version = '1.2.11';
13
- const lexer_1 = require("./lexer");
14
- const parser_1 = require("./parser");
15
- const typechecker_1 = require("./typechecker");
16
- const lowering_1 = require("./lowering");
17
- const passes_1 = require("./optimizer/passes");
18
- const dce_1 = require("./optimizer/dce");
19
- const mcfunction_1 = require("./codegen/mcfunction");
20
- const compile_1 = require("./compile");
21
- const commands_1 = require("./optimizer/commands");
22
- /**
23
- * Compile RedScript source code to a Minecraft datapack.
24
- *
25
- * @param source - The RedScript source code
26
- * @param options - Compilation options
27
- * @returns Compiled datapack files
28
- */
29
- function compile(source, options = {}) {
30
- const namespace = options.namespace ?? 'redscript';
31
- const shouldOptimize = options.optimize ?? true;
32
- const shouldTypeCheck = options.typeCheck ?? true;
33
- const shouldRunDce = options.dce ?? shouldOptimize;
34
- const mangle = options.mangle ?? false;
35
- const filePath = options.filePath;
36
- const preprocessed = (0, compile_1.preprocessSourceWithMetadata)(source, { filePath });
37
- const preprocessedSource = preprocessed.source;
38
- // Lexing
39
- const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
40
- // Parsing — user source
41
- const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
42
- // Library imports: files that declared `module library;` are parsed independently
43
- // (fresh Parser per file) so their functions are DCE-eligible but never bleed into user code.
44
- const allLibrarySources = [];
45
- for (const li of preprocessed.libraryImports ?? []) {
46
- allLibrarySources.push({ src: li.source, fp: li.filePath });
47
- }
48
- for (const { src, fp } of allLibrarySources) {
49
- const libPreprocessed = (0, compile_1.preprocessSourceWithMetadata)(src, fp ? { filePath: fp } : {});
50
- const libTokens = new lexer_1.Lexer(libPreprocessed.source, fp).tokenize();
51
- const libAst = new parser_1.Parser(libTokens, libPreprocessed.source, fp).parse(namespace);
52
- for (const fn of libAst.declarations)
53
- fn.isLibraryFn = true;
54
- parsedAst.declarations.push(...libAst.declarations);
55
- parsedAst.structs.push(...libAst.structs);
56
- parsedAst.implBlocks.push(...libAst.implBlocks);
57
- parsedAst.enums.push(...libAst.enums);
58
- parsedAst.consts.push(...libAst.consts);
59
- parsedAst.globals.push(...libAst.globals);
60
- }
61
- const dceResult = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst, preprocessed.ranges) : { program: parsedAst, warnings: [] };
62
- const ast = dceResult.program;
63
- // Type checking (warn mode - collect errors but don't block)
64
- let typeErrors;
65
- if (shouldTypeCheck) {
66
- const checker = new typechecker_1.TypeChecker(preprocessedSource, filePath);
67
- typeErrors = checker.check(ast);
68
- }
69
- // Configure scoreboard objective for this compilation.
70
- // Default: use the datapack namespace so each datapack gets its own objective
71
- // automatically, preventing variable collisions when multiple datapacks coexist.
72
- const scoreboardObj = options.scoreboardObjective ?? `__${namespace}`;
73
- (0, lowering_1.setScoreboardObjective)(scoreboardObj);
74
- // Lowering to IR
75
- const lowering = new lowering_1.Lowering(namespace, preprocessed.ranges);
76
- const ir = lowering.lower(ast);
77
- let optimizedIR = ir;
78
- let generated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: shouldOptimize, mangle, scoreboardObjective: scoreboardObj });
79
- let optimizationStats;
80
- if (shouldOptimize) {
81
- const stats = (0, commands_1.createEmptyOptimizationStats)();
82
- const copyPropagatedFunctions = [];
83
- const deadCodeEliminatedFunctions = [];
84
- for (const fn of ir.functions) {
85
- const folded = (0, passes_1.constantFoldingWithStats)(fn);
86
- stats.constantFolds += folded.stats.constantFolds ?? 0;
87
- const propagated = (0, passes_1.copyPropagation)(folded.fn);
88
- copyPropagatedFunctions.push(propagated);
89
- const dce = (0, passes_1.deadCodeEliminationWithStats)(propagated);
90
- deadCodeEliminatedFunctions.push(dce.fn);
91
- }
92
- const copyPropagatedIR = { ...ir, functions: copyPropagatedFunctions };
93
- optimizedIR = { ...ir, functions: deadCodeEliminatedFunctions };
94
- const baselineGenerated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: false, mangle, scoreboardObjective: scoreboardObj });
95
- const beforeDceGenerated = (0, mcfunction_1.generateDatapackWithStats)(copyPropagatedIR, { optimizeCommands: false, mangle, scoreboardObjective: scoreboardObj });
96
- const afterDceGenerated = (0, mcfunction_1.generateDatapackWithStats)(optimizedIR, { optimizeCommands: false, mangle, scoreboardObjective: scoreboardObj });
97
- generated = (0, mcfunction_1.generateDatapackWithStats)(optimizedIR, { optimizeCommands: true, mangle, scoreboardObjective: scoreboardObj });
98
- stats.deadCodeRemoved =
99
- (0, mcfunction_1.countMcfunctionCommands)(beforeDceGenerated.files) - (0, mcfunction_1.countMcfunctionCommands)(afterDceGenerated.files);
100
- stats.licmHoists = generated.stats.licmHoists;
101
- stats.licmLoopBodies = generated.stats.licmLoopBodies;
102
- stats.cseRedundantReads = generated.stats.cseRedundantReads;
103
- stats.cseArithmetic = generated.stats.cseArithmetic;
104
- stats.setblockMergedCommands = generated.stats.setblockMergedCommands;
105
- stats.setblockFillCommands = generated.stats.setblockFillCommands;
106
- stats.setblockSavedCommands = generated.stats.setblockSavedCommands;
107
- stats.totalCommandsBefore = (0, mcfunction_1.countMcfunctionCommands)(baselineGenerated.files);
108
- stats.totalCommandsAfter = (0, mcfunction_1.countMcfunctionCommands)(generated.files);
109
- optimizationStats = stats;
110
- }
111
- else {
112
- optimizedIR = ir;
113
- generated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: false, mangle, scoreboardObjective: scoreboardObj });
114
- }
115
- return {
116
- files: [...generated.files, ...generated.advancements],
117
- advancements: generated.advancements,
118
- ast,
119
- ir: optimizedIR,
120
- typeErrors,
121
- warnings: [...dceResult.warnings, ...lowering.warnings],
122
- stats: optimizationStats,
123
- sourceMap: generated.sourceMap,
124
- };
125
- }
126
- /**
127
- * Check RedScript source code for errors without generating output.
128
- *
129
- * @param source - The RedScript source code
130
- * @param namespace - Optional namespace
131
- * @returns null if no errors, or an error object
132
- */
133
- function check(source, namespace = 'redscript', filePath) {
134
- try {
135
- const preprocessedSource = (0, compile_1.preprocessSource)(source, { filePath });
136
- const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
137
- new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
138
- return null;
139
- }
140
- catch (err) {
141
- return err;
142
- }
143
- }
144
- // Re-export types and classes for advanced usage
145
- var lexer_2 = require("./lexer");
146
- Object.defineProperty(exports, "Lexer", { enumerable: true, get: function () { return lexer_2.Lexer; } });
147
- var parser_2 = require("./parser");
148
- Object.defineProperty(exports, "Parser", { enumerable: true, get: function () { return parser_2.Parser; } });
149
- var typechecker_2 = require("./typechecker");
150
- Object.defineProperty(exports, "TypeChecker", { enumerable: true, get: function () { return typechecker_2.TypeChecker; } });
151
- var lowering_2 = require("./lowering");
152
- Object.defineProperty(exports, "Lowering", { enumerable: true, get: function () { return lowering_2.Lowering; } });
153
- var passes_2 = require("./optimizer/passes");
154
- Object.defineProperty(exports, "optimize", { enumerable: true, get: function () { return passes_2.optimize; } });
155
- var mcfunction_2 = require("./codegen/mcfunction");
156
- Object.defineProperty(exports, "generateDatapack", { enumerable: true, get: function () { return mcfunction_2.generateDatapack; } });
157
- var mc_validator_1 = require("./mc-validator");
158
- Object.defineProperty(exports, "MCCommandValidator", { enumerable: true, get: function () { return mc_validator_1.MCCommandValidator; } });
159
- //# sourceMappingURL=index.js.map
1
+ // shim — delegates to dist/src/
2
+ module.exports = require('./src/index');
@@ -2483,7 +2483,9 @@ class Lowering {
2483
2483
  const strArgs = argResults.map(r => r.str);
2484
2484
  const cmd = BUILTINS[name]?.(strArgs);
2485
2485
  if (cmd) {
2486
- this.builder.emitRaw(hasMacroArg ? `$${cmd}` : cmd);
2486
+ // Use \x01 sentinel (not literal '$') so resolveRaw doesn't treat the
2487
+ // MC macro prefix as a variable reference and allocate a fresh temp for it.
2488
+ this.builder.emitRaw(hasMacroArg ? `\x01${cmd}` : cmd);
2487
2489
  }
2488
2490
  return { kind: 'const', value: 0 };
2489
2491
  }
@@ -3012,10 +3014,10 @@ class Lowering {
3012
3014
  this.currentFnMacroParams.add(r.macroParam); });
3013
3015
  const strs = argResults.map(r => r.str);
3014
3016
  if (args.length === 2) {
3015
- return { cmd: `$tp ${strs[0]} ${strs[1]}` };
3017
+ return { cmd: `\x01tp ${strs[0]} ${strs[1]}` };
3016
3018
  }
3017
3019
  if (args.length === 4) {
3018
- return { cmd: `$tp ${strs[0]} ${strs[1]} ${strs[2]} ${strs[3]}` };
3020
+ return { cmd: `\x01tp ${strs[0]} ${strs[1]} ${strs[2]} ${strs[3]}` };
3019
3021
  }
3020
3022
  }
3021
3023
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,104 @@
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
+ const index_1 = require("../index");
37
+ const fs = __importStar(require("fs"));
38
+ const os = __importStar(require("os"));
39
+ const path = __importStar(require("path"));
40
+ // Note: watch command is tested manually as it's an interactive long-running process
41
+ describe('CLI API', () => {
42
+ describe('imports', () => {
43
+ it('compiles a file with imported helpers', () => {
44
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'redscript-imports-'));
45
+ const libPath = path.join(tempDir, 'lib.mcrs');
46
+ const mainPath = path.join(tempDir, 'main.mcrs');
47
+ fs.writeFileSync(libPath, 'fn double(x: int) -> int { return x + x; }\n');
48
+ fs.writeFileSync(mainPath, 'import "./lib.mcrs"\n\nfn main() { let value: int = double(2); }\n');
49
+ const source = fs.readFileSync(mainPath, 'utf-8');
50
+ const result = (0, index_1.compile)(source, { namespace: 'imports', filePath: mainPath });
51
+ expect(result.files.length).toBeGreaterThan(0);
52
+ // Verify both functions are compiled by checking output files
53
+ expect(result.files.some(f => f.path.includes('/double.mcfunction'))).toBe(true);
54
+ expect(result.files.some(f => f.path.includes('/main.mcfunction'))).toBe(true);
55
+ });
56
+ it('deduplicates circular imports', () => {
57
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'redscript-circular-'));
58
+ const aPath = path.join(tempDir, 'a.mcrs');
59
+ const bPath = path.join(tempDir, 'b.mcrs');
60
+ const mainPath = path.join(tempDir, 'main.mcrs');
61
+ fs.writeFileSync(aPath, 'import "./b.mcrs"\n\nfn from_a() -> int { return 1; }\n');
62
+ fs.writeFileSync(bPath, 'import "./a.mcrs"\n\nfn from_b() -> int { return from_a(); }\n');
63
+ fs.writeFileSync(mainPath, 'import "./a.mcrs"\n\nfn main() { let value: int = from_b(); }\n');
64
+ const source = fs.readFileSync(mainPath, 'utf-8');
65
+ const result = (0, index_1.compile)(source, { namespace: 'circular', filePath: mainPath });
66
+ // Verify each function appears exactly once in output
67
+ expect(result.files.filter(f => f.path.endsWith('/from_a.mcfunction'))).toHaveLength(1);
68
+ expect(result.files.filter(f => f.path.endsWith('/from_b.mcfunction'))).toHaveLength(1);
69
+ });
70
+ });
71
+ describe('compile()', () => {
72
+ it('compiles simple source', () => {
73
+ const source = 'fn test() { say("hello"); }';
74
+ const result = (0, index_1.compile)(source, { namespace: 'mypack' });
75
+ expect(result.files.length).toBeGreaterThan(0);
76
+ });
77
+ it('generates correct file structure', () => {
78
+ const source = 'fn test() { say("hello"); }';
79
+ const result = (0, index_1.compile)(source, { namespace: 'game' });
80
+ const paths = result.files.map(f => f.path);
81
+ expect(paths).toContain('pack.mcmeta');
82
+ expect(paths).toContain('data/game/function/load.mcfunction');
83
+ expect(paths.some(p => p.includes('test.mcfunction'))).toBe(true);
84
+ });
85
+ });
86
+ describe('check()', () => {
87
+ it('returns null for valid source', () => {
88
+ const source = 'fn test() { say("hello"); }';
89
+ const error = (0, index_1.check)(source);
90
+ expect(error).toBeNull();
91
+ });
92
+ it('returns error for invalid source', () => {
93
+ const source = 'fn test( { say("hello"); }'; // Missing )
94
+ const error = (0, index_1.check)(source);
95
+ expect(error).toBeInstanceOf(Error);
96
+ });
97
+ it('returns error for syntax errors', () => {
98
+ const source = 'fn test() { let x = ; }'; // Missing value
99
+ const error = (0, index_1.check)(source);
100
+ expect(error).toBeInstanceOf(Error);
101
+ });
102
+ });
103
+ });
104
+ //# sourceMappingURL=cli.test.js.map
@@ -0,0 +1 @@
1
+ export {};