redscript-mc 1.0.0 → 1.2.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.
Files changed (136) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +72 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.yml +57 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +17 -25
  4. package/CHANGELOG.md +112 -0
  5. package/CONTRIBUTING.md +140 -0
  6. package/README.md +28 -19
  7. package/README.zh.md +28 -19
  8. package/dist/__tests__/cli.test.js +148 -10
  9. package/dist/__tests__/codegen.test.js +26 -1
  10. package/dist/__tests__/diagnostics.test.js +5 -5
  11. package/dist/__tests__/e2e.test.js +336 -17
  12. package/dist/__tests__/formatter.test.d.ts +1 -0
  13. package/dist/__tests__/formatter.test.js +40 -0
  14. package/dist/__tests__/lexer.test.js +12 -2
  15. package/dist/__tests__/lowering.test.js +200 -12
  16. package/dist/__tests__/mc-integration.test.js +370 -31
  17. package/dist/__tests__/mc-syntax.test.js +3 -3
  18. package/dist/__tests__/nbt.test.js +2 -2
  19. package/dist/__tests__/optimizer-advanced.test.js +5 -5
  20. package/dist/__tests__/parser.test.js +80 -0
  21. package/dist/__tests__/runtime.test.js +9 -9
  22. package/dist/__tests__/typechecker.test.js +158 -0
  23. package/dist/ast/types.d.ts +40 -3
  24. package/dist/cli.js +25 -7
  25. package/dist/codegen/mcfunction/index.d.ts +1 -1
  26. package/dist/codegen/mcfunction/index.js +38 -3
  27. package/dist/codegen/structure/index.js +32 -1
  28. package/dist/compile.d.ts +10 -0
  29. package/dist/compile.js +36 -5
  30. package/dist/events/types.d.ts +35 -0
  31. package/dist/events/types.js +59 -0
  32. package/dist/formatter/index.d.ts +1 -0
  33. package/dist/formatter/index.js +26 -0
  34. package/dist/index.js +3 -2
  35. package/dist/ir/builder.d.ts +2 -1
  36. package/dist/ir/types.d.ts +11 -2
  37. package/dist/ir/types.js +1 -1
  38. package/dist/lexer/index.d.ts +1 -1
  39. package/dist/lexer/index.js +2 -0
  40. package/dist/lowering/index.d.ts +34 -1
  41. package/dist/lowering/index.js +622 -23
  42. package/dist/mc-test/runner.d.ts +2 -2
  43. package/dist/mc-test/runner.js +3 -3
  44. package/dist/mc-test/setup.js +2 -2
  45. package/dist/parser/index.d.ts +4 -0
  46. package/dist/parser/index.js +153 -16
  47. package/dist/typechecker/index.d.ts +17 -0
  48. package/dist/typechecker/index.js +343 -17
  49. package/docs/COMPILATION_STATS.md +24 -24
  50. package/docs/ENTITY_TYPE_SYSTEM.md +242 -0
  51. package/docs/IMPLEMENTATION_GUIDE.md +1 -1
  52. package/docs/STRUCTURE_TARGET.md +1 -1
  53. package/editors/vscode/.vscodeignore +1 -0
  54. package/editors/vscode/CHANGELOG.md +9 -0
  55. package/editors/vscode/icons/mcrs.svg +7 -0
  56. package/editors/vscode/icons/redscript-icons.json +10 -0
  57. package/editors/vscode/out/extension.js +1295 -80
  58. package/editors/vscode/package-lock.json +2 -2
  59. package/editors/vscode/package.json +10 -3
  60. package/editors/vscode/src/hover.ts +55 -2
  61. package/editors/vscode/src/symbols.ts +42 -0
  62. package/package.json +1 -1
  63. package/src/__tests__/cli.test.ts +176 -10
  64. package/src/__tests__/codegen.test.ts +28 -1
  65. package/src/__tests__/diagnostics.test.ts +5 -5
  66. package/src/__tests__/e2e.test.ts +335 -17
  67. package/src/__tests__/fixtures/event-test.mcrs +13 -0
  68. package/src/__tests__/fixtures/impl-test.mcrs +46 -0
  69. package/src/__tests__/fixtures/interval-test.mcrs +11 -0
  70. package/src/__tests__/fixtures/is-check-test.mcrs +20 -0
  71. package/src/__tests__/fixtures/timeout-test.mcrs +7 -0
  72. package/src/__tests__/lexer.test.ts +14 -2
  73. package/src/__tests__/lowering.test.ts +226 -12
  74. package/src/__tests__/mc-integration.test.ts +421 -31
  75. package/src/__tests__/mc-syntax.test.ts +3 -3
  76. package/src/__tests__/nbt.test.ts +2 -2
  77. package/src/__tests__/optimizer-advanced.test.ts +5 -5
  78. package/src/__tests__/parser.test.ts +91 -5
  79. package/src/__tests__/runtime.test.ts +9 -9
  80. package/src/__tests__/typechecker.test.ts +171 -0
  81. package/src/ast/types.ts +44 -3
  82. package/src/cli.ts +10 -10
  83. package/src/codegen/mcfunction/index.ts +40 -3
  84. package/src/codegen/structure/index.ts +35 -1
  85. package/src/compile.ts +54 -6
  86. package/src/events/types.ts +69 -0
  87. package/src/examples/capture_the_flag.mcrs +208 -0
  88. package/src/examples/{counter.rs → counter.mcrs} +1 -1
  89. package/src/examples/hunger_games.mcrs +301 -0
  90. package/src/examples/new_features_demo.mcrs +193 -0
  91. package/src/examples/parkour_race.mcrs +233 -0
  92. package/src/examples/rpg.mcrs +13 -0
  93. package/src/examples/{shop.rs → shop.mcrs} +1 -1
  94. package/src/examples/{showcase_game.rs → showcase_game.mcrs} +3 -3
  95. package/src/examples/{turret.rs → turret.mcrs} +1 -1
  96. package/src/examples/zombie_survival.mcrs +314 -0
  97. package/src/index.ts +4 -3
  98. package/src/ir/builder.ts +3 -1
  99. package/src/ir/types.ts +12 -2
  100. package/src/lexer/index.ts +3 -1
  101. package/src/lowering/index.ts +684 -24
  102. package/src/mc-test/runner.ts +3 -3
  103. package/src/mc-test/setup.ts +2 -2
  104. package/src/parser/index.ts +170 -19
  105. package/src/stdlib/README.md +178 -140
  106. package/src/stdlib/bossbar.mcrs +68 -0
  107. package/src/stdlib/{cooldown.rs → cooldown.mcrs} +1 -1
  108. package/src/stdlib/effects.mcrs +64 -0
  109. package/src/stdlib/interactions.mcrs +195 -0
  110. package/src/stdlib/inventory.mcrs +38 -0
  111. package/src/stdlib/mobs.mcrs +99 -0
  112. package/src/stdlib/particles.mcrs +52 -0
  113. package/src/stdlib/sets.mcrs +20 -0
  114. package/src/stdlib/spawn.mcrs +41 -0
  115. package/src/stdlib/tags.mcrs +951 -0
  116. package/src/stdlib/teams.mcrs +68 -0
  117. package/src/stdlib/timer.mcrs +72 -0
  118. package/src/stdlib/world.mcrs +92 -0
  119. package/src/typechecker/index.ts +404 -18
  120. package/src/examples/rpg.rs +0 -13
  121. package/src/stdlib/mobs.rs +0 -99
  122. package/src/stdlib/timer.rs +0 -51
  123. /package/src/examples/{arena.rs → arena.mcrs} +0 -0
  124. /package/src/examples/{pvp_arena.rs → pvp_arena.mcrs} +0 -0
  125. /package/src/examples/{quiz.rs → quiz.mcrs} +0 -0
  126. /package/src/examples/{stdlib_demo.rs → stdlib_demo.mcrs} +0 -0
  127. /package/src/examples/{world_manager.rs → world_manager.mcrs} +0 -0
  128. /package/src/stdlib/{combat.rs → combat.mcrs} +0 -0
  129. /package/src/stdlib/{math.rs → math.mcrs} +0 -0
  130. /package/src/stdlib/{player.rs → player.mcrs} +0 -0
  131. /package/src/stdlib/{strings.rs → strings.mcrs} +0 -0
  132. /package/src/templates/{combat.rs → combat.mcrs} +0 -0
  133. /package/src/templates/{economy.rs → economy.mcrs} +0 -0
  134. /package/src/templates/{mini-game-framework.rs → mini-game-framework.mcrs} +0 -0
  135. /package/src/templates/{quest.rs → quest.mcrs} +0 -0
  136. /package/src/test_programs/{zombie_game.rs → zombie_game.mcrs} +0 -0
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * RedScript MC Integration Test Runner
3
3
  *
