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
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');
@@ -236,9 +236,17 @@ class Lexer {
236
236
  this.addToken('rel_coord', value, startLine, startCol);
237
237
  return;
238
238
  }
239
- // Local coordinate: ^ or ^5 or ^-3 or ^0.5
239
+ // Local coordinate: ^ or ^5 or ^-3 or ^0.5 or ^varname (macro variable)
240
240
  if (char === '^') {
241
241
  let value = '^';
242
+ // Check for identifier (variable name for macro substitution, e.g. ^px, ^height)
243
+ if (/[a-zA-Z_]/.test(this.peek())) {
244
+ while (/[a-zA-Z0-9_]/.test(this.peek())) {
245
+ value += this.advance();
246
+ }
247
+ this.addToken('local_coord', value, startLine, startCol);
248
+ return;
249
+ }
242
250
  // Check for optional sign
243
251
  if (this.peek() === '-' || this.peek() === '+') {
244
252
  value += this.advance();
@@ -495,16 +495,31 @@ class Lowering {
495
495
  }
496
496
  }
497
497
  // Set up NBT storage for each macro param
498
+ // float-typed params are stored as `double 0.01` so that an integer value N
499
+ // becomes N/100.0 in the command (e.g. scoreboard value 975 → NBT 9.75d → ^9.75)
498
500
  for (const macroParam of macroParamNames) {
499
501
  const paramIdx = params.findIndex(p => p.name === macroParam);
500
502
  if (paramIdx < 0 || paramIdx >= loweredArgs.length)
501
503
  continue;
502
504
  const operand = loweredArgs[paramIdx];
505
+ const paramType = params[paramIdx]?.type;
506
+ const isFloat = paramType?.kind === 'named' && paramType.name === 'float';
503
507
  if (operand.kind === 'const') {
504
- this.builder.emitRaw(`data modify storage rs:macro_args ${macroParam} set value ${operand.value}`);
508
+ if (isFloat) {
509
+ const floatVal = (operand.value / 100).toFixed(6);
510
+ this.builder.emitRaw(`data modify storage rs:macro_args ${macroParam} set value ${floatVal}d`);
511
+ }
512
+ else {
513
+ this.builder.emitRaw(`data modify storage rs:macro_args ${macroParam} set value ${operand.value}`);
514
+ }
505
515
  }
506
516
  else if (operand.kind === 'var') {
507
- this.builder.emitRaw(`execute store result storage rs:macro_args ${macroParam} int 1 run scoreboard players get ${operand.name} ${exports.LOWERING_OBJ}`);
517
+ if (isFloat) {
518
+ this.builder.emitRaw(`execute store result storage rs:macro_args ${macroParam} double 0.01 run scoreboard players get ${operand.name} ${exports.LOWERING_OBJ}`);
519
+ }
520
+ else {
521
+ this.builder.emitRaw(`execute store result storage rs:macro_args ${macroParam} int 1 run scoreboard players get ${operand.name} ${exports.LOWERING_OBJ}`);
522
+ }
508
523
  }
509
524
  }
510
525
  // Call with macro storage
@@ -2468,7 +2483,9 @@ class Lowering {
2468
2483
  const strArgs = argResults.map(r => r.str);
2469
2484
  const cmd = BUILTINS[name]?.(strArgs);
2470
2485
  if (cmd) {
2471
- 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);
2472
2489
  }
2473
2490
  return { kind: 'const', value: 0 };
2474
2491
  }
@@ -2997,10 +3014,10 @@ class Lowering {
2997
3014
  this.currentFnMacroParams.add(r.macroParam); });
2998
3015
  const strs = argResults.map(r => r.str);
2999
3016
  if (args.length === 2) {
3000
- return { cmd: `$tp ${strs[0]} ${strs[1]}` };
3017
+ return { cmd: `\x01tp ${strs[0]} ${strs[1]}` };
3001
3018
  }
3002
3019
  if (args.length === 4) {
3003
- return { cmd: `$tp ${strs[0]} ${strs[1]} ${strs[2]} ${strs[3]}` };
3020
+ return { cmd: `\x01tp ${strs[0]} ${strs[1]} ${strs[2]} ${strs[3]}` };
3004
3021
  }
3005
3022
  }
3006
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 {};