@harmoniclabs/pebble 0.1.8 → 0.1.9

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 (42) hide show
  1. package/dist/ast/nodes/expr/IsExpr.d.ts +10 -1
  2. package/dist/ast/nodes/expr/IsExpr.js +9 -13
  3. package/dist/ast/nodes/expr/PebbleExpr.d.ts +2 -1
  4. package/dist/ast/nodes/expr/PebbleExpr.js +2 -1
  5. package/dist/ast/nodes/statements/declarations/ContractDecl.d.ts +3 -1
  6. package/dist/ast/nodes/statements/declarations/ContractDecl.js +3 -1
  7. package/dist/ast/nodes/statements/declarations/StateDecl.d.ts +12 -0
  8. package/dist/ast/nodes/statements/declarations/StateDecl.js +12 -0
  9. package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +155 -6
  10. package/dist/compiler/AstCompiler/internal/exprs/_compileCaseExpr.d.ts +1 -1
  11. package/dist/compiler/AstCompiler/internal/exprs/_compileCaseExpr.js +30 -4
  12. package/dist/compiler/AstCompiler/internal/exprs/_compileExpr.js +4 -1
  13. package/dist/compiler/AstCompiler/internal/exprs/_compileIsExpr.d.ts +5 -1
  14. package/dist/compiler/AstCompiler/internal/exprs/_compileIsExpr.js +20 -41
  15. package/dist/compiler/AstCompiler/internal/exprs/_compileTernaryExpr.js +7 -2
  16. package/dist/compiler/AstCompiler/internal/statements/_compileAssertStmt.js +4 -0
  17. package/dist/compiler/AstCompiler/internal/statements/_compileIfStmt.js +7 -2
  18. package/dist/compiler/AstCompiler/internal/statements/_compileMatchStmt.d.ts +1 -1
  19. package/dist/compiler/AstCompiler/internal/statements/_compileMatchStmt.js +17 -4
  20. package/dist/compiler/AstCompiler/scope/AstScope.d.ts +12 -0
  21. package/dist/compiler/AstCompiler/scope/AstScope.js +25 -2
  22. package/dist/compiler/AstCompiler/utils/extractIsNarrowings.d.ts +30 -0
  23. package/dist/compiler/AstCompiler/utils/extractIsNarrowings.js +110 -0
  24. package/dist/compiler/Compiler.js +7 -3
  25. package/dist/compiler/TirCompiler/expressify/expressifyVars.js +6 -0
  26. package/dist/compiler/tir/expressions/TirCallExpr.js +4 -0
  27. package/dist/compiler/tir/expressions/TirCaseExpr.js +38 -7
  28. package/dist/compiler/tir/expressions/TirExpr.d.ts +2 -1
  29. package/dist/compiler/tir/expressions/TirExpr.js +2 -1
  30. package/dist/compiler/tir/expressions/TirFuncExpr.js +4 -1
  31. package/dist/compiler/tir/expressions/TirIsExpr.d.ts +23 -0
  32. package/dist/compiler/tir/expressions/TirIsExpr.js +87 -0
  33. package/dist/compiler/tir/types/TirStructType.d.ts +33 -2
  34. package/dist/compiler/tir/types/TirStructType.js +69 -4
  35. package/dist/compiler/tir/types/utils/canAssignTo.js +14 -0
  36. package/dist/parser/Parser.d.ts +2 -0
  37. package/dist/parser/Parser.js +87 -22
  38. package/dist/tokenizer/Token.d.ts +79 -78
  39. package/dist/tokenizer/Token.js +79 -78
  40. package/dist/tokenizer/utils/tokenFromKeyword.js +7 -2
  41. package/dist/tokenizer/utils/tokenIsAlsoIdentifier.js +1 -0
  42. package/package.json +1 -1
