@harmoniclabs/pebble 0.1.10 → 0.3.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.
- package/dist/IR/CompilationCtx.d.ts +40 -0
- package/dist/IR/CompilationCtx.js +54 -0
- package/dist/IR/IRHash.d.ts +23 -2
- package/dist/IR/IRHash.js +10 -60
- package/dist/IR/IRNodes/IRConst.js +35 -4
- package/dist/IR/IRNodes/IRHoisted.d.ts +0 -1
- package/dist/IR/IRNodes/IRHoisted.js +4 -6
- package/dist/IR/IRNodes/IRLetted.d.ts +0 -1
- package/dist/IR/IRNodes/IRLetted.js +4 -6
- package/dist/IR/IRNodes/IRNative/IRNativeTag.d.ts +22 -2
- package/dist/IR/IRNodes/IRNative/IRNativeTag.js +26 -2
- package/dist/IR/IRNodes/IRNative/index.d.ts +16 -1
- package/dist/IR/IRNodes/IRNative/index.js +31 -2
- package/dist/IR/IRNodes/utils/hashVarSym.d.ts +0 -1
- package/dist/IR/IRNodes/utils/hashVarSym.js +27 -33
- package/dist/IR/toUPLC/CompilerOptions.d.ts +34 -7
- package/dist/IR/toUPLC/CompilerOptions.js +19 -10
- package/dist/IR/toUPLC/compileIRToUPLC.js +39 -3
- package/dist/IR/toUPLC/subRoutines/inlineSingleUseLetBindingsAndReturnRoot.d.ts +23 -0
- package/dist/IR/toUPLC/subRoutines/inlineSingleUseLetBindingsAndReturnRoot.js +263 -0
- package/dist/IR/toUPLC/subRoutines/introduceCaseForDualHeadTailAndReturnRoot.d.ts +35 -0
- package/dist/IR/toUPLC/subRoutines/introduceCaseForDualHeadTailAndReturnRoot.js +169 -0
- package/dist/IR/toUPLC/subRoutines/replaceHoistedWithLetted.d.ts +0 -1
- package/dist/IR/toUPLC/subRoutines/replaceHoistedWithLetted.js +6 -6
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.d.ts +2 -3
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.js +106 -65
- package/dist/IR/toUPLC/subRoutines/rewriteHeadTailInCaseConsAndReturnRoot.d.ts +30 -0
- package/dist/IR/toUPLC/subRoutines/rewriteHeadTailInCaseConsAndReturnRoot.js +95 -0
- package/dist/IR/toUPLC/subRoutines/rewriteNativesAppliedToConstantsAndReturnRoot.js +36 -5
- package/dist/IR/toUPLC/subRoutines/rewriteToCaseOverConstAndReturnRoot.d.ts +35 -0
- package/dist/IR/toUPLC/subRoutines/rewriteToCaseOverConstAndReturnRoot.js +169 -0
- package/dist/IR/tree_utils/_ir_caseList.d.ts +15 -0
- package/dist/IR/tree_utils/_ir_caseList.js +19 -0
- package/dist/IR/tree_utils/bytesToHex.d.ts +8 -0
- package/dist/IR/tree_utils/bytesToHex.js +69 -0
- package/dist/ast/nodes/expr/functions/FuncExpr.d.ts +16 -2
- package/dist/ast/nodes/expr/functions/FuncExpr.js +17 -0
- package/dist/ast/nodes/expr/litteral/LitteralExpr.d.ts +2 -1
- package/dist/ast/nodes/expr/litteral/LitteralExpr.js +2 -0
- package/dist/ast/nodes/expr/litteral/TemplateStrExpr.d.ts +30 -0
- package/dist/ast/nodes/expr/litteral/TemplateStrExpr.js +35 -0
- package/dist/ast/nodes/statements/ExportStmt.d.ts +3 -3
- package/dist/ast/nodes/statements/PebbleStmt.d.ts +4 -3
- package/dist/ast/nodes/statements/PebbleStmt.js +6 -2
- package/dist/ast/nodes/statements/TestParam.d.ts +18 -0
- package/dist/ast/nodes/statements/TestParam.js +18 -0
- package/dist/ast/nodes/statements/TestStmt.d.ts +5 -3
- package/dist/ast/nodes/statements/TestStmt.js +3 -1
- package/dist/ast/nodes/statements/UsingStmt.d.ts +32 -2
- package/dist/ast/nodes/statements/UsingStmt.js +39 -3
- package/dist/ast/nodes/statements/declarations/NamespaceDecl.d.ts +21 -0
- package/dist/ast/nodes/statements/declarations/NamespaceDecl.js +31 -0
- package/dist/ast/nodes/statements/declarations/StructDecl.d.ts +16 -2
- package/dist/ast/nodes/statements/declarations/StructDecl.js +15 -1
- package/dist/compiler/AstCompiler/AstCompiler.d.ts +27 -0
- package/dist/compiler/AstCompiler/AstCompiler.js +244 -7
- package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +16 -5
- package/dist/compiler/AstCompiler/internal/exprs/_compileCallExpr.js +97 -6
- package/dist/compiler/AstCompiler/internal/exprs/_compileCaseExpr.js +31 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileFuncExpr.js +12 -5
- package/dist/compiler/AstCompiler/internal/exprs/_compileIsExpr.js +12 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileLitteralExpr.js +59 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compilePropAccessExpr.d.ts +2 -3
- package/dist/compiler/AstCompiler/internal/exprs/_compilePropAccessExpr.js +64 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileUnaryPrefixExpr.js +13 -1
- package/dist/compiler/AstCompiler/internal/exprs/_compileVarAccessExpr.js +2 -0
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileAddExpr.js +18 -5
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileEqualExpr.js +3 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileGreaterThanEqualExpr.js +2 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileGreaterThanExpr.js +2 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileLessThanEqualExpr.js +2 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileLessThanExpr.js +2 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileMultExpr.js +24 -6
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileNotEqualExpr.js +2 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileSubExpr.js +16 -5
- package/dist/compiler/AstCompiler/internal/statements/_compileMatchStmt.js +33 -20
- package/dist/compiler/AstCompiler/internal/statements/_compileStatement.js +4 -1
- package/dist/compiler/AstCompiler/internal/statements/_compileTestStmt.d.ts +15 -1
- package/dist/compiler/AstCompiler/internal/statements/_compileTestStmt.js +70 -30
- package/dist/compiler/AstCompiler/internal/statements/_compileUsingAliasStmt.d.ts +11 -0
- package/dist/compiler/AstCompiler/internal/statements/_compileUsingAliasStmt.js +26 -0
- package/dist/compiler/AstCompiler/internal/statements/_compileUsingStmt.d.ts +9 -4
- package/dist/compiler/AstCompiler/internal/statements/_compileUsingStmt.js +51 -10
- package/dist/compiler/AstCompiler/internal/types/_compileDataEncodedConcreteType.js +21 -2
- package/dist/compiler/AstCompiler/internal/types/_compileSopEncodedConcreteType.js +17 -2
- package/dist/compiler/AstCompiler/scope/AstScope.d.ts +70 -1
- package/dist/compiler/AstCompiler/scope/AstScope.js +91 -0
- package/dist/compiler/AstCompiler/utils/getPropAccessReturnType.js +36 -1
- package/dist/compiler/AstCompiler/utils/monomorphizeGeneric.d.ts +36 -0
- package/dist/compiler/AstCompiler/utils/monomorphizeGeneric.js +123 -0
- package/dist/compiler/AstCompiler/utils/resolveNamespaceChain.d.ts +28 -0
- package/dist/compiler/AstCompiler/utils/resolveNamespaceChain.js +95 -0
- package/dist/compiler/AstCompiler/utils/resolveNamespacePath.d.ts +37 -0
- package/dist/compiler/AstCompiler/utils/resolveNamespacePath.js +93 -0
- package/dist/compiler/Compiler.d.ts +9 -1
- package/dist/compiler/Compiler.js +218 -30
- package/dist/compiler/TirCompiler/expressify/ExpressifyCtx.js +1 -1
- package/dist/compiler/TirCompiler/expressify/expressify.js +30 -2
- package/dist/compiler/TirCompiler/expressify/expressifyForStmt.d.ts +2 -1
- package/dist/compiler/TirCompiler/expressify/expressifyForStmt.js +45 -7
- package/dist/compiler/TirCompiler/expressify/expressifyVars.d.ts +0 -1
- package/dist/compiler/TirCompiler/expressify/expressifyVars.js +49 -15
- package/dist/compiler/test/TestResult.d.ts +38 -0
- package/dist/compiler/test/TestResult.js +6 -0
- package/dist/compiler/test/fuzz/PRNG.d.ts +26 -0
- package/dist/compiler/test/fuzz/PRNG.js +59 -0
- package/dist/compiler/tir/expressions/TirCaseExpr.d.ts +9 -0
- package/dist/compiler/tir/expressions/TirCaseExpr.js +144 -122
- package/dist/compiler/tir/expressions/TirElemAccessExpr.js +2 -2
- package/dist/compiler/tir/expressions/TirExpr.d.ts +2 -1
- package/dist/compiler/tir/expressions/TirExpr.js +2 -0
- package/dist/compiler/tir/expressions/TirFromDataExpr.js +102 -67
- package/dist/compiler/tir/expressions/TirIsExpr.js +14 -1
- package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +18 -2
- package/dist/compiler/tir/expressions/TirNativeFunc.js +55 -118
- package/dist/compiler/tir/expressions/TirShowExpr.d.ts +52 -0
- package/dist/compiler/tir/expressions/TirShowExpr.js +199 -0
- package/dist/compiler/tir/expressions/TirToDataExpr.js +3 -0
- package/dist/compiler/tir/expressions/TirTraceExpr.js +11 -7
- package/dist/compiler/tir/expressions/TirTypeConversionExpr.js +10 -0
- package/dist/compiler/tir/expressions/TirVariableAccessExpr.d.ts +2 -3
- package/dist/compiler/tir/expressions/TirVariableAccessExpr.js +1 -4
- package/dist/compiler/tir/expressions/ToIRTermCtx.d.ts +20 -3
- package/dist/compiler/tir/expressions/ToIRTermCtx.js +48 -3
- package/dist/compiler/tir/expressions/binary/TirBinaryExpr.d.ts +2 -2
- package/dist/compiler/tir/expressions/binary/TirBinaryExpr.js +45 -8
- package/dist/compiler/tir/expressions/litteral/TirLitEnumMemberExpr.d.ts +19 -0
- package/dist/compiler/tir/expressions/litteral/TirLitEnumMemberExpr.js +24 -0
- package/dist/compiler/tir/expressions/litteral/TirLitteralExpr.d.ts +2 -1
- package/dist/compiler/tir/expressions/litteral/TirLitteralExpr.js +2 -0
- package/dist/compiler/tir/expressions/unary/TirUnaryMinus.js +4 -1
- package/dist/compiler/tir/program/TypedProgram.d.ts +101 -0
- package/dist/compiler/tir/program/TypedProgram.js +43 -0
- package/dist/compiler/tir/program/stdScope/populateBuiltinInterfaces.d.ts +17 -0
- package/dist/compiler/tir/program/stdScope/populateBuiltinInterfaces.js +70 -0
- package/dist/compiler/tir/program/stdScope/populateStdNamespace.d.ts +22 -0
- package/dist/compiler/tir/program/stdScope/populateStdNamespace.js +619 -0
- package/dist/compiler/tir/program/stdScope/prelude/preludeTypesSrc.js +35 -2
- package/dist/compiler/tir/program/stdScope/stdScope.d.ts +8 -0
- package/dist/compiler/tir/program/stdScope/stdScope.js +84 -41
- package/dist/compiler/tir/statements/TirStmt.js +0 -1
- package/dist/compiler/tir/statements/TirTestStmt.d.ts +46 -0
- package/dist/compiler/tir/statements/TirTestStmt.js +35 -0
- package/dist/compiler/tir/types/TirEnumType.d.ts +21 -0
- package/dist/compiler/tir/types/TirEnumType.js +36 -0
- package/dist/compiler/tir/types/TirNativeType/TirNativeType.d.ts +53 -2
- package/dist/compiler/tir/types/TirNativeType/TirNativeType.js +58 -1
- package/dist/compiler/tir/types/TirNativeType/native/array.d.ts +16 -0
- package/dist/compiler/tir/types/TirNativeType/native/array.js +38 -0
- package/dist/compiler/tir/types/TirNativeType/native/index.d.ts +2 -0
- package/dist/compiler/tir/types/TirNativeType/native/index.js +2 -0
- package/dist/compiler/tir/types/TirNativeType/native/value.d.ts +18 -0
- package/dist/compiler/tir/types/TirNativeType/native/value.js +17 -0
- package/dist/compiler/tir/types/TirStructType.js +6 -1
- package/dist/compiler/tir/types/TirType.d.ts +3 -2
- package/dist/compiler/tir/types/TirType.js +7 -2
- package/dist/compiler/tir/types/utils/canAssignTo.js +36 -1
- package/dist/compiler/tir/types/utils/canCastTo.js +14 -1
- package/dist/compiler/tir/types/utils/getDeconstructableType.d.ts +2 -1
- package/dist/compiler/tir/types/utils/getDeconstructableType.js +2 -0
- package/dist/compiler/tir/types/utils/inferTypeArgs.d.ts +19 -0
- package/dist/compiler/tir/types/utils/inferTypeArgs.js +83 -0
- package/dist/compiler/tir/types/utils/normalizeEnumToInt.d.ts +10 -0
- package/dist/compiler/tir/types/utils/normalizeEnumToInt.js +17 -0
- package/dist/compiler/tir/types/utils/substituteTypeParams.d.ts +9 -0
- package/dist/compiler/tir/types/utils/substituteTypeParams.js +67 -0
- package/dist/diagnostics/diagnosticMessages.generated.d.ts +10 -0
- package/dist/diagnostics/diagnosticMessages.generated.js +20 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/parser/Parser.d.ts +73 -3
- package/dist/parser/Parser.js +362 -46
- package/dist/tokenizer/Token.d.ts +106 -102
- package/dist/tokenizer/Token.js +111 -109
- package/dist/tokenizer/utils/tokenFromKeyword.js +11 -6
- package/dist/utils/semverSatisfies.d.ts +1 -0
- package/dist/utils/semverSatisfies.js +161 -0
- package/dist/version.generated.d.ts +1 -0
- package/dist/version.generated.js +2 -0
- package/package.json +5 -4
- package/dist/IR/tree_utils/_ir_lazyChooseList.d.ts +0 -3
- package/dist/IR/tree_utils/_ir_lazyChooseList.js +0 -7
package/dist/parser/Parser.js
CHANGED
|
@@ -21,13 +21,14 @@ import { LitThisExpr } from "../ast/nodes/expr/litteral/LitThisExpr.js";
|
|
|
21
21
|
import { LitTrueExpr } from "../ast/nodes/expr/litteral/LitTrueExpr.js";
|
|
22
22
|
import { ParentesizedExpr } from "../ast/nodes/expr/ParentesizedExpr.js";
|
|
23
23
|
import { ArrowKind } from "../ast/nodes/expr/functions/ArrowKind.js";
|
|
24
|
-
import { FuncExpr } from "../ast/nodes/expr/functions/FuncExpr.js";
|
|
24
|
+
import { FuncExpr, TypeParamDecl } from "../ast/nodes/expr/functions/FuncExpr.js";
|
|
25
25
|
import { AstBooleanType, AstBytesType, AstListType, AstIntType, AstNativeOptionalType, AstVoidType, AstLinearMapType, AstFuncType } from "../ast/nodes/types/AstNativeTypeExpr.js";
|
|
26
26
|
import { AstNamedTypeExpr } from "../ast/nodes/types/AstNamedTypeExpr.js";
|
|
27
27
|
import { LitArrExpr } from "../ast/nodes/expr/litteral/LitArrExpr.js";
|
|
28
28
|
import { LitNamedObjExpr } from "../ast/nodes/expr/litteral/LitNamedObjExpr.js";
|
|
29
29
|
import { LitObjExpr } from "../ast/nodes/expr/litteral/LitObjExpr.js";
|
|
30
30
|
import { LitStrExpr } from "../ast/nodes/expr/litteral/LitStrExpr.js";
|
|
31
|
+
import { TemplateStrExpr } from "../ast/nodes/expr/litteral/TemplateStrExpr.js";
|
|
31
32
|
import { LitIntExpr } from "../ast/nodes/expr/litteral/LitIntExpr.js";
|
|
32
33
|
import { LitHexBytesExpr } from "../ast/nodes/expr/litteral/LitHexBytesExpr.js";
|
|
33
34
|
import { CallExpr } from "../ast/nodes/expr/functions/CallExpr.js";
|
|
@@ -44,6 +45,7 @@ import { FailStmt } from "../ast/nodes/statements/FailStmt.js";
|
|
|
44
45
|
import { TraceStmt } from "../ast/nodes/statements/TraceStmt.js";
|
|
45
46
|
import { AssertStmt } from "../ast/nodes/statements/AssertStmt.js";
|
|
46
47
|
import { TestStmt } from "../ast/nodes/statements/TestStmt.js";
|
|
48
|
+
import { TestParam } from "../ast/nodes/statements/TestParam.js";
|
|
47
49
|
import { MatchStmt, MatchStmtCase, MatchStmtElseCase } from "../ast/nodes/statements/MatchStmt.js";
|
|
48
50
|
import { WhileStmt } from "../ast/nodes/statements/WhileStmt.js";
|
|
49
51
|
import { CaseExpr, CaseExprMatcher, CaseWildcardMatcher } from "../ast/nodes/expr/CaseExpr.js";
|
|
@@ -65,7 +67,8 @@ import { makePropAccessExpr } from "../ast/nodes/expr/PropAccessExpr.js";
|
|
|
65
67
|
import { makeBinaryExpr } from "../ast/nodes/expr/binary/BinaryExpr.js";
|
|
66
68
|
import { isAssignmentStmt, makeAssignmentStmt } from "../ast/nodes/statements/AssignmentStmt.js";
|
|
67
69
|
import { hoistStatementsInplace } from "./hoistStatementsInplace.js";
|
|
68
|
-
import { UsingStmt, UsingStmtDeclaredConstructor } from "../ast/nodes/statements/UsingStmt.js";
|
|
70
|
+
import { UsingAliasStmt, UsingPath, UsingStmt, UsingStmtDeclaredConstructor } from "../ast/nodes/statements/UsingStmt.js";
|
|
71
|
+
import { NamespaceDecl, NamespaceMember } from "../ast/nodes/statements/declarations/NamespaceDecl.js";
|
|
69
72
|
import { IncrStmt } from "../ast/nodes/statements/IncrStmt.js";
|
|
70
73
|
import { DecrStmt } from "../ast/nodes/statements/DecrStmt.js";
|
|
71
74
|
import { ExportStmt } from "../ast/nodes/statements/ExportStmt.js";
|
|
@@ -151,9 +154,15 @@ export class Parser extends DiagnosticEmitter {
|
|
|
151
154
|
break;
|
|
152
155
|
}
|
|
153
156
|
case Token.Using: {
|
|
157
|
+
tn.next(); // skip `using`
|
|
154
158
|
statement = this.parseUsingDecl();
|
|
155
159
|
break;
|
|
156
160
|
}
|
|
161
|
+
case Token.Namespace: {
|
|
162
|
+
tn.next(); // skip `namespace`
|
|
163
|
+
statement = this.parseNamespaceDecl(startPos);
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
157
166
|
case Token.Enum: {
|
|
158
167
|
tn.next();
|
|
159
168
|
statement = this.parseEnum(flags, startPos);
|
|
@@ -169,13 +178,19 @@ export class Parser extends DiagnosticEmitter {
|
|
|
169
178
|
case Token.Data: {
|
|
170
179
|
// `next()` skips `data` keyword
|
|
171
180
|
tn.next();
|
|
181
|
+
let extraFlags = StructDeclAstFlags.onlyDataEncoding;
|
|
182
|
+
// accept `data untagged struct ...`
|
|
183
|
+
if (tn.peek() === Token.Untagged) {
|
|
184
|
+
tn.next();
|
|
185
|
+
extraFlags |= StructDeclAstFlags.untagged;
|
|
186
|
+
}
|
|
172
187
|
// positions on (expected) `struct` keyword
|
|
173
188
|
if (tn.peek() !== Token.Struct) {
|
|
174
189
|
console.error(Token[tn.peek()]);
|
|
175
190
|
return this.error(DiagnosticCode._0_expected, tn.range(), "struct");
|
|
176
191
|
}
|
|
177
192
|
tn.next(); // skip `struct`
|
|
178
|
-
statement = this.parseStruct(
|
|
193
|
+
statement = this.parseStruct(extraFlags, flags, startPos);
|
|
179
194
|
break;
|
|
180
195
|
}
|
|
181
196
|
case Token.Runtime: {
|
|
@@ -194,6 +209,22 @@ export class Parser extends DiagnosticEmitter {
|
|
|
194
209
|
statement = this.parseStruct(StructDeclAstFlags.none, flags, startPos);
|
|
195
210
|
break;
|
|
196
211
|
}
|
|
212
|
+
case Token.Untagged: {
|
|
213
|
+
// `untagged` keyword forces listData encoding (single ctor).
|
|
214
|
+
// Accept: `untagged struct ...` or `untagged data struct ...`.
|
|
215
|
+
tn.next(); // skip `untagged`
|
|
216
|
+
let extraFlags = StructDeclAstFlags.untagged;
|
|
217
|
+
if (tn.peek() === Token.Data) {
|
|
218
|
+
tn.next(); // skip `data`
|
|
219
|
+
extraFlags |= StructDeclAstFlags.onlyDataEncoding;
|
|
220
|
+
}
|
|
221
|
+
if (tn.peek() !== Token.Struct) {
|
|
222
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), "struct");
|
|
223
|
+
}
|
|
224
|
+
tn.next(); // skip `struct`
|
|
225
|
+
statement = this.parseStruct(extraFlags, flags, startPos);
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
197
228
|
case Token.Interface: {
|
|
198
229
|
tn.next();
|
|
199
230
|
statement = this.parseInterface(flags, startPos);
|
|
@@ -374,8 +405,19 @@ export class Parser extends DiagnosticEmitter {
|
|
|
374
405
|
parseUsingDecl() {
|
|
375
406
|
const tn = this.tn;
|
|
376
407
|
const startPos = tn.tokenPos;
|
|
377
|
-
|
|
378
|
-
|
|
408
|
+
// alias form: `using <ident> = <NamespacePath>;`
|
|
409
|
+
if (!tn.skip(Token.OpenBrace)) {
|
|
410
|
+
if (!tn.skipIdentifier())
|
|
411
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), "{");
|
|
412
|
+
const alias = new Identifier(tn.readIdentifier(), tn.range());
|
|
413
|
+
if (!tn.skip(Token.Equals))
|
|
414
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), "=");
|
|
415
|
+
const path = this.parseUsingPath();
|
|
416
|
+
if (!path)
|
|
417
|
+
return undefined;
|
|
418
|
+
return new UsingAliasStmt(alias, path, tn.range(startPos, tn.pos));
|
|
419
|
+
}
|
|
420
|
+
// destructure form: `using { a, b: c } = <rhs>;`
|
|
379
421
|
const members = new Array();
|
|
380
422
|
while (!tn.skip(Token.CloseBrace)) {
|
|
381
423
|
const thisStartPos = tn.tokenPos;
|
|
@@ -397,10 +439,169 @@ export class Parser extends DiagnosticEmitter {
|
|
|
397
439
|
}
|
|
398
440
|
if (!tn.skip(Token.Equals))
|
|
399
441
|
return this.error(DiagnosticCode._0_expected, tn.range(), "=");
|
|
400
|
-
const
|
|
401
|
-
if (!
|
|
442
|
+
const rhs = this.parseUsingRhs();
|
|
443
|
+
if (!rhs)
|
|
402
444
|
return undefined;
|
|
403
|
-
return new UsingStmt(members,
|
|
445
|
+
return new UsingStmt(members, rhs, tn.range(startPos, tn.pos));
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* parse a dotted chain of identifiers: `A`, `A.B`, `A.B.C`, ...
|
|
449
|
+
* used for namespace paths on the RHS of `using` statements.
|
|
450
|
+
*/
|
|
451
|
+
parseUsingPath() {
|
|
452
|
+
const tn = this.tn;
|
|
453
|
+
const startPos = tn.tokenPos;
|
|
454
|
+
if (!tn.skipIdentifier())
|
|
455
|
+
return this.error(DiagnosticCode.Identifier_expected, tn.range());
|
|
456
|
+
const segments = [
|
|
457
|
+
new Identifier(tn.readIdentifier(), tn.range())
|
|
458
|
+
];
|
|
459
|
+
while (tn.skip(Token.Dot)) {
|
|
460
|
+
if (!tn.skipIdentifier())
|
|
461
|
+
return this.error(DiagnosticCode.Identifier_expected, tn.range());
|
|
462
|
+
segments.push(new Identifier(tn.readIdentifier(), tn.range()));
|
|
463
|
+
}
|
|
464
|
+
return new UsingPath(segments, tn.range(startPos, tn.pos));
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* parse the RHS of `using { ... } = <rhs>;`:
|
|
468
|
+
* - if it begins with a native type keyword (or a generic struct
|
|
469
|
+
* with type args), it's parsed as `AstTypeExpr` (legacy
|
|
470
|
+
* struct-destructure behavior)
|
|
471
|
+
* - if it's a single identifier followed by `<`, it's also parsed as
|
|
472
|
+
* a generic type expression
|
|
473
|
+
* - otherwise, it's parsed as a dotted `UsingPath`
|
|
474
|
+
* (a namespace path; the compiler decides whether it's a struct
|
|
475
|
+
* type or a namespace based on what the head identifier resolves to)
|
|
476
|
+
*/
|
|
477
|
+
parseUsingRhs() {
|
|
478
|
+
const tn = this.tn;
|
|
479
|
+
const next = tn.peek();
|
|
480
|
+
// native type keywords always go through parseTypeExpr
|
|
481
|
+
if (next === Token.Void
|
|
482
|
+
|| next === Token.Boolean
|
|
483
|
+
|| next === Token.Int
|
|
484
|
+
|| next === Token.Bytes
|
|
485
|
+
|| next === Token.Optional
|
|
486
|
+
|| next === Token.List
|
|
487
|
+
|| next === Token.LinearMap) {
|
|
488
|
+
const t = this.parseTypeExpr();
|
|
489
|
+
if (!t)
|
|
490
|
+
return undefined;
|
|
491
|
+
return t;
|
|
492
|
+
}
|
|
493
|
+
const path = this.parseUsingPath();
|
|
494
|
+
if (!path)
|
|
495
|
+
return undefined;
|
|
496
|
+
// single-segment path followed by `<...>` → generic struct type expression
|
|
497
|
+
if (path.segments.length === 1
|
|
498
|
+
&& tn.peek() === Token.LessThan) {
|
|
499
|
+
tn.next(); // consume `<`
|
|
500
|
+
const tyArgs = [];
|
|
501
|
+
do {
|
|
502
|
+
const ty = this.parseTypeExpr();
|
|
503
|
+
if (!ty)
|
|
504
|
+
return undefined;
|
|
505
|
+
tyArgs.push(ty);
|
|
506
|
+
} while (tn.skip(Token.Comma));
|
|
507
|
+
if (!tn.skip(Token.GreaterThan))
|
|
508
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), ">");
|
|
509
|
+
return new AstNamedTypeExpr(path.segments[0], tyArgs, tn.range(path.range.start, tn.pos));
|
|
510
|
+
}
|
|
511
|
+
return path;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* parse a namespace body: `{ (private? <member-decl>)* }`
|
|
515
|
+
*
|
|
516
|
+
* called with `namespace` already consumed; `startPos` is the position
|
|
517
|
+
* of the `namespace` keyword.
|
|
518
|
+
*/
|
|
519
|
+
parseNamespaceDecl(startPos) {
|
|
520
|
+
const tn = this.tn;
|
|
521
|
+
if (!tn.skipIdentifier())
|
|
522
|
+
return this.error(DiagnosticCode.Identifier_expected, tn.range());
|
|
523
|
+
const name = new Identifier(tn.readIdentifier(), tn.range());
|
|
524
|
+
if (!tn.skip(Token.OpenBrace))
|
|
525
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), "{");
|
|
526
|
+
const members = [];
|
|
527
|
+
while (!tn.skip(Token.CloseBrace)) {
|
|
528
|
+
tn.skip(Token.Semicolon);
|
|
529
|
+
if (tn.skip(Token.CloseBrace))
|
|
530
|
+
break;
|
|
531
|
+
const memberStartPos = tn.tokenPos;
|
|
532
|
+
const isPrivate = tn.skip(Token.Private);
|
|
533
|
+
const member = this.parseNamespaceMember();
|
|
534
|
+
if (!member)
|
|
535
|
+
return undefined;
|
|
536
|
+
members.push(new NamespaceMember(isPrivate, member, tn.range(memberStartPos, tn.pos)));
|
|
537
|
+
tn.skip(Token.Semicolon);
|
|
538
|
+
}
|
|
539
|
+
return new NamespaceDecl(name, members, tn.range(startPos, tn.pos));
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* parse a single namespace body member. delegates to the relevant
|
|
543
|
+
* top-level-style parser based on the next token, but rejects
|
|
544
|
+
* declarations that aren't allowed inside a namespace body
|
|
545
|
+
* (no `export`, no `import`, no `using`, no `contract`, no `test`).
|
|
546
|
+
*/
|
|
547
|
+
parseNamespaceMember() {
|
|
548
|
+
const tn = this.tn;
|
|
549
|
+
const startPos = tn.tokenPos;
|
|
550
|
+
const flags = CommonFlags.None;
|
|
551
|
+
const first = tn.peek();
|
|
552
|
+
switch (first) {
|
|
553
|
+
case Token.Namespace: {
|
|
554
|
+
tn.next();
|
|
555
|
+
return this.parseNamespaceDecl(startPos);
|
|
556
|
+
}
|
|
557
|
+
case Token.Function: {
|
|
558
|
+
tn.next();
|
|
559
|
+
return this.parseFuncDecl(flags, startPos);
|
|
560
|
+
}
|
|
561
|
+
case Token.Interface: {
|
|
562
|
+
tn.next();
|
|
563
|
+
return this.parseInterface(flags, startPos);
|
|
564
|
+
}
|
|
565
|
+
case Token.Var:
|
|
566
|
+
case Token.Let:
|
|
567
|
+
case Token.Const: {
|
|
568
|
+
tn.next();
|
|
569
|
+
return this.parseVarStmt(first === Token.Const ? CommonFlags.Const : CommonFlags.Let, startPos);
|
|
570
|
+
}
|
|
571
|
+
case Token.Enum: {
|
|
572
|
+
tn.next();
|
|
573
|
+
return this.parseEnum(flags, startPos);
|
|
574
|
+
}
|
|
575
|
+
case Token.Struct: {
|
|
576
|
+
tn.next();
|
|
577
|
+
return this.parseStruct(StructDeclAstFlags.none, flags, startPos);
|
|
578
|
+
}
|
|
579
|
+
case Token.Data: {
|
|
580
|
+
tn.next();
|
|
581
|
+
if (tn.peek() !== Token.Struct)
|
|
582
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), "struct");
|
|
583
|
+
tn.next();
|
|
584
|
+
return this.parseStruct(StructDeclAstFlags.onlyDataEncoding, flags, startPos);
|
|
585
|
+
}
|
|
586
|
+
case Token.Runtime: {
|
|
587
|
+
tn.next();
|
|
588
|
+
if (tn.peek() !== Token.Struct)
|
|
589
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), "struct");
|
|
590
|
+
tn.next();
|
|
591
|
+
return this.parseStruct(StructDeclAstFlags.onlySopEncoding, flags, startPos);
|
|
592
|
+
}
|
|
593
|
+
case Token.Type: {
|
|
594
|
+
tn.next();
|
|
595
|
+
const stmt = this.parseTypeStmt(flags, startPos);
|
|
596
|
+
if (!stmt)
|
|
597
|
+
return undefined;
|
|
598
|
+
if (!(stmt instanceof TypeAliasDecl))
|
|
599
|
+
return this.error(DiagnosticCode._0_expected, stmt.range, "type alias declaration");
|
|
600
|
+
return stmt;
|
|
601
|
+
}
|
|
602
|
+
default:
|
|
603
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), "namespace member declaration");
|
|
604
|
+
}
|
|
404
605
|
}
|
|
405
606
|
parseTypeParameters() {
|
|
406
607
|
const tn = this.tn;
|
|
@@ -419,6 +620,41 @@ export class Parser extends DiagnosticEmitter {
|
|
|
419
620
|
}
|
|
420
621
|
return typeParams;
|
|
421
622
|
}
|
|
623
|
+
/**
|
|
624
|
+
* Parses a function's type-parameter list with optional `implements`
|
|
625
|
+
* interface constraints:
|
|
626
|
+
* `<T, U implements ToData, V implements Foo>`
|
|
627
|
+
*
|
|
628
|
+
* Returns `TypeParamDecl[]` so the compiler can read each param's
|
|
629
|
+
* optional constraint at template-registration time. Struct/interface
|
|
630
|
+
* decls keep using the simpler {@link parseTypeParameters} which
|
|
631
|
+
* returns bare `Identifier[]`.
|
|
632
|
+
*/
|
|
633
|
+
parseFuncTypeParameters() {
|
|
634
|
+
const tn = this.tn;
|
|
635
|
+
// at '<': TypeParamDecl (',' TypeParamDecl)* '>'
|
|
636
|
+
const typeParams = new Array();
|
|
637
|
+
while (!tn.skip(Token.GreaterThan)) {
|
|
638
|
+
const startPos = tn.tokenPos;
|
|
639
|
+
if (!tn.skipIdentifier())
|
|
640
|
+
return this.error(DiagnosticCode.Identifier_expected, tn.range());
|
|
641
|
+
const name = new Identifier(tn.readIdentifier(), tn.range());
|
|
642
|
+
let constraint = undefined;
|
|
643
|
+
if (tn.skip(Token.Implements)) {
|
|
644
|
+
constraint = this.parseTypeExpr();
|
|
645
|
+
if (!constraint)
|
|
646
|
+
return undefined;
|
|
647
|
+
}
|
|
648
|
+
typeParams.push(new TypeParamDecl(name, constraint, tn.range(startPos, tn.pos)));
|
|
649
|
+
if (tn.skip(Token.Comma))
|
|
650
|
+
continue;
|
|
651
|
+
if (tn.skip(Token.GreaterThan))
|
|
652
|
+
break;
|
|
653
|
+
else
|
|
654
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), ">");
|
|
655
|
+
}
|
|
656
|
+
return typeParams;
|
|
657
|
+
}
|
|
422
658
|
parseTypeArguments() {
|
|
423
659
|
const tn = this.tn;
|
|
424
660
|
// at '<': TypeParameter (',' TypeParameter)* '>'
|
|
@@ -537,7 +773,11 @@ export class Parser extends DiagnosticEmitter {
|
|
|
537
773
|
const body = this.parseBlockStmt();
|
|
538
774
|
if (!body)
|
|
539
775
|
return undefined;
|
|
540
|
-
members.push(new InterfaceMethodImpl(methodName,
|
|
776
|
+
members.push(new InterfaceMethodImpl(methodName,
|
|
777
|
+
// InterfaceMethodImpl still uses bare Identifier[];
|
|
778
|
+
// strip any constraint clauses (method-decl constraints
|
|
779
|
+
// would be a separate feature).
|
|
780
|
+
typeParams?.map(p => p.name) ?? [], sig, body, tn.range(startPos, tn.pos)));
|
|
541
781
|
}
|
|
542
782
|
tn.skip(Token.Semicolon); // if any
|
|
543
783
|
return new TypeImplementsStmt(typeId, interfaceType, members, tn.range());
|
|
@@ -666,7 +906,7 @@ export class Parser extends DiagnosticEmitter {
|
|
|
666
906
|
[
|
|
667
907
|
new StructConstrDecl(new Identifier(name.text, name.range), [], // fields
|
|
668
908
|
range)
|
|
669
|
-
], structDeclFlags | StructDeclAstFlags.
|
|
909
|
+
], structDeclFlags | StructDeclAstFlags.shortcutSingleConstructor, range.clone());
|
|
670
910
|
}
|
|
671
911
|
let constrIdentifier = undefined;
|
|
672
912
|
// in case of single constr shortcut
|
|
@@ -687,7 +927,7 @@ export class Parser extends DiagnosticEmitter {
|
|
|
687
927
|
tn.skip(Token.Semicolon); // if any
|
|
688
928
|
return new StructDecl(name, typeParams, [
|
|
689
929
|
new StructConstrDecl(new Identifier(name.text, name.range), fields, tn.range(startPos, tn.pos))
|
|
690
|
-
], structDeclFlags | StructDeclAstFlags.
|
|
930
|
+
], structDeclFlags | StructDeclAstFlags.shortcutSingleConstructor, tn.range(startPos, tn.pos));
|
|
691
931
|
}
|
|
692
932
|
const constrFields = this.parseStructConstrFields(flags);
|
|
693
933
|
if (!Array.isArray(constrFields))
|
|
@@ -747,7 +987,7 @@ export class Parser extends DiagnosticEmitter {
|
|
|
747
987
|
let typeParams = undefined;
|
|
748
988
|
if (tn.skip(Token.LessThan)) {
|
|
749
989
|
sigStart = tn.tokenPos;
|
|
750
|
-
typeParams = this.
|
|
990
|
+
typeParams = this.parseFuncTypeParameters();
|
|
751
991
|
if (!typeParams || typeParams.length === 0)
|
|
752
992
|
return undefined;
|
|
753
993
|
// flags |= CommonFlags.Generic;
|
|
@@ -776,15 +1016,11 @@ export class Parser extends DiagnosticEmitter {
|
|
|
776
1016
|
const namedSig = this.parseNamedFuncSig(flags, startPos, defaultReturnType);
|
|
777
1017
|
if (!namedSig)
|
|
778
1018
|
return undefined;
|
|
779
|
-
const [name,
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
if (!(arg instanceof AstNamedTypeExpr))
|
|
785
|
-
return this.error(DiagnosticCode.Type_parameters_must_be_identifiers, arg.range);
|
|
786
|
-
typeParams[i] = arg.name;
|
|
787
|
-
}
|
|
1019
|
+
const [name, typeParamsRaw, sig] = namedSig;
|
|
1020
|
+
// `parseNamedFuncSig` returns `TypeParamDecl[]` (with optional
|
|
1021
|
+
// `implements` constraint per param) — `FuncExpr.typeParams` carries
|
|
1022
|
+
// them through to template registration.
|
|
1023
|
+
const typeParams = typeParamsRaw ?? [];
|
|
788
1024
|
if (!tn.skip(Token.OpenBrace))
|
|
789
1025
|
return this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, tn.range());
|
|
790
1026
|
const body = this.parseBlockStmt();
|
|
@@ -792,7 +1028,7 @@ export class Parser extends DiagnosticEmitter {
|
|
|
792
1028
|
return undefined;
|
|
793
1029
|
const endPos = tn.pos;
|
|
794
1030
|
tn.skip(Token.Semicolon); // if any
|
|
795
|
-
const expr = new FuncExpr(name, flags, typeParams
|
|
1031
|
+
const expr = new FuncExpr(name, flags, typeParams, sig, body, ArrowKind.None, tn.range(startPos, endPos));
|
|
796
1032
|
return new FuncDecl(expr);
|
|
797
1033
|
}
|
|
798
1034
|
parseEnum(flags, startPos) {
|
|
@@ -1113,11 +1349,15 @@ export class Parser extends DiagnosticEmitter {
|
|
|
1113
1349
|
switch (token) {
|
|
1114
1350
|
case Token.Void: return new AstVoidType(currRange);
|
|
1115
1351
|
// case Token.True:
|
|
1116
|
-
// case Token.False:
|
|
1352
|
+
// case Token.False:
|
|
1117
1353
|
case Token.Boolean: return new AstBooleanType(currRange);
|
|
1118
1354
|
case Token.Int: return new AstIntType(currRange);
|
|
1119
1355
|
// case Token.Number: return new AstIntType( currRange )
|
|
1120
1356
|
case Token.Bytes: return new AstBytesType(currRange);
|
|
1357
|
+
// `data` is registered in the prelude as a named type; expose it
|
|
1358
|
+
// as a plain `AstNamedTypeExpr` so it can be written in type
|
|
1359
|
+
// position (e.g. `function f(x: data): ...`).
|
|
1360
|
+
case Token.Data: return new AstNamedTypeExpr(new Identifier("data", currRange), [], currRange);
|
|
1121
1361
|
case Token.Optional: {
|
|
1122
1362
|
if (!tn.skip(Token.LessThan)) {
|
|
1123
1363
|
canError && this.error(DiagnosticCode._0_expected, currRange, "Type argument for Optional");
|
|
@@ -1308,7 +1548,10 @@ export class Parser extends DiagnosticEmitter {
|
|
|
1308
1548
|
if (tn.skipIdentifier(IdentifierHandling.Always)) {
|
|
1309
1549
|
prop = new Identifier(tn.readIdentifier(), tn.range());
|
|
1310
1550
|
expr = makePropAccessExpr(token, expr, prop, tn.range(startPos, tn.pos));
|
|
1311
|
-
|
|
1551
|
+
// pass `true` so we attempt `<TypeArgs>` parsing —
|
|
1552
|
+
// generic calls on dotted paths (e.g. `std.x.f<T>(a)`)
|
|
1553
|
+
// need this to consume the type arguments.
|
|
1554
|
+
expr = this.tryParseCallExprOrReturnSame(expr, true);
|
|
1312
1555
|
break;
|
|
1313
1556
|
}
|
|
1314
1557
|
const state = tn.mark();
|
|
@@ -1578,9 +1821,7 @@ export class Parser extends DiagnosticEmitter {
|
|
|
1578
1821
|
return new LitStrExpr(tn.readString(), tn.range(startPos, tn.pos));
|
|
1579
1822
|
}
|
|
1580
1823
|
case Token.StringTemplateLiteralQuote: {
|
|
1581
|
-
this.
|
|
1582
|
-
return undefined;
|
|
1583
|
-
// return this.parseTemplateLiteral();
|
|
1824
|
+
return this.parseTemplateLiteral(startPos);
|
|
1584
1825
|
}
|
|
1585
1826
|
case Token.IntegerLiteral: {
|
|
1586
1827
|
const value = tn.readInteger();
|
|
@@ -1666,17 +1907,14 @@ export class Parser extends DiagnosticEmitter {
|
|
|
1666
1907
|
const expr = this.parseExpr(Precedence.Relational + 1);
|
|
1667
1908
|
if (!expr)
|
|
1668
1909
|
return undefined;
|
|
1669
|
-
let noPatternCaseSeen = false;
|
|
1670
1910
|
const cases = new Array();
|
|
1671
1911
|
while (tn.skip(Token.Is)) {
|
|
1672
|
-
if (noPatternCaseSeen)
|
|
1673
|
-
return this.error(DiagnosticCode.This_case_will_never_be_evaluated_because_all_patterns_will_be_catched_before, tn.range());
|
|
1674
1912
|
const startPos = tn.tokenPos;
|
|
1675
1913
|
const matcher = this._parseVarDecl(CommonFlags.Const);
|
|
1676
1914
|
if (!matcher)
|
|
1677
1915
|
return undefined;
|
|
1678
|
-
|
|
1679
|
-
|
|
1916
|
+
// SimpleVarDecl patterns are validated by the AstCompiler, which
|
|
1917
|
+
// has type info (enum-member promotion vs invalid catch-all).
|
|
1680
1918
|
if (matcher.initExpr || matcher.type)
|
|
1681
1919
|
return this.error(DiagnosticCode.Patterns_may_not_have_initializers_or_explicit_types, matcher.initExpr ? matcher.initExpr.range : matcher.type.range);
|
|
1682
1920
|
if (!tn.skip(Token.FatArrow))
|
|
@@ -2340,17 +2578,63 @@ export class Parser extends DiagnosticEmitter {
|
|
|
2340
2578
|
}
|
|
2341
2579
|
parseTestStatement() {
|
|
2342
2580
|
const tn = this.tn;
|
|
2343
|
-
// at 'test':
|
|
2344
|
-
const
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2581
|
+
// at 'test': Identifier '(' TestParam (',' TestParam)* ')' '{' BlockStmt
|
|
2582
|
+
const startPos = tn.pos;
|
|
2583
|
+
if (!tn.skipIdentifier())
|
|
2584
|
+
return this.error(DiagnosticCode.Identifier_expected, tn.range());
|
|
2585
|
+
const testName = new Identifier(tn.readIdentifier(), tn.range());
|
|
2586
|
+
if (!tn.skip(Token.OpenParen))
|
|
2587
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), "(");
|
|
2588
|
+
const params = this.parseTestParameters();
|
|
2589
|
+
if (!params)
|
|
2590
|
+
return undefined;
|
|
2591
|
+
if (!tn.skip(Token.OpenBrace))
|
|
2592
|
+
return this.error(DiagnosticCode.Tests_must_be_specified_in_a_block_statement, tn.range());
|
|
2593
|
+
let body = this.parseBlockStmt();
|
|
2351
2594
|
if (!body)
|
|
2352
2595
|
return this.error(DiagnosticCode.Tests_must_be_specified_in_a_block_statement, tn.range());
|
|
2353
|
-
return new TestStmt(testName, body, tn.range(
|
|
2596
|
+
return new TestStmt(testName, params, body, tn.range(startPos, tn.pos));
|
|
2597
|
+
}
|
|
2598
|
+
/**
|
|
2599
|
+
* Parses the parameter list of a `test` declaration:
|
|
2600
|
+
* `( <id>: <type> ('via' <expr>)? (, <id>: <type> ('via' <expr>)? )* )?`
|
|
2601
|
+
*
|
|
2602
|
+
* Assumes the opening `(` has already been consumed by the caller.
|
|
2603
|
+
* Consumes the closing `)` on success.
|
|
2604
|
+
*
|
|
2605
|
+
* `via` is recognised here ONLY — function/method/contract parameter
|
|
2606
|
+
* parsing uses `parseParameters()` which never looks for `Token.Via`.
|
|
2607
|
+
*/
|
|
2608
|
+
parseTestParameters() {
|
|
2609
|
+
const tn = this.tn;
|
|
2610
|
+
const params = [];
|
|
2611
|
+
if (tn.skip(Token.CloseParen))
|
|
2612
|
+
return params;
|
|
2613
|
+
while (true) {
|
|
2614
|
+
const paramStart = tn.pos;
|
|
2615
|
+
if (!tn.skipIdentifier())
|
|
2616
|
+
return this.error(DiagnosticCode.Identifier_expected, tn.range());
|
|
2617
|
+
const name = new Identifier(tn.readIdentifier(), tn.range());
|
|
2618
|
+
if (!tn.skip(Token.Colon))
|
|
2619
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), ":");
|
|
2620
|
+
const type = this.parseTypeExpr();
|
|
2621
|
+
if (!type)
|
|
2622
|
+
return undefined;
|
|
2623
|
+
let viaExpr = undefined;
|
|
2624
|
+
if (tn.skip(Token.Via)) {
|
|
2625
|
+
const expr = this.parseExpr();
|
|
2626
|
+
if (!expr)
|
|
2627
|
+
return undefined;
|
|
2628
|
+
viaExpr = expr;
|
|
2629
|
+
}
|
|
2630
|
+
params.push(new TestParam(name, type, viaExpr, tn.range(paramStart, tn.pos)));
|
|
2631
|
+
if (tn.skip(Token.Comma))
|
|
2632
|
+
continue;
|
|
2633
|
+
if (tn.skip(Token.CloseParen))
|
|
2634
|
+
break;
|
|
2635
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), ")");
|
|
2636
|
+
}
|
|
2637
|
+
return params;
|
|
2354
2638
|
}
|
|
2355
2639
|
parseMatchStatement() {
|
|
2356
2640
|
const tn = this.tn;
|
|
@@ -2361,7 +2645,6 @@ export class Parser extends DiagnosticEmitter {
|
|
|
2361
2645
|
return this.error(DiagnosticCode.Expression_expected, tn.range(startPos - 5, startPos));
|
|
2362
2646
|
if (!tn.skip(Token.OpenBrace))
|
|
2363
2647
|
return this.error(DiagnosticCode._0_expected, tn.range(), "{");
|
|
2364
|
-
let noPatternCaseSeen = false;
|
|
2365
2648
|
const cases = new Array();
|
|
2366
2649
|
while (!tn.skip(Token.CloseBrace)
|
|
2367
2650
|
&& tn.peek() !== Token.Else) {
|
|
@@ -2372,10 +2655,8 @@ export class Parser extends DiagnosticEmitter {
|
|
|
2372
2655
|
const pattern = this._parseVarDecl(CommonFlags.Const, true);
|
|
2373
2656
|
if (!pattern)
|
|
2374
2657
|
return this.error(DiagnosticCode.Pattern_expected, tn.range());
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
if (pattern instanceof SimpleVarDecl)
|
|
2378
|
-
noPatternCaseSeen = true;
|
|
2658
|
+
// SimpleVarDecl patterns are validated by the AstCompiler, which
|
|
2659
|
+
// has type info (enum-member promotion vs invalid catch-all).
|
|
2379
2660
|
if (!tn.skip(Token.Colon))
|
|
2380
2661
|
return this.error(DiagnosticCode._0_expected, tn.range(), ":");
|
|
2381
2662
|
const statePreBody = tn.mark();
|
|
@@ -2416,6 +2697,41 @@ export class Parser extends DiagnosticEmitter {
|
|
|
2416
2697
|
return this.error(DiagnosticCode.Expression_expected, tn.range());
|
|
2417
2698
|
return new TraceStmt(expr, tn.range());
|
|
2418
2699
|
}
|
|
2700
|
+
/**
|
|
2701
|
+
* Parse a backtick-delimited template literal:
|
|
2702
|
+
*
|
|
2703
|
+
* `text ${expr1} more text ${expr2} ...`
|
|
2704
|
+
*
|
|
2705
|
+
* Tokenizer state: on entry, the current token is
|
|
2706
|
+
* `Token.StringTemplateLiteralQuote`; the tokenizer is positioned at
|
|
2707
|
+
* the opening backtick. `readString()` (called with no arg) consumes
|
|
2708
|
+
* the backtick + the first fragment up to `${` or to the closing
|
|
2709
|
+
* backtick; if it stopped at `${` it sets `readingTemplateString = true`
|
|
2710
|
+
* and the parser must consume an expression + `}` and then call
|
|
2711
|
+
* `readString(CharCode.Backtick)` to read the next fragment.
|
|
2712
|
+
*/
|
|
2713
|
+
parseTemplateLiteral(startPos) {
|
|
2714
|
+
const tn = this.tn;
|
|
2715
|
+
const parts = [];
|
|
2716
|
+
const exprs = [];
|
|
2717
|
+
// First fragment — readString advances past the opening backtick.
|
|
2718
|
+
let fragment = tn.readString();
|
|
2719
|
+
parts.push(fragment);
|
|
2720
|
+
while (tn.readingTemplateString) {
|
|
2721
|
+
// Just consumed `${`. Parse the interpolated expression.
|
|
2722
|
+
const interp = this.parseExpr();
|
|
2723
|
+
if (!interp)
|
|
2724
|
+
return this.error(DiagnosticCode.Expression_expected, tn.range());
|
|
2725
|
+
exprs.push(interp);
|
|
2726
|
+
if (!tn.skip(Token.CloseBrace))
|
|
2727
|
+
return this.error(DiagnosticCode._0_expected, tn.range(), "}");
|
|
2728
|
+
// Read the next fragment up to the next `${` or the closing
|
|
2729
|
+
// backtick. `readingTemplateString` is set inside readString.
|
|
2730
|
+
fragment = tn.readString(96 /* CharCode.Backtick */);
|
|
2731
|
+
parts.push(fragment);
|
|
2732
|
+
}
|
|
2733
|
+
return new TemplateStrExpr(parts, exprs, tn.range(startPos, tn.pos));
|
|
2734
|
+
}
|
|
2419
2735
|
parseAssertStatement() {
|
|
2420
2736
|
const tn = this.tn;
|
|
2421
2737
|
const startPos = tn.tokenPos;
|