4
- * Compiles a .rs file, installs it to a running Paper server,
4
+ * Compiles a .mcrs file, installs it to a running Paper server,
5
5
  * runs test scenarios, and reports results.
6
6
  *
7
7
  * Usage:
8
- * npx ts-node src/mc-test/runner.ts src/examples/counter.rs
8
+ * npx ts-node src/mc-test/runner.ts src/examples/counter.mcrs
9
9
  *
10
10
  * Requires:
11
11
  * - Paper server running with TestHarnessPlugin
@@ -2,11 +2,11 @@
2
2
  /**
3
3
  * RedScript MC Integration Test Runner
4
4
  *
5
- * Compiles a .rs file, installs it to a running Paper server,
5
+ * Compiles a .mcrs file, installs it to a running Paper server,
6
6
  * runs test scenarios, and reports results.
7
7
  *
8
8
  * Usage:
9
- * npx ts-node src/mc-test/runner.ts src/examples/counter.rs
9
+ * npx ts-node src/mc-test/runner.ts src/examples/counter.mcrs
10
10
  *
11
11
  * Requires:
12
12
  * - Paper server running with TestHarnessPlugin
@@ -115,7 +115,7 @@ async function runMCTests(sourceFile, tests, options = {}) {
115
115
  if (require.main === module) {
116
116
  const sourceFile = process.argv[2];
117
117
  if (!sourceFile) {
118
- console.error('Usage: ts-node runner.ts <source.rs>');
118
+ console.error('Usage: ts-node runner.ts <source.mcrs>');
119
119
  process.exit(1);
120
120
  }
121
121
  // Example test suite (replace with actual tests)
@@ -66,12 +66,12 @@ function main() {
66
66
  // Example files
67
67
  const exampleNamespaces = ['counter', 'world_manager'];
68
68
  for (const ns of exampleNamespaces) {
69
- const file = path.join(EXAMPLES_DIR, `${ns}.rs`);
69
+ const file = path.join(EXAMPLES_DIR, `${ns}.mcrs`);
70
70
  if (fs.existsSync(file)) {
71
71
  writeFixture(fs.readFileSync(file, 'utf-8'), ns);
72
72
  }
73
73
  else {
74
- console.log(` ⚠ ${ns}.rs not found, skipping`);
74
+ console.log(` ⚠ ${ns}.mcrs not found, skipping`);
75
75
  }
76
76
  }
77
77
  // Inline test fixtures
@@ -23,7 +23,9 @@ export declare class Parser {
23
23
  parse(defaultNamespace?: string): Program;
24
24
  private parseStructDecl;
25
25
  private parseEnumDecl;
26
+ private parseImplBlock;
26
27
  private parseConstDecl;
28
+ private parseGlobalDecl;
27
29
  private parseFnDecl;
28
30
  private parseDecorators;
29
31
  private parseDecoratorValue;
@@ -48,6 +50,7 @@ export declare class Parser {
48
50
  private parseAssignment;
49
51
  private parseBinaryExpr;
50
52
  private parseUnaryExpr;
53
+ private parseEntityTypeName;
51
54
  private isSubtraction;
52
55
  private parsePostfixExpr;
53
56
  private parseArgs;
@@ -68,6 +71,7 @@ export declare class Parser {
68
71
  private parseCoordComponent;
69
72
  private parseSignedCoordOffset;
70
73
  private parseSelector;
74
+ private parseSelectorOrVarSelector;
71
75
  private parseSelectorValue;
72
76
  private parseSelectorFilters;
73
77
  private splitSelectorParams;
@@ -16,11 +16,31 @@ const PRECEDENCE = {
16
16
  '||': 1,
17
17
  '&&': 2,
18
18
  '==': 3, '!=': 3,
19
- '<': 4, '<=': 4, '>': 4, '>=': 4,
19
+ '<': 4, '<=': 4, '>': 4, '>=': 4, 'is': 4,
20
20
  '+': 5, '-': 5,
21
21
  '*': 6, '/': 6, '%': 6,
22
22
  };
23
- const BINARY_OPS = new Set(['||', '&&', '==', '!=', '<', '<=', '>', '>=', '+', '-', '*', '/', '%']);
23
+ const BINARY_OPS = new Set(['||', '&&', '==', '!=', '<', '<=', '>', '>=', 'is', '+', '-', '*', '/', '%']);
24
+ const ENTITY_TYPE_NAMES = new Set([
25
+ 'entity',
26
+ 'Player',
27
+ 'Mob',
28
+ 'HostileMob',
29
+ 'PassiveMob',
30
+ 'Zombie',
31
+ 'Skeleton',
32
+ 'Creeper',
33
+ 'Spider',
34
+ 'Enderman',
35
+ 'Pig',
36
+ 'Cow',
37
+ 'Sheep',
38
+ 'Chicken',
39
+ 'Villager',
40
+ 'ArmorStand',
41
+ 'Item',
42
+ 'Arrow',
43
+ ]);
24
44
  function computeIsSingle(raw) {
25
45
  if (/^@[spr](\[|$)/.test(raw))
26
46
  return true;
@@ -99,8 +119,10 @@ class Parser {
99
119
  // -------------------------------------------------------------------------
100
120
  parse(defaultNamespace = 'redscript') {
101
121
  let namespace = defaultNamespace;
122
+ const globals = [];
102
123
  const declarations = [];
103
124
  const structs = [];
125
+ const implBlocks = [];
104
126
  const enums = [];
105
127
  const consts = [];
106
128
  // Check for namespace declaration
@@ -112,9 +134,15 @@ class Parser {
112
134
  }
113
135
  // Parse struct and function declarations
114
136
  while (!this.check('eof')) {
115
- if (this.check('struct')) {
137
+ if (this.check('let')) {
138
+ globals.push(this.parseGlobalDecl(true));
139
+ }
140
+ else if (this.check('struct')) {
116
141
  structs.push(this.parseStructDecl());
117
142
  }
143
+ else if (this.check('impl')) {
144
+ implBlocks.push(this.parseImplBlock());
145
+ }
118
146
  else if (this.check('enum')) {
119
147
  enums.push(this.parseEnumDecl());
120
148
  }
@@ -125,7 +153,7 @@ class Parser {
125
153
  declarations.push(this.parseFnDecl());
126
154
  }
127
155
  }
128
- return { namespace, declarations, structs, enums, consts };
156
+ return { namespace, globals, declarations, structs, implBlocks, enums, consts };
129
157
  }
130
158
  // -------------------------------------------------------------------------
131
159
  // Struct Declaration
@@ -171,6 +199,17 @@ class Parser {
171
199
  this.expect('}');
172
200
  return this.withLoc({ name, variants }, enumToken);
173
201
  }
202
+ parseImplBlock() {
203
+ const implToken = this.expect('impl');
204
+ const typeName = this.expect('ident').value;
205
+ this.expect('{');
206
+ const methods = [];
207
+ while (!this.check('}') && !this.check('eof')) {
208
+ methods.push(this.parseFnDecl(typeName));
209
+ }
210
+ this.expect('}');
211
+ return this.withLoc({ kind: 'impl_block', typeName, methods }, implToken);
212
+ }
174
213
  parseConstDecl() {
175
214
  const constToken = this.expect('const');
176
215
  const name = this.expect('ident').value;
@@ -181,18 +220,28 @@ class Parser {
181
220
  this.match(';');
182
221
  return this.withLoc({ name, type, value }, constToken);
183
222
  }
223
+ parseGlobalDecl(mutable) {
224
+ const token = this.advance(); // consume 'let'
225
+ const name = this.expect('ident').value;
226
+ this.expect(':');
227
+ const type = this.parseType();
228
+ this.expect('=');
229
+ const init = this.parseExpr();
230
+ this.expect(';');
231
+ return this.withLoc({ kind: 'global', name, type, init, mutable }, token);
232
+ }
184
233
  // -------------------------------------------------------------------------
185
234
  // Function Declaration
186
235
  // -------------------------------------------------------------------------
187
- parseFnDecl() {
236
+ parseFnDecl(implTypeName) {
188
237
  const decorators = this.parseDecorators();
189
238
  const fnToken = this.expect('fn');
190
239
  const name = this.expect('ident').value;
191
240
  this.expect('(');
192
- const params = this.parseParams();
241
+ const params = this.parseParams(implTypeName);
193
242
  this.expect(')');
194
243
  let returnType = { kind: 'named', name: 'void' };
195
- if (this.match('->')) {
244
+ if (this.match('->') || this.match(':')) {
196
245
  returnType = this.parseType();
197
246
  }
198
247
  const body = this.parseBlock();
@@ -208,7 +257,7 @@ class Parser {
208
257
  return decorators;
209
258
  }
210
259
  parseDecoratorValue(value) {
211
- // Parse @tick or @on_trigger("name") or @on_advancement("story/mine_diamond")
260
+ // Parse @tick, @on(PlayerDeath), or @on_trigger("name")
212
261
  const match = value.match(/^@(\w+)(?:\(([^)]*)\))?$/);
213
262
  if (!match) {
214
263
  this.error(`Invalid decorator: ${value}`);
@@ -219,6 +268,13 @@ class Parser {
219
268
  return { name };
220
269
  }
221
270
  const args = {};
271
+ if (name === 'on') {
272
+ const eventTypeMatch = argsStr.match(/^([A-Za-z_][A-Za-z0-9_]*)$/);
273
+ if (eventTypeMatch) {
274
+ args.eventType = eventTypeMatch[1];
275
+ return { name, args };
276
+ }
277
+ }
222
278
  // Handle @on_trigger("name"), @on_advancement("id"), @on_craft("item"), @on_join_team("team")
223
279
  if (name === 'on_trigger' || name === 'on_advancement' || name === 'on_craft' || name === 'on_join_team') {
224
280
  const strMatch = argsStr.match(/^"([^"]*)"$/);
@@ -259,14 +315,20 @@ class Parser {
259
315
  }
260
316
  return { name, args };
261
317
  }
262
- parseParams() {
318
+ parseParams(implTypeName) {
263
319
  const params = [];
264
320
  if (!this.check(')')) {
265
321
  do {
266
322
  const paramToken = this.expect('ident');
267
323
  const name = paramToken.value;
268
- this.expect(':');
269
- const type = this.parseType();
324
+ let type;
325
+ if (implTypeName && params.length === 0 && name === 'self' && !this.check(':')) {
326
+ type = { kind: 'struct', name: implTypeName };
327
+ }
328
+ else {
329
+ this.expect(':');
330
+ type = this.parseType();
331
+ }
270
332
  let defaultValue;
271
333
  if (this.match('=')) {
272
334
  defaultValue = this.parseExpr();
@@ -534,16 +596,16 @@ class Parser {
534
596
  if (this.peek().kind === 'ident' && this.peek().value === 'entity') {
535
597
  this.advance(); // consume 'entity'
536
598
  }
537
- const selector = this.parseSelector();
538
- subcommands.push({ kind: 'if_entity', selector });
599
+ const selectorOrVar = this.parseSelectorOrVarSelector();
600
+ subcommands.push({ kind: 'if_entity', ...selectorOrVar });
539
601
  }
540
602
  else if (this.match('unless')) {
541
603
  // Expect 'entity' keyword (as ident) or just parse selector directly
542
604
  if (this.peek().kind === 'ident' && this.peek().value === 'entity') {
543
605
  this.advance(); // consume 'entity'
544
606
  }
545
- const selector = this.parseSelector();
546
- subcommands.push({ kind: 'unless_entity', selector });
607
+ const selectorOrVar = this.parseSelectorOrVarSelector();
608
+ subcommands.push({ kind: 'unless_entity', ...selectorOrVar });
547
609
  }
548
610
  else if (this.match('in')) {
549
611
  const dim = this.expect('ident').value;
@@ -598,6 +660,11 @@ class Parser {
598
660
  if (prec < minPrec)
599
661
  break;
600
662
  const opToken = this.advance();
663
+ if (op === 'is') {
664
+ const entityType = this.parseEntityTypeName();
665
+ left = this.withLoc({ kind: 'is_check', expr: left, entityType }, this.getLocToken(left) ?? opToken);
666
+ continue;
667
+ }
601
668
  const right = this.parseBinaryExpr(prec + 1); // left associative
602
669
  left = this.withLoc({ kind: 'binary', op: op, left, right }, this.getLocToken(left) ?? opToken);
603
670
  }
@@ -616,6 +683,13 @@ class Parser {
616
683
  }
617
684
  return this.parsePostfixExpr();
618
685
  }
686
+ parseEntityTypeName() {
687
+ const token = this.expect('ident');
688
+ if (ENTITY_TYPE_NAMES.has(token.value)) {
689
+ return token.value;
690
+ }
691
+ this.error(`Unknown entity type '${token.value}'`);
692
+ }
619
693
  isSubtraction() {
620
694
  // Check if this minus is binary (subtraction) by looking at previous token
621
695
  // If previous was a value (literal, ident, ), ]) it's subtraction
@@ -645,6 +719,10 @@ class Parser {
645
719
  'has_tag': '__entity_has_tag',
646
720
  'push': '__array_push',
647
721
  'pop': '__array_pop',
722
+ 'add': 'set_add',
723
+ 'contains': 'set_contains',
724
+ 'remove': 'set_remove',
725
+ 'clear': 'set_clear',
648
726
  };
649
727
  const internalFn = methodMap[expr.field];
650
728
  if (internalFn) {
@@ -653,7 +731,11 @@ class Parser {
653
731
  expr = this.withLoc({ kind: 'call', fn: internalFn, args: [expr.obj, ...args] }, this.getLocToken(expr) ?? openParenToken);
654
732
  continue;
655
733
  }
656
- this.error(`Unknown method '${expr.field}'`);
734
+ // Generic method sugar: obj.method(args) method(obj, args)
735
+ const args = this.parseArgs();
736
+ this.expect(')');
737
+ expr = this.withLoc({ kind: 'call', fn: expr.field, args: [expr.obj, ...args] }, this.getLocToken(expr) ?? openParenToken);
738
+ continue;
657
739
  }
658
740
  const args = this.parseArgs();
659
741
  this.expect(')');
@@ -688,6 +770,15 @@ class Parser {
688
770
  }
689
771
  parsePrimaryExpr() {
690
772
  const token = this.peek();
773
+ if (token.kind === 'ident' && this.peek(1).kind === '::') {
774
+ const typeToken = this.advance();
775
+ this.expect('::');
776
+ const methodToken = this.expect('ident');
777
+ this.expect('(');
778
+ const args = this.parseArgs();
779
+ this.expect(')');
780
+ return this.withLoc({ kind: 'static_call', type: typeToken.value, method: methodToken.value, args }, typeToken);
781
+ }
691
782
  if (token.kind === 'ident' && this.peek(1).kind === '=>') {
692
783
  return this.parseSingleParamLambda();
693
784
  }
@@ -1077,6 +1168,37 @@ class Parser {
1077
1168
  const token = this.expect('selector');
1078
1169
  return this.parseSelectorValue(token.value);
1079
1170
  }
1171
+ // Parse either a selector (@a[...]) or a variable with filters (p[...])
1172
+ // Returns { selector } for selectors or { varName, filters } for variables
1173
+ parseSelectorOrVarSelector() {
1174
+ if (this.check('selector')) {
1175
+ return { selector: this.parseSelector() };
1176
+ }
1177
+ // Must be an identifier (variable) possibly with filters
1178
+ const varToken = this.expect('ident');
1179
+ const varName = varToken.value;
1180
+ // Check for optional filters [...]
1181
+ if (this.check('[')) {
1182
+ this.advance(); // consume '['
1183
+ // Collect everything until ']'
1184
+ let filterStr = '';
1185
+ let depth = 1;
1186
+ while (depth > 0 && !this.check('eof')) {
1187
+ if (this.check('['))
1188
+ depth++;
1189
+ else if (this.check(']'))
1190
+ depth--;
1191
+ if (depth > 0) {
1192
+ filterStr += this.peek().value ?? this.peek().kind;
1193
+ this.advance();
1194
+ }
1195
+ }
1196
+ this.expect(']');
1197
+ const filters = this.parseSelectorFilters(filterStr);
1198
+ return { varName, filters };
1199
+ }
1200
+ return { varName };
1201
+ }
1080
1202
  parseSelectorValue(value) {
1081
1203
  // Parse @e[type=zombie, distance=..5]
1082
1204
  const bracketIndex = value.indexOf('[');
@@ -1129,6 +1251,21 @@ class Parser {
1129
1251
  case 'scores':
1130
1252
  filters.scores = this.parseScoresFilter(val);
1131
1253
  break;
1254
+ case 'x':
1255
+ filters.x = this.parseRangeValue(val);
1256
+ break;
1257
+ case 'y':
1258
+ filters.y = this.parseRangeValue(val);
1259
+ break;
1260
+ case 'z':
1261
+ filters.z = this.parseRangeValue(val);
1262
+ break;
1263
+ case 'x_rotation':
1264
+ filters.x_rotation = this.parseRangeValue(val);
1265
+ break;
1266
+ case 'y_rotation':
1267
+ filters.y_rotation = this.parseRangeValue(val);
1268
+ break;
1132
1269
  }
1133
1270
  }
1134
1271
  return filters;
@@ -9,12 +9,14 @@ import { DiagnosticError } from '../diagnostics';
9
9
  export declare class TypeChecker {
10
10
  private collector;
11
11
  private functions;
12
+ private implMethods;
12
13
  private structs;
13
14
  private enums;
14
15
  private consts;
15
16
  private currentFn;
16
17
  private currentReturnType;
17
18
  private scope;
19
+ private selfTypeStack;
18
20
  constructor(source?: string, filePath?: string);
19
21
  private getNodeLocation;
20
22
  private report;
@@ -23,6 +25,7 @@ export declare class TypeChecker {
23
25
  */
24
26
  check(program: Program): DiagnosticError[];
25
27
  private checkFunction;
28
+ private checkFunctionDecorators;
26
29
  private checkBlock;
27
30
  private checkStmt;
28
31
  private checkLetStmt;
@@ -33,9 +36,23 @@ export declare class TypeChecker {
33
36
  private checkFunctionCallArgs;
34
37
  private checkTpCall;
35
38
  private checkMemberExpr;
39
+ private checkStaticCallExpr;
36
40
  private checkLambdaExpr;
41
+ private checkIfBranches;
42
+ private getThenBranchNarrowing;
37
43
  private inferType;
38
44
  private inferLambdaType;
45
+ /** Infer entity type from a selector */
46
+ private inferEntityTypeFromSelector;
47
+ private resolveInstanceMethod;
48
+ /** Check if childType is a subtype of parentType */
49
+ private isEntitySubtype;
50
+ /** Push a new self type context */
51
+ private pushSelfType;
52
+ /** Pop self type context */
53
+ private popSelfType;
54
+ /** Get current @s type */
55
+ private getCurrentSelfType;
39
56
  private typesMatch;
40
57
  private typeToString;
41
58
  private normalizeType;