@@ -17,13 +17,33 @@ export declare class TirDataStructType implements ITirStructType {
17
17
  /** points to an array possibly shared with alternative encoding types */
18
18
  readonly methodNamesPtr: Map<AstFuncName, TirFuncName>;
19
19
  readonly untagged: boolean;
20
+ /**
21
+ * indexes (in the ORIGINAL parent struct's constructors array) of the
22
+ * constructors still possible after flow-sensitive narrowing.
23
+ *
24
+ * `undefined` means "not narrowed" (full struct).
25
+ * If present, length matches `this.constructors.length` and entries
26
+ * correspond positionally to `this.constructors`.
27
+ */
28
+ readonly narrowedFromParentCtorIdxs: number[] | undefined;
20
29
  constructor(name: string, fileUid: string, constructors: TirStructConstr[],
21
30
  /** points to an array possibly shared with alternative encoding types */
22
- methodNamesPtr: Map<AstFuncName, TirFuncName>, untagged?: boolean);
31
+ methodNamesPtr: Map<AstFuncName, TirFuncName>, untagged?: boolean, narrowedFromParentCtorIdxs?: number[] | undefined);
23
32
  hasDataEncoding(): boolean;
24
33
  toTirTypeKey(): string;
25
34
  toConcreteTirTypeName(): string;
26
35
  isSingleConstr(): boolean;
36
+ isNarrowed(): boolean;
37
+ /**
38
+ * Original ctor index of `this.constructors[localIdx]` in the
39
+ * un-narrowed parent type. For un-narrowed types this is identity.
40
+ */
41
+ parentCtorIdx(localIdx: number): number;
42
+ /**
43
+ * Returns a clone of this struct type narrowed to the constructors
44
+ * whose ORIGINAL parent indexes are listed in `parentIdxs`.
45
+ */
46
+ narrowTo(parentIdxs: number[]): TirDataStructType;
27
47
  toString(): string;
28
48
  toAstName(): string;
29
49
  protected _isConcrete: boolean | undefined;
@@ -37,13 +57,24 @@ export declare class TirSoPStructType implements ITirStructType {
37
57
  readonly constructors: TirStructConstr[];
38
58
  /** points to an array possibly shared with alternative encoding types */
39
59
  readonly methodNamesPtr: Map<AstFuncName, TirFuncName>;
60
+ /**
61
+ * indexes (in the ORIGINAL parent struct's constructors array) of the
62
+ * constructors still possible after flow-sensitive narrowing.
63
+ *
64
+ * `undefined` means "not narrowed" (full struct).
65
+ * If present, length matches `this.constructors.length`.
66
+ */
67
+ readonly narrowedFromParentCtorIdxs: number[] | undefined;
40
68
  constructor(name: string, fileUid: string, constructors: TirStructConstr[],
41
69
  /** points to an array possibly shared with alternative encoding types */
42
- methodNamesPtr: Map<AstFuncName, TirFuncName>);
70
+ methodNamesPtr: Map<AstFuncName, TirFuncName>, narrowedFromParentCtorIdxs?: number[] | undefined);
43
71
  hasDataEncoding(): boolean;
44
72
  toTirTypeKey(): string;
45
73
  toConcreteTirTypeName(): string;
46
74
  isSingleConstr(): boolean;
75
+ isNarrowed(): boolean;
76
+ parentCtorIdx(localIdx: number): number;
77
+ narrowTo(parentIdxs: number[]): TirSoPStructType;
47
78
  toString(): string;
48
79
  toAstName(): string;
49
80
  protected _isConcrete: boolean | undefined;
