redscript-mc 1.2.0 → 1.2.2
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/CHANGELOG.md +5 -0
- package/README.md +53 -10
- package/README.zh.md +53 -10
- package/dist/__tests__/dce.test.d.ts +1 -0
- package/dist/__tests__/dce.test.js +137 -0
- package/dist/__tests__/lexer.test.js +19 -2
- package/dist/__tests__/lowering.test.js +8 -0
- package/dist/__tests__/mc-syntax.test.js +12 -0
- package/dist/__tests__/parser.test.js +10 -0
- package/dist/__tests__/runtime.test.js +13 -0
- package/dist/__tests__/typechecker.test.js +30 -0
- package/dist/ast/types.d.ts +22 -2
- package/dist/cli.js +15 -10
- package/dist/codegen/structure/index.d.ts +4 -1
- package/dist/codegen/structure/index.js +4 -2
- package/dist/compile.d.ts +1 -0
- package/dist/compile.js +4 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -1
- package/dist/lexer/index.d.ts +2 -1
- package/dist/lexer/index.js +89 -1
- package/dist/lowering/index.js +37 -1
- package/dist/optimizer/dce.d.ts +23 -0
- package/dist/optimizer/dce.js +592 -0
- package/dist/parser/index.d.ts +2 -0
- package/dist/parser/index.js +81 -16
- package/dist/typechecker/index.d.ts +2 -0
- package/dist/typechecker/index.js +49 -0
- package/docs/ARCHITECTURE.zh.md +1088 -0
- package/editors/vscode/.vscodeignore +3 -0
- package/editors/vscode/icon.png +0 -0
- package/editors/vscode/out/extension.js +834 -19
- package/editors/vscode/package-lock.json +2 -2
- package/editors/vscode/package.json +1 -1
- package/editors/vscode/syntaxes/redscript.tmLanguage.json +6 -2
- package/examples/spiral.mcrs +41 -0
- package/logo.png +0 -0
- package/package.json +1 -1
- package/src/__tests__/dce.test.ts +129 -0
- package/src/__tests__/lexer.test.ts +21 -2
- package/src/__tests__/lowering.test.ts +9 -0
- package/src/__tests__/mc-syntax.test.ts +14 -0
- package/src/__tests__/parser.test.ts +11 -0
- package/src/__tests__/runtime.test.ts +16 -0
- package/src/__tests__/typechecker.test.ts +33 -0
- package/src/ast/types.ts +14 -1
- package/src/cli.ts +24 -10
- package/src/codegen/structure/index.ts +13 -2
- package/src/compile.ts +5 -1
- package/src/index.ts +5 -1
- package/src/lexer/index.ts +102 -1
- package/src/lowering/index.ts +38 -2
- package/src/optimizer/dce.ts +619 -0
- package/src/parser/index.ts +97 -17
- package/src/typechecker/index.ts +65 -0
|
@@ -14,5 +14,8 @@ export interface StructureCompileResult {
|
|
|
14
14
|
blocks: StructureBlockInfo[];
|
|
15
15
|
stats?: OptimizationStats;
|
|
16
16
|
}
|
|
17
|
+
export interface StructureCompileOptions {
|
|
18
|
+
dce?: boolean;
|
|
19
|
+
}
|
|
17
20
|
export declare function generateStructure(input: IRModule | DatapackFile[]): StructureCompileResult;
|
|
18
|
-
export declare function compileToStructure(source: string, namespace: string, filePath?: string): StructureCompileResult;
|
|
21
|
+
export declare function compileToStructure(source: string, namespace: string, filePath?: string, options?: StructureCompileOptions): StructureCompileResult;
|
|
@@ -9,6 +9,7 @@ const nbt_1 = require("../../nbt");
|
|
|
9
9
|
const commands_1 = require("../../optimizer/commands");
|
|
10
10
|
const passes_1 = require("../../optimizer/passes");
|
|
11
11
|
const structure_1 = require("../../optimizer/structure");
|
|
12
|
+
const dce_1 = require("../../optimizer/dce");
|
|
12
13
|
const compile_1 = require("../../compile");
|
|
13
14
|
const types_1 = require("../../events/types");
|
|
14
15
|
const DATA_VERSION = 3953;
|
|
@@ -255,10 +256,11 @@ function generateStructure(input) {
|
|
|
255
256
|
})),
|
|
256
257
|
};
|
|
257
258
|
}
|
|
258
|
-
function compileToStructure(source, namespace, filePath) {
|
|
259
|
+
function compileToStructure(source, namespace, filePath, options = {}) {
|
|
259
260
|
const preprocessedSource = (0, compile_1.preprocessSource)(source, { filePath });
|
|
260
261
|
const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
|
|
261
|
-
const
|
|
262
|
+
const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
|
|
263
|
+
const ast = options.dce ?? true ? (0, dce_1.eliminateDeadCode)(parsedAst) : parsedAst;
|
|
262
264
|
const ir = new lowering_1.Lowering(namespace).lower(ast);
|
|
263
265
|
const stats = (0, commands_1.createEmptyOptimizationStats)();
|
|
264
266
|
const optimizedIRFunctions = ir.functions.map(fn => {
|
package/dist/compile.d.ts
CHANGED
package/dist/compile.js
CHANGED
|
@@ -48,6 +48,7 @@ const lexer_1 = require("./lexer");
|
|
|
48
48
|
const parser_1 = require("./parser");
|
|
49
49
|
const lowering_1 = require("./lowering");
|
|
50
50
|
const passes_1 = require("./optimizer/passes");
|
|
51
|
+
const dce_1 = require("./optimizer/dce");
|
|
51
52
|
const mcfunction_1 = require("./codegen/mcfunction");
|
|
52
53
|
const diagnostics_1 = require("./diagnostics");
|
|
53
54
|
const IMPORT_RE = /^\s*import\s+"([^"]+)"\s*;?\s*$/;
|
|
@@ -126,6 +127,7 @@ function preprocessSource(source, options = {}) {
|
|
|
126
127
|
// ---------------------------------------------------------------------------
|
|
127
128
|
function compile(source, options = {}) {
|
|
128
129
|
const { namespace = 'redscript', filePath, optimize: shouldOptimize = true } = options;
|
|
130
|
+
const shouldRunDce = options.dce ?? shouldOptimize;
|
|
129
131
|
let sourceLines = source.split('\n');
|
|
130
132
|
try {
|
|
131
133
|
const preprocessed = preprocessSourceWithMetadata(source, { filePath });
|
|
@@ -134,7 +136,8 @@ function compile(source, options = {}) {
|
|
|
134
136
|
// Lexing
|
|
135
137
|
const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
|
|
136
138
|
// Parsing
|
|
137
|
-
const
|
|
139
|
+
const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
|
|
140
|
+
const ast = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : parsedAst;
|
|
138
141
|
// Lowering
|
|
139
142
|
const ir = new lowering_1.Lowering(namespace, preprocessed.ranges).lower(ast);
|
|
140
143
|
// Optimization
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const parser_1 = require("./parser");
|
|
|
13
13
|
const typechecker_1 = require("./typechecker");
|
|
14
14
|
const lowering_1 = require("./lowering");
|
|
15
15
|
const passes_1 = require("./optimizer/passes");
|
|
16
|
+
const dce_1 = require("./optimizer/dce");
|
|
16
17
|
const mcfunction_1 = require("./codegen/mcfunction");
|
|
17
18
|
const compile_1 = require("./compile");
|
|
18
19
|
const commands_1 = require("./optimizer/commands");
|
|
@@ -27,13 +28,15 @@ function compile(source, options = {}) {
|
|
|
27
28
|
const namespace = options.namespace ?? 'redscript';
|
|
28
29
|
const shouldOptimize = options.optimize ?? true;
|
|
29
30
|
const shouldTypeCheck = options.typeCheck ?? true;
|
|
31
|
+
const shouldRunDce = options.dce ?? shouldOptimize;
|
|
30
32
|
const filePath = options.filePath;
|
|
31
33
|
const preprocessed = (0, compile_1.preprocessSourceWithMetadata)(source, { filePath });
|
|
32
34
|
const preprocessedSource = preprocessed.source;
|
|
33
35
|
// Lexing
|
|
34
36
|
const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
|
|
35
37
|
// Parsing
|
|
36
|
-
const
|
|
38
|
+
const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
|
|
39
|
+
const ast = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : parsedAst;
|
|
37
40
|
// Type checking (warn mode - collect errors but don't block)
|
|
38
41
|
let typeErrors;
|
|
39
42
|
if (shouldTypeCheck) {
|
package/dist/lexer/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Handles special cases like entity selectors vs decorators,
|
|
6
6
|
* range literals, and raw commands.
|
|
7
7
|
*/
|
|
8
|
-
export type TokenKind = 'fn' | 'let' | 'const' | 'if' | 'else' | 'while' | 'for' | 'foreach' | 'match' | 'return' | 'as' | 'at' | 'in' | 'is' | 'struct' | 'impl' | 'enum' | 'trigger' | 'namespace' | 'execute' | 'run' | 'unless' | 'int' | 'bool' | 'float' | 'string' | 'void' | 'BlockPos' | 'true' | 'false' | 'selector' | 'decorator' | 'int_lit' | 'float_lit' | 'byte_lit' | 'short_lit' | 'long_lit' | 'double_lit' | 'string_lit' | 'range_lit' | '+' | '-' | '*' | '/' | '%' | '~' | '^' | '==' | '!=' | '<' | '<=' | '>' | '>=' | '&&' | '||' | '!' | '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '{' | '}' | '(' | ')' | '[' | ']' | ',' | ';' | ':' | '::' | '->' | '=>' | '.' | 'ident' | 'mc_name' | 'raw_cmd' | 'eof';
|
|
8
|
+
export type TokenKind = 'fn' | 'let' | 'const' | 'if' | 'else' | 'while' | 'for' | 'foreach' | 'match' | 'return' | 'as' | 'at' | 'in' | 'is' | 'struct' | 'impl' | 'enum' | 'trigger' | 'namespace' | 'execute' | 'run' | 'unless' | 'int' | 'bool' | 'float' | 'string' | 'void' | 'BlockPos' | 'true' | 'false' | 'selector' | 'decorator' | 'int_lit' | 'float_lit' | 'byte_lit' | 'short_lit' | 'long_lit' | 'double_lit' | 'string_lit' | 'f_string' | 'range_lit' | 'rel_coord' | 'local_coord' | '+' | '-' | '*' | '/' | '%' | '~' | '^' | '==' | '!=' | '<' | '<=' | '>' | '>=' | '&&' | '||' | '!' | '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '{' | '}' | '(' | ')' | '[' | ']' | ',' | ';' | ':' | '::' | '->' | '=>' | '.' | 'ident' | 'mc_name' | 'raw_cmd' | 'eof';
|
|
9
9
|
export interface Token {
|
|
10
10
|
kind: TokenKind;
|
|
11
11
|
value: string;
|
|
@@ -31,6 +31,7 @@ export declare class Lexer {
|
|
|
31
31
|
private scanAtToken;
|
|
32
32
|
private scanSelectorParams;
|
|
33
33
|
private scanString;
|
|
34
|
+
private scanFString;
|
|
34
35
|
private scanNumber;
|
|
35
36
|
private scanIdentifier;
|
|
36
37
|
}
|
package/dist/lexer/index.js
CHANGED
|
@@ -202,8 +202,50 @@ class Lexer {
|
|
|
202
202
|
this.addToken('range_lit', value, startLine, startCol);
|
|
203
203
|
return;
|
|
204
204
|
}
|
|
205
|
+
// Relative coordinate: ~ or ~5 or ~-3 or ~0.5
|
|
206
|
+
if (char === '~') {
|
|
207
|
+
let value = '~';
|
|
208
|
+
// Check for optional sign
|
|
209
|
+
if (this.peek() === '-' || this.peek() === '+') {
|
|
210
|
+
value += this.advance();
|
|
211
|
+
}
|
|
212
|
+
// Check for number
|
|
213
|
+
while (/[0-9]/.test(this.peek())) {
|
|
214
|
+
value += this.advance();
|
|
215
|
+
}
|
|
216
|
+
// Check for decimal part
|
|
217
|
+
if (this.peek() === '.' && /[0-9]/.test(this.peek(1))) {
|
|
218
|
+
value += this.advance(); // .
|
|
219
|
+
while (/[0-9]/.test(this.peek())) {
|
|
220
|
+
value += this.advance();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
this.addToken('rel_coord', value, startLine, startCol);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
// Local coordinate: ^ or ^5 or ^-3 or ^0.5
|
|
227
|
+
if (char === '^') {
|
|
228
|
+
let value = '^';
|
|
229
|
+
// Check for optional sign
|
|
230
|
+
if (this.peek() === '-' || this.peek() === '+') {
|
|
231
|
+
value += this.advance();
|
|
232
|
+
}
|
|
233
|
+
// Check for number
|
|
234
|
+
while (/[0-9]/.test(this.peek())) {
|
|
235
|
+
value += this.advance();
|
|
236
|
+
}
|
|
237
|
+
// Check for decimal part
|
|
238
|
+
if (this.peek() === '.' && /[0-9]/.test(this.peek(1))) {
|
|
239
|
+
value += this.advance(); // .
|
|
240
|
+
while (/[0-9]/.test(this.peek())) {
|
|
241
|
+
value += this.advance();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
this.addToken('local_coord', value, startLine, startCol);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
205
247
|
// Single-character operators and delimiters
|
|
206
|
-
const singleChar = ['+', '-', '*', '/', '%', '
|
|
248
|
+
const singleChar = ['+', '-', '*', '/', '%', '<', '>', '!', '=',
|
|
207
249
|
'{', '}', '(', ')', '[', ']', ',', ';', ':', '.'];
|
|
208
250
|
if (singleChar.includes(char)) {
|
|
209
251
|
this.addToken(char, char, startLine, startCol);
|
|
@@ -214,6 +256,12 @@ class Lexer {
|
|
|
214
256
|
this.scanAtToken(startLine, startCol);
|
|
215
257
|
return;
|
|
216
258
|
}
|
|
259
|
+
// f-string literal
|
|
260
|
+
if (char === 'f' && this.peek() === '"') {
|
|
261
|
+
this.advance();
|
|
262
|
+
this.scanFString(startLine, startCol);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
217
265
|
// String literal
|
|
218
266
|
if (char === '"') {
|
|
219
267
|
this.scanString(startLine, startCol);
|
|
@@ -340,6 +388,46 @@ class Lexer {
|
|
|
340
388
|
this.advance(); // closing quote
|
|
341
389
|
this.addToken('string_lit', value, startLine, startCol);
|
|
342
390
|
}
|
|
391
|
+
scanFString(startLine, startCol) {
|
|
392
|
+
let value = '';
|
|
393
|
+
let interpolationDepth = 0;
|
|
394
|
+
let interpolationString = false;
|
|
395
|
+
while (!this.isAtEnd()) {
|
|
396
|
+
if (interpolationDepth === 0 && this.peek() === '"') {
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
if (this.peek() === '\\' && this.peek(1) === '"') {
|
|
400
|
+
this.advance();
|
|
401
|
+
value += this.advance();
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
if (interpolationDepth === 0 && this.peek() === '{') {
|
|
405
|
+
value += this.advance();
|
|
406
|
+
interpolationDepth = 1;
|
|
407
|
+
interpolationString = false;
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
const char = this.advance();
|
|
411
|
+
value += char;
|
|
412
|
+
if (interpolationDepth === 0)
|
|
413
|
+
continue;
|
|
414
|
+
if (char === '"' && this.source[this.pos - 2] !== '\\') {
|
|
415
|
+
interpolationString = !interpolationString;
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (interpolationString)
|
|
419
|
+
continue;
|
|
420
|
+
if (char === '{')
|
|
421
|
+
interpolationDepth++;
|
|
422
|
+
if (char === '}')
|
|
423
|
+
interpolationDepth--;
|
|
424
|
+
}
|
|
425
|
+
if (this.isAtEnd()) {
|
|
426
|
+
this.error('Unterminated f-string', startLine, startCol);
|
|
427
|
+
}
|
|
428
|
+
this.advance(); // closing quote
|
|
429
|
+
this.addToken('f_string', value, startLine, startCol);
|
|
430
|
+
}
|
|
343
431
|
scanNumber(firstChar, startLine, startCol) {
|
|
344
432
|
let value = firstChar;
|
|
345
433
|
// Consume integer part
|
package/dist/lowering/index.js
CHANGED
|
@@ -50,6 +50,7 @@ const types_1 = require("../events/types");
|
|
|
50
50
|
const BUILTINS = {
|
|
51
51
|
say: ([msg]) => `say ${msg}`,
|
|
52
52
|
tell: ([sel, msg]) => `tellraw ${sel} {"text":"${msg}"}`,
|
|
53
|
+
tellraw: ([sel, msg]) => `tellraw ${sel} {"text":"${msg}"}`,
|
|
53
54
|
title: ([sel, msg]) => `title ${sel} title {"text":"${msg}"}`,
|
|
54
55
|
actionbar: ([sel, msg]) => `title ${sel} actionbar {"text":"${msg}"}`,
|
|
55
56
|
subtitle: ([sel, msg]) => `title ${sel} subtitle {"text":"${msg}"}`,
|
|
@@ -1029,6 +1030,7 @@ class Lowering {
|
|
|
1029
1030
|
// MC names (#health, #red) treated as string constants
|
|
1030
1031
|
return { kind: 'const', value: 0 }; // Handled inline in exprToString
|
|
1031
1032
|
case 'str_interp':
|
|
1033
|
+
case 'f_string':
|
|
1032
1034
|
// Interpolated strings are handled inline in message builtins.
|
|
1033
1035
|
return { kind: 'const', value: 0 };
|
|
1034
1036
|
case 'range_lit':
|
|
@@ -1919,7 +1921,7 @@ class Lowering {
|
|
|
1919
1921
|
return null;
|
|
1920
1922
|
}
|
|
1921
1923
|
const messageExpr = args[messageArgIndex];
|
|
1922
|
-
if (!messageExpr || messageExpr.kind !== 'str_interp') {
|
|
1924
|
+
if (!messageExpr || (messageExpr.kind !== 'str_interp' && messageExpr.kind !== 'f_string')) {
|
|
1923
1925
|
return null;
|
|
1924
1926
|
}
|
|
1925
1927
|
const json = this.buildRichTextJson(messageExpr);
|
|
@@ -1928,6 +1930,7 @@ class Lowering {
|
|
|
1928
1930
|
case 'announce':
|
|
1929
1931
|
return `tellraw @a ${json}`;
|
|
1930
1932
|
case 'tell':
|
|
1933
|
+
case 'tellraw':
|
|
1931
1934
|
return `tellraw ${this.exprToString(args[0])} ${json}`;
|
|
1932
1935
|
case 'title':
|
|
1933
1936
|
return `title ${this.exprToString(args[0])} title ${json}`;
|
|
@@ -1945,6 +1948,7 @@ class Lowering {
|
|
|
1945
1948
|
case 'announce':
|
|
1946
1949
|
return 0;
|
|
1947
1950
|
case 'tell':
|
|
1951
|
+
case 'tellraw':
|
|
1948
1952
|
case 'title':
|
|
1949
1953
|
case 'actionbar':
|
|
1950
1954
|
case 'subtitle':
|
|
@@ -1955,6 +1959,18 @@ class Lowering {
|
|
|
1955
1959
|
}
|
|
1956
1960
|
buildRichTextJson(expr) {
|
|
1957
1961
|
const components = [''];
|
|
1962
|
+
if (expr.kind === 'f_string') {
|
|
1963
|
+
for (const part of expr.parts) {
|
|
1964
|
+
if (part.kind === 'text') {
|
|
1965
|
+
if (part.value.length > 0) {
|
|
1966
|
+
components.push({ text: part.value });
|
|
1967
|
+
}
|
|
1968
|
+
continue;
|
|
1969
|
+
}
|
|
1970
|
+
this.appendRichTextExpr(components, part.expr);
|
|
1971
|
+
}
|
|
1972
|
+
return JSON.stringify(components);
|
|
1973
|
+
}
|
|
1958
1974
|
for (const part of expr.parts) {
|
|
1959
1975
|
if (typeof part === 'string') {
|
|
1960
1976
|
if (part.length > 0) {
|
|
@@ -1998,6 +2014,19 @@ class Lowering {
|
|
|
1998
2014
|
}
|
|
1999
2015
|
return;
|
|
2000
2016
|
}
|
|
2017
|
+
if (expr.kind === 'f_string') {
|
|
2018
|
+
for (const part of expr.parts) {
|
|
2019
|
+
if (part.kind === 'text') {
|
|
2020
|
+
if (part.value.length > 0) {
|
|
2021
|
+
components.push({ text: part.value });
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
else {
|
|
2025
|
+
this.appendRichTextExpr(components, part.expr);
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
return;
|
|
2029
|
+
}
|
|
2001
2030
|
if (expr.kind === 'bool_lit') {
|
|
2002
2031
|
components.push({ text: expr.value ? 'true' : 'false' });
|
|
2003
2032
|
return;
|
|
@@ -2031,6 +2060,10 @@ class Lowering {
|
|
|
2031
2060
|
return `${expr.value}L`;
|
|
2032
2061
|
case 'double_lit':
|
|
2033
2062
|
return `${expr.value}d`;
|
|
2063
|
+
case 'rel_coord':
|
|
2064
|
+
return expr.value; // ~ or ~5 or ~-3 - output as-is for MC commands
|
|
2065
|
+
case 'local_coord':
|
|
2066
|
+
return expr.value; // ^ or ^5 or ^-3 - output as-is for MC commands
|
|
2034
2067
|
case 'bool_lit':
|
|
2035
2068
|
return expr.value ? '1' : '0';
|
|
2036
2069
|
case 'str_lit':
|
|
@@ -2038,6 +2071,7 @@ class Lowering {
|
|
|
2038
2071
|
case 'mc_name':
|
|
2039
2072
|
return expr.value; // #health → "health" (no quotes, used as bare MC name)
|
|
2040
2073
|
case 'str_interp':
|
|
2074
|
+
case 'f_string':
|
|
2041
2075
|
return this.buildRichTextJson(expr);
|
|
2042
2076
|
case 'blockpos':
|
|
2043
2077
|
return emitBlockPos(expr);
|
|
@@ -2328,6 +2362,8 @@ class Lowering {
|
|
|
2328
2362
|
return { kind: 'named', name: 'bool' };
|
|
2329
2363
|
if (expr.kind === 'str_lit' || expr.kind === 'str_interp')
|
|
2330
2364
|
return { kind: 'named', name: 'string' };
|
|
2365
|
+
if (expr.kind === 'f_string')
|
|
2366
|
+
return { kind: 'named', name: 'format_string' };
|
|
2331
2367
|
if (expr.kind === 'blockpos')
|
|
2332
2368
|
return { kind: 'named', name: 'BlockPos' };
|
|
2333
2369
|
if (expr.kind === 'ident') {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Program } from '../ast/types';
|
|
2
|
+
export declare class DeadCodeEliminator {
|
|
3
|
+
private readonly functionMap;
|
|
4
|
+
private readonly reachableFunctions;
|
|
5
|
+
private readonly usedConstants;
|
|
6
|
+
private readonly localReads;
|
|
7
|
+
private readonly localDeclIds;
|
|
8
|
+
private localIdCounter;
|
|
9
|
+
eliminate(program: Program): Program;
|
|
10
|
+
private findEntryPoints;
|
|
11
|
+
private markReachable;
|
|
12
|
+
private collectFunctionRefs;
|
|
13
|
+
private collectStmtRefs;
|
|
14
|
+
private collectStmtRef;
|
|
15
|
+
private collectNestedStmtRefs;
|
|
16
|
+
private collectExprRefs;
|
|
17
|
+
private resolveLocal;
|
|
18
|
+
private transformFunction;
|
|
19
|
+
private transformBlock;
|
|
20
|
+
private transformStmt;
|
|
21
|
+
private transformExpr;
|
|
22
|
+
}
|
|
23
|
+
export declare function eliminateDeadCode(program: Program): Program;
|