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 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,124 @@
|
|
|
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 fs = __importStar(require("fs"));
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const compile_1 = require("../compile");
|
|
39
|
+
const mc_validator_1 = require("../mc-validator");
|
|
40
|
+
const FIXTURE_PATH = path.join(__dirname, 'fixtures', 'mc-commands-1.21.4.json');
|
|
41
|
+
const EXAMPLES = ['counter', 'arena', 'shop', 'quiz', 'turret'];
|
|
42
|
+
function getCommands(source, namespace = 'test') {
|
|
43
|
+
const result = (0, compile_1.compile)(source, { namespace });
|
|
44
|
+
expect(result.success).toBe(true);
|
|
45
|
+
expect(result.files).toBeDefined();
|
|
46
|
+
return (result.files ?? [])
|
|
47
|
+
.filter(file => file.path.endsWith('.mcfunction'))
|
|
48
|
+
.flatMap(file => file.content.split('\n'))
|
|
49
|
+
.filter(line => line.trim().length > 0);
|
|
50
|
+
}
|
|
51
|
+
function validateSource(validator, source, namespace) {
|
|
52
|
+
return getCommands(source, namespace)
|
|
53
|
+
.map(cmd => ({ cmd, result: validator.validate(cmd) }))
|
|
54
|
+
.filter(entry => !entry.result.valid)
|
|
55
|
+
.map(entry => ({ cmd: entry.cmd, error: entry.result.error }));
|
|
56
|
+
}
|
|
57
|
+
describe('MC Command Syntax Validation', () => {
|
|
58
|
+
const validator = new mc_validator_1.MCCommandValidator(FIXTURE_PATH);
|
|
59
|
+
test('counter example generates valid MC commands', () => {
|
|
60
|
+
const src = fs.readFileSync(path.join(__dirname, '..', 'examples', 'counter.mcrs'), 'utf-8');
|
|
61
|
+
const errors = validateSource(validator, src, 'counter');
|
|
62
|
+
expect(errors).toHaveLength(0);
|
|
63
|
+
});
|
|
64
|
+
EXAMPLES.forEach(name => {
|
|
65
|
+
test(`${name}.mcrs generates valid MC commands`, () => {
|
|
66
|
+
const src = fs.readFileSync(path.join(__dirname, '..', 'examples', `${name}.mcrs`), 'utf-8');
|
|
67
|
+
const errors = validateSource(validator, src, name);
|
|
68
|
+
if (errors.length > 0) {
|
|
69
|
+
console.log('Invalid commands:', errors);
|
|
70
|
+
}
|
|
71
|
+
expect(errors).toHaveLength(0);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
test('string interpolation generates valid tellraw', () => {
|
|
75
|
+
const errors = validateSource(validator, `
|
|
76
|
+
fn chat() {
|
|
77
|
+
let score: int = 7;
|
|
78
|
+
say("You have \${score} points");
|
|
79
|
+
}
|
|
80
|
+
`, 'interpolation');
|
|
81
|
+
expect(errors).toHaveLength(0);
|
|
82
|
+
});
|
|
83
|
+
test('f-strings generate valid tellraw/title commands', () => {
|
|
84
|
+
const errors = validateSource(validator, `
|
|
85
|
+
fn chat() {
|
|
86
|
+
let score: int = 7;
|
|
87
|
+
say(f"You have {score} points");
|
|
88
|
+
tellraw(@a, f"Score: {score}");
|
|
89
|
+
actionbar(@s, f"Score: {score}");
|
|
90
|
+
title(@s, f"Score: {score}");
|
|
91
|
+
}
|
|
92
|
+
`, 'f-string');
|
|
93
|
+
expect(errors).toHaveLength(0);
|
|
94
|
+
});
|
|
95
|
+
test('array operations generate valid data commands', () => {
|
|
96
|
+
const errors = validateSource(validator, `
|
|
97
|
+
fn arrays() {
|
|
98
|
+
let arr: int[] = [];
|
|
99
|
+
arr.push(4);
|
|
100
|
+
arr.push(9);
|
|
101
|
+
let popped: int = arr.pop();
|
|
102
|
+
let len: int = arr.len;
|
|
103
|
+
|
|
104
|
+
scoreboard_set("arrays", "len", len);
|
|
105
|
+
scoreboard_set("arrays", "last", popped);
|
|
106
|
+
}
|
|
107
|
+
`, 'arrays');
|
|
108
|
+
expect(errors).toHaveLength(0);
|
|
109
|
+
});
|
|
110
|
+
test('match generates valid execute commands', () => {
|
|
111
|
+
const errors = validateSource(validator, `
|
|
112
|
+
fn choose() {
|
|
113
|
+
let choice: int = 2;
|
|
114
|
+
match (choice) {
|
|
115
|
+
1 => { say("one"); }
|
|
116
|
+
2 => { say("two"); }
|
|
117
|
+
_ => { say("other"); }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
`, 'matching');
|
|
121
|
+
expect(errors).toHaveLength(0);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
//# sourceMappingURL=mc-syntax.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
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 fs = __importStar(require("fs"));
|
|
37
|
+
const structure_1 = require("../codegen/structure");
|
|
38
|
+
const nbt_1 = require("../nbt");
|
|
39
|
+
describe('NBT codec', () => {
|
|
40
|
+
test('round-trips a compound tag', () => {
|
|
41
|
+
const tag = nbt_1.nbt.compound({ x: nbt_1.nbt.int(42), name: nbt_1.nbt.string('test') });
|
|
42
|
+
const buf = (0, nbt_1.writeNbt)(tag, 'root');
|
|
43
|
+
const parsed = (0, nbt_1.readNbt)(buf);
|
|
44
|
+
expect(parsed.name).toBe('root');
|
|
45
|
+
expect(parsed.tag).toEqual(tag);
|
|
46
|
+
});
|
|
47
|
+
test('round-trips nested lists and arrays', () => {
|
|
48
|
+
const tag = nbt_1.nbt.compound({
|
|
49
|
+
nested: nbt_1.nbt.list(10 /* TagType.Compound */, [
|
|
50
|
+
nbt_1.nbt.compound({ values: nbt_1.nbt.intArray([1, 2, 3]) }),
|
|
51
|
+
nbt_1.nbt.compound({ bytes: nbt_1.nbt.byteArray([-1, 0, 1]) }),
|
|
52
|
+
]),
|
|
53
|
+
longs: { type: 12 /* TagType.LongArray */, value: BigInt64Array.from([1n, 2n, 3n]) },
|
|
54
|
+
});
|
|
55
|
+
const buf = (0, nbt_1.writeNbt)(tag, 'root');
|
|
56
|
+
const parsed = (0, nbt_1.readNbt)(buf);
|
|
57
|
+
expect(parsed.tag).toEqual(tag);
|
|
58
|
+
});
|
|
59
|
+
test('handles longs correctly', () => {
|
|
60
|
+
const tag = nbt_1.nbt.compound({ ts: nbt_1.nbt.long(9007199254740993n) });
|
|
61
|
+
const buf = (0, nbt_1.writeNbt)(tag, '');
|
|
62
|
+
const parsed = (0, nbt_1.readNbt)(buf);
|
|
63
|
+
const root = parsed.tag;
|
|
64
|
+
expect(root.entries.get('ts')).toEqual(nbt_1.nbt.long(9007199254740993n));
|
|
65
|
+
expect(root.entries.get('ts').value).toBe(9007199254740993n);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe('Structure generator', () => {
|
|
69
|
+
test('compiles counter.mcrs to a non-empty structure', () => {
|
|
70
|
+
const filePath = 'src/examples/counter.mcrs';
|
|
71
|
+
const src = fs.readFileSync(filePath, 'utf-8');
|
|
72
|
+
const { buffer, blockCount } = (0, structure_1.compileToStructure)(src, 'counter', filePath);
|
|
73
|
+
expect(buffer.length).toBeGreaterThan(100);
|
|
74
|
+
expect(blockCount).toBeGreaterThan(0);
|
|
75
|
+
const parsed = (0, nbt_1.readNbt)(buffer);
|
|
76
|
+
const root = parsed.tag;
|
|
77
|
+
const blocks = root.entries.get('blocks');
|
|
78
|
+
expect(parsed.name).toBe('');
|
|
79
|
+
expect(blocks?.type).toBe(9 /* TagType.List */);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=nbt.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const index_1 = require("../index");
|
|
4
|
+
const structure_1 = require("../codegen/structure");
|
|
5
|
+
function getFileContent(files, suffix) {
|
|
6
|
+
const file = files.find(candidate => candidate.path.endsWith(suffix));
|
|
7
|
+
if (!file) {
|
|
8
|
+
throw new Error(`Missing file: ${suffix}`);
|
|
9
|
+
}
|
|
10
|
+
return file.content;
|
|
11
|
+
}
|
|
12
|
+
describe('LICM', () => {
|
|
13
|
+
test('hoists loop-invariant scoreboard read out of foreach', () => {
|
|
14
|
+
const source = `
|
|
15
|
+
fn turret_tick() {
|
|
16
|
+
foreach (turret in @e[tag=turret]) {
|
|
17
|
+
let range: int = scoreboard_get("config", "turret_range");
|
|
18
|
+
if (range > 0) {
|
|
19
|
+
if (range > -1) {
|
|
20
|
+
say("ready");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
const result = (0, index_1.compile)(source, { namespace: 'test' });
|
|
27
|
+
const parent = getFileContent(result.files, 'data/test/function/turret_tick.mcfunction');
|
|
28
|
+
const loopBody = getFileContent(result.files, 'data/test/function/turret_tick/foreach_0.mcfunction');
|
|
29
|
+
const hoistedRead = 'execute store result score $_0 __test run scoreboard players get config test.turret_range';
|
|
30
|
+
const executeCall = 'execute as @e[tag=turret] run function test:turret_tick/foreach_0';
|
|
31
|
+
expect(parent).toContain(hoistedRead);
|
|
32
|
+
expect(parent.indexOf(hoistedRead)).toBeLessThan(parent.indexOf(executeCall));
|
|
33
|
+
expect(loopBody).not.toContain('scoreboard players get config test.turret_range');
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe('CSE', () => {
|
|
37
|
+
test('eliminates duplicate scoreboard reads', () => {
|
|
38
|
+
const source = `
|
|
39
|
+
fn read_twice() {
|
|
40
|
+
let a: int = scoreboard_get(@s, "coins");
|
|
41
|
+
let b: int = scoreboard_get(@s, "coins");
|
|
42
|
+
if (a == b) {
|
|
43
|
+
say("same");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
const result = (0, index_1.compile)(source, { namespace: 'test' });
|
|
48
|
+
const fn = getFileContent(result.files, 'data/test/function/read_twice.mcfunction');
|
|
49
|
+
const readMatches = fn.match(/scoreboard players get @s test\.coins/g) ?? [];
|
|
50
|
+
expect(readMatches).toHaveLength(1);
|
|
51
|
+
expect(fn).toContain('scoreboard players operation $_1 __test = $_0 __test');
|
|
52
|
+
});
|
|
53
|
+
test('reuses duplicate arithmetic sequences', () => {
|
|
54
|
+
const source = `
|
|
55
|
+
fn math() {
|
|
56
|
+
let base: int = 4;
|
|
57
|
+
let a: int = base + 2;
|
|
58
|
+
let b: int = base + 2;
|
|
59
|
+
if (a == b) {
|
|
60
|
+
say("same");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
64
|
+
const result = (0, index_1.compile)(source, { namespace: 'test' });
|
|
65
|
+
const fn = getFileContent(result.files, 'data/test/function/math.mcfunction');
|
|
66
|
+
const addMatches = fn.match(/\+= \$const_2 __test/g) ?? [];
|
|
67
|
+
expect(addMatches).toHaveLength(1);
|
|
68
|
+
expect(fn).toContain('scoreboard players operation $_1 __test = $_0 __test');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('setblock batching', () => {
|
|
72
|
+
test('merges 4 consecutive setblocks into fill', () => {
|
|
73
|
+
const source = `
|
|
74
|
+
fn build() {
|
|
75
|
+
setblock((0, 64, 0), "minecraft:stone");
|
|
76
|
+
setblock((1, 64, 0), "minecraft:stone");
|
|
77
|
+
setblock((2, 64, 0), "minecraft:stone");
|
|
78
|
+
setblock((3, 64, 0), "minecraft:stone");
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
81
|
+
const result = (0, index_1.compile)(source, { namespace: 'test' });
|
|
82
|
+
const fn = getFileContent(result.files, 'data/test/function/build.mcfunction');
|
|
83
|
+
expect(fn).toContain('fill 0 64 0 3 64 0 minecraft:stone');
|
|
84
|
+
expect(fn).not.toContain('setblock 1 64 0 minecraft:stone');
|
|
85
|
+
});
|
|
86
|
+
test('does not merge setblocks with different blocks', () => {
|
|
87
|
+
const source = `
|
|
88
|
+
fn build() {
|
|
89
|
+
setblock((0, 64, 0), "minecraft:stone");
|
|
90
|
+
setblock((1, 64, 0), "minecraft:dirt");
|
|
91
|
+
}
|
|
92
|
+
`;
|
|
93
|
+
const result = (0, index_1.compile)(source, { namespace: 'test' });
|
|
94
|
+
const fn = getFileContent(result.files, 'data/test/function/build.mcfunction');
|
|
95
|
+
expect(fn).toContain('setblock 0 64 0 minecraft:stone');
|
|
96
|
+
expect(fn).toContain('setblock 1 64 0 minecraft:dirt');
|
|
97
|
+
expect(fn).not.toContain('fill 0 64 0 1 64 0');
|
|
98
|
+
});
|
|
99
|
+
test('does not merge non-adjacent setblocks', () => {
|
|
100
|
+
const source = `
|
|
101
|
+
fn build() {
|
|
102
|
+
setblock((0, 64, 0), "minecraft:stone");
|
|
103
|
+
setblock((2, 64, 0), "minecraft:stone");
|
|
104
|
+
}
|
|
105
|
+
`;
|
|
106
|
+
const result = (0, index_1.compile)(source, { namespace: 'test' });
|
|
107
|
+
const fn = getFileContent(result.files, 'data/test/function/build.mcfunction');
|
|
108
|
+
expect(fn).toContain('setblock 0 64 0 minecraft:stone');
|
|
109
|
+
expect(fn).toContain('setblock 2 64 0 minecraft:stone');
|
|
110
|
+
expect(fn).not.toContain('fill 0 64 0 2 64 0');
|
|
111
|
+
});
|
|
112
|
+
test('applies batching to structure target output too', () => {
|
|
113
|
+
const source = `
|
|
114
|
+
fn build() {
|
|
115
|
+
setblock((0, 64, 0), "minecraft:stone");
|
|
116
|
+
setblock((1, 64, 0), "minecraft:stone");
|
|
117
|
+
setblock((2, 64, 0), "minecraft:stone");
|
|
118
|
+
}
|
|
119
|
+
`;
|
|
120
|
+
const result = (0, structure_1.compileToStructure)(source, 'test');
|
|
121
|
+
expect(result.blocks.some(block => block.command === 'fill 0 64 0 2 64 0 minecraft:stone')).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
//# sourceMappingURL=optimizer-advanced.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const passes_1 = require("../optimizer/passes");
|
|
4
|
+
function makeFn(instrs, term = { op: 'return' }) {
|
|
5
|
+
return {
|
|
6
|
+
name: 'test',
|
|
7
|
+
params: [],
|
|
8
|
+
locals: [],
|
|
9
|
+
blocks: [{ label: 'entry', instrs, term }],
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
describe('constantFolding', () => {
|
|
13
|
+
it('folds 2 + 3 → 5', () => {
|
|
14
|
+
const fn = makeFn([
|
|
15
|
+
{ op: 'binop', dst: '$x', lhs: { kind: 'const', value: 2 }, bop: '+', rhs: { kind: 'const', value: 3 } },
|
|
16
|
+
]);
|
|
17
|
+
const opt = (0, passes_1.constantFolding)(fn);
|
|
18
|
+
expect(opt.blocks[0].instrs[0]).toEqual({
|
|
19
|
+
op: 'assign', dst: '$x', src: { kind: 'const', value: 5 },
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
it('folds 10 / 3 → 3 (truncated int division)', () => {
|
|
23
|
+
const fn = makeFn([
|
|
24
|
+
{ op: 'binop', dst: '$x', lhs: { kind: 'const', value: 10 }, bop: '/', rhs: { kind: 'const', value: 3 } },
|
|
25
|
+
]);
|
|
26
|
+
const opt = (0, passes_1.constantFolding)(fn);
|
|
27
|
+
expect(opt.blocks[0].instrs[0].src.value).toBe(3);
|
|
28
|
+
});
|
|
29
|
+
it('folds cmp 5 == 5 → 1', () => {
|
|
30
|
+
const fn = makeFn([
|
|
31
|
+
{ op: 'cmp', dst: '$r', lhs: { kind: 'const', value: 5 }, cop: '==', rhs: { kind: 'const', value: 5 } },
|
|
32
|
+
]);
|
|
33
|
+
const opt = (0, passes_1.constantFolding)(fn);
|
|
34
|
+
expect(opt.blocks[0].instrs[0].src.value).toBe(1);
|
|
35
|
+
});
|
|
36
|
+
it('folds cmp 5 > 10 → 0', () => {
|
|
37
|
+
const fn = makeFn([
|
|
38
|
+
{ op: 'cmp', dst: '$r', lhs: { kind: 'const', value: 5 }, cop: '>', rhs: { kind: 'const', value: 10 } },
|
|
39
|
+
]);
|
|
40
|
+
const opt = (0, passes_1.constantFolding)(fn);
|
|
41
|
+
expect(opt.blocks[0].instrs[0].src.value).toBe(0);
|
|
42
|
+
});
|
|
43
|
+
it('does not fold division by zero', () => {
|
|
44
|
+
const fn = makeFn([
|
|
45
|
+
{ op: 'binop', dst: '$x', lhs: { kind: 'const', value: 5 }, bop: '/', rhs: { kind: 'const', value: 0 } },
|
|
46
|
+
]);
|
|
47
|
+
const opt = (0, passes_1.constantFolding)(fn);
|
|
48
|
+
expect(opt.blocks[0].instrs[0].op).toBe('binop');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('copyPropagation', () => {
|
|
52
|
+
it('propagates simple copy', () => {
|
|
53
|
+
const fn = makeFn([
|
|
54
|
+
{ op: 'assign', dst: '$t0', src: { kind: 'var', name: '$x' } },
|
|
55
|
+
{ op: 'binop', dst: '$y', lhs: { kind: 'var', name: '$t0' }, bop: '+', rhs: { kind: 'const', value: 1 } },
|
|
56
|
+
]);
|
|
57
|
+
const opt = (0, passes_1.copyPropagation)(fn);
|
|
58
|
+
const binop = opt.blocks[0].instrs[1];
|
|
59
|
+
expect(binop.lhs).toEqual({ kind: 'var', name: '$x' });
|
|
60
|
+
});
|
|
61
|
+
it('propagates constant copies', () => {
|
|
62
|
+
const fn = makeFn([
|
|
63
|
+
{ op: 'assign', dst: '$t0', src: { kind: 'const', value: 42 } },
|
|
64
|
+
{ op: 'assign', dst: '$y', src: { kind: 'var', name: '$t0' } },
|
|
65
|
+
]);
|
|
66
|
+
const opt = (0, passes_1.copyPropagation)(fn);
|
|
67
|
+
const second = opt.blocks[0].instrs[1];
|
|
68
|
+
expect(second.src).toEqual({ kind: 'const', value: 42 });
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('deadCodeElimination', () => {
|
|
72
|
+
it('removes unused assignment', () => {
|
|
73
|
+
const fn = makeFn([
|
|
74
|
+
{ op: 'assign', dst: '$t0', src: { kind: 'const', value: 99 } }, // unused temp
|
|
75
|
+
{ op: 'assign', dst: '$t1', src: { kind: 'const', value: 1 } }, // used temp
|
|
76
|
+
], { op: 'return', value: { kind: 'var', name: '$t1' } });
|
|
77
|
+
const opt = (0, passes_1.deadCodeElimination)(fn);
|
|
78
|
+
expect(opt.blocks[0].instrs).toHaveLength(1);
|
|
79
|
+
expect(opt.blocks[0].instrs[0].dst).toBe('$t1');
|
|
80
|
+
});
|
|
81
|
+
it('keeps call even if return value unused (side effects)', () => {
|
|
82
|
+
const fn = makeFn([
|
|
83
|
+
{ op: 'call', fn: 'foo', args: [], dst: '$unused' },
|
|
84
|
+
]);
|
|
85
|
+
const opt = (0, passes_1.deadCodeElimination)(fn);
|
|
86
|
+
expect(opt.blocks[0].instrs).toHaveLength(1);
|
|
87
|
+
});
|
|
88
|
+
it('keeps assignments referenced by raw commands', () => {
|
|
89
|
+
const fn = makeFn([
|
|
90
|
+
{ op: 'assign', dst: '$used_by_raw', src: { kind: 'const', value: 7 } },
|
|
91
|
+
{ op: 'raw', cmd: 'execute store result score player obj run scoreboard players get $used_by_raw rs' },
|
|
92
|
+
]);
|
|
93
|
+
const opt = (0, passes_1.deadCodeElimination)(fn);
|
|
94
|
+
expect(opt.blocks[0].instrs).toHaveLength(2);
|
|
95
|
+
expect(opt.blocks[0].instrs[0].dst).toBe('$used_by_raw');
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
describe('copyPropagation – stale alias invalidation', () => {
|
|
99
|
+
it('does not propagate $tmp = $y after $y is overwritten (swap pattern)', () => {
|
|
100
|
+
// Simulates: let tmp = y; y = x % y; x = tmp
|
|
101
|
+
// The copy $tmp = $y must be invalidated when $y is reassigned.
|
|
102
|
+
// Before fix: x = tmp was propagated to x = y (new y, wrong value).
|
|
103
|
+
const fn = makeFn([
|
|
104
|
+
{ op: 'assign', dst: '$tmp', src: { kind: 'var', name: '$y' } }, // tmp = y
|
|
105
|
+
{ op: 'binop', dst: '$r', lhs: { kind: 'var', name: '$x' }, bop: '%', rhs: { kind: 'var', name: '$y' } }, // r = x%y
|
|
106
|
+
{ op: 'assign', dst: '$y', src: { kind: 'var', name: '$r' } }, // y = r ← stale: tmp still points to OLD y
|
|
107
|
+
{ op: 'assign', dst: '$x', src: { kind: 'var', name: '$tmp' } }, // x = tmp (should NOT be x = y)
|
|
108
|
+
]);
|
|
109
|
+
const opt = (0, passes_1.copyPropagation)(fn);
|
|
110
|
+
const instrs = opt.blocks[0].instrs;
|
|
111
|
+
const xAssign = instrs.find((i) => i.dst === '$x');
|
|
112
|
+
// x = tmp must NOT be optimised to x = $y (stale) or x = $r (new y).
|
|
113
|
+
// It should stay as x = $tmp (the original copy).
|
|
114
|
+
expect(xAssign.src).toEqual({ kind: 'var', name: '$tmp' });
|
|
115
|
+
});
|
|
116
|
+
it('still propagates simple non-conflicting copies', () => {
|
|
117
|
+
// a = 5; b = a; c = b → after propagation b and c should both be const 5
|
|
118
|
+
const fn = makeFn([
|
|
119
|
+
{ op: 'assign', dst: '$a', src: { kind: 'const', value: 5 } },
|
|
120
|
+
{ op: 'assign', dst: '$b', src: { kind: 'var', name: '$a' } },
|
|
121
|
+
{ op: 'assign', dst: '$c', src: { kind: 'var', name: '$b' } },
|
|
122
|
+
]);
|
|
123
|
+
const opt = (0, passes_1.copyPropagation)(fn);
|
|
124
|
+
const instrs = opt.blocks[0].instrs;
|
|
125
|
+
const cAssign = instrs.find((i) => i.dst === '$c');
|
|
126
|
+
expect(cAssign.src).toEqual({ kind: 'const', value: 5 });
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe('optimize pipeline', () => {
|
|
130
|
+
it('combines all passes', () => {
|
|
131
|
+
// t0 = 2 + 3 (→ constant fold → t0 = 5)
|
|
132
|
+
// x = t0 (→ copy prop → x = 5)
|
|
133
|
+
// unused = 0 (→ DCE → removed)
|
|
134
|
+
// return x
|
|
135
|
+
const fn = makeFn([
|
|
136
|
+
{ op: 'binop', dst: '$t0', lhs: { kind: 'const', value: 2 }, bop: '+', rhs: { kind: 'const', value: 3 } },
|
|
137
|
+
{ op: 'assign', dst: '$x', src: { kind: 'var', name: '$t0' } },
|
|
138
|
+
{ op: 'assign', dst: '$t1', src: { kind: 'const', value: 0 } }, // unused temp, should be removed
|
|
139
|
+
], { op: 'return', value: { kind: 'var', name: '$x' } });
|
|
140
|
+
const opt = (0, passes_1.optimize)(fn);
|
|
141
|
+
const instrs = opt.blocks[0].instrs;
|
|
142
|
+
// $t1 (unused temp) should be gone
|
|
143
|
+
expect(instrs.some((i) => i.dst === '$t1')).toBe(false);
|
|
144
|
+
// $x should be const 5 (after folding + propagation)
|
|
145
|
+
const xInstr = instrs.find((i) => i.dst === '$x');
|
|
146
|
+
expect(xInstr?.src).toEqual({ kind: 'const', value: 5 });
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
//# sourceMappingURL=optimizer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|