@@ -10,15 +10,25 @@ export class TirDataStructType {
10
10
  constructors;
11
11
  methodNamesPtr;
12
12
  untagged;
13
+ /**
14
+ * indexes (in the ORIGINAL parent struct's constructors array) of the
15
+ * constructors still possible after flow-sensitive narrowing.
16
+ *
17
+ * `undefined` means "not narrowed" (full struct).
18
+ * If present, length matches `this.constructors.length` and entries
19
+ * correspond positionally to `this.constructors`.
20
+ */
21
+ narrowedFromParentCtorIdxs;
13
22
  constructor(name, fileUid, constructors,
14
23
  /** points to an array possibly shared with alternative encoding types */
15
- methodNamesPtr, untagged = false) {
24
+ methodNamesPtr, untagged = false, narrowedFromParentCtorIdxs = undefined) {
16
25
  this.name = name;
17
26
  this.fileUid = fileUid;
18
27
  this.constructors = constructors;
19
28
  this.methodNamesPtr = methodNamesPtr;
20
29
  this.untagged = untagged;
21
30
  this.untagged = false; // always false for now
31
+ this.narrowedFromParentCtorIdxs = narrowedFromParentCtorIdxs;
22
32
  }
23
33
  hasDataEncoding() { return true; }
24
34
  toTirTypeKey() {
@@ -30,6 +40,33 @@ export class TirDataStructType {
30
40
  isSingleConstr() {
31
41
  return this.constructors.length === 1;
32
42
  }
43
+ isNarrowed() {
44
+ return this.narrowedFromParentCtorIdxs !== undefined;
45
+ }
46
+ /**
47
+ * Original ctor index of `this.constructors[localIdx]` in the
48
+ * un-narrowed parent type. For un-narrowed types this is identity.
49
+ */
50
+ parentCtorIdx(localIdx) {
51
+ return this.narrowedFromParentCtorIdxs?.[localIdx] ?? localIdx;
52
+ }
53
+ /**
54
+ * Returns a clone of this struct type narrowed to the constructors
55
+ * whose ORIGINAL parent indexes are listed in `parentIdxs`.
56
+ */
57
+ narrowTo(parentIdxs) {
58
+ const baseIdxs = this.narrowedFromParentCtorIdxs ?? this.constructors.map((_, i) => i);
59
+ const filtered = [];
60
+ const filteredCtors = [];
61
+ for (let i = 0; i < this.constructors.length; i++) {
62
+ const parentIdx = baseIdxs[i];
63
+ if (parentIdxs.includes(parentIdx)) {
64
+ filtered.push(parentIdx);
65
+ filteredCtors.push(this.constructors[i]);
66
+ }
67
+ }
68
+ return new TirDataStructType(this.name, this.fileUid, filteredCtors, this.methodNamesPtr, this.untagged, filtered);
69
+ }
33
70
  toString() {
34
71
  return this.name;
35
72
  }
@@ -43,7 +80,7 @@ export class TirDataStructType {
43
80
  return this._isConcrete;
44
81
  }
45
82
  clone() {
46
- const result = new TirDataStructType(this.name, this.fileUid, this.constructors.map(c => c.clone()), this.methodNamesPtr);
83
+ const result = new TirDataStructType(this.name, this.fileUid, this.constructors.map(c => c.clone()), this.methodNamesPtr, this.untagged, this.narrowedFromParentCtorIdxs ? [...this.narrowedFromParentCtorIdxs] : undefined);
47
84
  result._isConcrete = this._isConcrete;
48
85
  return result;
49
86
  }
@@ -56,13 +93,22 @@ export class TirSoPStructType {
56
93
  fileUid;
57
94
  constructors;
58
95
  methodNamesPtr;
96
+ /**
97
+ * indexes (in the ORIGINAL parent struct's constructors array) of the
98
+ * constructors still possible after flow-sensitive narrowing.
99
+ *
100
+ * `undefined` means "not narrowed" (full struct).
101
+ * If present, length matches `this.constructors.length`.
102
+ */
103
+ narrowedFromParentCtorIdxs;
59
104
  constructor(name, fileUid, constructors,
60
105
  /** points to an array possibly shared with alternative encoding types */
61
- methodNamesPtr) {
106
+ methodNamesPtr, narrowedFromParentCtorIdxs = undefined) {
62
107
  this.name = name;
63
108
  this.fileUid = fileUid;
64
109
  this.constructors = constructors;
65
110
  this.methodNamesPtr = methodNamesPtr;
111
+ this.narrowedFromParentCtorIdxs = narrowedFromParentCtorIdxs;
66
112
  }
67
113
  hasDataEncoding() { return false; }
68
114
  toTirTypeKey() {
@@ -74,6 +120,25 @@ export class TirSoPStructType {
74
120
  isSingleConstr() {
75
121
  return this.constructors.length === 1;
76
122
  }
123
+ isNarrowed() {
124
+ return this.narrowedFromParentCtorIdxs !== undefined;
125
+ }
126
+ parentCtorIdx(localIdx) {
127
+ return this.narrowedFromParentCtorIdxs?.[localIdx] ?? localIdx;
128
+ }
129
+ narrowTo(parentIdxs) {
130
+ const baseIdxs = this.narrowedFromParentCtorIdxs ?? this.constructors.map((_, i) => i);
131
+ const filtered = [];
132
+ const filteredCtors = [];
133
+ for (let i = 0; i < this.constructors.length; i++) {
134
+ const parentIdx = baseIdxs[i];
135
+ if (parentIdxs.includes(parentIdx)) {
136
+ filtered.push(parentIdx);
137
+ filteredCtors.push(this.constructors[i]);
138
+ }
139
+ }
140
+ return new TirSoPStructType(this.name, this.fileUid, filteredCtors, this.methodNamesPtr, filtered);
141
+ }
77
142
  toString() {
78
143
  return this.name;
79
144
  }
@@ -87,7 +152,7 @@ export class TirSoPStructType {
87
152
  return this._isConcrete;
88
153
  }
89
154
  clone() {
90
- const result = new TirSoPStructType(this.name, this.fileUid, this.constructors.map(c => c.clone()), this.methodNamesPtr);
155
+ const result = new TirSoPStructType(this.name, this.fileUid, this.constructors.map(c => c.clone()), this.methodNamesPtr, this.narrowedFromParentCtorIdxs ? [...this.narrowedFromParentCtorIdxs] : undefined);
91
156
  result._isConcrete = this._isConcrete;
92
157
  return result;
93
158
  }
@@ -240,6 +240,20 @@ function canAssignStruct(a, b, symbols) {
240
240
  a = a.aliased;
241
241
  while (b instanceof TirAliasType)
242
242
  b = b.aliased;
243
+ // Same logical struct type? (same name + fileUid). When this holds,
244
+ // we use parent-ctor-idx based subset checks to handle narrowing.
245
+ const sameLogicalType = a.name === b.name
246
+ && a.fileUid === b.fileUid;
247
+ if (sameLogicalType) {
248
+ const aIdxs = a.narrowedFromParentCtorIdxs ?? a.constructors.map((_, i) => i);
249
+ const bIdxs = b.narrowedFromParentCtorIdxs ?? b.constructors.map((_, i) => i);
250
+ // a is assignable to b iff a's parent-ctor set is a SUBSET of b's
251
+ for (const idx of aIdxs) {
252
+ if (!bIdxs.includes(idx))
253
+ return CanAssign.No;
254
+ }
255
+ return CanAssign.Yes;
256
+ }
243
257
  const aCtors = a.constructors;
244
258
  const bCtors = b.constructors;
245
259
  if (aCtors.length !== bCtors.length)
@@ -43,6 +43,7 @@ import { UsingStmt } from "../ast/nodes/statements/UsingStmt.js";
43
43
  import { BodyStmt, TopLevelStmt } from "../ast/nodes/statements/PebbleStmt.js";
44
44
  import { Precedence } from "./Precedence.js";
45
45
  import { ContractDecl } from "../ast/nodes/statements/declarations/ContractDecl.js";
46
+ import { StateDecl } from "../ast/nodes/statements/declarations/StateDecl.js";
46
47
  interface ParseStmtOpts {
47
48
  isExport?: boolean;
48
49
  topLevel?: boolean;
@@ -55,6 +56,7 @@ export declare class Parser extends DiagnosticEmitter {
55
56
  parseSource(): DiagnosticMessage[];
56
57
  parseTopLevelStatement(): TopLevelStmt | undefined;
57
58
  parseContractDecl(startPos: number): ContractDecl | undefined;
59
+ parseStateDecl(startPos: number): StateDecl | undefined;
58
60
  parseUsingDecl(): UsingStmt | undefined;
59
61
  parseTypeParameters(): Identifier[] | undefined;
60
62
  parseTypeArguments(): AstTypeExpr[] | undefined;
@@ -59,6 +59,7 @@ import { EnumDecl, EnumValueDecl } from "../ast/nodes/statements/declarations/En
59
59
  import { TypeConversionExpr } from "../ast/nodes/expr/TypeConversionExpr.js";
60
60
  import { NonNullExpr } from "../ast/nodes/expr/unary/NonNullExpr.js";
61
61
  import { ElemAccessExpr } from "../ast/nodes/expr/ElemAccessExpr.js";
62
+ import { IsExpr } from "../ast/nodes/expr/IsExpr.js";
62
63
  import { TernaryExpr } from "../ast/nodes/expr/TernaryExpr.js";
63
64
  import { makePropAccessExpr } from "../ast/nodes/expr/PropAccessExpr.js";
64
65
  import { makeBinaryExpr } from "../ast/nodes/expr/binary/BinaryExpr.js";
@@ -72,6 +73,7 @@ import { defaultSymbolForge } from "../compiler/internalVar.js";
72
73
  import { Precedence, determinePrecedence } from "./Precedence.js";
73
74
  import { LitFailExpr } from "../ast/nodes/expr/litteral/LitFailExpr.js";
74
75
  import { ContractDecl } from "../ast/nodes/statements/declarations/ContractDecl.js";
76
+ import { StateDecl } from "../ast/nodes/statements/declarations/StateDecl.js";
75
77
  import { LitContextExpr } from "../ast/nodes/expr/litteral/LitContextExpr.js";
76
78
  import { tokenIsAlsoIdentifier } from "../tokenizer/utils/tokenIsAlsoIdentifier.js";
77
79
  export class Parser extends DiagnosticEmitter {
@@ -247,12 +249,24 @@ export class Parser extends DiagnosticEmitter {
247
249
  const withdrawMethods = [];
248
250
  const proposeMethods = [];
249
251
  const voteMethods = [];
252
+ const stateDecls = [];
250
253
  while (!tn.skip(Token.CloseBrace)) {
251
254
  tn.skip(Token.Semicolon); // if any
252
255
  const thisStartPos = tn.tokenPos;
253
256
  const prevState = tn.mark();
254
257
  const nextToken = tn.next();
255
258
  switch (nextToken) {
259
+ case Token.State:
260
+ {
261
+ const stateDecl = this.parseStateDecl(thisStartPos);
262
+ if (!stateDecl)
263
+ return undefined;
264
+ if (stateDecls.some(s => s.name.text === stateDecl.name.text))
265
+ return this.error(DiagnosticCode.Duplicate_identifier_0, stateDecl.name.range, stateDecl.name.text);
266
+ stateDecls.push(stateDecl);
267
+ continue;
268
+ }
269
+ break;
256
270
  case Token.Param:
257
271
  {
258
272
  const varDecl = this._parseVarDecl(CommonFlags.Const);
@@ -300,7 +314,62 @@ export class Parser extends DiagnosticEmitter {
300
314
  }
301
315
  continue;
302
316
  }
303
- return new ContractDecl(contractName, params, spendMethods, mintMethods, certifyMethods, withdrawMethods, proposeMethods, voteMethods, tn.range(startPos, tn.pos));
317
+ return new ContractDecl(contractName, params, spendMethods, mintMethods, certifyMethods, withdrawMethods, proposeMethods, voteMethods, stateDecls, tn.range(startPos, tn.pos));
318
+ }
319
+ parseStateDecl(startPos) {
320
+ const tn = this.tn;
321
+ startPos = typeof startPos === "number" ? startPos : tn.tokenPos;
322
+ // at 'state': Identifier '{' ... '}'
323
+ if (!tn.skipIdentifier())
324
+ return this.error(DiagnosticCode.Identifier_expected, tn.range());
325
+ const name = new Identifier(tn.readIdentifier(), tn.range());
326
+ if (!tn.skip(Token.OpenBrace))
327
+ return this.error(DiagnosticCode._0_expected, tn.range(), "{");
328
+ const fields = [];
329
+ const spendMethods = [];
330
+ while (!tn.skip(Token.CloseBrace)) {
331
+ tn.skip(Token.Comma); // if any
332
+ tn.skip(Token.Semicolon); // if any
333
+ if (tn.skip(Token.CloseBrace))
334
+ break;
335
+ const memberStartPos = tn.tokenPos;
336
+ const prevState = tn.mark();
337
+ const nextToken = tn.next();
338
+ if (nextToken === Token.Spend) {
339
+ const funcDecl = this.parseFuncDecl(CommonFlags.None, memberStartPos, new AstVoidType(tn.range()));
340
+ if (!funcDecl)
341
+ return undefined;
342
+ if (!(funcDecl.expr.signature.returnType instanceof AstVoidType))
343
+ return this.error(DiagnosticCode.Contract_methods_must_return_void_or_fail, funcDecl.expr.signature.returnType?.range ?? funcDecl.expr.signature.range);
344
+ spendMethods.push(funcDecl);
345
+ continue;
346
+ }
347
+ if (nextToken === Token.Mint
348
+ || nextToken === Token.Certify
349
+ || nextToken === Token.Withdraw
350
+ || nextToken === Token.Propose
351
+ || nextToken === Token.Vote) {
352
+ return this.error(DiagnosticCode._0_expected, tn.range(), "spend method or field");
353
+ }
354
+ // not a method: parse as field declaration
355
+ tn.reset(prevState);
356
+ if (spendMethods.length > 0) {
357
+ // fields must come before spend methods
358
+ return this.error(DiagnosticCode._0_expected, tn.range(), "spend method");
359
+ }
360
+ const field = this._parseVarDecl(CommonFlags.Const);
361
+ if (!field)
362
+ return undefined;
363
+ if (!(field instanceof SimpleVarDecl))
364
+ return this.error(DiagnosticCode.Invalid_field_declaration, field.range);
365
+ if (!field.type)
366
+ return this.error(DiagnosticCode.Type_expected, field.range.atEnd());
367
+ if (field.initExpr)
368
+ return this.error(DiagnosticCode.Initialization_expressions_are_not_allowed_in_a_struct_declaration, SourceRange.join(field.type.range.atEnd(), field.initExpr.range));
369
+ fields.push(field);
370
+ }
371
+ tn.skip(Token.Semicolon); // if any
372
+ return new StateDecl(name, fields, spendMethods, tn.range(startPos, tn.pos));
304
373
  }
305
374
  parseUsingDecl() {
306
375
  const tn = this.tn;
@@ -1171,28 +1240,15 @@ export class Parser extends DiagnosticEmitter {
1171
1240
  expr = this.tryParseCallExprOrReturnSame(expr);
1172
1241
  break;
1173
1242
  }
1174
- /*
1175
1243
  case Token.Is: {
1176
- // TODO:
1177
- // should optionally check for destructuring
1178
- if(!(tn.skipIdentifier()))
1179
- {
1180
- this.error(
1181
- DiagnosticCode.Identifier_expected,
1182
- tn.range()
1183
- );
1184
- return undefined
1244
+ if (!tn.skipIdentifier()) {
1245
+ this.error(DiagnosticCode.Identifier_expected, tn.range());
1246
+ return undefined;
1185
1247
  }
1186
- const ofType = new Identifier( tn.readIdentifier(), tn.range() );
1187
- tn.skip( Token.Semicolon); // if any
1188
- expr = new IsExpr(
1189
- expr,
1190
- ofType,
1191
- tn.range( startPos, tn.pos )
1192
- );
1248
+ const ofConstr = new Identifier(tn.readIdentifier(), tn.range());
1249
+ expr = new IsExpr(expr, ofConstr, tn.range(startPos, tn.pos));
1193
1250
  break;
1194
1251
  }
1195
- //*/
1196
1252
  case Token.OpenBracket: { // [ // accessing list element
1197
1253
  const idxExpr = this.parseExpr();
1198
1254
  if (!idxExpr)
@@ -1565,6 +1621,7 @@ export class Parser extends DiagnosticEmitter {
1565
1621
  const expr = this.parseCaseExpr();
1566
1622
  if (!expr)
1567
1623
  return undefined;
1624
+ return expr;
1568
1625
  }
1569
1626
  case Token.Fail: {
1570
1627
  return new LitFailExpr(tn.range());
@@ -1604,7 +1661,9 @@ export class Parser extends DiagnosticEmitter {
1604
1661
  const tn = this.tn;
1605
1662
  // at 'case': Expression ('is' VarDecl '=>' Expression)+ ('else' Expression)?
1606
1663
  const startPos = tn.tokenPos;
1607
- const expr = this.parseExpr();
1664
+ // parse the matched expression at a precedence higher than `is`
1665
+ // so the case-level `is` is left unconsumed
1666
+ const expr = this.parseExpr(Precedence.Relational + 1);
1608
1667
  if (!expr)
1609
1668
  return undefined;
1610
1669
  let noPatternCaseSeen = false;
@@ -1622,7 +1681,10 @@ export class Parser extends DiagnosticEmitter {
1622
1681
  return this.error(DiagnosticCode.Patterns_may_not_have_initializers_or_explicit_types, matcher.initExpr ? matcher.initExpr.range : matcher.type.range);
1623
1682
  if (!tn.skip(Token.FatArrow))
1624
1683
  return this.error(DiagnosticCode._0_expected, tn.range(), "=>");
1625
- const body = this.parseExpr(Precedence.CaseExpr);
1684
+ // parse body at precedence higher than `is` so the next case-arm's
1685
+ // `is` is left unconsumed (otherwise `is` would be greedily parsed
1686
+ // as the binary `is` operator inside the body)
1687
+ const body = this.parseExpr(Precedence.Relational + 1);
1626
1688
  if (!body)
1627
1689
  return undefined;
1628
1690
  cases.push(new CaseExprMatcher(matcher, body, tn.range(startPos, tn.pos)));
@@ -1630,7 +1692,10 @@ export class Parser extends DiagnosticEmitter {
1630
1692
  let wildcardCase = undefined;
1631
1693
  if (tn.skip(Token.Else)) {
1632
1694
  const wildcardStart = tn.tokenPos;
1633
- const body = this.parseExpr(Precedence.CaseExpr);
1695
+ // parse body at precedence higher than `is` so the next case-arm's
1696
+ // `is` is left unconsumed (otherwise `is` would be greedily parsed
1697
+ // as the binary `is` operator inside the body)
1698
+ const body = this.parseExpr(Precedence.Relational + 1);
1634
1699
  if (!body)
1635
1700
  return undefined;
1636
1701
  wildcardCase = new CaseWildcardMatcher(body, tn.range(wildcardStart));
@@ -45,126 +45,127 @@ export declare enum Token {
45
45
  Contract = 42,
46
46
  Param = 43,
47
47
  Spend = 44,
48
- Mint = 45,
49
- Certify = 46,
50
- Withdraw = 47,
51
- Propose = 48,
52
- Vote = 49,
53
- Context = 50,
48
+ State = 45,
49
+ Mint = 46,
50
+ Certify = 47,
51
+ Withdraw = 48,
52
+ Propose = 49,
53
+ Vote = 50,
54
+ Context = 51,
54
55
  /** `{` */
55
- OpenBrace = 51,
56
+ OpenBrace = 52,
56
57
  /** `}` */
57
- CloseBrace = 52,
58
- OpenParen = 53,
59
- CloseParen = 54,
58
+ CloseBrace = 53,
59
+ OpenParen = 54,
60
+ CloseParen = 55,
60
61
  /** `[` */
61
- OpenBracket = 55,
62
+ OpenBracket = 56,
62
63
  /** `]` */
63
- CloseBracket = 56,
64
+ CloseBracket = 57,
64
65
  /** `.` */
65
- Dot = 57,
66
+ Dot = 58,
66
67
  /** `...` */
67
- Dot_Dot_Dot = 58,
68
+ Dot_Dot_Dot = 59,
68
69
  /** `;` */
69
- Semicolon = 59,
70
+ Semicolon = 60,
70
71
  /** `,` */
71
- Comma = 60,
72
+ Comma = 61,
72
73
  /** `<` */
73
- LessThan = 61,
74
+ LessThan = 62,
74
75
  /** `>` */
75
- GreaterThan = 62,
76
+ GreaterThan = 63,
76
77
  /** `<=` */
77
- LessThan_Equals = 63,
78
+ LessThan_Equals = 64,
78
79
  /** `>=` */
79
- GreaterThan_Equals = 64,
80
+ GreaterThan_Equals = 65,
80
81
  /** `==` */
81
- Equals_Equals = 65,
82
+ Equals_Equals = 66,
82
83
  /** `!=` */
83
- Exclamation_Equals = 66,
84
+ Exclamation_Equals = 67,
84
85
  /** `===` */
85
- Equals_Equals_Equals = 67,
86
+ Equals_Equals_Equals = 68,
86
87
  /** `!==` */
87
- Exclamation_Equals_Equals = 68,
88
+ Exclamation_Equals_Equals = 69,
88
89
  /** `=>` */
89
- FatArrow = 69,
90
+ FatArrow = 70,
90
91
  /** `+` */
91
- Plus = 70,
92
+ Plus = 71,
92
93
  /** `-` */
93
- Minus = 71,
94
+ Minus = 72,
94
95
  /** `**` */
95
- Asterisk_Asterisk = 72,
96
+ Asterisk_Asterisk = 73,
96
97
  /** `*` */
97
- Asterisk = 73,
98
+ Asterisk = 74,
98
99
  /** `/` */
99
- Slash = 74,
100
+ Slash = 75,
100
101
  /** `%` */
101
- Percent = 75,
102
+ Percent = 76,
102
103
  /** `++` */
103
- Plus_Plus = 76,
104
+ Plus_Plus = 77,
104
105
  /** `--` */
105
- Minus_Minus = 77,
106
+ Minus_Minus = 78,
106
107
  /** `<<` */
107
- LessThan_LessThan = 78,
108
+ LessThan_LessThan = 79,
108
109
  /** `>>` */
109
- GreaterThan_GreaterThan = 79,
110
+ GreaterThan_GreaterThan = 80,
110
111
  /** `>>>` */
111
- GreaterThan_GreaterThan_GreaterThan = 80,
112
+ GreaterThan_GreaterThan_GreaterThan = 81,
112
113
  /** `+` */
113
- Ampersand = 81,
114
+ Ampersand = 82,
114
115
  /** `|` */
115
- Bar = 82,
116
+ Bar = 83,
116
117
  /** `^` */
117
- Caret = 83,
118
+ Caret = 84,
118
119
  /** `!` */
119
- Exclamation = 84,
120
+ Exclamation = 85,
120
121
  /** `~` */
121
- Tilde = 85,
122
+ Tilde = 86,
122
123
  /** `&&` */
123
- Ampersand_Ampersand = 86,
124
+ Ampersand_Ampersand = 87,
124
125
  /** `||` */
125
- Bar_Bar = 87,
126
+ Bar_Bar = 88,
126
127
  /** `?` */
127
- Question = 88,
128
+ Question = 89,
128
129
  /** `:` */
129
- Colon = 89,
130
+ Colon = 90,
130
131
  /** `=` */
131
- Equals = 90,
132
- Plus_Equals = 91,
133
- Minus_Equals = 92,
134
- Asterisk_Equals = 93,
135
- Asterisk_Asterisk_Equals = 94,
136
- Slash_Equals = 95,
137
- Percent_Equals = 96,
138
- LessThan_LessThan_Equals = 97,
139
- GreaterThan_GreaterThan_Equals = 98,
140
- GreaterThan_GreaterThan_GreaterThan_Equals = 99,
141
- Ampersand_Equals = 100,
142
- Bar_Equals = 101,
143
- Caret_Equals = 102,
144
- At = 103,
132
+ Equals = 91,
133
+ Plus_Equals = 92,
134
+ Minus_Equals = 93,
135
+ Asterisk_Equals = 94,
136
+ Asterisk_Asterisk_Equals = 95,
137
+ Slash_Equals = 96,
138
+ Percent_Equals = 97,
139
+ LessThan_LessThan_Equals = 98,
140
+ GreaterThan_GreaterThan_Equals = 99,
141
+ GreaterThan_GreaterThan_GreaterThan_Equals = 100,
142
+ Ampersand_Equals = 101,
143
+ Bar_Equals = 102,
144
+ Caret_Equals = 103,
145
+ At = 104,
145
146
  /** `??=` */
146
- Question_Question_Equals = 104,
147
+ Question_Question_Equals = 105,
147
148
  /** `||=` */
148
- Bar_Bar_Equals = 105,
149
+ Bar_Bar_Equals = 106,
149
150
  /** `&&=` */
150
- Ampersand_Ampersand_Equals = 106,
151
+ Ampersand_Ampersand_Equals = 107,
151
152
  /** `??` */
152
- Question_Question = 107,
153
+ Question_Question = 108,
153
154
  /** `?.` */
154
- Question_Dot = 108,
155
+ Question_Dot = 109,
155
156
  /** `!.` */
156
- Exclamation_Dot = 109,
157
- Data = 110,
158
- Bytes = 111,
159
- Optional = 112,
160
- List = 113,
161
- LinearMap = 114,
162
- Runtime = 115,
163
- Identifier = 116,
164
- StringLiteral = 117,
165
- HexBytesLiteral = 118,
166
- IntegerLiteral = 119,
167
- StringTemplateLiteralQuote = 120,
168
- Invalid = 121,
169
- EndOfFile = 122
157
+ Exclamation_Dot = 110,
158
+ Data = 111,
159
+ Bytes = 112,
160
+ Optional = 113,
161
+ List = 114,
162
+ LinearMap = 115,
163
+ Runtime = 116,
164
+ Identifier = 117,
165
+ StringLiteral = 118,
166
+ HexBytesLiteral = 119,
167
+ IntegerLiteral = 120,
168
+ StringTemplateLiteralQuote = 121,
169
+ Invalid = 122,
170
+ EndOfFile = 123
170
171
  }