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,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const mcfunction_1 = require("../codegen/mcfunction");
|
|
4
|
+
describe('generateDatapack', () => {
|
|
5
|
+
it('generates pack.mcmeta', () => {
|
|
6
|
+
const mod = { namespace: 'test', functions: [], globals: [] };
|
|
7
|
+
const files = (0, mcfunction_1.generateDatapack)(mod);
|
|
8
|
+
const meta = files.find(f => f.path === 'pack.mcmeta');
|
|
9
|
+
expect(meta).toBeDefined();
|
|
10
|
+
expect(JSON.parse(meta.content).pack.pack_format).toBe(26);
|
|
11
|
+
});
|
|
12
|
+
it('generates __load.mcfunction with objective setup', () => {
|
|
13
|
+
const mod = { namespace: 'mypack', functions: [], globals: [{ name: 'counter', init: 0 }] };
|
|
14
|
+
const files = (0, mcfunction_1.generateDatapack)(mod);
|
|
15
|
+
const load = files.find(f => f.path.includes('__load.mcfunction'));
|
|
16
|
+
expect(load?.content).toContain('scoreboard objectives add rs dummy');
|
|
17
|
+
expect(load?.content).toContain('scoreboard players set $counter rs 0');
|
|
18
|
+
});
|
|
19
|
+
it('generates function file for simple add(a, b)', () => {
|
|
20
|
+
// IR now uses { kind: 'param', index: i } for param-copy instructions,
|
|
21
|
+
// matching what the lowering emits. Pass mangle:false so we can check
|
|
22
|
+
// readable names without worrying about sequential mangled names.
|
|
23
|
+
const mod = {
|
|
24
|
+
namespace: 'mypack',
|
|
25
|
+
globals: [],
|
|
26
|
+
functions: [{
|
|
27
|
+
name: 'add',
|
|
28
|
+
params: ['$a', '$b'],
|
|
29
|
+
locals: ['$a', '$b', '$result'],
|
|
30
|
+
blocks: [{
|
|
31
|
+
label: 'entry',
|
|
32
|
+
instrs: [
|
|
33
|
+
// param-copy instructions (what the lowering now emits)
|
|
34
|
+
{ op: 'assign', dst: '$a', src: { kind: 'param', index: 0 } },
|
|
35
|
+
{ op: 'assign', dst: '$b', src: { kind: 'param', index: 1 } },
|
|
36
|
+
{ op: 'binop', dst: '$result', lhs: { kind: 'var', name: '$a' }, bop: '+', rhs: { kind: 'var', name: '$b' } },
|
|
37
|
+
],
|
|
38
|
+
term: { op: 'return', value: { kind: 'var', name: '$result' } },
|
|
39
|
+
}],
|
|
40
|
+
}],
|
|
41
|
+
};
|
|
42
|
+
const files = (0, mcfunction_1.generateDatapackWithStats)(mod, { mangle: false }).files;
|
|
43
|
+
const fn = files.find(f => f.path.includes('add.mcfunction'));
|
|
44
|
+
expect(fn).toBeDefined();
|
|
45
|
+
// param setup emitted from the IR
|
|
46
|
+
expect(fn.content).toContain('scoreboard players operation $a rs = $p0 rs');
|
|
47
|
+
expect(fn.content).toContain('scoreboard players operation $b rs = $p1 rs');
|
|
48
|
+
// Should have add operation
|
|
49
|
+
expect(fn.content).toContain('+=');
|
|
50
|
+
});
|
|
51
|
+
it('generates tick tag for tick loop function', () => {
|
|
52
|
+
const mod = {
|
|
53
|
+
namespace: 'mypack',
|
|
54
|
+
globals: [],
|
|
55
|
+
functions: [{
|
|
56
|
+
name: 'game_loop',
|
|
57
|
+
params: [],
|
|
58
|
+
locals: [],
|
|
59
|
+
blocks: [{ label: 'entry', instrs: [], term: { op: 'return' } }],
|
|
60
|
+
isTickLoop: true,
|
|
61
|
+
}],
|
|
62
|
+
};
|
|
63
|
+
const files = (0, mcfunction_1.generateDatapack)(mod);
|
|
64
|
+
// tick.json should point to __tick
|
|
65
|
+
const tickTag = files.find(f => f.path.includes('tick.json'));
|
|
66
|
+
expect(tickTag).toBeDefined();
|
|
67
|
+
expect(JSON.parse(tickTag.content).values).toContain('mypack:__tick');
|
|
68
|
+
// __tick.mcfunction should call the game_loop function
|
|
69
|
+
const tickFn = files.find(f => f.path.includes('__tick.mcfunction'));
|
|
70
|
+
expect(tickFn).toBeDefined();
|
|
71
|
+
expect(tickFn.content).toContain('function mypack:game_loop');
|
|
72
|
+
});
|
|
73
|
+
it('generates conditional branches with execute if/unless', () => {
|
|
74
|
+
const mod = {
|
|
75
|
+
namespace: 'mypack',
|
|
76
|
+
globals: [],
|
|
77
|
+
functions: [{
|
|
78
|
+
name: 'check',
|
|
79
|
+
params: [],
|
|
80
|
+
locals: ['cond'],
|
|
81
|
+
blocks: [
|
|
82
|
+
{
|
|
83
|
+
label: 'entry',
|
|
84
|
+
instrs: [
|
|
85
|
+
{ op: 'assign', dst: 'cond', src: { kind: 'const', value: 1 } },
|
|
86
|
+
],
|
|
87
|
+
term: { op: 'jump_if', cond: 'cond', then: 'then_block', else_: 'else_block' },
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
label: 'then_block',
|
|
91
|
+
instrs: [{ op: 'raw', cmd: 'say hello' }],
|
|
92
|
+
term: { op: 'return' },
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
label: 'else_block',
|
|
96
|
+
instrs: [{ op: 'raw', cmd: 'say goodbye' }],
|
|
97
|
+
term: { op: 'return' },
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
}],
|
|
101
|
+
};
|
|
102
|
+
const files = (0, mcfunction_1.generateDatapack)(mod);
|
|
103
|
+
const entry = files.find(f => f.path.endsWith('check.mcfunction'));
|
|
104
|
+
expect(entry?.content).toContain('execute if score $cond rs matches 1..');
|
|
105
|
+
expect(entry?.content).toContain('execute if score $cond rs matches ..0');
|
|
106
|
+
});
|
|
107
|
+
it('generates advancement json for event decorators', () => {
|
|
108
|
+
const mod = {
|
|
109
|
+
namespace: 'mypack',
|
|
110
|
+
globals: [],
|
|
111
|
+
functions: [{
|
|
112
|
+
name: 'on_mine_diamond',
|
|
113
|
+
params: [],
|
|
114
|
+
locals: [],
|
|
115
|
+
blocks: [{ label: 'entry', instrs: [], term: { op: 'return' } }],
|
|
116
|
+
eventTrigger: { kind: 'advancement', value: 'story/mine_diamond' },
|
|
117
|
+
}],
|
|
118
|
+
};
|
|
119
|
+
const result = (0, mcfunction_1.generateDatapackWithStats)(mod);
|
|
120
|
+
const advancement = result.advancements.find(f => f.path === 'data/mypack/advancements/on_advancement_on_mine_diamond.json');
|
|
121
|
+
expect(advancement).toBeDefined();
|
|
122
|
+
const json = JSON.parse(advancement.content);
|
|
123
|
+
expect(json.criteria.trigger.trigger).toBe('minecraft:story/mine_diamond');
|
|
124
|
+
expect(json.rewards.function).toBe('mypack:on_mine_diamond');
|
|
125
|
+
});
|
|
126
|
+
it('generates static event dispatcher in __tick', () => {
|
|
127
|
+
const mod = {
|
|
128
|
+
namespace: 'mypack',
|
|
129
|
+
globals: [],
|
|
130
|
+
functions: [{
|
|
131
|
+
name: 'handle_death',
|
|
132
|
+
params: [],
|
|
133
|
+
locals: [],
|
|
134
|
+
blocks: [{ label: 'entry', instrs: [], term: { op: 'return' } }],
|
|
135
|
+
eventHandler: { eventType: 'PlayerDeath', tag: 'rs.just_died' },
|
|
136
|
+
}, {
|
|
137
|
+
name: 'handle_death_2',
|
|
138
|
+
params: [],
|
|
139
|
+
locals: [],
|
|
140
|
+
blocks: [{ label: 'entry', instrs: [], term: { op: 'return' } }],
|
|
141
|
+
eventHandler: { eventType: 'PlayerDeath', tag: 'rs.just_died' },
|
|
142
|
+
}],
|
|
143
|
+
};
|
|
144
|
+
const files = (0, mcfunction_1.generateDatapack)(mod);
|
|
145
|
+
const tickFn = files.find(f => f.path.includes('__tick.mcfunction'));
|
|
146
|
+
expect(tickFn).toBeDefined();
|
|
147
|
+
expect(tickFn.content).toContain('execute as @a[tag=rs.just_died] run function mypack:handle_death');
|
|
148
|
+
expect(tickFn.content).toContain('execute as @a[tag=rs.just_died] run function mypack:handle_death_2');
|
|
149
|
+
expect(tickFn.content).toContain('tag @a[tag=rs.just_died] remove rs.just_died');
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
//# sourceMappingURL=codegen.test.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-all smoke test
|
|
3
|
+
*
|
|
4
|
+
* Finds every .mcrs file in the repo (excluding declaration files and node_modules)
|
|
5
|
+
* and verifies that each one compiles without errors via the CLI (which handles
|
|
6
|
+
* `import` statements, unlike the bare `compile()` function).
|
|
7
|
+
*
|
|
8
|
+
* This catches regressions where a language change breaks existing source files.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Compile-all smoke test
|
|
4
|
+
*
|
|
5
|
+
* Finds every .mcrs file in the repo (excluding declaration files and node_modules)
|
|
6
|
+
* and verifies that each one compiles without errors via the CLI (which handles
|
|
7
|
+
* `import` statements, unlike the bare `compile()` function).
|
|
8
|
+
*
|
|
9
|
+
* This catches regressions where a language change breaks existing source files.
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
const child_process_1 = require("child_process");
|
|
48
|
+
const os = __importStar(require("os"));
|
|
49
|
+
const REPO_ROOT = path.resolve(__dirname, '../../');
|
|
50
|
+
const CLI = path.join(REPO_ROOT, 'dist', 'cli.js');
|
|
51
|
+
// Ensure dist/cli.js exists — build first if not (e.g. in CI)
|
|
52
|
+
if (!fs.existsSync(CLI)) {
|
|
53
|
+
console.log('[compile-all] dist/cli.js not found, running npm run build...');
|
|
54
|
+
(0, child_process_1.execSync)('npm run build', { cwd: REPO_ROOT, stdio: 'inherit' });
|
|
55
|
+
}
|
|
56
|
+
/** Patterns to skip */
|
|
57
|
+
const SKIP_GLOBS = [
|
|
58
|
+
'node_modules',
|
|
59
|
+
'.git',
|
|
60
|
+
'builtins.d.mcrs', // declaration-only file, not valid source
|
|
61
|
+
'editors/', // copy of builtins.d.mcrs
|
|
62
|
+
];
|
|
63
|
+
function shouldSkip(filePath) {
|
|
64
|
+
const rel = path.relative(REPO_ROOT, filePath);
|
|
65
|
+
return SKIP_GLOBS.some(pat => rel.includes(pat));
|
|
66
|
+
}
|
|
67
|
+
function findMcrsFiles(dir) {
|
|
68
|
+
const results = [];
|
|
69
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
70
|
+
const fullPath = path.join(dir, entry.name);
|
|
71
|
+
if (shouldSkip(fullPath))
|
|
72
|
+
continue;
|
|
73
|
+
if (entry.isDirectory()) {
|
|
74
|
+
results.push(...findMcrsFiles(fullPath));
|
|
75
|
+
}
|
|
76
|
+
else if (entry.isFile() && entry.name.endsWith('.mcrs')) {
|
|
77
|
+
results.push(fullPath);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return results;
|
|
81
|
+
}
|
|
82
|
+
const mcrsFiles = findMcrsFiles(REPO_ROOT);
|
|
83
|
+
const TMP_OUT = path.join(os.tmpdir(), 'redscript-compile-all');
|
|
84
|
+
describe('compile-all: every .mcrs file should compile without errors (CLI)', () => {
|
|
85
|
+
test('found at least one .mcrs file', () => {
|
|
86
|
+
expect(mcrsFiles.length).toBeGreaterThan(0);
|
|
87
|
+
});
|
|
88
|
+
for (const filePath of mcrsFiles) {
|
|
89
|
+
const label = path.relative(REPO_ROOT, filePath);
|
|
90
|
+
test(label, () => {
|
|
91
|
+
const outDir = path.join(TMP_OUT, label.replace(/[^a-zA-Z0-9]/g, '_'));
|
|
92
|
+
let stdout = '';
|
|
93
|
+
let stderr = '';
|
|
94
|
+
try {
|
|
95
|
+
const result = (0, child_process_1.execSync)(`node "${CLI}" compile "${filePath}" -o "${outDir}"`, { encoding: 'utf8', stdio: 'pipe' });
|
|
96
|
+
stdout = result;
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
stdout = err.stdout ?? '';
|
|
100
|
+
stderr = err.stderr ?? '';
|
|
101
|
+
const output = (stdout + stderr).trim();
|
|
102
|
+
// Fail with the compiler error message
|
|
103
|
+
throw new Error(`Compile failed for ${label}:\n${output}`);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=compile-all.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
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 os = __importStar(require("os"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const child_process_1 = require("child_process");
|
|
40
|
+
const index_1 = require("../index");
|
|
41
|
+
function getFileContent(files, suffix) {
|
|
42
|
+
const file = files.find(candidate => candidate.path.endsWith(suffix));
|
|
43
|
+
if (!file) {
|
|
44
|
+
throw new Error(`Missing file: ${suffix}`);
|
|
45
|
+
}
|
|
46
|
+
return file.content;
|
|
47
|
+
}
|
|
48
|
+
describe('AST dead code elimination', () => {
|
|
49
|
+
it('keeps non-library functions even if unused (v2 DCE only strips library fns)', () => {
|
|
50
|
+
const source = `
|
|
51
|
+
fn _unused() { say("never called"); }
|
|
52
|
+
fn used() { say("called"); }
|
|
53
|
+
@tick fn main() { used(); }
|
|
54
|
+
`;
|
|
55
|
+
const result = (0, index_1.compile)(source, { namespace: 'test' });
|
|
56
|
+
// v2 keeps all non-library functions; DCE only applies to `module library;` imports
|
|
57
|
+
expect(result.files.some(f => f.path.includes('/_unused.mcfunction'))).toBe(true);
|
|
58
|
+
expect(result.files.some(f => f.path.includes('/used.mcfunction'))).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
it('eliminates dead branches with constant conditions', () => {
|
|
61
|
+
const source = `
|
|
62
|
+
@tick fn main() {
|
|
63
|
+
if (false) {
|
|
64
|
+
say("dead code");
|
|
65
|
+
} else {
|
|
66
|
+
say("live code");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
const result = (0, index_1.compile)(source, { namespace: 'test' });
|
|
71
|
+
const output = getFileContent(result.files, 'data/test/function/main.mcfunction');
|
|
72
|
+
expect(output).not.toContain('dead code');
|
|
73
|
+
expect(output).toContain('live code');
|
|
74
|
+
});
|
|
75
|
+
it('keeps decorated entry points', () => {
|
|
76
|
+
const source = `
|
|
77
|
+
@tick fn ticker() { }
|
|
78
|
+
@load fn loader() { }
|
|
79
|
+
`;
|
|
80
|
+
const result = (0, index_1.compile)(source, { namespace: 'test' });
|
|
81
|
+
const paths = result.files.map(f => f.path);
|
|
82
|
+
expect(paths.some(p => p.includes('/ticker.mcfunction'))).toBe(true);
|
|
83
|
+
expect(paths.some(p => p.includes('/loader.mcfunction'))).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('CLI --no-dce', () => {
|
|
87
|
+
it('preserves unused functions when requested', () => {
|
|
88
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'redscript-dce-cli-'));
|
|
89
|
+
const inputPath = path.join(tempDir, 'main.mcrs');
|
|
90
|
+
const outputDir = path.join(tempDir, 'out');
|
|
91
|
+
fs.writeFileSync(inputPath, [
|
|
92
|
+
'fn unused() { say("keep me"); }',
|
|
93
|
+
'@tick fn main() { say("live"); }',
|
|
94
|
+
'',
|
|
95
|
+
].join('\n'));
|
|
96
|
+
(0, child_process_1.execFileSync)(process.execPath, ['-r', 'ts-node/register', 'src/cli.ts', 'compile', inputPath, '-o', outputDir, '--namespace', 'test'], { cwd: path.resolve(process.cwd()) });
|
|
97
|
+
// v2 pipeline compiles all functions
|
|
98
|
+
const mainPath = path.join(outputDir, 'data', 'test', 'function', 'main.mcfunction');
|
|
99
|
+
expect(fs.existsSync(mainPath)).toBe(true);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
//# sourceMappingURL=dce.test.js.map
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Diagnostics Tests
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const diagnostics_1 = require("../diagnostics");
|
|
7
|
+
const compile_1 = require("../compile");
|
|
8
|
+
describe('DiagnosticError', () => {
|
|
9
|
+
describe('formatError', () => {
|
|
10
|
+
it('formats source context with a caret pointer', () => {
|
|
11
|
+
const source = [
|
|
12
|
+
'fn main() {',
|
|
13
|
+
' let x = foo(',
|
|
14
|
+
'}',
|
|
15
|
+
].join('\n');
|
|
16
|
+
const error = new diagnostics_1.DiagnosticError('TypeError', 'Unknown function: foo', { line: 2, col: 11 }, source.split('\n'));
|
|
17
|
+
expect((0, diagnostics_1.formatError)(error, source)).toBe([
|
|
18
|
+
'Error at line 2, col 11:',
|
|
19
|
+
' let x = foo(',
|
|
20
|
+
' ^',
|
|
21
|
+
'Unknown function: foo',
|
|
22
|
+
].join('\n'));
|
|
23
|
+
});
|
|
24
|
+
it('includes file path when available', () => {
|
|
25
|
+
const source = 'let x = foo();';
|
|
26
|
+
const error = new diagnostics_1.DiagnosticError('TypeError', 'Unknown function: foo', { file: 'test.mcrs', line: 1, col: 9 }, source.split('\n'));
|
|
27
|
+
expect((0, diagnostics_1.formatError)(error, source)).toContain('Error in test.mcrs at line 1, col 9:');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
describe('format', () => {
|
|
31
|
+
it('formats error with source line and pointer', () => {
|
|
32
|
+
const sourceLines = [
|
|
33
|
+
'fn main() {',
|
|
34
|
+
' let x = 42',
|
|
35
|
+
'}',
|
|
36
|
+
];
|
|
37
|
+
const error = new diagnostics_1.DiagnosticError('ParseError', "Expected ';' after statement", { line: 2, col: 14 }, sourceLines);
|
|
38
|
+
const formatted = error.format();
|
|
39
|
+
expect(formatted).toContain('[ParseError]');
|
|
40
|
+
expect(formatted).toContain('line 2');
|
|
41
|
+
expect(formatted).toContain('col 14');
|
|
42
|
+
expect(formatted).toContain('let x = 42');
|
|
43
|
+
expect(formatted).toContain('^');
|
|
44
|
+
});
|
|
45
|
+
it('formats error with file path', () => {
|
|
46
|
+
const error = new diagnostics_1.DiagnosticError('LexError', 'Unexpected character', { file: 'test.mcrs', line: 1, col: 1 }, ['@@@']);
|
|
47
|
+
const formatted = error.format();
|
|
48
|
+
expect(formatted).toContain('test.mcrs:');
|
|
49
|
+
expect(formatted).toContain('[LexError]');
|
|
50
|
+
});
|
|
51
|
+
it('handles missing source lines gracefully', () => {
|
|
52
|
+
const error = new diagnostics_1.DiagnosticError('ParseError', 'Syntax error', { line: 10, col: 5 });
|
|
53
|
+
const formatted = error.format();
|
|
54
|
+
expect(formatted).toContain('[ParseError]');
|
|
55
|
+
expect(formatted).toContain('line 10');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe('DiagnosticCollector', () => {
|
|
60
|
+
it('collects multiple errors', () => {
|
|
61
|
+
const collector = new diagnostics_1.DiagnosticCollector('line1\nline2\nline3');
|
|
62
|
+
collector.error('ParseError', 'First error', 1, 1);
|
|
63
|
+
collector.error('ParseError', 'Second error', 2, 1);
|
|
64
|
+
expect(collector.hasErrors()).toBe(true);
|
|
65
|
+
expect(collector.getErrors()).toHaveLength(2);
|
|
66
|
+
});
|
|
67
|
+
it('formats all errors', () => {
|
|
68
|
+
const collector = new diagnostics_1.DiagnosticCollector('let x');
|
|
69
|
+
collector.error('ParseError', 'Missing semicolon', 1, 6);
|
|
70
|
+
const formatted = collector.formatAll();
|
|
71
|
+
expect(formatted).toContain('Missing semicolon');
|
|
72
|
+
expect(formatted).toContain('let x');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('parseErrorMessage', () => {
|
|
76
|
+
it('extracts line and col from error message', () => {
|
|
77
|
+
const err = (0, diagnostics_1.parseErrorMessage)('ParseError', "Expected ';' at line 5, col 12", ['', '', '', '', 'let x = 42']);
|
|
78
|
+
expect(err.location.line).toBe(5);
|
|
79
|
+
expect(err.location.col).toBe(12);
|
|
80
|
+
expect(err.message).toBe("Expected ';'");
|
|
81
|
+
});
|
|
82
|
+
it('defaults to line 1, col 1 if no position in message', () => {
|
|
83
|
+
const err = (0, diagnostics_1.parseErrorMessage)('LexError', 'Unknown error');
|
|
84
|
+
expect(err.location.line).toBe(1);
|
|
85
|
+
expect(err.location.col).toBe(1);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('compile function', () => {
|
|
89
|
+
it('returns success for valid code', () => {
|
|
90
|
+
const result = (0, compile_1.compile)('fn main() { let x = 1; }', { namespace: 'test' });
|
|
91
|
+
expect(result.success).toBe(true);
|
|
92
|
+
expect(result.files).toBeDefined();
|
|
93
|
+
});
|
|
94
|
+
it('throws DiagnosticError for lex errors', () => {
|
|
95
|
+
expect(() => (0, compile_1.compile)('fn main() { let x = $ }', { namespace: 'test' }))
|
|
96
|
+
.toThrow();
|
|
97
|
+
try {
|
|
98
|
+
(0, compile_1.compile)('fn main() { let x = $ }', { namespace: 'test' });
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
expect(e).toBeInstanceOf(diagnostics_1.DiagnosticError);
|
|
102
|
+
expect(e.kind).toBe('LexError');
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
it('throws DiagnosticError for parse errors', () => {
|
|
106
|
+
expect(() => (0, compile_1.compile)('fn main() { let x = }', { namespace: 'test' }))
|
|
107
|
+
.toThrow();
|
|
108
|
+
try {
|
|
109
|
+
(0, compile_1.compile)('fn main() { let x = }', { namespace: 'test' });
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
expect(e).toBeInstanceOf(diagnostics_1.DiagnosticError);
|
|
113
|
+
expect(e.kind).toBe('ParseError');
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
it('throws DiagnosticError for missing semicolon', () => {
|
|
117
|
+
try {
|
|
118
|
+
(0, compile_1.compile)('fn main() { let x = 42 }', { namespace: 'test' });
|
|
119
|
+
fail('Expected compile to throw');
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
expect(e.kind).toBe('ParseError');
|
|
123
|
+
expect(e.message).toContain("Expected ';'");
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
it('includes file path in error', () => {
|
|
127
|
+
const result = (0, compile_1.compile)('fn main() { }', { filePath: 'test.mcrs', namespace: 'test' });
|
|
128
|
+
expect(result.success).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
it('formats error nicely', () => {
|
|
131
|
+
try {
|
|
132
|
+
(0, compile_1.compile)('fn main() {\n let x = 42\n}', { namespace: 'test' });
|
|
133
|
+
fail('Expected compile to throw');
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
expect(e).toBeInstanceOf(diagnostics_1.DiagnosticError);
|
|
137
|
+
const formatted = e.format();
|
|
138
|
+
expect(formatted).toContain('line');
|
|
139
|
+
expect(formatted).toContain('^');
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe('Lexer DiagnosticError', () => {
|
|
144
|
+
it('throws DiagnosticError for unexpected character', () => {
|
|
145
|
+
try {
|
|
146
|
+
(0, compile_1.compile)('fn main() { let x = $ }', { namespace: 'test' });
|
|
147
|
+
fail('Expected compile to throw');
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
expect(e.kind).toBe('LexError');
|
|
151
|
+
expect(e.message).toContain('Unexpected character');
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
it('throws DiagnosticError for unterminated string', () => {
|
|
155
|
+
try {
|
|
156
|
+
(0, compile_1.compile)('fn main() { let x = "hello }', { namespace: 'test' });
|
|
157
|
+
fail('Expected compile to throw');
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
expect(e.kind).toBe('LexError');
|
|
161
|
+
expect(e.message).toContain('Unterminated string');
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe('Parser DiagnosticError', () => {
|
|
166
|
+
it('includes line and column info', () => {
|
|
167
|
+
try {
|
|
168
|
+
(0, compile_1.compile)('fn main() { return }', { namespace: 'test' });
|
|
169
|
+
fail('Expected compile to throw');
|
|
170
|
+
}
|
|
171
|
+
catch (e) {
|
|
172
|
+
expect(e.location.line).toBeGreaterThan(0);
|
|
173
|
+
expect(e.location.col).toBeGreaterThan(0);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
//# sourceMappingURL=diagnostics.test.js.map
|