@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
|
@@ -5,6 +5,7 @@ import { TirLitFailExpr } from "../../tir/expressions/litteral/TirLitFailExpr.js
|
|
|
5
5
|
import { TirLitFalseExpr } from "../../tir/expressions/litteral/TirLitFalseExpr.js";
|
|
6
6
|
import { TirLitHexBytesExpr } from "../../tir/expressions/litteral/TirLitHexBytesExpr.js";
|
|
7
7
|
import { TirLitIntExpr } from "../../tir/expressions/litteral/TirLitIntExpr.js";
|
|
8
|
+
import { TirLitEnumMemberExpr } from "../../tir/expressions/litteral/TirLitEnumMemberExpr.js";
|
|
8
9
|
import { TirLitNamedObjExpr } from "../../tir/expressions/litteral/TirLitNamedObjExpr.js";
|
|
9
10
|
import { TirLitObjExpr } from "../../tir/expressions/litteral/TirLitObjExpr.js";
|
|
10
11
|
import { TirLitStrExpr } from "../../tir/expressions/litteral/TirLitStrExpr.js";
|
|
@@ -30,6 +31,7 @@ import { TirTernaryExpr } from "../../tir/expressions/TirTernaryExpr.js";
|
|
|
30
31
|
import { TirToDataExpr } from "../../tir/expressions/TirToDataExpr.js";
|
|
31
32
|
import { TirTraceIfFalseExpr } from "../../tir/expressions/TirTraceIfFalseExpr.js";
|
|
32
33
|
import { TirTraceExpr } from "../../tir/expressions/TirTraceExpr.js";
|
|
34
|
+
import { TirShowExpr } from "../../tir/expressions/TirShowExpr.js";
|
|
33
35
|
import { TirTypeConversionExpr } from "../../tir/expressions/TirTypeConversionExpr.js";
|
|
34
36
|
import { TirVariableAccessExpr } from "../../tir/expressions/TirVariableAccessExpr.js";
|
|
35
37
|
import { TirUnaryExclamation } from "../../tir/expressions/unary/TirUnaryExclamation.js";
|
|
@@ -37,8 +39,9 @@ import { TirUnaryMinus } from "../../tir/expressions/unary/TirUnaryMinus.js";
|
|
|
37
39
|
import { TirUnaryPlus } from "../../tir/expressions/unary/TirUnaryPlus.js";
|
|
38
40
|
import { isTirUnaryPrefixExpr } from "../../tir/expressions/unary/TirUnaryPrefixExpr.js";
|
|
39
41
|
import { TirUnaryTilde } from "../../tir/expressions/unary/TirUnaryTilde.js";
|
|
40
|
-
import { bool_t, bytes_t, data_t, int_t,
|
|
42
|
+
import { bool_t, bytes_t, data_t, int_t, valueMapAmountOfName } from "../../tir/program/stdScope/stdScope.js";
|
|
41
43
|
import { IRNativeTag } from "../../../IR/IRNodes/IRNative/IRNativeTag.js";
|
|
44
|
+
import { currentCompilationCtx } from "../../../IR/CompilationCtx.js";
|
|
42
45
|
import { TirReturnStmt } from "../../tir/statements/TirReturnStmt.js";
|
|
43
46
|
import { TirArrayLikeDeconstr } from "../../tir/statements/TirVarDecl/TirArrayLikeDeconstr.js";
|
|
44
47
|
import { TirNamedDeconstructVarDecl } from "../../tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.js";
|
|
@@ -75,6 +78,7 @@ export function expressifyVars(ctx, expr) {
|
|
|
75
78
|
|| expr instanceof TirLitThisExpr
|
|
76
79
|
|| expr instanceof TirLitStrExpr
|
|
77
80
|
|| expr instanceof TirLitIntExpr
|
|
81
|
+
|| expr instanceof TirLitEnumMemberExpr
|
|
78
82
|
|| expr instanceof TirLitHexBytesExpr
|
|
79
83
|
|| expr instanceof TirNativeFunc
|
|
80
84
|
// hoisted expressions are necessarily closed, so no external variables
|
|
@@ -242,6 +246,11 @@ export function expressifyVars(ctx, expr) {
|
|
|
242
246
|
}
|
|
243
247
|
if (expr instanceof TirInlineClosedIR)
|
|
244
248
|
return expr;
|
|
249
|
+
if (expr instanceof TirShowExpr) {
|
|
250
|
+
// recurse into inner so any nested variables / casts get expressified;
|
|
251
|
+
// the show-bytes lowering happens at IR-emit time inside TirShowExpr.toIR.
|
|
252
|
+
return new TirShowExpr(expressifyVars(ctx, expr.inner), expr.range);
|
|
253
|
+
}
|
|
245
254
|
const tsEnsureExhautstiveCheck = expr;
|
|
246
255
|
console.error(expr);
|
|
247
256
|
throw new Error("unreachable::expressifyVars");
|
|
@@ -260,6 +269,7 @@ function expressifyPropAccess(ctx, propAccessExpr) {
|
|
|
260
269
|
|| expr instanceof TirLitArrExpr
|
|
261
270
|
|| expr instanceof TirLitStrExpr
|
|
262
271
|
|| expr instanceof TirLitIntExpr
|
|
272
|
+
|| expr instanceof TirLitEnumMemberExpr
|
|
263
273
|
|| expr instanceof TirLitHexBytesExpr
|
|
264
274
|
|| expr instanceof TirNativeFunc
|
|
265
275
|
|| expr instanceof TirPropAccessExpr // `expressifyVars` is called recursively on the object before this check
|
|
@@ -276,7 +286,9 @@ function expressifyPropAccess(ctx, propAccessExpr) {
|
|
|
276
286
|
|| expr instanceof TirAssertAndContinueExpr
|
|
277
287
|
|| expr instanceof TirTraceIfFalseExpr
|
|
278
288
|
|| expr instanceof TirTraceExpr
|
|
279
|
-
|| expr instanceof TirInlineClosedIR
|
|
289
|
+
|| expr instanceof TirInlineClosedIR
|
|
290
|
+
|| expr instanceof TirShowExpr // result is bytes, properties already handled via .show() returning bytes_t
|
|
291
|
+
)
|
|
280
292
|
throw new Error("Invalid property access expression");
|
|
281
293
|
if (expr instanceof TirLitThisExpr) {
|
|
282
294
|
let varName = ctx.properties.get("this")?.get(prop);
|
|
@@ -364,6 +376,20 @@ function expressifyPropAccess(ctx, propAccessExpr) {
|
|
|
364
376
|
throw new Error(`Property '${prop}' does not exist on type '${objType.toString()}'`);
|
|
365
377
|
const fName = ctor.fields[fIdx].name;
|
|
366
378
|
const fType = ctor.fields[fIdx].type;
|
|
379
|
+
// Untagged data structs encode as `listData(fields)` rather than
|
|
380
|
+
// `constrData(0, fields)`. Field access lowers directly to
|
|
381
|
+
// `unIData (or _inlineFromData) <$> headList (dropList idx (unListData v))`
|
|
382
|
+
// — no case-rewrite needed, no constructor index to check.
|
|
383
|
+
if (objType instanceof TirDataStructType
|
|
384
|
+
&& objType.untagged) {
|
|
385
|
+
const fieldsListT = new TirListT(data_t);
|
|
386
|
+
return new TirFromDataExpr(new TirCallExpr(TirNativeFunc.headList(data_t), [
|
|
387
|
+
new TirCallExpr(TirNativeFunc.dropList(data_t), [
|
|
388
|
+
new TirLitIntExpr(BigInt(fIdx), propAccessExpr.range),
|
|
389
|
+
new TirCallExpr(TirNativeFunc.unListData, [expr], fieldsListT, propAccessExpr.range)
|
|
390
|
+
], fieldsListT, propAccessExpr.range)
|
|
391
|
+
], data_t, propAccessExpr.range), fType, propAccessExpr.range);
|
|
392
|
+
}
|
|
367
393
|
return new TirCaseExpr(expr, [
|
|
368
394
|
new TirCaseMatcher(new TirNamedDeconstructVarDecl(ctor.name, new Map([
|
|
369
395
|
[fName, new TirSimpleVarDecl(fName, fType, undefined, true, propAccessExpr.range)]
|
|
@@ -404,7 +430,7 @@ function expressifyMethodCall(ctx, methodCall) {
|
|
|
404
430
|
// fast-path: `Value.amountOf(policy, name)` compiles directly to
|
|
405
431
|
// `_amountOfValue(eqByteString(policy))(value)(eqByteString(name))`
|
|
406
432
|
// skipping the wrapper function indirection.
|
|
407
|
-
if (tirMethodName ===
|
|
433
|
+
if (tirMethodName === valueMapAmountOfName
|
|
408
434
|
&& methodCall.args.length === 2) {
|
|
409
435
|
const [policyArg, nameArg] = methodCall.args;
|
|
410
436
|
const bytesToBoolT = new TirFuncT([bytes_t], bool_t);
|
|
@@ -445,12 +471,15 @@ function expressifyMethodCall(ctx, methodCall) {
|
|
|
445
471
|
}
|
|
446
472
|
const structMethods = objectType.methodNamesPtr;
|
|
447
473
|
const tirMethodName = structMethods.get(methodName);
|
|
448
|
-
if (
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
474
|
+
if (tirMethodName) {
|
|
475
|
+
const funcExpr = ctx.program.functions.get(tirMethodName);
|
|
476
|
+
if (!funcExpr)
|
|
477
|
+
throw new Error(`Definition of method '${methodName}' on type '${objectType.toString()}' is missing.`);
|
|
478
|
+
return new TirCallExpr(funcExpr, [objectExpr, ...methodCall.args], methodCall.type, SourceRange.join(methodIdentifierProp.range, methodCall.range.atEnd()));
|
|
479
|
+
}
|
|
480
|
+
// No user impl — fall through to the generic `.show()` fallback at the
|
|
481
|
+
// end of expressifyMethodCall (which auto-derives via _showIR for
|
|
482
|
+
// data-encoded structs).
|
|
454
483
|
}
|
|
455
484
|
if (objectType instanceof TirListT) {
|
|
456
485
|
const result = expressifyListMethodCall(ctx, objectExpr, methodCall, methodName, objectType, SourceRange.join(methodIdentifierProp.range, methodCall.range.atEnd()));
|
|
@@ -491,6 +520,14 @@ function expressifyMethodCall(ctx, methodCall) {
|
|
|
491
520
|
return new TirCallExpr(TirNativeFunc.consByteString, [methodCall.args[0], objectExpr], bytes_t, exprRange);
|
|
492
521
|
}
|
|
493
522
|
}
|
|
523
|
+
// Generic `.show()` fallback: any value whose type has a built-in
|
|
524
|
+
// `_showIR` impl can be shown by emitting a TirShowExpr. User types
|
|
525
|
+
// override this by declaring `type X implements Show { show(self): bytes
|
|
526
|
+
// { ... } }` — that path is taken earlier (alias/struct method-table
|
|
527
|
+
// dispatch) and never reaches here.
|
|
528
|
+
if (methodName === "show" && methodCall.args.length === 0) {
|
|
529
|
+
return new TirShowExpr(objectExpr, SourceRange.join(methodIdentifierProp.range, methodCall.range.atEnd())); // TirShowExpr is in TirExpr union, cast for return-type compat
|
|
530
|
+
}
|
|
494
531
|
throw new Error(`not implemented::expressifyMethodCall for type '${objectType.toString()}' (method name: '${methodName}')`);
|
|
495
532
|
// const tsEnsureExhautstiveCheck: never = objectType;
|
|
496
533
|
throw new Error(`Cannot call method '${methodName}' on non-struct type '${objectType.toString()}'`);
|
|
@@ -563,7 +600,8 @@ function expressifyListMethodCall(ctx, objectExpr, methodCall, methodName, listT
|
|
|
563
600
|
throw new Error(`Argument 1 of method 'map' of type 'list' must be a function, got '${arg.type.toString()}'`);
|
|
564
601
|
const mapReturnT = argFuncType.returnType;
|
|
565
602
|
const elemTypeTirName = elemsType.toTirTypeKey();
|
|
566
|
-
|
|
603
|
+
const mapToTypeCache = currentCompilationCtx().mapToTypeCache;
|
|
604
|
+
let base_mapToType = mapToTypeCache.get(elemTypeTirName)?.clone();
|
|
567
605
|
if (!base_mapToType) {
|
|
568
606
|
base_mapToType = new TirHoistedExpr("_map_to_list_of_" + elemTypeTirName, new TirCallExpr(TirNativeFunc._mkMap(elemsType, mapReturnT), [new TirLitArrExpr([], new TirListT(mapReturnT), SourceRange.unknown)], new TirFuncT([
|
|
569
607
|
// mapping function
|
|
@@ -574,7 +612,7 @@ function expressifyListMethodCall(ctx, objectExpr, methodCall, methodName, listT
|
|
|
574
612
|
new TirListT(elemsType)
|
|
575
613
|
], new TirListT(mapReturnT)), SourceRange.unknown));
|
|
576
614
|
base_mapToType.varName; // precompute hash and symbol
|
|
577
|
-
|
|
615
|
+
mapToTypeCache.set(elemTypeTirName, base_mapToType.clone());
|
|
578
616
|
}
|
|
579
617
|
return new TirCallExpr(base_mapToType, [methodCall.args[0], objectExpr], methodCall.type, exprRange);
|
|
580
618
|
}
|
|
@@ -586,7 +624,3 @@ function expressifyListMethodCall(ctx, objectExpr, methodCall, methodName, listT
|
|
|
586
624
|
};
|
|
587
625
|
*/
|
|
588
626
|
}
|
|
589
|
-
const _base_mapToType_cache = new Map();
|
|
590
|
-
export function __unsafe_clear_mapToType_cache() {
|
|
591
|
-
_base_mapToType_cache.clear();
|
|
592
|
-
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { SourceRange } from "../../ast/Source/SourceRange.js";
|
|
2
|
+
export type TestKind = "unit" | "property";
|
|
3
|
+
export interface TestBudget {
|
|
4
|
+
cpu: bigint;
|
|
5
|
+
mem: bigint;
|
|
6
|
+
}
|
|
7
|
+
export interface TestInput {
|
|
8
|
+
name: string;
|
|
9
|
+
value: unknown;
|
|
10
|
+
}
|
|
11
|
+
export interface TestIterationResult {
|
|
12
|
+
passed: boolean;
|
|
13
|
+
budgetSpent: TestBudget;
|
|
14
|
+
logs: string[];
|
|
15
|
+
error?: {
|
|
16
|
+
msg?: string;
|
|
17
|
+
};
|
|
18
|
+
/** the fuzzed input tuple for this iteration; undefined for unit tests */
|
|
19
|
+
inputs?: TestInput[];
|
|
20
|
+
}
|
|
21
|
+
export interface TestResult {
|
|
22
|
+
name: string;
|
|
23
|
+
sourceFile: string;
|
|
24
|
+
range: SourceRange;
|
|
25
|
+
kind: TestKind;
|
|
26
|
+
/** aggregate pass/fail across all iterations */
|
|
27
|
+
passed: boolean;
|
|
28
|
+
/** length 1 for unit tests, N for property tests */
|
|
29
|
+
iterations: TestIterationResult[];
|
|
30
|
+
/** sum of `budgetSpent` across iterations */
|
|
31
|
+
totalBudget: TestBudget;
|
|
32
|
+
/** non-empty when the test could not be executed at all (e.g. unsupported feature) */
|
|
33
|
+
skippedReason?: string;
|
|
34
|
+
/** seed used by the property runner (only set for property tests) */
|
|
35
|
+
seed?: number;
|
|
36
|
+
}
|
|
37
|
+
export declare function zeroBudget(): TestBudget;
|
|
38
|
+
export declare function addBudget(a: TestBudget, b: TestBudget): TestBudget;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny seedable PRNG (mulberry32).
|
|
3
|
+
*
|
|
4
|
+
* Single-purpose, deterministic, no dependencies. Used by the Phase 1
|
|
5
|
+
* property-test runner to sample primitive values for parameters whose
|
|
6
|
+
* type has a built-in TS-side fuzzer (`int`, `bool`).
|
|
7
|
+
*
|
|
8
|
+
* Phase 2 will replace this with a Pebble-side fuzzer pipeline that runs
|
|
9
|
+
* on the CEK machine; that will let user-defined fuzzers (`via <expr>`)
|
|
10
|
+
* compose deterministically with the built-in ones.
|
|
11
|
+
*/
|
|
12
|
+
export declare class PRNG {
|
|
13
|
+
private state;
|
|
14
|
+
constructor(seed: number);
|
|
15
|
+
/** Returns an unsigned 32-bit integer. */
|
|
16
|
+
next32(): number;
|
|
17
|
+
/** Returns a boolean (uniform). */
|
|
18
|
+
nextBool(): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Returns a random bigint, biased toward edge values.
|
|
21
|
+
*
|
|
22
|
+
* 1 in 16 returns one of: 0, 1, -1, INT64_MAX, INT64_MIN, INT32_MAX, INT32_MIN.
|
|
23
|
+
* Otherwise samples uniformly across signed 64-bit range.
|
|
24
|
+
*/
|
|
25
|
+
nextIntBiased(): bigint;
|
|
26
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny seedable PRNG (mulberry32).
|
|
3
|
+
*
|
|
4
|
+
* Single-purpose, deterministic, no dependencies. Used by the Phase 1
|
|
5
|
+
* property-test runner to sample primitive values for parameters whose
|
|
6
|
+
* type has a built-in TS-side fuzzer (`int`, `bool`).
|
|
7
|
+
*
|
|
8
|
+
* Phase 2 will replace this with a Pebble-side fuzzer pipeline that runs
|
|
9
|
+
* on the CEK machine; that will let user-defined fuzzers (`via <expr>`)
|
|
10
|
+
* compose deterministically with the built-in ones.
|
|
11
|
+
*/
|
|
12
|
+
export class PRNG {
|
|
13
|
+
state;
|
|
14
|
+
constructor(seed) {
|
|
15
|
+
// ensure non-zero, fits in u32
|
|
16
|
+
this.state = (seed | 0) || 1;
|
|
17
|
+
}
|
|
18
|
+
/** Returns an unsigned 32-bit integer. */
|
|
19
|
+
next32() {
|
|
20
|
+
// mulberry32
|
|
21
|
+
let t = (this.state = (this.state + 0x6D2B79F5) | 0);
|
|
22
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
23
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
24
|
+
return (t ^ (t >>> 14)) >>> 0;
|
|
25
|
+
}
|
|
26
|
+
/** Returns a boolean (uniform). */
|
|
27
|
+
nextBool() {
|
|
28
|
+
return (this.next32() & 1) === 1;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Returns a random bigint, biased toward edge values.
|
|
32
|
+
*
|
|
33
|
+
* 1 in 16 returns one of: 0, 1, -1, INT64_MAX, INT64_MIN, INT32_MAX, INT32_MIN.
|
|
34
|
+
* Otherwise samples uniformly across signed 64-bit range.
|
|
35
|
+
*/
|
|
36
|
+
nextIntBiased() {
|
|
37
|
+
const edgeRoll = this.next32() & 0xF; // 0..15
|
|
38
|
+
if (edgeRoll === 0) {
|
|
39
|
+
const edges = [
|
|
40
|
+
0n,
|
|
41
|
+
1n,
|
|
42
|
+
-1n,
|
|
43
|
+
(1n << 63n) - 1n,
|
|
44
|
+
-(1n << 63n),
|
|
45
|
+
(1n << 31n) - 1n,
|
|
46
|
+
-(1n << 31n),
|
|
47
|
+
];
|
|
48
|
+
return edges[this.next32() % edges.length];
|
|
49
|
+
}
|
|
50
|
+
// assemble a 64-bit signed value from two u32 samples
|
|
51
|
+
const hi = BigInt(this.next32());
|
|
52
|
+
const lo = BigInt(this.next32());
|
|
53
|
+
let v = (hi << 32n) | lo;
|
|
54
|
+
// interpret as signed (sign bit is bit 63)
|
|
55
|
+
if (v & (1n << 63n))
|
|
56
|
+
v -= (1n << 64n);
|
|
57
|
+
return v;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -20,6 +20,15 @@ export declare class TirCaseExpr implements ITirExpr {
|
|
|
20
20
|
deps(): string[];
|
|
21
21
|
get isConstant(): boolean;
|
|
22
22
|
toIR(ctx: ToIRTermCtx): IRTerm;
|
|
23
|
+
/**
|
|
24
|
+
* Lowers a `case` over an untagged data struct (single constructor;
|
|
25
|
+
* runtime form is `listData(fields)`). No constructor dispatch is
|
|
26
|
+
* needed — there's only one possible ctor — so the lowering is just
|
|
27
|
+
* "find the matching arm (or wildcard), extract any bound fields, run
|
|
28
|
+
* the body".
|
|
29
|
+
*/
|
|
30
|
+
private _untaggedDataStructToIR;
|
|
31
|
+
private _enumToIR;
|
|
23
32
|
private _sopStructToIR;
|
|
24
33
|
private _dataStructToIR;
|
|
25
34
|
}
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { IRApp, _ir_apps } from "../../../IR/IRNodes/IRApp.js";
|
|
2
2
|
import { IRCase } from "../../../IR/IRNodes/IRCase.js";
|
|
3
3
|
import { IRConst } from "../../../IR/IRNodes/IRConst.js";
|
|
4
|
-
import { IRDelayed } from "../../../IR/IRNodes/IRDelayed.js";
|
|
5
4
|
import { IRError } from "../../../IR/IRNodes/IRError.js";
|
|
6
5
|
import { IRFunc } from "../../../IR/IRNodes/IRFunc.js";
|
|
6
|
+
import { IRLetted } from "../../../IR/IRNodes/IRLetted.js";
|
|
7
7
|
import { IRNative } from "../../../IR/IRNodes/IRNative/index.js";
|
|
8
8
|
import { IRVar } from "../../../IR/IRNodes/IRVar.js";
|
|
9
|
-
import {
|
|
10
|
-
import { _ir_let, _ir_let_sym } from "../../../IR/tree_utils/_ir_let.js";
|
|
9
|
+
import { _ir_let_sym } from "../../../IR/tree_utils/_ir_let.js";
|
|
11
10
|
import { filterSortedStrArrInplace } from "../../../utils/array/filterSortedStrArrInplace.js";
|
|
12
11
|
import { mergeSortedStrArrInplace } from "../../../utils/array/mergeSortedStrArrInplace.js";
|
|
13
12
|
import { TirSimpleVarDecl } from "../statements/TirVarDecl/TirSimpleVarDecl.js";
|
|
14
13
|
import { TirDataOptT } from "../types/TirNativeType/native/Optional/data.js";
|
|
15
14
|
import { TirSopOptT } from "../types/TirNativeType/native/Optional/sop.js";
|
|
16
15
|
import { TirDataStructType, TirSoPStructType } from "../types/TirStructType.js";
|
|
17
|
-
import {
|
|
16
|
+
import { TirEnumType } from "../types/TirEnumType.js";
|
|
18
17
|
import { getUnaliased } from "../types/utils/getUnaliased.js";
|
|
19
18
|
import { _inlineFromData } from "./TirFromDataExpr.js";
|
|
20
19
|
export class TirCaseExpr {
|
|
@@ -73,13 +72,83 @@ export class TirCaseExpr {
|
|
|
73
72
|
if (matchExprType instanceof TirSoPStructType
|
|
74
73
|
|| matchExprType instanceof TirSopOptT)
|
|
75
74
|
return this._sopStructToIR(matchExprType, ctx);
|
|
75
|
+
if (matchExprType instanceof TirDataStructType
|
|
76
|
+
&& matchExprType.untagged)
|
|
77
|
+
return this._untaggedDataStructToIR(matchExprType, ctx);
|
|
76
78
|
if (matchExprType instanceof TirDataStructType
|
|
77
79
|
|| matchExprType instanceof TirDataOptT)
|
|
78
80
|
return this._dataStructToIR(matchExprType, ctx);
|
|
81
|
+
if (matchExprType instanceof TirEnumType)
|
|
82
|
+
return this._enumToIR(matchExprType, ctx);
|
|
79
83
|
console.error(this);
|
|
80
84
|
throw new Error("`case` expressions are only supported on Sum-of-Products or Data Struct types; got: "
|
|
81
85
|
+ this.matchExpr.type.toString());
|
|
82
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Lowers a `case` over an untagged data struct (single constructor;
|
|
89
|
+
* runtime form is `listData(fields)`). No constructor dispatch is
|
|
90
|
+
* needed — there's only one possible ctor — so the lowering is just
|
|
91
|
+
* "find the matching arm (or wildcard), extract any bound fields, run
|
|
92
|
+
* the body".
|
|
93
|
+
*/
|
|
94
|
+
_untaggedDataStructToIR(matchExprType, ctx) {
|
|
95
|
+
if (matchExprType.constructors.length !== 1) {
|
|
96
|
+
throw new Error("untagged data struct must have exactly one constructor");
|
|
97
|
+
}
|
|
98
|
+
const ctor = matchExprType.constructors[0];
|
|
99
|
+
const wildcardBodyIR = this.wildcardCase?.body.toIR(ctx) ?? new IRError();
|
|
100
|
+
const matchedArm = this.cases.find(c => c.pattern.constrName === ctor.name);
|
|
101
|
+
if (!matchedArm) {
|
|
102
|
+
// no matching arm: just run the wildcard body (the scrutinee is
|
|
103
|
+
// evaluated for side-effects via `unListData` only if any field
|
|
104
|
+
// would have been bound; here, nothing).
|
|
105
|
+
return wildcardBodyIR;
|
|
106
|
+
}
|
|
107
|
+
const pattern = matchedArm.pattern;
|
|
108
|
+
const usedFields = ctor.fields
|
|
109
|
+
.map((f, idx) => ({ name: f.name, type: f.type, idx }))
|
|
110
|
+
.filter(f => pattern.fields.has(f.name));
|
|
111
|
+
// 0 bound fields → just run the body; no extraction.
|
|
112
|
+
if (usedFields.length === 0)
|
|
113
|
+
return matchedArm.body.toIR(ctx);
|
|
114
|
+
// fields-list = unListData(scrutinee), bound once and reused via
|
|
115
|
+
// IRLetted so the let-handling pass elides or shares as appropriate.
|
|
116
|
+
const fieldsListLetted = new IRLetted(Symbol("untaggedFields"), _ir_apps(IRNative.unListData, this.matchExpr.toIR(ctx)));
|
|
117
|
+
const branchCtx = ctx.newChild();
|
|
118
|
+
// bind each used field with a let in declaration order.
|
|
119
|
+
// sort by ctor field index so earlier extractions don't need to
|
|
120
|
+
// re-drop past already-bound fields.
|
|
121
|
+
usedFields.sort((a, b) => a.idx - b.idx);
|
|
122
|
+
const bindings = usedFields.map(f => {
|
|
123
|
+
const varDecl = pattern.fields.get(f.name);
|
|
124
|
+
if (!(varDecl instanceof TirSimpleVarDecl))
|
|
125
|
+
throw new Error("case pattern not expressified.");
|
|
126
|
+
const sym = branchCtx.defineVar(varDecl.name);
|
|
127
|
+
return {
|
|
128
|
+
sym,
|
|
129
|
+
extract: _inlineFromData(f.type, _ir_apps(IRNative.headList, _ir_apps(IRNative.dropList, IRConst.int(f.idx), fieldsListLetted.clone())))
|
|
130
|
+
};
|
|
131
|
+
});
|
|
132
|
+
// build nested let-bindings around the body
|
|
133
|
+
let result = matchedArm.body.toIR(branchCtx);
|
|
134
|
+
for (let i = bindings.length - 1; i >= 0; i--) {
|
|
135
|
+
const { sym, extract } = bindings[i];
|
|
136
|
+
result = _ir_let_sym(sym, extract, result);
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
_enumToIR(enumType, ctx) {
|
|
141
|
+
const wildcardBodyIR = this.wildcardCase?.body.toIR(ctx) ?? new IRError();
|
|
142
|
+
const branches = enumType.members.map(memberName => {
|
|
143
|
+
const branch = this.cases.find(c => c.pattern.constrName === memberName);
|
|
144
|
+
return branch ? branch.body.toIR(ctx) : wildcardBodyIR;
|
|
145
|
+
});
|
|
146
|
+
while (branches.length > 0 && branches[branches.length - 1] instanceof IRError)
|
|
147
|
+
branches.pop();
|
|
148
|
+
return branches.length > 0
|
|
149
|
+
? new IRCase(this.matchExpr.toIR(ctx), branches)
|
|
150
|
+
: new IRError();
|
|
151
|
+
}
|
|
83
152
|
_sopStructToIR(matchExprType, ctx) {
|
|
84
153
|
if (matchExprType instanceof TirSopOptT) {
|
|
85
154
|
const wildcardBodyIR = this.wildcardCase?.body.toIR(ctx) ?? new IRError();
|
|
@@ -172,134 +241,87 @@ export class TirCaseExpr {
|
|
|
172
241
|
return branches.length > 0 ? new IRCase(this.matchExpr.toIR(ctx), branches) : new IRError(); // all branches fail, so the whole expression fails
|
|
173
242
|
}
|
|
174
243
|
_dataStructToIR(matchExprType, ctx) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
)),
|
|
197
|
-
// then Just{ value }
|
|
198
|
-
someBranchIR(unConstrMatchSym),
|
|
199
|
-
// else None
|
|
200
|
-
noneBranchIR));
|
|
201
|
-
}
|
|
202
|
-
// TirDataStructType
|
|
203
|
-
const stmtCtx = ctx.newChild();
|
|
204
|
-
const unConstrStructSym = stmtCtx.pushUnusedVar("unconstrStruct"); // unconstrStruct
|
|
205
|
-
const isConstrIdxSym = stmtCtx.pushUnusedVar("isConstrIdx"); // isConstrIdx
|
|
206
|
-
const noVarsWildcardBodyIR = (this.wildcardCase?.body.toIR(stmtCtx)
|
|
207
|
-
?? new IRError());
|
|
208
|
-
const delayedNoVarWildcardBodyIR = new IRDelayed(noVarsWildcardBodyIR);
|
|
209
|
-
let ifThenElseMatchingStatements = noVarsWildcardBodyIR;
|
|
244
|
+
// TirDataOptT extends TirDataStructType (constructors Some{value}, None{}),
|
|
245
|
+
// so the same logic handles it.
|
|
246
|
+
//
|
|
247
|
+
// Lowering structure (UPLC `Case` accepts pair / int scrutinees
|
|
248
|
+
// as untagged constructors):
|
|
249
|
+
//
|
|
250
|
+
// Case (unConstrData scrutinee) [
|
|
251
|
+
// \idxSym fieldsSym ->
|
|
252
|
+
// Case idxSym [body_0, body_1, ..., body_(maxParent)]
|
|
253
|
+
// ]
|
|
254
|
+
//
|
|
255
|
+
// - The outer `Case` over the `pair(int, list<data>)` returned by
|
|
256
|
+
// `unConstrData` extracts both halves via a single 2-arg branch
|
|
257
|
+
// (pair is treated as `constr 0 [fst, snd]`).
|
|
258
|
+
// - The inner `Case` over `idxSym` dispatches by tag in O(1) —
|
|
259
|
+
// no `equalsInteger` chain, no `lazyIfThenElse`.
|
|
260
|
+
// - Each inner branch takes 0 args (an int N is treated as
|
|
261
|
+
// `constr N []`). The branch body extracts fields lazily from
|
|
262
|
+
// `fieldsSym` via deferred access on `thenCtx`, wrapped in
|
|
263
|
+
// `IRLetted` so the letted-handling pass dedups, inlines or
|
|
264
|
+
// elides as appropriate.
|
|
210
265
|
if (this.cases.some(({ pattern }) => matchExprType.constructors.findIndex(ctor => ctor.name === pattern.constrName) < 0))
|
|
211
266
|
throw new Error("case expression includes unknown constructor.");
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
267
|
+
const stmtCtx = ctx.newChild();
|
|
268
|
+
const wildcardBodyIR = this.wildcardCase?.body.toIR(stmtCtx) ?? new IRError();
|
|
269
|
+
// outer destructuring binders — symbols allocated up-front so
|
|
270
|
+
// per-arm deferred accesses (closures) reference the same syms
|
|
271
|
+
const idxSym = Symbol("ctorIdx");
|
|
272
|
+
const fieldsListSym = Symbol("fieldsList");
|
|
273
|
+
// The runtime value's ctor tag spans all parent indices known to
|
|
274
|
+
// this type — not just the indices that appear as arm patterns.
|
|
275
|
+
// Size the inner-Case branch array to cover all of them and fill
|
|
276
|
+
// missing slots with the wildcard.
|
|
277
|
+
const armsByParentIdx = new Map();
|
|
278
|
+
// TirDataOptT extends TirDataStructType, so both have parentCtorIdx
|
|
279
|
+
const allParentIdxs = matchExprType.constructors.map((_, i) => matchExprType.parentCtorIdx(i));
|
|
280
|
+
let maxParentIdx = allParentIdxs.reduce((m, x) => x > m ? x : m, -1);
|
|
281
|
+
for (const matchCase of this.cases) {
|
|
282
|
+
const { pattern, body } = matchCase;
|
|
219
283
|
const ctorIdx = matchExprType.constructors.findIndex(ctor => ctor.name === pattern.constrName);
|
|
220
|
-
if (ctorIdx < 0)
|
|
221
|
-
throw new Error("case expression includes unknown constructor."); // unreachable
|
|
222
284
|
const ctor = matchExprType.constructors[ctorIdx];
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
body.toIR(stmtCtx),
|
|
235
|
-
// else
|
|
236
|
-
ifThenElseMatchingStatements);
|
|
237
|
-
continue;
|
|
238
|
-
}
|
|
239
|
-
function indexOfField(fieldName) {
|
|
240
|
-
const idx = ctor.fields.findIndex(f => f.name === fieldName);
|
|
241
|
-
if (idx < 0)
|
|
242
|
-
throw new Error("case pattern not expressified.");
|
|
243
|
-
return idx;
|
|
244
|
-
}
|
|
245
|
-
if (usedFieldsCtorNames.length === 1) {
|
|
246
|
-
const thenCtx = stmtCtx.newChild();
|
|
247
|
-
const fName = usedFieldsCtorNames[0];
|
|
285
|
+
const parentCtorIdx = matchExprType instanceof TirDataStructType
|
|
286
|
+
? matchExprType.parentCtorIdx(ctorIdx)
|
|
287
|
+
: ctorIdx;
|
|
288
|
+
// bind each pattern-named field as a deferred access on
|
|
289
|
+
// `fieldsListSym`. Each access produces an `IRLetted`
|
|
290
|
+
// wrapping `_inlineFromData(type, headList(_dropList(idx, fields)))`.
|
|
291
|
+
const armCtx = stmtCtx.newChild();
|
|
292
|
+
const usedFieldsCtorNames = ctor.fields
|
|
293
|
+
.map(f => f.name)
|
|
294
|
+
.filter(fName => pattern.fields.has(fName));
|
|
295
|
+
for (const fName of usedFieldsCtorNames) {
|
|
248
296
|
const patternVarDecl = pattern.fields.get(fName);
|
|
249
297
|
if (!(patternVarDecl instanceof TirSimpleVarDecl))
|
|
250
298
|
throw new Error("case pattern not expressified.");
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
_ir_apps(// fileds as data list
|
|
254
|
-
IRNative.sndPair, new IRVar(unConstrStructSym) // unconstrStruct
|
|
255
|
-
)))), body.toIR(thenCtx));
|
|
256
|
-
ifThenElseMatchingStatements = _ir_lazyIfThenElse(
|
|
257
|
-
// condition (compare against the PARENT ctor index — the
|
|
258
|
-
// value's runtime tag is unaffected by narrowing)
|
|
259
|
-
_ir_apps(new IRVar(isConstrIdxSym), // isConstrIdx
|
|
260
|
-
IRConst.int(matchExprType instanceof TirDataStructType
|
|
261
|
-
? matchExprType.parentCtorIdx(ctorIdx)
|
|
262
|
-
: ctorIdx)),
|
|
263
|
-
// then
|
|
264
|
-
thenCase,
|
|
265
|
-
// else
|
|
266
|
-
ifThenElseMatchingStatements);
|
|
267
|
-
continue;
|
|
268
|
-
} // single field used edge case
|
|
269
|
-
// multiple fields used
|
|
270
|
-
const thenCtx = stmtCtx.newChild();
|
|
271
|
-
const fieldsAsDataList = thenCtx.pushUnusedVar(); // fileds as data list
|
|
272
|
-
const sortedUsedFields = [...usedFieldsCtorNames].sort((a, b) => indexOfField(a) - indexOfField(b));
|
|
273
|
-
const introducedVars = new Array(sortedUsedFields.length);
|
|
274
|
-
for (let fIdx = 0; fIdx < sortedUsedFields.length; fIdx++) {
|
|
275
|
-
const fName = sortedUsedFields[fIdx];
|
|
276
|
-
const patternVarDecl = pattern.fields.get(fName);
|
|
277
|
-
if (!(patternVarDecl instanceof TirSimpleVarDecl))
|
|
299
|
+
const fieldIdx = ctor.fields.findIndex(f => f.name === fName);
|
|
300
|
+
if (fieldIdx < 0)
|
|
278
301
|
throw new Error("case pattern not expressified.");
|
|
279
|
-
|
|
302
|
+
const fieldType = patternVarDecl.type;
|
|
303
|
+
armCtx.defineDeferredAccess(patternVarDecl.name, () => new IRLetted(Symbol(`${ctor.name}_${fName}`), _inlineFromData(fieldType, _ir_apps(IRNative.headList, _ir_apps(IRNative.dropList, IRConst.int(fieldIdx), new IRVar(fieldsListSym))))));
|
|
280
304
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
// condition (compare against the PARENT ctor index — the
|
|
289
|
-
// value's runtime tag is unaffected by narrowing)
|
|
290
|
-
_ir_apps(new IRVar(isConstrIdxSym), // isConstrIdx
|
|
291
|
-
IRConst.int(matchExprType instanceof TirDataStructType
|
|
292
|
-
? matchExprType.parentCtorIdx(ctorIdx)
|
|
293
|
-
: ctorIdx)),
|
|
294
|
-
// then
|
|
295
|
-
thenCase,
|
|
296
|
-
// else
|
|
297
|
-
ifThenElseMatchingStatements);
|
|
305
|
+
armsByParentIdx.set(parentCtorIdx, body.toIR(armCtx));
|
|
306
|
+
}
|
|
307
|
+
// build inner-Case branches sized to `maxParentIdx + 1`, filling
|
|
308
|
+
// missing slots with the wildcard body
|
|
309
|
+
const innerBranches = new Array(maxParentIdx + 1);
|
|
310
|
+
for (let i = 0; i < innerBranches.length; i++) {
|
|
311
|
+
innerBranches[i] = armsByParentIdx.get(i) ?? wildcardBodyIR;
|
|
298
312
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
313
|
+
// trailing `IRError` branches can be omitted — the CEK machine
|
|
314
|
+
// fails naturally if no branch exists for the runtime tag
|
|
315
|
+
while (innerBranches.length > 0
|
|
316
|
+
&& innerBranches[innerBranches.length - 1] instanceof IRError)
|
|
317
|
+
innerBranches.pop();
|
|
318
|
+
const innerCase = innerBranches.length > 0
|
|
319
|
+
? new IRCase(new IRVar(idxSym), innerBranches)
|
|
320
|
+
: new IRError();
|
|
321
|
+
// outer Case over the pair: single branch destructures (idx, fields)
|
|
322
|
+
return new IRCase(_ir_apps(IRNative.unConstrData, this.matchExpr.toIR(ctx)), [
|
|
323
|
+
new IRFunc([idxSym, fieldsListSym], innerCase)
|
|
324
|
+
]);
|
|
303
325
|
}
|
|
304
326
|
}
|
|
305
327
|
export class TirCaseMatcher {
|
|
@@ -44,8 +44,8 @@ export class TirElemAccessExpr {
|
|
|
44
44
|
const result = Machine.evalSimple(compileIRToUPLC(irIndex));
|
|
45
45
|
if ((result instanceof CEKConst)
|
|
46
46
|
&& (typeof result.value === "number" || typeof result.value === "bigint"))
|
|
47
|
-
return _ir_apps(IRNative.headList, _ir_apps(IRNative.
|
|
47
|
+
return _ir_apps(IRNative.headList, _ir_apps(IRNative.dropList, IRConst.int(result.value), irArr));
|
|
48
48
|
}
|
|
49
|
-
return _ir_apps(IRNative.headList, _ir_apps(IRNative.
|
|
49
|
+
return _ir_apps(IRNative.headList, _ir_apps(IRNative.dropList, irIndex, irArr));
|
|
50
50
|
}
|
|
51
51
|
}
|