redscript-mc 1.2.3 → 1.2.5

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.
@@ -298,6 +298,7 @@ export type Stmt = {
298
298
  binding: string;
299
299
  iterable: Expr;
300
300
  body: Block;
301
+ executeContext?: string;
301
302
  span?: Span;
302
303
  } | {
303
304
  kind: 'for_range';
@@ -757,8 +757,9 @@ class Lowering {
757
757
  // Extract body into a separate function
758
758
  const subFnName = `${this.currentFn}/foreach_${this.foreachCounter++}`;
759
759
  const selector = this.exprToString(stmt.iterable);
760
- // Emit execute as ... run function ...
761
- this.builder.emitRaw(`execute as ${selector} run function ${this.namespace}:${subFnName}`);
760
+ // Emit execute as ... [context modifiers] run function ...
761
+ const execContext = stmt.executeContext ? ` ${stmt.executeContext}` : '';
762
+ this.builder.emitRaw(`execute as ${selector}${execContext} run function ${this.namespace}:${subFnName}`);
762
763
  // Create the sub-function
763
764
  const savedBuilder = this.builder;
764
765
  const savedVarMap = new Map(this.varMap);
@@ -534,8 +534,20 @@ class Parser {
534
534
  this.expect('in');
535
535
  const iterable = this.parseExpr();
536
536
  this.expect(')');
537
+ // Parse optional execute context modifiers (at, positioned, rotated, facing, etc.)
538
+ let executeContext;
539
+ // Check for 'at' keyword or identifiers like 'positioned', 'rotated', 'facing', 'anchored', 'align'
540
+ const execIdentKeywords = ['positioned', 'rotated', 'facing', 'anchored', 'align'];
541
+ if (this.check('at') || this.check('in') || (this.check('ident') && execIdentKeywords.includes(this.peek().value))) {
542
+ // Collect everything until we hit '{'
543
+ let context = '';
544
+ while (!this.check('{') && !this.check('eof')) {
545
+ context += this.advance().value + ' ';
546
+ }
547
+ executeContext = context.trim();
548
+ }
537
549
  const body = this.parseBlock();
538
- return this.withLoc({ kind: 'foreach', binding, iterable, body }, foreachToken);
550
+ return this.withLoc({ kind: 'foreach', binding, iterable, body, executeContext }, foreachToken);
539
551
  }
540
552
  parseMatchStmt() {
541
553
  const matchToken = this.expect('match');
@@ -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",
@@ -12,8 +12,10 @@ let running: bool = false;
12
12
  // 每 tick 增加计数器
13
13
  counter = counter + 1;
14
14
 
15
- // 在玩家位置生成粒子
16
- particle("minecraft:end_rod", ~0, ~1, ~0, 0.5, 0.5, 0.5, 0.1, 5);
15
+ // 在每个玩家位置生成粒子
16
+ foreach (p in @a) at @s {
17
+ particle("minecraft:end_rod", ~0, ~1, ~0, 0.5, 0.5, 0.5, 0.1, 5);
18
+ }
17
19
 
18
20
  // 每 20 ticks (1秒) 报告一次
19
21
  if (counter % 20 == 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redscript-mc",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "A high-level programming language that compiles to Minecraft datapacks",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/ast/types.ts CHANGED
@@ -192,7 +192,7 @@ export type Stmt =
192
192
  | { kind: 'if'; cond: Expr; then: Block; else_?: Block; span?: Span }
193
193
  | { kind: 'while'; cond: Expr; body: Block; span?: Span }
194
194
  | { kind: 'for'; init?: Stmt; cond: Expr; step: Expr; body: Block; span?: Span }
195
- | { kind: 'foreach'; binding: string; iterable: Expr; body: Block; span?: Span }
195
+ | { kind: 'foreach'; binding: string; iterable: Expr; body: Block; executeContext?: string; span?: Span }
196
196
  | { kind: 'for_range'; varName: string; start: Expr; end: Expr; body: Block; span?: Span }
197
197
  | { kind: 'match'; expr: Expr; arms: { pattern: Expr | null; body: Block }[]; span?: Span }
198
198
  | { kind: 'as_block'; selector: EntitySelector; body: Block; span?: Span }
@@ -898,8 +898,9 @@ export class Lowering {
898
898
  const subFnName = `${this.currentFn}/foreach_${this.foreachCounter++}`
899
899
  const selector = this.exprToString(stmt.iterable)
900
900
 
901
- // Emit execute as ... run function ...
902
- this.builder.emitRaw(`execute as ${selector} run function ${this.namespace}:${subFnName}`)
901
+ // Emit execute as ... [context modifiers] run function ...
902
+ const execContext = stmt.executeContext ? ` ${stmt.executeContext}` : ''
903
+ this.builder.emitRaw(`execute as ${selector}${execContext} run function ${this.namespace}:${subFnName}`)
903
904
 
904
905
  // Create the sub-function
905
906
  const savedBuilder = this.builder
@@ -645,9 +645,23 @@ export class Parser {
645
645
  this.expect('in')
646
646
  const iterable = this.parseExpr()
647
647
  this.expect(')')
648
+
649
+ // Parse optional execute context modifiers (at, positioned, rotated, facing, etc.)
650
+ let executeContext: string | undefined
651
+ // Check for 'at' keyword or identifiers like 'positioned', 'rotated', 'facing', 'anchored', 'align'
652
+ const execIdentKeywords = ['positioned', 'rotated', 'facing', 'anchored', 'align']
653
+ if (this.check('at') || this.check('in') || (this.check('ident') && execIdentKeywords.includes(this.peek().value))) {
654
+ // Collect everything until we hit '{'
655
+ let context = ''
656
+ while (!this.check('{') && !this.check('eof')) {
657
+ context += this.advance().value + ' '
658
+ }
659
+ executeContext = context.trim()
660
+ }
661
+
648
662
  const body = this.parseBlock()
649
663
 
650
- return this.withLoc({ kind: 'foreach', binding, iterable, body }, foreachToken)
664
+ return this.withLoc({ kind: 'foreach', binding, iterable, body, executeContext }, foreachToken)
651
665
  }
652
666
 
653
667
  private parseMatchStmt(): Stmt {