redscript-mc 1.2.4 → 1.2.6

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.
@@ -260,7 +260,8 @@ function compileToStructure(source, namespace, filePath, options = {}) {
260
260
  const preprocessedSource = (0, compile_1.preprocessSource)(source, { filePath });
261
261
  const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
262
262
  const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
263
- const ast = options.dce ?? true ? (0, dce_1.eliminateDeadCode)(parsedAst) : parsedAst;
263
+ const dceResult = options.dce ?? true ? (0, dce_1.eliminateDeadCode)(parsedAst) : { program: parsedAst, warnings: [] };
264
+ const ast = dceResult.program;
264
265
  const ir = new lowering_1.Lowering(namespace).lower(ast);
265
266
  const stats = (0, commands_1.createEmptyOptimizationStats)();
266
267
  const optimizedIRFunctions = ir.functions.map(fn => {
package/dist/compile.js CHANGED
@@ -137,7 +137,8 @@ function compile(source, options = {}) {
137
137
  const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
138
138
  // Parsing
139
139
  const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
140
- const ast = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : parsedAst;
140
+ const dceResult = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : { program: parsedAst, warnings: [] };
141
+ const ast = dceResult.program;
141
142
  // Lowering
142
143
  const ir = new lowering_1.Lowering(namespace, preprocessed.ranges).lower(ast);
143
144
  // Optimization
package/dist/index.js CHANGED
@@ -36,7 +36,8 @@ function compile(source, options = {}) {
36
36
  const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
37
37
  // Parsing
38
38
  const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
39
- const ast = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : parsedAst;
39
+ const dceResult = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : { program: parsedAst, warnings: [] };
40
+ const ast = dceResult.program;
40
41
  // Type checking (warn mode - collect errors but don't block)
41
42
  let typeErrors;
42
43
  if (shouldTypeCheck) {
@@ -90,7 +91,7 @@ function compile(source, options = {}) {
90
91
  ast,
91
92
  ir: optimizedIR,
92
93
  typeErrors,
93
- warnings: lowering.warnings,
94
+ warnings: [...dceResult.warnings, ...lowering.warnings],
94
95
  stats: optimizationStats,
95
96
  };
96
97
  }
@@ -1,4 +1,10 @@
1
1
  import type { Program } from '../ast/types';
2
+ export interface DCEWarning {
3
+ message: string;
4
+ code: string;
5
+ line?: number;
6
+ col?: number;
7
+ }
2
8
  export declare class DeadCodeEliminator {
3
9
  private readonly functionMap;
4
10
  private readonly reachableFunctions;
@@ -6,6 +12,7 @@ export declare class DeadCodeEliminator {
6
12
  private readonly localReads;
7
13
  private readonly localDeclIds;
8
14
  private localIdCounter;
15
+ readonly warnings: DCEWarning[];
9
16
  eliminate(program: Program): Program;
10
17
  private findEntryPoints;
11
18
  private markReachable;
@@ -20,4 +27,7 @@ export declare class DeadCodeEliminator {
20
27
  private transformStmt;
21
28
  private transformExpr;
22
29
  }
23
- export declare function eliminateDeadCode(program: Program): Program;
30
+ export declare function eliminateDeadCode(program: Program): {
31
+ program: Program;
32
+ warnings: DCEWarning[];
33
+ };
@@ -69,6 +69,7 @@ class DeadCodeEliminator {
69
69
  this.localReads = new Set();
70
70
  this.localDeclIds = new WeakMap();
71
71
  this.localIdCounter = 0;
72
+ this.warnings = [];
72
73
  }
73
74
  eliminate(program) {
74
75
  this.functionMap.clear();
@@ -76,6 +77,7 @@ class DeadCodeEliminator {
76
77
  this.usedConstants.clear();
77
78
  this.localReads.clear();
78
79
  this.localIdCounter = 0;
80
+ this.warnings.length = 0;
79
81
  for (const fn of program.declarations) {
80
82
  this.functionMap.set(fn.name, fn);
81
83
  }
@@ -402,6 +404,13 @@ class DeadCodeEliminator {
402
404
  }
403
405
  return [copySpan({ ...stmt, init }, stmt)];
404
406
  }
407
+ // Unused variable - emit warning
408
+ this.warnings.push({
409
+ message: `Unused variable '${stmt.name}'`,
410
+ code: 'W_UNUSED_VAR',
411
+ line: stmt.span?.line,
412
+ col: stmt.span?.col,
413
+ });
405
414
  if (isPureExpr(init)) {
406
415
  return [];
407
416
  }
@@ -587,6 +596,8 @@ class DeadCodeEliminator {
587
596
  }
588
597
  exports.DeadCodeEliminator = DeadCodeEliminator;
589
598
  function eliminateDeadCode(program) {
590
- return new DeadCodeEliminator().eliminate(program);
599
+ const eliminator = new DeadCodeEliminator();
600
+ const result = eliminator.eliminate(program);
601
+ return { program: result, warnings: eliminator.warnings };
591
602
  }
592
603
  //# sourceMappingURL=dce.js.map
@@ -1163,8 +1163,17 @@ var require_parser = __commonJS({
1163
1163
  this.expect("in");
1164
1164
  const iterable = this.parseExpr();
1165
1165
  this.expect(")");
1166
+ let executeContext;
1167
+ const execIdentKeywords = ["positioned", "rotated", "facing", "anchored", "align"];
1168
+ if (this.check("at") || this.check("in") || this.check("ident") && execIdentKeywords.includes(this.peek().value)) {
1169
+ let context = "";
1170
+ while (!this.check("{") && !this.check("eof")) {
1171
+ context += this.advance().value + " ";
1172
+ }
1173
+ executeContext = context.trim();
1174
+ }
1166
1175
  const body = this.parseBlock();
1167
- return this.withLoc({ kind: "foreach", binding, iterable, body }, foreachToken);
1176
+ return this.withLoc({ kind: "foreach", binding, iterable, body, executeContext }, foreachToken);
1168
1177
  }
1169
1178
  parseMatchStmt() {
1170
1179
  const matchToken = this.expect("match");
@@ -3799,7 +3808,8 @@ var require_lowering = __commonJS({
3799
3808
  }
3800
3809
  const subFnName = `${this.currentFn}/foreach_${this.foreachCounter++}`;
3801
3810
  const selector = this.exprToString(stmt.iterable);
3802
- this.builder.emitRaw(`execute as ${selector} run function ${this.namespace}:${subFnName}`);
3811
+ const execContext = stmt.executeContext ? ` ${stmt.executeContext}` : "";
3812
+ this.builder.emitRaw(`execute as ${selector}${execContext} run function ${this.namespace}:${subFnName}`);
3803
3813
  const savedBuilder = this.builder;
3804
3814
  const savedVarMap = new Map(this.varMap);
3805
3815
  const savedContext = this.currentContext;
@@ -6122,7 +6132,8 @@ var require_passes = __commonJS({
6122
6132
  ...block,
6123
6133
  instrs: block.instrs.filter((instr) => {
6124
6134
  if (instr.op === "assign" || instr.op === "binop" || instr.op === "cmp") {
6125
- const keep = readVars.has(instr.dst);
6135
+ const isTemp = /^\$t\d+$/.test(instr.dst) || /^\$p\d+$/.test(instr.dst) || /^\$_\d+$/.test(instr.dst);
6136
+ const keep = !isTemp || readVars.has(instr.dst);
6126
6137
  if (!keep)
6127
6138
  removed++;
6128
6139
  return keep;
@@ -2,7 +2,7 @@
2
2
  "name": "redscript-vscode",
3
3
  "displayName": "RedScript for Minecraft",
4
4
  "description": "Syntax highlighting, error diagnostics, and language support for RedScript — a compiler targeting Minecraft Java Edition",
5
- "version": "1.0.5",
5
+ "version": "1.0.6",
6
6
  "publisher": "bkmashiro",
7
7
  "icon": "icon.png",
8
8
  "license": "MIT",
@@ -133,7 +133,7 @@
133
133
  "patterns": [
134
134
  {
135
135
  "name": "keyword.control.redscript",
136
- "match": "\\b(if|else|while|for|foreach|return|match|in|execute|as|at|unless|run|is)\\b"
136
+ "match": "\\b(if|else|while|for|foreach|return|match|in|execute|as|at|unless|run|is|positioned|rotated|facing|anchored|align)\\b"
137
137
  },
138
138
  {
139
139
  "name": "keyword.declaration.redscript",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redscript-mc",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "description": "A high-level programming language that compiles to Minecraft datapacks",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -329,7 +329,8 @@ export function compileToStructure(
329
329
  const preprocessedSource = preprocessSource(source, { filePath })
330
330
  const tokens = new Lexer(preprocessedSource, filePath).tokenize()
331
331
  const parsedAst = new Parser(tokens, preprocessedSource, filePath).parse(namespace)
332
- const ast = options.dce ?? true ? eliminateDeadCode(parsedAst) : parsedAst
332
+ const dceResult = options.dce ?? true ? eliminateDeadCode(parsedAst) : { program: parsedAst, warnings: [] }
333
+ const ast = dceResult.program
333
334
  const ir = new Lowering(namespace).lower(ast)
334
335
  const stats = createEmptyOptimizationStats()
335
336
  const optimizedIRFunctions = ir.functions.map(fn => {
package/src/compile.ts CHANGED
@@ -175,7 +175,8 @@ export function compile(source: string, options: CompileOptions = {}): CompileRe
175
175
 
176
176
  // Parsing
177
177
  const parsedAst = new Parser(tokens, preprocessedSource, filePath).parse(namespace)
178
- const ast = shouldRunDce ? eliminateDeadCode(parsedAst) : parsedAst
178
+ const dceResult = shouldRunDce ? eliminateDeadCode(parsedAst) : { program: parsedAst, warnings: [] }
179
+ const ast = dceResult.program
179
180
 
180
181
  // Lowering
181
182
  const ir = new Lowering(namespace, preprocessed.ranges).lower(ast)
package/src/index.ts CHANGED
@@ -65,7 +65,8 @@ export function compile(source: string, options: CompileOptions = {}): CompileRe
65
65
 
66
66
  // Parsing
67
67
  const parsedAst = new Parser(tokens, preprocessedSource, filePath).parse(namespace)
68
- const ast = shouldRunDce ? eliminateDeadCode(parsedAst) : parsedAst
68
+ const dceResult = shouldRunDce ? eliminateDeadCode(parsedAst) : { program: parsedAst, warnings: [] }
69
+ const ast = dceResult.program
69
70
 
70
71
  // Type checking (warn mode - collect errors but don't block)
71
72
  let typeErrors: DiagnosticError[] | undefined
@@ -129,7 +130,7 @@ export function compile(source: string, options: CompileOptions = {}): CompileRe
129
130
  ast,
130
131
  ir: optimizedIR,
131
132
  typeErrors,
132
- warnings: lowering.warnings,
133
+ warnings: [...dceResult.warnings, ...lowering.warnings],
133
134
  stats: optimizationStats,
134
135
  }
135
136
  }
@@ -67,6 +67,13 @@ function isPureExpr(expr: Expr): boolean {
67
67
  }
68
68
  }
69
69
 
70
+ export interface DCEWarning {
71
+ message: string
72
+ code: string
73
+ line?: number
74
+ col?: number
75
+ }
76
+
70
77
  export class DeadCodeEliminator {
71
78
  private readonly functionMap = new Map<string, FnDecl>()
72
79
  private readonly reachableFunctions = new Set<string>()
@@ -74,6 +81,7 @@ export class DeadCodeEliminator {
74
81
  private readonly localReads = new Set<string>()
75
82
  private readonly localDeclIds = new WeakMap<Stmt, string>()
76
83
  private localIdCounter = 0
84
+ readonly warnings: DCEWarning[] = []
77
85
 
78
86
  eliminate(program: Program): Program {
79
87
  this.functionMap.clear()
@@ -81,6 +89,7 @@ export class DeadCodeEliminator {
81
89
  this.usedConstants.clear()
82
90
  this.localReads.clear()
83
91
  this.localIdCounter = 0
92
+ this.warnings.length = 0
84
93
 
85
94
  for (const fn of program.declarations) {
86
95
  this.functionMap.set(fn.name, fn)
@@ -429,6 +438,13 @@ export class DeadCodeEliminator {
429
438
  }
430
439
  return [copySpan({ ...stmt, init }, stmt)]
431
440
  }
441
+ // Unused variable - emit warning
442
+ this.warnings.push({
443
+ message: `Unused variable '${stmt.name}'`,
444
+ code: 'W_UNUSED_VAR',
445
+ line: stmt.span?.line,
446
+ col: stmt.span?.col,
447
+ })
432
448
  if (isPureExpr(init)) {
433
449
  return []
434
450
  }
@@ -614,6 +630,8 @@ export class DeadCodeEliminator {
614
630
  }
615
631
  }
616
632
 
617
- export function eliminateDeadCode(program: Program): Program {
618
- return new DeadCodeEliminator().eliminate(program)
633
+ export function eliminateDeadCode(program: Program): { program: Program; warnings: DCEWarning[] } {
634
+ const eliminator = new DeadCodeEliminator()
635
+ const result = eliminator.eliminate(program)
636
+ return { program: result, warnings: eliminator.warnings }
619
637
  }