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.
- package/.claude/commands/build-test.md +10 -0
- package/.claude/commands/deploy-demo.md +12 -0
- package/.claude/commands/stage-status.md +13 -0
- package/.claude/settings.json +12 -0
- package/.github/workflows/ci.yml +1 -0
- package/CLAUDE.md +231 -0
- package/demo.gif +0 -0
- package/dist/cli.js +2 -554
- package/dist/compile.js +2 -266
- package/dist/index.js +2 -159
- package/dist/lowering/index.js +5 -3
- package/dist/src/__tests__/cli.test.d.ts +1 -0
- package/dist/src/__tests__/cli.test.js +104 -0
- package/dist/src/__tests__/codegen.test.d.ts +1 -0
- package/dist/src/__tests__/codegen.test.js +152 -0
- package/dist/src/__tests__/compile-all.test.d.ts +10 -0
- package/dist/src/__tests__/compile-all.test.js +108 -0
- package/dist/src/__tests__/dce.test.d.ts +1 -0
- package/dist/src/__tests__/dce.test.js +102 -0
- package/dist/src/__tests__/diagnostics.test.d.ts +4 -0
- package/dist/src/__tests__/diagnostics.test.js +177 -0
- package/dist/src/__tests__/e2e.test.d.ts +6 -0
- package/dist/src/__tests__/e2e.test.js +1789 -0
- package/dist/src/__tests__/entity-types.test.d.ts +1 -0
- package/dist/src/__tests__/entity-types.test.js +203 -0
- package/dist/src/__tests__/formatter.test.d.ts +1 -0
- package/dist/src/__tests__/formatter.test.js +40 -0
- package/dist/src/__tests__/lexer.test.d.ts +1 -0
- package/dist/src/__tests__/lexer.test.js +343 -0
- package/dist/src/__tests__/lowering.test.d.ts +1 -0
- package/dist/src/__tests__/lowering.test.js +1015 -0
- package/dist/src/__tests__/macro.test.d.ts +8 -0
- package/dist/src/__tests__/macro.test.js +306 -0
- package/dist/src/__tests__/mc-integration.test.d.ts +12 -0
- package/dist/src/__tests__/mc-integration.test.js +817 -0
- package/dist/src/__tests__/mc-syntax.test.d.ts +1 -0
- package/dist/src/__tests__/mc-syntax.test.js +124 -0
- package/dist/src/__tests__/nbt.test.d.ts +1 -0
- package/dist/src/__tests__/nbt.test.js +82 -0
- package/dist/src/__tests__/optimizer-advanced.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer-advanced.test.js +124 -0
- package/dist/src/__tests__/optimizer.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer.test.js +149 -0
- package/dist/src/__tests__/parser.test.d.ts +1 -0
- package/dist/src/__tests__/parser.test.js +807 -0
- package/dist/src/__tests__/repl.test.d.ts +1 -0
- package/dist/src/__tests__/repl.test.js +27 -0
- package/dist/src/__tests__/runtime.test.d.ts +1 -0
- package/dist/src/__tests__/runtime.test.js +289 -0
- package/dist/src/__tests__/stdlib-advanced.test.d.ts +4 -0
- package/dist/src/__tests__/stdlib-advanced.test.js +374 -0
- package/dist/src/__tests__/stdlib-bigint.test.d.ts +7 -0
- package/dist/src/__tests__/stdlib-bigint.test.js +426 -0
- package/dist/src/__tests__/stdlib-math.test.d.ts +7 -0
- package/dist/src/__tests__/stdlib-math.test.js +351 -0
- package/dist/src/__tests__/stdlib-vec.test.d.ts +4 -0
- package/dist/src/__tests__/stdlib-vec.test.js +263 -0
- package/dist/src/__tests__/structure-optimizer.test.d.ts +1 -0
- package/dist/src/__tests__/structure-optimizer.test.js +33 -0
- package/dist/src/__tests__/typechecker.test.d.ts +1 -0
- package/dist/src/__tests__/typechecker.test.js +552 -0
- package/dist/src/__tests__/var-allocator.test.d.ts +1 -0
- package/dist/src/__tests__/var-allocator.test.js +69 -0
- package/dist/src/ast/types.d.ts +515 -0
- package/dist/src/ast/types.js +9 -0
- package/dist/src/builtins/metadata.d.ts +36 -0
- package/dist/src/builtins/metadata.js +1014 -0
- package/dist/src/cli.d.ts +11 -0
- package/dist/src/cli.js +443 -0
- package/dist/src/codegen/cmdblock/index.d.ts +26 -0
- package/dist/src/codegen/cmdblock/index.js +45 -0
- package/dist/src/codegen/mcfunction/index.d.ts +40 -0
- package/dist/src/codegen/mcfunction/index.js +606 -0
- package/dist/src/codegen/structure/index.d.ts +24 -0
- package/dist/src/codegen/structure/index.js +279 -0
- package/dist/src/codegen/var-allocator.d.ts +45 -0
- package/dist/src/codegen/var-allocator.js +104 -0
- package/dist/src/compile.d.ts +37 -0
- package/dist/src/compile.js +165 -0
- package/dist/src/diagnostics/index.d.ts +44 -0
- package/dist/src/diagnostics/index.js +140 -0
- package/dist/src/events/types.d.ts +35 -0
- package/dist/src/events/types.js +59 -0
- package/dist/src/formatter/index.d.ts +1 -0
- package/dist/src/formatter/index.js +26 -0
- package/dist/src/index.d.ts +22 -0
- package/dist/src/index.js +45 -0
- package/dist/src/ir/builder.d.ts +33 -0
- package/dist/src/ir/builder.js +99 -0
- package/dist/src/ir/types.d.ts +132 -0
- package/dist/src/ir/types.js +15 -0
- package/dist/src/lexer/index.d.ts +37 -0
- package/dist/src/lexer/index.js +569 -0
- package/dist/src/lowering/index.d.ts +188 -0
- package/dist/src/lowering/index.js +3405 -0
- package/dist/src/mc-test/client.d.ts +128 -0
- package/dist/src/mc-test/client.js +174 -0
- package/dist/src/mc-test/runner.d.ts +28 -0
- package/dist/src/mc-test/runner.js +151 -0
- package/dist/src/mc-test/setup.d.ts +11 -0
- package/dist/src/mc-test/setup.js +98 -0
- package/dist/src/mc-validator/index.d.ts +17 -0
- package/dist/src/mc-validator/index.js +322 -0
- package/dist/src/nbt/index.d.ts +86 -0
- package/dist/src/nbt/index.js +250 -0
- package/dist/src/optimizer/commands.d.ts +38 -0
- package/dist/src/optimizer/commands.js +451 -0
- package/dist/src/optimizer/dce.d.ts +34 -0
- package/dist/src/optimizer/dce.js +639 -0
- package/dist/src/optimizer/passes.d.ts +34 -0
- package/dist/src/optimizer/passes.js +243 -0
- package/dist/src/optimizer/structure.d.ts +9 -0
- package/dist/src/optimizer/structure.js +356 -0
- package/dist/src/parser/index.d.ts +93 -0
- package/dist/src/parser/index.js +1687 -0
- package/dist/src/repl.d.ts +16 -0
- package/dist/src/repl.js +165 -0
- package/dist/src/runtime/index.d.ts +107 -0
- package/dist/src/runtime/index.js +1409 -0
- package/dist/src/typechecker/index.d.ts +61 -0
- package/dist/src/typechecker/index.js +1034 -0
- package/dist/src/types/entity-hierarchy.d.ts +29 -0
- package/dist/src/types/entity-hierarchy.js +107 -0
- package/dist/src2/__tests__/e2e/basic.test.d.ts +8 -0
- package/dist/src2/__tests__/e2e/basic.test.js +140 -0
- package/dist/src2/__tests__/e2e/macros.test.d.ts +9 -0
- package/dist/src2/__tests__/e2e/macros.test.js +182 -0
- package/dist/src2/__tests__/e2e/migrate.test.d.ts +13 -0
- package/dist/src2/__tests__/e2e/migrate.test.js +2739 -0
- package/dist/src2/__tests__/hir/desugar.test.d.ts +1 -0
- package/dist/src2/__tests__/hir/desugar.test.js +234 -0
- package/dist/src2/__tests__/lir/lower.test.d.ts +1 -0
- package/dist/src2/__tests__/lir/lower.test.js +559 -0
- package/dist/src2/__tests__/lir/types.test.d.ts +1 -0
- package/dist/src2/__tests__/lir/types.test.js +185 -0
- package/dist/src2/__tests__/lir/verify.test.d.ts +1 -0
- package/dist/src2/__tests__/lir/verify.test.js +221 -0
- package/dist/src2/__tests__/mir/arithmetic.test.d.ts +1 -0
- package/dist/src2/__tests__/mir/arithmetic.test.js +130 -0
- package/dist/src2/__tests__/mir/control-flow.test.d.ts +1 -0
- package/dist/src2/__tests__/mir/control-flow.test.js +205 -0
- package/dist/src2/__tests__/mir/verify.test.d.ts +1 -0
- package/dist/src2/__tests__/mir/verify.test.js +223 -0
- package/dist/src2/__tests__/optimizer/block_merge.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/block_merge.test.js +78 -0
- package/dist/src2/__tests__/optimizer/branch_simplify.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/branch_simplify.test.js +58 -0
- package/dist/src2/__tests__/optimizer/constant_fold.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/constant_fold.test.js +131 -0
- package/dist/src2/__tests__/optimizer/copy_prop.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/copy_prop.test.js +91 -0
- package/dist/src2/__tests__/optimizer/dce.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/dce.test.js +76 -0
- package/dist/src2/__tests__/optimizer/pipeline.test.d.ts +1 -0
- package/dist/src2/__tests__/optimizer/pipeline.test.js +102 -0
- package/dist/src2/emit/compile.d.ts +19 -0
- package/dist/src2/emit/compile.js +80 -0
- package/dist/src2/emit/index.d.ts +17 -0
- package/dist/src2/emit/index.js +172 -0
- package/dist/src2/hir/lower.d.ts +15 -0
- package/dist/src2/hir/lower.js +378 -0
- package/dist/src2/hir/types.d.ts +373 -0
- package/dist/src2/hir/types.js +16 -0
- package/dist/src2/lir/lower.d.ts +15 -0
- package/dist/src2/lir/lower.js +453 -0
- package/dist/src2/lir/types.d.ts +136 -0
- package/dist/src2/lir/types.js +11 -0
- package/dist/src2/lir/verify.d.ts +14 -0
- package/dist/src2/lir/verify.js +113 -0
- package/dist/src2/mir/lower.d.ts +9 -0
- package/dist/src2/mir/lower.js +1030 -0
- package/dist/src2/mir/macro.d.ts +22 -0
- package/dist/src2/mir/macro.js +168 -0
- package/dist/src2/mir/types.d.ts +183 -0
- package/dist/src2/mir/types.js +11 -0
- package/dist/src2/mir/verify.d.ts +16 -0
- package/dist/src2/mir/verify.js +216 -0
- package/dist/src2/optimizer/block_merge.d.ts +12 -0
- package/dist/src2/optimizer/block_merge.js +84 -0
- package/dist/src2/optimizer/branch_simplify.d.ts +9 -0
- package/dist/src2/optimizer/branch_simplify.js +28 -0
- package/dist/src2/optimizer/constant_fold.d.ts +10 -0
- package/dist/src2/optimizer/constant_fold.js +85 -0
- package/dist/src2/optimizer/copy_prop.d.ts +9 -0
- package/dist/src2/optimizer/copy_prop.js +113 -0
- package/dist/src2/optimizer/dce.d.ts +8 -0
- package/dist/src2/optimizer/dce.js +155 -0
- package/dist/src2/optimizer/pipeline.d.ts +10 -0
- package/dist/src2/optimizer/pipeline.js +42 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/docs/compiler-pipeline-redesign.md +2243 -0
- package/docs/optimization-ideas.md +1076 -0
- package/editors/vscode/package-lock.json +3 -3
- package/editors/vscode/package.json +1 -1
- package/jest.config.js +1 -1
- package/package.json +6 -5
- package/scripts/postbuild.js +15 -0
- package/src/__tests__/cli.test.ts +8 -220
- package/src/__tests__/dce.test.ts +11 -56
- package/src/__tests__/diagnostics.test.ts +59 -38
- package/src/__tests__/mc-integration.test.ts +1 -2
- package/src/ast/types.ts +6 -1
- package/src/cli.ts +29 -156
- package/src/compile.ts +6 -162
- package/src/index.ts +14 -178
- package/src/mc-test/runner.ts +4 -3
- package/src/parser/index.ts +1 -1
- package/src/repl.ts +1 -1
- package/src/runtime/index.ts +1 -1
- package/src2/__tests__/e2e/basic.test.ts +154 -0
- package/src2/__tests__/e2e/macros.test.ts +199 -0
- package/src2/__tests__/e2e/migrate.test.ts +3008 -0
- package/src2/__tests__/hir/desugar.test.ts +263 -0
- package/src2/__tests__/lir/lower.test.ts +619 -0
- package/src2/__tests__/lir/types.test.ts +207 -0
- package/src2/__tests__/lir/verify.test.ts +249 -0
- package/src2/__tests__/mir/arithmetic.test.ts +156 -0
- package/src2/__tests__/mir/control-flow.test.ts +242 -0
- package/src2/__tests__/mir/verify.test.ts +254 -0
- package/src2/__tests__/optimizer/block_merge.test.ts +84 -0
- package/src2/__tests__/optimizer/branch_simplify.test.ts +64 -0
- package/src2/__tests__/optimizer/constant_fold.test.ts +145 -0
- package/src2/__tests__/optimizer/copy_prop.test.ts +99 -0
- package/src2/__tests__/optimizer/dce.test.ts +83 -0
- package/src2/__tests__/optimizer/pipeline.test.ts +116 -0
- package/src2/emit/compile.ts +99 -0
- package/src2/emit/index.ts +222 -0
- package/src2/hir/lower.ts +428 -0
- package/src2/hir/types.ts +216 -0
- package/src2/lir/lower.ts +556 -0
- package/src2/lir/types.ts +109 -0
- package/src2/lir/verify.ts +129 -0
- package/src2/mir/lower.ts +1160 -0
- package/src2/mir/macro.ts +167 -0
- package/src2/mir/types.ts +106 -0
- package/src2/mir/verify.ts +218 -0
- package/src2/optimizer/block_merge.ts +93 -0
- package/src2/optimizer/branch_simplify.ts +27 -0
- package/src2/optimizer/constant_fold.ts +88 -0
- package/src2/optimizer/copy_prop.ts +106 -0
- package/src2/optimizer/dce.ts +133 -0
- package/src2/optimizer/pipeline.ts +44 -0
- package/tsconfig.json +2 -2
- package/src/__tests__/codegen.test.ts +0 -161
- package/src/__tests__/e2e.test.ts +0 -2039
- package/src/__tests__/entity-types.test.ts +0 -236
- package/src/__tests__/lowering.test.ts +0 -1185
- package/src/__tests__/macro.test.ts +0 -343
- package/src/__tests__/nbt.test.ts +0 -58
- package/src/__tests__/optimizer-advanced.test.ts +0 -144
- package/src/__tests__/optimizer.test.ts +0 -162
- package/src/__tests__/runtime.test.ts +0 -305
- package/src/__tests__/stdlib-advanced.test.ts +0 -379
- package/src/__tests__/stdlib-bigint.test.ts +0 -427
- package/src/__tests__/stdlib-math.test.ts +0 -374
- package/src/__tests__/stdlib-vec.test.ts +0 -259
- package/src/__tests__/structure-optimizer.test.ts +0 -38
- package/src/__tests__/var-allocator.test.ts +0 -75
- package/src/codegen/cmdblock/index.ts +0 -63
- package/src/codegen/mcfunction/index.ts +0 -662
- package/src/codegen/structure/index.ts +0 -346
- package/src/codegen/var-allocator.ts +0 -104
- package/src/ir/builder.ts +0 -116
- package/src/ir/types.ts +0 -134
- package/src/lowering/index.ts +0 -3876
- package/src/optimizer/commands.ts +0 -534
- package/src/optimizer/dce.ts +0 -679
- package/src/optimizer/passes.ts +0 -250
- package/src/optimizer/structure.ts +0 -450
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const constant_fold_1 = require("../../optimizer/constant_fold");
|
|
4
|
+
function mkFn(blocks) {
|
|
5
|
+
return { name: 'test', params: [], blocks, entry: 'entry', isMacro: false };
|
|
6
|
+
}
|
|
7
|
+
function mkBlock(id, instrs, term) {
|
|
8
|
+
return { id, instrs, term, preds: [] };
|
|
9
|
+
}
|
|
10
|
+
const c = (v) => ({ kind: 'const', value: v });
|
|
11
|
+
const t = (n) => ({ kind: 'temp', name: n });
|
|
12
|
+
describe('constant folding', () => {
|
|
13
|
+
test('folds add(const, const)', () => {
|
|
14
|
+
const fn = mkFn([
|
|
15
|
+
mkBlock('entry', [
|
|
16
|
+
{ kind: 'add', dst: 't0', a: c(3), b: c(4) },
|
|
17
|
+
], { kind: 'return', value: t('t0') }),
|
|
18
|
+
]);
|
|
19
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
20
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: 7 });
|
|
21
|
+
});
|
|
22
|
+
test('folds sub(const, const)', () => {
|
|
23
|
+
const fn = mkFn([
|
|
24
|
+
mkBlock('entry', [
|
|
25
|
+
{ kind: 'sub', dst: 't0', a: c(10), b: c(3) },
|
|
26
|
+
], { kind: 'return', value: t('t0') }),
|
|
27
|
+
]);
|
|
28
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
29
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: 7 });
|
|
30
|
+
});
|
|
31
|
+
test('folds mul(const, const)', () => {
|
|
32
|
+
const fn = mkFn([
|
|
33
|
+
mkBlock('entry', [
|
|
34
|
+
{ kind: 'mul', dst: 't0', a: c(3), b: c(5) },
|
|
35
|
+
], { kind: 'return', value: t('t0') }),
|
|
36
|
+
]);
|
|
37
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
38
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: 15 });
|
|
39
|
+
});
|
|
40
|
+
test('folds div(const, const) with truncation', () => {
|
|
41
|
+
const fn = mkFn([
|
|
42
|
+
mkBlock('entry', [
|
|
43
|
+
{ kind: 'div', dst: 't0', a: c(7), b: c(2) },
|
|
44
|
+
], { kind: 'return', value: t('t0') }),
|
|
45
|
+
]);
|
|
46
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
47
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: 3 });
|
|
48
|
+
});
|
|
49
|
+
test('does not fold div by zero', () => {
|
|
50
|
+
const fn = mkFn([
|
|
51
|
+
mkBlock('entry', [
|
|
52
|
+
{ kind: 'div', dst: 't0', a: c(7), b: c(0) },
|
|
53
|
+
], { kind: 'return', value: t('t0') }),
|
|
54
|
+
]);
|
|
55
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
56
|
+
expect(result.blocks[0].instrs[0].kind).toBe('div');
|
|
57
|
+
});
|
|
58
|
+
test('folds mod(const, const)', () => {
|
|
59
|
+
const fn = mkFn([
|
|
60
|
+
mkBlock('entry', [
|
|
61
|
+
{ kind: 'mod', dst: 't0', a: c(7), b: c(3) },
|
|
62
|
+
], { kind: 'return', value: t('t0') }),
|
|
63
|
+
]);
|
|
64
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
65
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: 1 });
|
|
66
|
+
});
|
|
67
|
+
test('folds neg(const)', () => {
|
|
68
|
+
const fn = mkFn([
|
|
69
|
+
mkBlock('entry', [
|
|
70
|
+
{ kind: 'neg', dst: 't0', src: c(5) },
|
|
71
|
+
], { kind: 'return', value: t('t0') }),
|
|
72
|
+
]);
|
|
73
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
74
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: -5 });
|
|
75
|
+
});
|
|
76
|
+
test('folds not(0) → 1', () => {
|
|
77
|
+
const fn = mkFn([
|
|
78
|
+
mkBlock('entry', [
|
|
79
|
+
{ kind: 'not', dst: 't0', src: c(0) },
|
|
80
|
+
], { kind: 'return', value: t('t0') }),
|
|
81
|
+
]);
|
|
82
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
83
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: 1 });
|
|
84
|
+
});
|
|
85
|
+
test('folds cmp(lt, 3, 4) → 1', () => {
|
|
86
|
+
const fn = mkFn([
|
|
87
|
+
mkBlock('entry', [
|
|
88
|
+
{ kind: 'cmp', dst: 't0', op: 'lt', a: c(3), b: c(4) },
|
|
89
|
+
], { kind: 'return', value: t('t0') }),
|
|
90
|
+
]);
|
|
91
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
92
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: 1 });
|
|
93
|
+
});
|
|
94
|
+
test('folds cmp(eq, 5, 5) → 1', () => {
|
|
95
|
+
const fn = mkFn([
|
|
96
|
+
mkBlock('entry', [
|
|
97
|
+
{ kind: 'cmp', dst: 't0', op: 'eq', a: c(5), b: c(5) },
|
|
98
|
+
], { kind: 'return', value: t('t0') }),
|
|
99
|
+
]);
|
|
100
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
101
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: 1 });
|
|
102
|
+
});
|
|
103
|
+
test('folds and(1, 0) → 0', () => {
|
|
104
|
+
const fn = mkFn([
|
|
105
|
+
mkBlock('entry', [
|
|
106
|
+
{ kind: 'and', dst: 't0', a: c(1), b: c(0) },
|
|
107
|
+
], { kind: 'return', value: t('t0') }),
|
|
108
|
+
]);
|
|
109
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
110
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: 0 });
|
|
111
|
+
});
|
|
112
|
+
test('folds or(0, 1) → 1', () => {
|
|
113
|
+
const fn = mkFn([
|
|
114
|
+
mkBlock('entry', [
|
|
115
|
+
{ kind: 'or', dst: 't0', a: c(0), b: c(1) },
|
|
116
|
+
], { kind: 'return', value: t('t0') }),
|
|
117
|
+
]);
|
|
118
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
119
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 't0', value: 1 });
|
|
120
|
+
});
|
|
121
|
+
test('does not fold when operand is temp', () => {
|
|
122
|
+
const fn = mkFn([
|
|
123
|
+
mkBlock('entry', [
|
|
124
|
+
{ kind: 'add', dst: 't0', a: t('a'), b: c(4) },
|
|
125
|
+
], { kind: 'return', value: t('t0') }),
|
|
126
|
+
]);
|
|
127
|
+
const result = (0, constant_fold_1.constantFold)(fn);
|
|
128
|
+
expect(result.blocks[0].instrs[0].kind).toBe('add');
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
//# sourceMappingURL=constant_fold.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const copy_prop_1 = require("../../optimizer/copy_prop");
|
|
4
|
+
function mkFn(blocks) {
|
|
5
|
+
return { name: 'test', params: [], blocks, entry: 'entry', isMacro: false };
|
|
6
|
+
}
|
|
7
|
+
function mkBlock(id, instrs, term) {
|
|
8
|
+
return { id, instrs, term, preds: [] };
|
|
9
|
+
}
|
|
10
|
+
const c = (v) => ({ kind: 'const', value: v });
|
|
11
|
+
const t = (n) => ({ kind: 'temp', name: n });
|
|
12
|
+
describe('copy propagation', () => {
|
|
13
|
+
test('propagates copy into subsequent use', () => {
|
|
14
|
+
const fn = mkFn([
|
|
15
|
+
mkBlock('entry', [
|
|
16
|
+
{ kind: 'copy', dst: 'x', src: t('y') },
|
|
17
|
+
{ kind: 'add', dst: 'z', a: t('x'), b: c(1) },
|
|
18
|
+
], { kind: 'return', value: t('z') }),
|
|
19
|
+
]);
|
|
20
|
+
const result = (0, copy_prop_1.copyProp)(fn);
|
|
21
|
+
const add = result.blocks[0].instrs[1];
|
|
22
|
+
expect(add.kind).toBe('add');
|
|
23
|
+
expect(add.a).toEqual(t('y'));
|
|
24
|
+
});
|
|
25
|
+
test('propagates into terminator', () => {
|
|
26
|
+
const fn = mkFn([
|
|
27
|
+
mkBlock('entry', [
|
|
28
|
+
{ kind: 'copy', dst: 'x', src: t('y') },
|
|
29
|
+
], { kind: 'return', value: t('x') }),
|
|
30
|
+
]);
|
|
31
|
+
const result = (0, copy_prop_1.copyProp)(fn);
|
|
32
|
+
expect(result.blocks[0].term).toEqual({ kind: 'return', value: t('y') });
|
|
33
|
+
});
|
|
34
|
+
test('invalidates mapping when source is redefined', () => {
|
|
35
|
+
const fn = mkFn([
|
|
36
|
+
mkBlock('entry', [
|
|
37
|
+
{ kind: 'copy', dst: 'x', src: t('y') },
|
|
38
|
+
{ kind: 'const', dst: 'y', value: 99 },
|
|
39
|
+
{ kind: 'add', dst: 'z', a: t('x'), b: c(1) },
|
|
40
|
+
], { kind: 'return', value: t('z') }),
|
|
41
|
+
]);
|
|
42
|
+
const result = (0, copy_prop_1.copyProp)(fn);
|
|
43
|
+
// x's mapping was invalidated because y was redefined
|
|
44
|
+
const add = result.blocks[0].instrs[2];
|
|
45
|
+
expect(add.a).toEqual(t('x'));
|
|
46
|
+
});
|
|
47
|
+
test('propagates const definitions into uses', () => {
|
|
48
|
+
const fn = mkFn([
|
|
49
|
+
mkBlock('entry', [
|
|
50
|
+
{ kind: 'const', dst: 'x', value: 42 },
|
|
51
|
+
{ kind: 'add', dst: 'z', a: t('x'), b: c(1) },
|
|
52
|
+
], { kind: 'return', value: t('z') }),
|
|
53
|
+
]);
|
|
54
|
+
const result = (0, copy_prop_1.copyProp)(fn);
|
|
55
|
+
const add = result.blocks[0].instrs[1];
|
|
56
|
+
expect(add.a).toEqual(c(42));
|
|
57
|
+
});
|
|
58
|
+
test('propagates copy-of-const into uses', () => {
|
|
59
|
+
const fn = mkFn([
|
|
60
|
+
mkBlock('entry', [
|
|
61
|
+
{ kind: 'copy', dst: 'x', src: c(42) },
|
|
62
|
+
{ kind: 'add', dst: 'z', a: t('x'), b: c(1) },
|
|
63
|
+
], { kind: 'return', value: t('z') }),
|
|
64
|
+
]);
|
|
65
|
+
const result = (0, copy_prop_1.copyProp)(fn);
|
|
66
|
+
const add = result.blocks[0].instrs[1];
|
|
67
|
+
expect(add.a).toEqual(c(42));
|
|
68
|
+
});
|
|
69
|
+
test('chains propagation: x=y, z=x → z uses y', () => {
|
|
70
|
+
const fn = mkFn([
|
|
71
|
+
mkBlock('entry', [
|
|
72
|
+
{ kind: 'copy', dst: 'x', src: t('y') },
|
|
73
|
+
{ kind: 'copy', dst: 'z', src: t('x') },
|
|
74
|
+
], { kind: 'return', value: t('z') }),
|
|
75
|
+
]);
|
|
76
|
+
const result = (0, copy_prop_1.copyProp)(fn);
|
|
77
|
+
// z = copy x → rewritten to z = copy y
|
|
78
|
+
// then return z → rewritten to return y
|
|
79
|
+
expect(result.blocks[0].term).toEqual({ kind: 'return', value: t('y') });
|
|
80
|
+
});
|
|
81
|
+
test('propagates into branch condition', () => {
|
|
82
|
+
const fn = mkFn([
|
|
83
|
+
mkBlock('entry', [
|
|
84
|
+
{ kind: 'copy', dst: 'c', src: t('flag') },
|
|
85
|
+
], { kind: 'branch', cond: t('c'), then: 'b1', else: 'b2' }),
|
|
86
|
+
]);
|
|
87
|
+
const result = (0, copy_prop_1.copyProp)(fn);
|
|
88
|
+
expect(result.blocks[0].term).toEqual({ kind: 'branch', cond: t('flag'), then: 'b1', else: 'b2' });
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=copy_prop.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const dce_1 = require("../../optimizer/dce");
|
|
4
|
+
function mkFn(blocks, entry = 'entry') {
|
|
5
|
+
return { name: 'test', params: [], blocks, entry, isMacro: false };
|
|
6
|
+
}
|
|
7
|
+
function mkBlock(id, instrs, term, preds = []) {
|
|
8
|
+
return { id, instrs, term, preds };
|
|
9
|
+
}
|
|
10
|
+
const c = (v) => ({ kind: 'const', value: v });
|
|
11
|
+
const t = (n) => ({ kind: 'temp', name: n });
|
|
12
|
+
describe('dead code elimination', () => {
|
|
13
|
+
test('removes unused temp definition', () => {
|
|
14
|
+
const fn = mkFn([
|
|
15
|
+
mkBlock('entry', [
|
|
16
|
+
{ kind: 'const', dst: 'dead', value: 42 },
|
|
17
|
+
{ kind: 'const', dst: 'live', value: 1 },
|
|
18
|
+
], { kind: 'return', value: t('live') }),
|
|
19
|
+
]);
|
|
20
|
+
const result = (0, dce_1.dce)(fn);
|
|
21
|
+
expect(result.blocks[0].instrs).toHaveLength(1);
|
|
22
|
+
expect(result.blocks[0].instrs[0]).toEqual({ kind: 'const', dst: 'live', value: 1 });
|
|
23
|
+
});
|
|
24
|
+
test('keeps side-effectful instructions even if dst unused', () => {
|
|
25
|
+
const fn = mkFn([
|
|
26
|
+
mkBlock('entry', [
|
|
27
|
+
{ kind: 'call', dst: 'unused', fn: 'sideEffect', args: [] },
|
|
28
|
+
], { kind: 'return', value: null }),
|
|
29
|
+
]);
|
|
30
|
+
const result = (0, dce_1.dce)(fn);
|
|
31
|
+
expect(result.blocks[0].instrs).toHaveLength(1);
|
|
32
|
+
});
|
|
33
|
+
test('removes unreachable blocks', () => {
|
|
34
|
+
const fn = mkFn([
|
|
35
|
+
mkBlock('entry', [], { kind: 'return', value: null }),
|
|
36
|
+
mkBlock('dead_block', [
|
|
37
|
+
{ kind: 'const', dst: 't0', value: 99 },
|
|
38
|
+
], { kind: 'return', value: t('t0') }),
|
|
39
|
+
]);
|
|
40
|
+
const result = (0, dce_1.dce)(fn);
|
|
41
|
+
expect(result.blocks).toHaveLength(1);
|
|
42
|
+
expect(result.blocks[0].id).toBe('entry');
|
|
43
|
+
});
|
|
44
|
+
test('keeps reachable blocks', () => {
|
|
45
|
+
const fn = mkFn([
|
|
46
|
+
mkBlock('entry', [
|
|
47
|
+
{ kind: 'const', dst: 't0', value: 1 },
|
|
48
|
+
], { kind: 'branch', cond: t('t0'), then: 'b1', else: 'b2' }),
|
|
49
|
+
mkBlock('b1', [], { kind: 'return', value: null }, ['entry']),
|
|
50
|
+
mkBlock('b2', [], { kind: 'return', value: null }, ['entry']),
|
|
51
|
+
]);
|
|
52
|
+
const result = (0, dce_1.dce)(fn);
|
|
53
|
+
expect(result.blocks).toHaveLength(3);
|
|
54
|
+
});
|
|
55
|
+
test('recomputes preds after block removal', () => {
|
|
56
|
+
const fn = mkFn([
|
|
57
|
+
mkBlock('entry', [], { kind: 'jump', target: 'b1' }),
|
|
58
|
+
mkBlock('b1', [], { kind: 'return', value: null }, ['entry']),
|
|
59
|
+
mkBlock('dead', [], { kind: 'jump', target: 'b1' }),
|
|
60
|
+
]);
|
|
61
|
+
const result = (0, dce_1.dce)(fn);
|
|
62
|
+
expect(result.blocks).toHaveLength(2);
|
|
63
|
+
const b1 = result.blocks.find(b => b.id === 'b1');
|
|
64
|
+
expect(b1.preds).toEqual(['entry']);
|
|
65
|
+
});
|
|
66
|
+
test('keeps nbt_write even though it has no dst', () => {
|
|
67
|
+
const fn = mkFn([
|
|
68
|
+
mkBlock('entry', [
|
|
69
|
+
{ kind: 'nbt_write', ns: 'rs:data', path: 'x', type: 'int', scale: 1, src: c(5) },
|
|
70
|
+
], { kind: 'return', value: null }),
|
|
71
|
+
]);
|
|
72
|
+
const result = (0, dce_1.dce)(fn);
|
|
73
|
+
expect(result.blocks[0].instrs).toHaveLength(1);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=dce.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const pipeline_1 = require("../../optimizer/pipeline");
|
|
4
|
+
function mkFn(blocks, entry = 'entry') {
|
|
5
|
+
return { name: 'test', params: [], blocks, entry, isMacro: false };
|
|
6
|
+
}
|
|
7
|
+
function mkBlock(id, instrs, term, preds = []) {
|
|
8
|
+
return { id, instrs, term, preds };
|
|
9
|
+
}
|
|
10
|
+
const c = (v) => ({ kind: 'const', value: v });
|
|
11
|
+
const t = (n) => ({ kind: 'temp', name: n });
|
|
12
|
+
describe('optimization pipeline', () => {
|
|
13
|
+
test('constant fold + branch simplify + DCE removes dead branch', () => {
|
|
14
|
+
// cmp(lt, 1, 2) → 1 → branch(1, then, else) → jump(then) → else is dead
|
|
15
|
+
const fn = mkFn([
|
|
16
|
+
mkBlock('entry', [
|
|
17
|
+
{ kind: 'cmp', dst: 't0', op: 'lt', a: c(1), b: c(2) },
|
|
18
|
+
], { kind: 'branch', cond: t('t0'), then: 'then', else: 'else' }),
|
|
19
|
+
mkBlock('then', [], { kind: 'return', value: c(1) }, ['entry']),
|
|
20
|
+
mkBlock('else', [], { kind: 'return', value: c(0) }, ['entry']),
|
|
21
|
+
]);
|
|
22
|
+
const result = (0, pipeline_1.optimizeFunction)(fn);
|
|
23
|
+
// After optimization: entry should return 1 directly, else block removed
|
|
24
|
+
// The cmp folds to const 1, branch simplifies to jump(then),
|
|
25
|
+
// else block becomes unreachable and is removed,
|
|
26
|
+
// then block merges into entry
|
|
27
|
+
expect(result.blocks).toHaveLength(1);
|
|
28
|
+
expect(result.blocks[0].term).toEqual({ kind: 'return', value: c(1) });
|
|
29
|
+
});
|
|
30
|
+
test('copy prop + const fold + DCE eliminates dead copy and folds', () => {
|
|
31
|
+
const fn = mkFn([
|
|
32
|
+
mkBlock('entry', [
|
|
33
|
+
{ kind: 'const', dst: 'a', value: 5 },
|
|
34
|
+
{ kind: 'copy', dst: 'b', src: t('a') },
|
|
35
|
+
{ kind: 'add', dst: 'c', a: t('b'), b: c(1) },
|
|
36
|
+
], { kind: 'return', value: t('c') }),
|
|
37
|
+
]);
|
|
38
|
+
const result = (0, pipeline_1.optimizeFunction)(fn);
|
|
39
|
+
// const a=5 propagated into copy and add, add(5,1) folded to 6
|
|
40
|
+
// all dead defs removed, returns const 6
|
|
41
|
+
expect(result.blocks[0].term).toEqual({ kind: 'return', value: c(6) });
|
|
42
|
+
});
|
|
43
|
+
test('full pipeline: fold + simplify + merge + dce', () => {
|
|
44
|
+
// if (3 > 2) { return 10 + 20; } else { return 0; }
|
|
45
|
+
const fn = mkFn([
|
|
46
|
+
mkBlock('entry', [
|
|
47
|
+
{ kind: 'cmp', dst: 't0', op: 'gt', a: c(3), b: c(2) },
|
|
48
|
+
], { kind: 'branch', cond: t('t0'), then: 'then', else: 'else' }),
|
|
49
|
+
mkBlock('then', [
|
|
50
|
+
{ kind: 'add', dst: 't1', a: c(10), b: c(20) },
|
|
51
|
+
], { kind: 'return', value: t('t1') }, ['entry']),
|
|
52
|
+
mkBlock('else', [], { kind: 'return', value: c(0) }, ['entry']),
|
|
53
|
+
]);
|
|
54
|
+
const result = (0, pipeline_1.optimizeFunction)(fn);
|
|
55
|
+
// Everything folds away: single block returning const 30
|
|
56
|
+
expect(result.blocks).toHaveLength(1);
|
|
57
|
+
expect(result.blocks[0].term).toEqual({ kind: 'return', value: c(30) });
|
|
58
|
+
});
|
|
59
|
+
test('optimizeModule applies to all functions', () => {
|
|
60
|
+
const mod = {
|
|
61
|
+
namespace: 'test',
|
|
62
|
+
objective: '__test',
|
|
63
|
+
functions: [
|
|
64
|
+
mkFn([
|
|
65
|
+
mkBlock('entry', [
|
|
66
|
+
{ kind: 'add', dst: 't0', a: c(1), b: c(2) },
|
|
67
|
+
], { kind: 'return', value: t('t0') }),
|
|
68
|
+
]),
|
|
69
|
+
mkFn([
|
|
70
|
+
mkBlock('entry', [
|
|
71
|
+
{ kind: 'mul', dst: 't0', a: c(3), b: c(4) },
|
|
72
|
+
], { kind: 'return', value: t('t0') }),
|
|
73
|
+
]),
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
const result = (0, pipeline_1.optimizeModule)(mod);
|
|
77
|
+
// Both functions should have their constants folded
|
|
78
|
+
for (const fn of result.functions) {
|
|
79
|
+
const instrs = fn.blocks[0].instrs;
|
|
80
|
+
const hasArith = instrs.some(i => i.kind === 'add' || i.kind === 'mul');
|
|
81
|
+
expect(hasArith).toBe(false);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
test('fixpoint: multiple iterations needed', () => {
|
|
85
|
+
// First iteration: fold add → const, fold cmp → const
|
|
86
|
+
// Second iteration: branch simplify on newly-const cond
|
|
87
|
+
// Third iteration: DCE removes dead block, merge
|
|
88
|
+
const fn = mkFn([
|
|
89
|
+
mkBlock('entry', [
|
|
90
|
+
{ kind: 'add', dst: 't0', a: c(1), b: c(1) },
|
|
91
|
+
{ kind: 'cmp', dst: 't1', op: 'eq', a: t('t0'), b: c(2) },
|
|
92
|
+
], { kind: 'branch', cond: t('t1'), then: 'yes', else: 'no' }),
|
|
93
|
+
mkBlock('yes', [], { kind: 'return', value: c(1) }, ['entry']),
|
|
94
|
+
mkBlock('no', [], { kind: 'return', value: c(0) }, ['entry']),
|
|
95
|
+
]);
|
|
96
|
+
const result = (0, pipeline_1.optimizeFunction)(fn);
|
|
97
|
+
// 1+1=2, 2==2 → 1, branch(1) → jump(yes), dead block removed, merged
|
|
98
|
+
expect(result.blocks).toHaveLength(1);
|
|
99
|
+
expect(result.blocks[0].term).toEqual({ kind: 'return', value: c(1) });
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
//# sourceMappingURL=pipeline.test.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top-level compile function for the v2 pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Pipeline: source → Lexer → Parser → HIR → MIR → optimize → LIR → emit
|
|
5
|
+
*/
|
|
6
|
+
import { type DatapackFile } from './index';
|
|
7
|
+
export interface CompileOptions {
|
|
8
|
+
namespace?: string;
|
|
9
|
+
filePath?: string;
|
|
10
|
+
/** v1 compat: inline library sources (treated as `module library;` imports) */
|
|
11
|
+
librarySources?: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface CompileResult {
|
|
14
|
+
files: DatapackFile[];
|
|
15
|
+
warnings: string[];
|
|
16
|
+
/** Always true — v1 compat shim (compile() throws on error) */
|
|
17
|
+
readonly success: true;
|
|
18
|
+
}
|
|
19
|
+
export declare function compile(source: string, options?: CompileOptions): CompileResult;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Top-level compile function for the v2 pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Pipeline: source → Lexer → Parser → HIR → MIR → optimize → LIR → emit
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.compile = compile;
|
|
9
|
+
const lexer_1 = require("../../src/lexer");
|
|
10
|
+
const parser_1 = require("../../src/parser");
|
|
11
|
+
const compile_1 = require("../../src/compile");
|
|
12
|
+
const lower_1 = require("../hir/lower");
|
|
13
|
+
const lower_2 = require("../mir/lower");
|
|
14
|
+
const pipeline_1 = require("../optimizer/pipeline");
|
|
15
|
+
const lower_3 = require("../lir/lower");
|
|
16
|
+
const index_1 = require("./index");
|
|
17
|
+
function compile(source, options = {}) {
|
|
18
|
+
const { namespace = 'redscript', filePath } = options;
|
|
19
|
+
const warnings = [];
|
|
20
|
+
// Preprocess: resolve import directives, merge imported sources
|
|
21
|
+
const preprocessed = (0, compile_1.preprocessSourceWithMetadata)(source, { filePath });
|
|
22
|
+
const processedSource = preprocessed.source;
|
|
23
|
+
// Stage 1: Lex + Parse → AST
|
|
24
|
+
const lexer = new lexer_1.Lexer(processedSource);
|
|
25
|
+
const tokens = lexer.tokenize();
|
|
26
|
+
const parser = new parser_1.Parser(tokens, processedSource, filePath);
|
|
27
|
+
const ast = parser.parse(namespace);
|
|
28
|
+
// Merge library imports (files with `module library;`) into AST
|
|
29
|
+
for (const li of preprocessed.libraryImports ?? []) {
|
|
30
|
+
const libPreprocessed = (0, compile_1.preprocessSourceWithMetadata)(li.source, { filePath: li.filePath });
|
|
31
|
+
const libTokens = new lexer_1.Lexer(libPreprocessed.source, li.filePath).tokenize();
|
|
32
|
+
const libAst = new parser_1.Parser(libTokens, libPreprocessed.source, li.filePath).parse(namespace);
|
|
33
|
+
for (const fn of libAst.declarations)
|
|
34
|
+
fn.isLibraryFn = true;
|
|
35
|
+
ast.declarations.push(...libAst.declarations);
|
|
36
|
+
ast.structs.push(...libAst.structs);
|
|
37
|
+
ast.implBlocks.push(...libAst.implBlocks);
|
|
38
|
+
ast.enums.push(...libAst.enums);
|
|
39
|
+
ast.consts.push(...libAst.consts);
|
|
40
|
+
ast.globals.push(...libAst.globals);
|
|
41
|
+
}
|
|
42
|
+
// Merge librarySources (v1 compat: inline library strings) before HIR
|
|
43
|
+
if (options.librarySources) {
|
|
44
|
+
for (const libSrc of options.librarySources) {
|
|
45
|
+
const libTokens = new lexer_1.Lexer(libSrc).tokenize();
|
|
46
|
+
const libAst = new parser_1.Parser(libTokens, libSrc).parse(namespace);
|
|
47
|
+
for (const fn of libAst.declarations)
|
|
48
|
+
fn.isLibraryFn = true;
|
|
49
|
+
ast.declarations.push(...libAst.declarations);
|
|
50
|
+
ast.structs.push(...libAst.structs);
|
|
51
|
+
ast.implBlocks.push(...libAst.implBlocks);
|
|
52
|
+
ast.enums.push(...libAst.enums);
|
|
53
|
+
ast.consts.push(...libAst.consts);
|
|
54
|
+
ast.globals.push(...libAst.globals);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Stage 2: AST → HIR
|
|
58
|
+
const hir = (0, lower_1.lowerToHIR)(ast);
|
|
59
|
+
// Extract @tick and @load functions from HIR (before decorator info is lost)
|
|
60
|
+
const tickFunctions = [];
|
|
61
|
+
const loadFunctions = [];
|
|
62
|
+
for (const fn of hir.functions) {
|
|
63
|
+
for (const dec of fn.decorators) {
|
|
64
|
+
if (dec.name === 'tick')
|
|
65
|
+
tickFunctions.push(fn.name);
|
|
66
|
+
if (dec.name === 'load')
|
|
67
|
+
loadFunctions.push(fn.name);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Stage 3: HIR → MIR
|
|
71
|
+
const mir = (0, lower_2.lowerToMIR)(hir);
|
|
72
|
+
// Stage 4: MIR optimization
|
|
73
|
+
const mirOpt = (0, pipeline_1.optimizeModule)(mir);
|
|
74
|
+
// Stage 5: MIR → LIR
|
|
75
|
+
const lir = (0, lower_3.lowerToLIR)(mirOpt);
|
|
76
|
+
// Stage 7: LIR → .mcfunction
|
|
77
|
+
const files = (0, index_1.emit)(lir, { namespace, tickFunctions, loadFunctions });
|
|
78
|
+
return { files, warnings, success: true };
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 7 — LIR → .mcfunction Emission
|
|
3
|
+
*
|
|
4
|
+
* Converts a LIRModule into DatapackFile[] representing a Minecraft datapack.
|
|
5
|
+
* Each LIRFunction becomes a .mcfunction file under data/<ns>/function/.
|
|
6
|
+
*/
|
|
7
|
+
import type { LIRModule } from '../lir/types';
|
|
8
|
+
export interface DatapackFile {
|
|
9
|
+
path: string;
|
|
10
|
+
content: string;
|
|
11
|
+
}
|
|
12
|
+
export interface EmitOptions {
|
|
13
|
+
namespace: string;
|
|
14
|
+
tickFunctions?: string[];
|
|
15
|
+
loadFunctions?: string[];
|
|
16
|
+
}
|
|
17
|
+
export declare function emit(module: LIRModule, options: EmitOptions): DatapackFile[];
|