@harmoniclabs/pebble 0.2.0 → 0.3.1
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 +22 -2
- 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 +27 -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 +12 -0
- package/dist/IR/toUPLC/CompilerOptions.js +14 -9
- 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/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 +1 -0
- package/dist/compiler/AstCompiler/AstCompiler.js +41 -4
- package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +3 -3
- package/dist/compiler/AstCompiler/internal/exprs/_compileCallExpr.js +57 -10
- package/dist/compiler/AstCompiler/internal/exprs/_compileCaseExpr.js +31 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileIsExpr.js +12 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compilePropAccessExpr.js +36 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileUnaryPrefixExpr.js +13 -1
- 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/utils/getPropAccessReturnType.js +11 -0
- package/dist/compiler/Compiler.js +20 -27
- 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 +23 -8
- 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/TirFromDataExpr.js +102 -67
- package/dist/compiler/tir/expressions/TirIsExpr.js +14 -1
- package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +1 -2
- package/dist/compiler/tir/expressions/TirNativeFunc.js +2 -12
- package/dist/compiler/tir/expressions/TirToDataExpr.js +3 -0
- 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/stdScope/populateStdNamespace.js +49 -4
- package/dist/compiler/tir/program/stdScope/prelude/preludeTypesSrc.js +35 -2
- package/dist/compiler/tir/program/stdScope/stdScope.d.ts +7 -0
- package/dist/compiler/tir/program/stdScope/stdScope.js +83 -40
- 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 +4 -2
- package/dist/compiler/tir/types/TirNativeType/TirNativeType.js +5 -0
- 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 +4 -1
- package/dist/compiler/tir/types/utils/canAssignTo.js +28 -0
- 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.js +4 -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.js +5 -0
- package/dist/diagnostics/diagnosticMessages.generated.d.ts +5 -0
- package/dist/diagnostics/diagnosticMessages.generated.js +10 -0
- package/dist/parser/Parser.js +29 -13
- package/dist/tokenizer/Token.d.ts +8 -7
- package/dist/tokenizer/Token.js +8 -7
- package/dist/tokenizer/utils/tokenFromKeyword.js +2 -0
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/package.json +3 -3
- package/dist/IR/tree_utils/_ir_lazyChooseList.d.ts +0 -3
- package/dist/IR/tree_utils/_ir_lazyChooseList.js +0 -7
|
@@ -1,10 +1,7 @@
|
|
|
1
|
+
import { currentCompilationCtx } from "../../CompilationCtx.js";
|
|
1
2
|
import { IRHoisted } from "../../IRNodes/IRHoisted.js";
|
|
2
3
|
import { IRLetted } from "../../IRNodes/IRLetted.js";
|
|
3
4
|
import { _modifyChildFromTo } from "../_internal/_modifyChildFromTo.js";
|
|
4
|
-
const _hoisted_cache = new Map();
|
|
5
|
-
export function __unsafe_clear_hoisted_cache() {
|
|
6
|
-
_hoisted_cache.clear();
|
|
7
|
-
}
|
|
8
5
|
export function replaceHoistedWithLetted(term) {
|
|
9
6
|
// children first
|
|
10
7
|
const children = term.children();
|
|
@@ -16,11 +13,14 @@ export function replaceHoistedWithLetted(term) {
|
|
|
16
13
|
const parent = term.parent;
|
|
17
14
|
if (!parent)
|
|
18
15
|
throw new Error("hoisted node has no parent");
|
|
19
|
-
|
|
16
|
+
// per-compilation cache: maps a hoisted term's content hash to the
|
|
17
|
+
// letted node it lowers to, so repeated occurrences share one binder.
|
|
18
|
+
const hoistedCache = currentCompilationCtx().hoistedCache;
|
|
19
|
+
const cached = hoistedCache.get(term.hash)?.deref();
|
|
20
20
|
const letted = (cached ??
|
|
21
21
|
new IRLetted(term.name, term.hoisted, { isClosed: true })).clone();
|
|
22
22
|
if (!cached)
|
|
23
|
-
|
|
23
|
+
hoistedCache.set(term.hash, new WeakRef(letted));
|
|
24
24
|
// replace hoisted with letted
|
|
25
25
|
_modifyChildFromTo(parent, term, letted);
|
|
26
26
|
}
|
|
@@ -8,20 +8,19 @@ export declare const hoisted_decr: IRHoisted;
|
|
|
8
8
|
export declare const hoisted_isZero: IRHoisted;
|
|
9
9
|
export declare const hoisted_isOne: IRHoisted;
|
|
10
10
|
export declare const hoisted_isTwo: IRHoisted;
|
|
11
|
+
export declare const hoisted_negateValue: IRHoisted;
|
|
12
|
+
export declare const hoisted_valueEq: IRHoisted;
|
|
11
13
|
export declare const hoisted_isThree: IRHoisted;
|
|
12
14
|
export declare const hoisted_addOne: IRHoisted;
|
|
13
15
|
export declare const hoisted_subOne: IRHoisted;
|
|
14
16
|
export declare const hoisted_negateInteger: IRHoisted;
|
|
15
17
|
export declare const hoisted_isPositive: IRHoisted;
|
|
16
18
|
export declare const hoisted_isNonNegative: IRHoisted;
|
|
17
|
-
export declare const hoisted_matchList: IRHoisted;
|
|
18
19
|
export declare const hoisted_recursiveList: IRHoisted;
|
|
19
20
|
export declare const hoisted_foldr: IRHoisted;
|
|
20
|
-
export declare const hosited_lazyChooseList: IRHoisted;
|
|
21
21
|
export declare const hoisted_isMoreThanOrEqualTo4: IRHoisted;
|
|
22
22
|
export declare const hoisted_sub4: IRHoisted;
|
|
23
23
|
export declare const hoisted_length: IRHoisted;
|
|
24
|
-
export declare const hoisted_dropList: IRHoisted;
|
|
25
24
|
export declare const hoisted_findSopOptional: IRHoisted;
|
|
26
25
|
export declare const hoisted_lookupLinearMap: IRHoisted;
|
|
27
26
|
export declare const hoisted_mkFindDataOptional: IRHoisted;
|
|
@@ -13,10 +13,9 @@ import { IRSelfCall } from "../../../IRNodes/IRSelfCall.js";
|
|
|
13
13
|
import { IRError } from "../../../IRNodes/IRError.js";
|
|
14
14
|
import { _ir_apps } from "../../../IRNodes/IRApp.js";
|
|
15
15
|
import { _ir_let, _ir_let_sym } from "../../../tree_utils/_ir_let.js";
|
|
16
|
-
import {
|
|
16
|
+
import { _ir_caseList } from "../../../tree_utils/_ir_caseList.js";
|
|
17
17
|
import { _ir_lazyIfThenElse } from "../../../tree_utils/_ir_lazyIfThenElse.js";
|
|
18
|
-
import {
|
|
19
|
-
import { IRConstr } from "../../../IRNodes/index.js";
|
|
18
|
+
import { IRCase, IRConstr } from "../../../IRNodes/index.js";
|
|
20
19
|
import { _ir_and, _ir_or } from "../../../../compiler/tir/expressions/binary/TirBinaryExpr.js";
|
|
21
20
|
function _ir_strictAnd(left, right) {
|
|
22
21
|
return _ir_apps(IRNative.strictIfThenElse, left, right, IRConst.bool(false));
|
|
@@ -39,6 +38,22 @@ export const hoisted_isOne = new IRHoisted(new IRApp(IRNative.equalsInteger, IRC
|
|
|
39
38
|
hoisted_isZero.hash;
|
|
40
39
|
export const hoisted_isTwo = new IRHoisted(new IRApp(IRNative.equalsInteger, IRConst.int(2)));
|
|
41
40
|
hoisted_isTwo.hash;
|
|
41
|
+
// negateValue = (scaleValue -1)
|
|
42
|
+
// the scaleValue builtin is `(int, Value) -> Value`; partially applying
|
|
43
|
+
// -1 yields a unary `Value -> Value` negation. Cheaper than running a
|
|
44
|
+
// user-level multiply over the entire map.
|
|
45
|
+
export const hoisted_negateValue = new IRHoisted(new IRApp(IRNative.scaleValue, IRConst.int(-1)));
|
|
46
|
+
hoisted_negateValue.hash;
|
|
47
|
+
// valueEq a b = if valueContains(a, b) then valueContains(b, a) else false
|
|
48
|
+
// Bidirectional containment is equality for canonical Values (the
|
|
49
|
+
// only form the runtime ever produces). Short-circuits on the first
|
|
50
|
+
// non-containment to save the second `valueContains` traversal.
|
|
51
|
+
export const hoisted_valueEq = new IRHoisted((() => {
|
|
52
|
+
const a = Symbol("valueEq_a");
|
|
53
|
+
const b = Symbol("valueEq_b");
|
|
54
|
+
return new IRFunc([a, b], _ir_lazyIfThenElse(_ir_apps(IRNative.valueContains, new IRVar(a), new IRVar(b)), _ir_apps(IRNative.valueContains, new IRVar(b), new IRVar(a)), IRConst.bool(false)));
|
|
55
|
+
})());
|
|
56
|
+
hoisted_valueEq.hash;
|
|
42
57
|
export const hoisted_isThree = new IRHoisted(new IRApp(IRNative.equalsInteger, IRConst.int(3)));
|
|
43
58
|
export const hoisted_addOne = new IRHoisted(new IRApp(IRNative.addInteger, IRConst.int(1)));
|
|
44
59
|
hoisted_addOne.hash;
|
|
@@ -50,22 +65,24 @@ export const hoisted_isPositive = new IRHoisted(new IRApp(IRNative.lessThanInteg
|
|
|
50
65
|
hoisted_isPositive.hash;
|
|
51
66
|
export const hoisted_isNonNegative = new IRHoisted(new IRApp(IRNative.lessThanEqualInteger, IRConst.int(0)));
|
|
52
67
|
hoisted_isNonNegative.hash;
|
|
53
|
-
export const hoisted_matchList = new IRHoisted((() => {
|
|
54
|
-
const delayed_matchNil = Symbol("delayed_matchNil");
|
|
55
|
-
const matchCons = Symbol("matchCons");
|
|
56
|
-
const list = Symbol("list");
|
|
57
|
-
return new IRFunc([delayed_matchNil, matchCons, list], new IRForced(new IRForced(_ir_apps(IRNative.strictChooseList, new IRVar(list), new IRVar(delayed_matchNil), new IRDelayed(_ir_apps(new IRVar(matchCons), new IRApp(IRNative.headList, new IRVar(list)), new IRApp(IRNative.tailList, new IRVar(list))))))));
|
|
58
|
-
})());
|
|
59
|
-
hoisted_matchList.hash;
|
|
60
|
-
//*
|
|
61
68
|
// hoisted_recursiveList (needed by hoisted_foldr)
|
|
69
|
+
// λ matchNil matchCons → recurse self → λ lst →
|
|
70
|
+
// case lst of
|
|
71
|
+
// cons h t -> (matchCons self) h t
|
|
72
|
+
// nil -> force (matchNil self)
|
|
73
|
+
// `matchNil` is expected to return a delayed value (so it can close over
|
|
74
|
+
// recursive state without forcing eagerly); the nil branch forces it.
|
|
62
75
|
const recList_matchNil = Symbol("matchNil");
|
|
63
76
|
const recList_matchCons = Symbol("matchCons");
|
|
64
77
|
const recList_self = Symbol("recursiveList_self");
|
|
65
78
|
const recList_lst = Symbol("lst");
|
|
66
|
-
|
|
79
|
+
const recList_h = Symbol("h");
|
|
80
|
+
const recList_t = Symbol("t");
|
|
81
|
+
export const hoisted_recursiveList = new IRHoisted(new IRFunc([recList_matchNil, recList_matchCons], new IRRecursive(recList_self, new IRFunc([recList_lst], new IRCase(new IRVar(recList_lst), [
|
|
82
|
+
new IRFunc([recList_h, recList_t], _ir_apps(new IRApp(new IRVar(recList_matchCons), new IRSelfCall(recList_self)), new IRVar(recList_h), new IRVar(recList_t))),
|
|
83
|
+
new IRForced(new IRApp(new IRVar(recList_matchNil), new IRSelfCall(recList_self)))
|
|
84
|
+
])))));
|
|
67
85
|
hoisted_recursiveList.hash;
|
|
68
|
-
//*/
|
|
69
86
|
// hoisted_foldr
|
|
70
87
|
const foldr_reducer = Symbol("reduceFunc");
|
|
71
88
|
const foldr_acc = Symbol("accumulator");
|
|
@@ -75,36 +92,49 @@ const foldr_head = Symbol("head");
|
|
|
75
92
|
const foldr_tail = Symbol("tail");
|
|
76
93
|
export const hoisted_foldr = new IRHoisted(new IRFunc([foldr_reducer, foldr_acc], _ir_apps(hoisted_recursiveList.clone(), new IRFunc([foldr__dummy], new IRDelayed(new IRVar(foldr_acc))), new IRFunc([foldr_self, foldr_head, foldr_tail], _ir_apps(new IRVar(foldr_reducer), new IRVar(foldr_head), new IRApp(new IRVar(foldr_self), new IRVar(foldr_tail)))))));
|
|
77
94
|
hoisted_foldr.hash;
|
|
78
|
-
export const hosited_lazyChooseList = new IRHoisted((() => {
|
|
79
|
-
const list = Symbol("list");
|
|
80
|
-
const delayed_caseNil = Symbol("delayed_caseNil");
|
|
81
|
-
const delayed_caseCons = Symbol("delayed_caseCons");
|
|
82
|
-
return new IRFunc([list, delayed_caseNil, delayed_caseCons], new IRForced(_ir_apps(IRNative.strictChooseList, new IRVar(list), new IRVar(delayed_caseNil), new IRVar(delayed_caseCons))));
|
|
83
|
-
})());
|
|
84
|
-
hosited_lazyChooseList.hash;
|
|
85
|
-
//*/
|
|
86
95
|
export const hoisted_isMoreThanOrEqualTo4 = new IRHoisted(_ir_apps(IRNative.lessThanInteger, IRConst.int(4)));
|
|
87
96
|
hoisted_isMoreThanOrEqualTo4.hash;
|
|
88
97
|
export const hoisted_sub4 = new IRHoisted(_ir_apps(IRNative.addInteger, IRConst.int(-4)));
|
|
89
98
|
hoisted_sub4.hash;
|
|
90
99
|
const self_length = Symbol("self_length");
|
|
91
100
|
const length_list_sym = Symbol("length_list_sym");
|
|
92
|
-
export const hoisted_length = new IRHoisted(
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
export const hoisted_length = new IRHoisted(
|
|
102
|
+
// new IRRecursive(
|
|
103
|
+
// self_length,
|
|
104
|
+
// new IRFunc(
|
|
105
|
+
// [ length_list_sym ],
|
|
106
|
+
// _ir_caseList(
|
|
107
|
+
// new IRVar( length_list_sym ),
|
|
108
|
+
// IRConst.int( 0 ),
|
|
109
|
+
// _ir_apps(
|
|
110
|
+
// hoisted_incr.clone(),
|
|
111
|
+
// new IRApp(
|
|
112
|
+
// new IRSelfCall( self_length ), // self
|
|
113
|
+
// new IRApp(
|
|
114
|
+
// IRNative.tailList,
|
|
115
|
+
// new IRVar( length_list_sym ) // list
|
|
116
|
+
// )
|
|
117
|
+
// )
|
|
118
|
+
// )
|
|
119
|
+
// )
|
|
120
|
+
// )
|
|
121
|
+
// )
|
|
122
|
+
new IRFunc([length_list_sym], _ir_apps(IRNative.lengthOfArray, _ir_apps(IRNative.listToArray, new IRVar(length_list_sym)))));
|
|
95
123
|
hoisted_length.hash;
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
export const hoisted_dropList = new IRHoisted(new IRRecursive(drop_self, new IRFunc([drop_n, drop_lst], _ir_lazyIfThenElse(_ir_apps(hoisted_isMoreThanOrEqualTo4.clone(), new IRVar(drop_n)), _ir_apps(new IRSelfCall(drop_self), _ir_apps(hoisted_sub4.clone(), new IRVar(drop_n)), _ir_apps(hoisted_drop4.clone(), new IRVar(drop_lst))), _ir_lazyIfThenElse(_ir_apps(hoisted_isZero.clone(), new IRVar(drop_n)), new IRVar(drop_lst), _ir_lazyIfThenElse(_ir_apps(hoisted_isOne.clone(), new IRVar(drop_n)), _ir_apps(IRNative.tailList, new IRVar(drop_lst)), _ir_lazyIfThenElse(_ir_apps(hoisted_isTwo.clone(), new IRVar(drop_n)), _ir_apps(hoisted_drop2.clone(), new IRVar(drop_lst)), _ir_apps(hoisted_drop3.clone(), new IRVar(drop_lst)))))))));
|
|
101
|
-
hoisted_dropList.hash;
|
|
124
|
+
// λ reduce → recurse self → λ acc → λ list →
|
|
125
|
+
// case list of
|
|
126
|
+
// cons h t -> self (reduce acc h) t
|
|
127
|
+
// nil -> acc
|
|
102
128
|
const foldl_reduce = Symbol("reduceFunc");
|
|
103
129
|
const foldl_self = Symbol("foldl_self");
|
|
104
130
|
const foldl_acc = Symbol("accum");
|
|
131
|
+
const foldl_list = Symbol("list");
|
|
105
132
|
const foldl_head = Symbol("head");
|
|
106
133
|
const foldl_tail = Symbol("tail");
|
|
107
|
-
const hoiseted_foldl = new IRHoisted(new IRFunc([foldl_reduce], new IRRecursive(foldl_self, new IRFunc([foldl_acc
|
|
134
|
+
const hoiseted_foldl = new IRHoisted(new IRFunc([foldl_reduce], new IRRecursive(foldl_self, new IRFunc([foldl_acc, foldl_list], new IRCase(new IRVar(foldl_list), [
|
|
135
|
+
new IRFunc([foldl_head, foldl_tail], _ir_apps(new IRSelfCall(foldl_self), _ir_apps(new IRVar(foldl_reduce), new IRVar(foldl_acc), new IRVar(foldl_head)), new IRVar(foldl_tail))),
|
|
136
|
+
new IRVar(foldl_acc)
|
|
137
|
+
])))));
|
|
108
138
|
hoiseted_foldl.hash;
|
|
109
139
|
// hoisted _findSopOptional
|
|
110
140
|
// (predicate: (a -> Bool)) -> (list: [a]) -> Optional<a>
|
|
@@ -112,7 +142,7 @@ const findSop_predicate = Symbol("predicate");
|
|
|
112
142
|
const findSop_self = Symbol("findOpt_self");
|
|
113
143
|
const findSop_list = Symbol("list");
|
|
114
144
|
const findSop_head = Symbol("head");
|
|
115
|
-
export const hoisted_findSopOptional = new IRHoisted(new IRFunc([findSop_predicate], new IRRecursive(findSop_self, new IRFunc([findSop_list],
|
|
145
|
+
export const hoisted_findSopOptional = new IRHoisted(new IRFunc([findSop_predicate], new IRRecursive(findSop_self, new IRFunc([findSop_list], _ir_caseList(new IRVar(findSop_list),
|
|
116
146
|
// case nil
|
|
117
147
|
new IRConstr(1, []), // None
|
|
118
148
|
// case cons
|
|
@@ -128,7 +158,7 @@ const lookup_key = Symbol("lookup_key");
|
|
|
128
158
|
const lookup_self = Symbol("lookup_self");
|
|
129
159
|
const lookup_map = Symbol("lookup_map");
|
|
130
160
|
const lookup_head = Symbol("lookup_head");
|
|
131
|
-
export const hoisted_lookupLinearMap = new IRHoisted(new IRFunc([lookup_key], new IRRecursive(lookup_self, new IRFunc([lookup_map],
|
|
161
|
+
export const hoisted_lookupLinearMap = new IRHoisted(new IRFunc([lookup_key], new IRRecursive(lookup_self, new IRFunc([lookup_map], _ir_caseList(new IRVar(lookup_map),
|
|
132
162
|
// case nil => None
|
|
133
163
|
new IRConstr(1, []),
|
|
134
164
|
// case cons
|
|
@@ -146,7 +176,11 @@ const mkFind_pred = Symbol("predicate");
|
|
|
146
176
|
const mkFind_self = Symbol("findOpt_self");
|
|
147
177
|
const mkFind_list = Symbol("list");
|
|
148
178
|
const mkFind_head = Symbol("head");
|
|
149
|
-
|
|
179
|
+
const mkFind_tail = Symbol("tail");
|
|
180
|
+
export const hoisted_mkFindDataOptional = new IRHoisted(new IRFunc([mkFind_elemToData, mkFind_pred], new IRRecursive(mkFind_self, new IRFunc([mkFind_list], new IRCase(new IRVar(mkFind_list), [
|
|
181
|
+
new IRFunc([mkFind_head, mkFind_tail], _ir_lazyIfThenElse(new IRApp(new IRVar(mkFind_pred), new IRVar(mkFind_head)), _ir_apps(IRNative.constrData, IRConst.int(0), new IRApp(new IRVar(mkFind_elemToData), new IRVar(mkFind_head))), new IRApp(new IRSelfCall(mkFind_self), new IRVar(mkFind_tail)))),
|
|
182
|
+
IRConst.data(new DataConstr(1, []))
|
|
183
|
+
])))));
|
|
150
184
|
hoisted_mkFindDataOptional.hash;
|
|
151
185
|
// hoisted strictAnd / strictOr
|
|
152
186
|
const strictAnd_a = Symbol("a");
|
|
@@ -161,7 +195,7 @@ hoisted_strictOr.hash;
|
|
|
161
195
|
const some_pred = Symbol("predicate");
|
|
162
196
|
const some_lst = Symbol("lst");
|
|
163
197
|
const some_self = Symbol("self");
|
|
164
|
-
export const hoisted_some = new IRHoisted(new IRFunc([some_pred], new IRRecursive(some_self, new IRFunc([some_lst],
|
|
198
|
+
export const hoisted_some = new IRHoisted(new IRFunc([some_pred], new IRRecursive(some_self, new IRFunc([some_lst], _ir_caseList(new IRVar(some_lst), IRConst.bool(false), // case nil => false
|
|
165
199
|
_ir_or(
|
|
166
200
|
// either predicate(head) is true
|
|
167
201
|
_ir_apps(new IRVar(some_pred), new IRApp(IRNative.headList, new IRVar(some_lst))),
|
|
@@ -172,7 +206,7 @@ hoisted_some.hash;
|
|
|
172
206
|
const every_pred = Symbol("predicate");
|
|
173
207
|
const every_self = Symbol("self");
|
|
174
208
|
const every_lst = Symbol("lst");
|
|
175
|
-
export const hoisted_every = new IRHoisted(new IRFunc([every_pred], new IRRecursive(every_self, new IRFunc([every_lst],
|
|
209
|
+
export const hoisted_every = new IRHoisted(new IRFunc([every_pred], new IRRecursive(every_self, new IRFunc([every_lst], _ir_caseList(new IRVar(every_lst), IRConst.bool(true), // case nil => true
|
|
176
210
|
_ir_and(
|
|
177
211
|
// both predicate(head) is true
|
|
178
212
|
_ir_apps(new IRVar(every_pred), new IRApp(IRNative.headList, new IRVar(every_lst))),
|
|
@@ -184,7 +218,7 @@ const filt_pred = Symbol("predicate");
|
|
|
184
218
|
const filt_self = Symbol("filter_self");
|
|
185
219
|
const filt_list = Symbol("list");
|
|
186
220
|
const filt_elem = Symbol("elem");
|
|
187
|
-
export const hoisted_filter = new IRHoisted(new IRFunc([filt_pred], new IRRecursive(filt_self, new IRFunc([filt_list],
|
|
221
|
+
export const hoisted_filter = new IRHoisted(new IRFunc([filt_pred], new IRRecursive(filt_self, new IRFunc([filt_list], _ir_caseList(new IRVar(filt_list),
|
|
188
222
|
// case nil
|
|
189
223
|
new IRVar(filt_list), // nil
|
|
190
224
|
// case cons
|
|
@@ -285,7 +319,7 @@ export function nativeToIR(native) {
|
|
|
285
319
|
case IRNativeTag._isZero: return hoisted_isZero.clone();
|
|
286
320
|
case IRNativeTag._sortedValueLovelaces: return hoisted_sortedValueLovelaces.clone();
|
|
287
321
|
case IRNativeTag._getCredentialsHash: return hoisted_getCredentialsHash.clone();
|
|
288
|
-
case IRNativeTag._dropList: return hoisted_dropList.clone();
|
|
322
|
+
// case IRNativeTag._dropList: return hoisted_dropList.clone();
|
|
289
323
|
case IRNativeTag._mkMapList: return hoisted_mkMapList.clone();
|
|
290
324
|
case IRNativeTag._increment: return hoisted_addOne.clone();
|
|
291
325
|
case IRNativeTag._decrement: return hoisted_subOne.clone();
|
|
@@ -295,6 +329,8 @@ export function nativeToIR(native) {
|
|
|
295
329
|
case IRNativeTag._mkEqualsList: return hoisted_mkEqualsList.clone();
|
|
296
330
|
case IRNativeTag._negateInt: return hoisted_negateInteger.clone();
|
|
297
331
|
case IRNativeTag._lookupLinearMap: return hoisted_lookupLinearMap.clone();
|
|
332
|
+
case IRNativeTag._negateValue: return hoisted_negateValue.clone();
|
|
333
|
+
case IRNativeTag._valueEq: return hoisted_valueEq.clone();
|
|
298
334
|
// case IRNativeTag._mkEqualsList: return hoisted_mkEqualsList.clone();
|
|
299
335
|
default:
|
|
300
336
|
throw new Error("unknown (negative) native calling 'nativeToIR'; " +
|
|
@@ -306,11 +342,11 @@ const eqList_eqFunc = Symbol("elemEq");
|
|
|
306
342
|
const eqList_self = Symbol("eqList_self");
|
|
307
343
|
const eqList_listA = Symbol("listA");
|
|
308
344
|
const eqList_listB = Symbol("listB");
|
|
309
|
-
export const hoisted_mkEqualsList = new IRHoisted(new IRFunc([eqList_eqFunc], new IRRecursive(eqList_self, new IRFunc([eqList_listA, eqList_listB],
|
|
345
|
+
export const hoisted_mkEqualsList = new IRHoisted(new IRFunc([eqList_eqFunc], new IRRecursive(eqList_self, new IRFunc([eqList_listA, eqList_listB], _ir_caseList(new IRVar(eqList_listA),
|
|
310
346
|
// case nil: check if listB is also nil
|
|
311
347
|
_ir_apps(IRNative.nullList, new IRVar(eqList_listB)),
|
|
312
348
|
// case cons
|
|
313
|
-
|
|
349
|
+
_ir_caseList(new IRVar(eqList_listB),
|
|
314
350
|
// listB is nil => false
|
|
315
351
|
IRConst.bool(false),
|
|
316
352
|
// both lists are cons
|
|
@@ -321,7 +357,7 @@ const mkMap_nil = Symbol("nilOfType");
|
|
|
321
357
|
const mkMap_mapFunc = Symbol("mapFunc");
|
|
322
358
|
const mkMap_map = Symbol("map_self");
|
|
323
359
|
const mkMap_list = Symbol("list");
|
|
324
|
-
export const hoisted_mkMapList = new IRHoisted(new IRFunc([mkMap_nil, mkMap_mapFunc], new IRRecursive(mkMap_map, new IRFunc([mkMap_list],
|
|
360
|
+
export const hoisted_mkMapList = new IRHoisted(new IRFunc([mkMap_nil, mkMap_mapFunc], new IRRecursive(mkMap_map, new IRFunc([mkMap_list], _ir_caseList(new IRVar(mkMap_list),
|
|
325
361
|
// case nil: return nil of type
|
|
326
362
|
new IRVar(mkMap_nil),
|
|
327
363
|
// case cons
|
|
@@ -348,28 +384,33 @@ const amount_tokenNameLoop = Symbol("tokenNameLoop_self");
|
|
|
348
384
|
const amount_tokenMap = Symbol("tokenMap");
|
|
349
385
|
export const hoisted_amountOfValue = new IRHoisted(new IRFunc([amount_isPolicy], // (policy => bool)
|
|
350
386
|
new IRRecursive(amount_policyLoop, new IRFunc([amount_value], // value
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
//
|
|
359
|
-
|
|
360
|
-
//
|
|
361
|
-
new
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
387
|
+
(() => {
|
|
388
|
+
const valHead = Symbol("valHead");
|
|
389
|
+
const valTail = Symbol("valTail");
|
|
390
|
+
const tokHead = Symbol("tokHead");
|
|
391
|
+
const tokTail = Symbol("tokTail");
|
|
392
|
+
return new IRCase(new IRVar(amount_value), [
|
|
393
|
+
new IRFunc([valHead, valTail], _ir_lazyIfThenElse(
|
|
394
|
+
// isPolicy( unBData( fst valHead ) )
|
|
395
|
+
_ir_apps(new IRVar(amount_isPolicy), _ir_apps(IRNative.unBData, _ir_apps(IRNative.fstPair, new IRVar(valHead)))),
|
|
396
|
+
// then: build (tokenName => amount)
|
|
397
|
+
new IRFunc([amount_isTokenName], _ir_apps(new IRRecursive(amount_tokenNameLoop, new IRFunc([amount_tokenMap], new IRCase(new IRVar(amount_tokenMap), [
|
|
398
|
+
new IRFunc([tokHead, tokTail], _ir_lazyIfThenElse(
|
|
399
|
+
// isTokenName( unBData( fst tokHead ) )
|
|
400
|
+
_ir_apps(new IRVar(amount_isTokenName), _ir_apps(IRNative.unBData, _ir_apps(IRNative.fstPair, new IRVar(tokHead)))),
|
|
401
|
+
// then: return amount
|
|
402
|
+
_ir_apps(IRNative.unIData, _ir_apps(IRNative.sndPair, new IRVar(tokHead))),
|
|
403
|
+
// else: recurse on tokTail
|
|
404
|
+
_ir_apps(new IRSelfCall(amount_tokenNameLoop), new IRVar(tokTail)))),
|
|
405
|
+
// token map empty => 0
|
|
406
|
+
IRConst.int(0)
|
|
407
|
+
]))),
|
|
408
|
+
// pass token map (unMapData( snd valHead ))
|
|
409
|
+
_ir_apps(IRNative.unMapData, _ir_apps(IRNative.sndPair, new IRVar(valHead))))),
|
|
410
|
+
// else: recurse policyLoop on valTail
|
|
411
|
+
_ir_apps(new IRSelfCall(amount_policyLoop), new IRVar(valTail)))),
|
|
412
|
+
// case nil: return (tokenName => 0)
|
|
413
|
+
new IRFunc([amount_isTokenName], IRConst.int(0))
|
|
414
|
+
]);
|
|
415
|
+
})()))));
|
|
375
416
|
hoisted_amountOfValue.hash;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `case L of cons h t -> body | nil -> ...` already binds the list's head
|
|
3
|
+
* and tail to `h` and `t` in the cons branch. If `body` then re-extracts
|
|
4
|
+
* them via `headList(L)` / `tailList(L)`, those calls are redundant — the
|
|
5
|
+
* values are already in scope. This pass walks every `IRCase` whose
|
|
6
|
+
* scrutinee is a plain `IRVar(L)` and substitutes those head/tail calls
|
|
7
|
+
* inside the cons branch with `IRVar(h)` / `IRVar(t)`.
|
|
8
|
+
*
|
|
9
|
+
* Concretely, this turns
|
|
10
|
+
*
|
|
11
|
+
* case body_xs of
|
|
12
|
+
* cons body_xs_head body_xs_tail ->
|
|
13
|
+
* ... headList(body_xs) ... tailList(body_xs) ...
|
|
14
|
+
*
|
|
15
|
+
* into
|
|
16
|
+
*
|
|
17
|
+
* case body_xs of
|
|
18
|
+
* cons body_xs_head body_xs_tail ->
|
|
19
|
+
* ... body_xs_head ... body_xs_tail ...
|
|
20
|
+
*
|
|
21
|
+
* which (combined with `removeUnusedVarsAndReturnRoot`) drops the
|
|
22
|
+
* `(force headList) body_xs` / `(force tailList) body_xs` builtin
|
|
23
|
+
* applications entirely when the originally-bound `h`/`t` were unused.
|
|
24
|
+
*
|
|
25
|
+
* Substitution stops at any nested `IRFunc`/`IRRecursive` whose params
|
|
26
|
+
* shadow `L`, `h`, or `t` — those re-bindings would otherwise let us
|
|
27
|
+
* silently substitute a stale outer scope.
|
|
28
|
+
*/
|
|
29
|
+
import { IRTerm } from "../../IRTerm.js";
|
|
30
|
+
export declare function rewriteHeadTailInCaseConsAndReturnRoot(term: IRTerm): IRTerm;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `case L of cons h t -> body | nil -> ...` already binds the list's head
|
|
3
|
+
* and tail to `h` and `t` in the cons branch. If `body` then re-extracts
|
|
4
|
+
* them via `headList(L)` / `tailList(L)`, those calls are redundant — the
|
|
5
|
+
* values are already in scope. This pass walks every `IRCase` whose
|
|
6
|
+
* scrutinee is a plain `IRVar(L)` and substitutes those head/tail calls
|
|
7
|
+
* inside the cons branch with `IRVar(h)` / `IRVar(t)`.
|
|
8
|
+
*
|
|
9
|
+
* Concretely, this turns
|
|
10
|
+
*
|
|
11
|
+
* case body_xs of
|
|
12
|
+
* cons body_xs_head body_xs_tail ->
|
|
13
|
+
* ... headList(body_xs) ... tailList(body_xs) ...
|
|
14
|
+
*
|
|
15
|
+
* into
|
|
16
|
+
*
|
|
17
|
+
* case body_xs of
|
|
18
|
+
* cons body_xs_head body_xs_tail ->
|
|
19
|
+
* ... body_xs_head ... body_xs_tail ...
|
|
20
|
+
*
|
|
21
|
+
* which (combined with `removeUnusedVarsAndReturnRoot`) drops the
|
|
22
|
+
* `(force headList) body_xs` / `(force tailList) body_xs` builtin
|
|
23
|
+
* applications entirely when the originally-bound `h`/`t` were unused.
|
|
24
|
+
*
|
|
25
|
+
* Substitution stops at any nested `IRFunc`/`IRRecursive` whose params
|
|
26
|
+
* shadow `L`, `h`, or `t` — those re-bindings would otherwise let us
|
|
27
|
+
* silently substitute a stale outer scope.
|
|
28
|
+
*/
|
|
29
|
+
import { IRApp } from "../../IRNodes/IRApp.js";
|
|
30
|
+
import { IRCase } from "../../IRNodes/IRCase.js";
|
|
31
|
+
import { IRFunc } from "../../IRNodes/IRFunc.js";
|
|
32
|
+
import { IRHoisted } from "../../IRNodes/IRHoisted.js";
|
|
33
|
+
import { IRLetted } from "../../IRNodes/IRLetted.js";
|
|
34
|
+
import { IRNative } from "../../IRNodes/IRNative/index.js";
|
|
35
|
+
import { IRNativeTag } from "../../IRNodes/IRNative/IRNativeTag.js";
|
|
36
|
+
import { IRRecursive } from "../../IRNodes/IRRecursive.js";
|
|
37
|
+
import { IRVar } from "../../IRNodes/IRVar.js";
|
|
38
|
+
import { _modifyChildFromTo } from "../_internal/_modifyChildFromTo.js";
|
|
39
|
+
function unwrap(t) {
|
|
40
|
+
while (t instanceof IRHoisted)
|
|
41
|
+
t = t.hoisted;
|
|
42
|
+
while (t instanceof IRLetted)
|
|
43
|
+
t = t.value;
|
|
44
|
+
return t;
|
|
45
|
+
}
|
|
46
|
+
export function rewriteHeadTailInCaseConsAndReturnRoot(term) {
|
|
47
|
+
const stack = [term];
|
|
48
|
+
while (stack.length > 0) {
|
|
49
|
+
const t = stack.pop();
|
|
50
|
+
if (t instanceof IRCase) {
|
|
51
|
+
const scrutinee = t.constrTerm;
|
|
52
|
+
const consBranch = t.continuations[0];
|
|
53
|
+
if (scrutinee instanceof IRVar
|
|
54
|
+
&& consBranch instanceof IRFunc
|
|
55
|
+
&& consBranch.params.length === 2) {
|
|
56
|
+
const listSym = scrutinee.name;
|
|
57
|
+
const [hSym, tSym] = consBranch.params;
|
|
58
|
+
substituteHeadTailInBody(consBranch.body, listSym, hSym, tSym);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
stack.push(...t.children());
|
|
62
|
+
}
|
|
63
|
+
return term;
|
|
64
|
+
}
|
|
65
|
+
function substituteHeadTailInBody(root, listSym, hSym, tSym) {
|
|
66
|
+
const stack = [root];
|
|
67
|
+
while (stack.length > 0) {
|
|
68
|
+
const t = stack.pop();
|
|
69
|
+
// Stop at a fresh binding that would shadow any of the symbols
|
|
70
|
+
// we're substituting for (extremely rare but cheap to guard).
|
|
71
|
+
if (t instanceof IRFunc || t instanceof IRRecursive) {
|
|
72
|
+
const params = t instanceof IRFunc ? t.params : [t.name];
|
|
73
|
+
if (params.includes(listSym)
|
|
74
|
+
|| params.includes(hSym)
|
|
75
|
+
|| params.includes(tSym))
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (t instanceof IRApp) {
|
|
79
|
+
const fn = unwrap(t.fn);
|
|
80
|
+
const arg = t.arg;
|
|
81
|
+
if (fn instanceof IRNative
|
|
82
|
+
&& (fn.tag === IRNativeTag.headList || fn.tag === IRNativeTag.tailList)
|
|
83
|
+
&& arg instanceof IRVar
|
|
84
|
+
&& arg.name === listSym) {
|
|
85
|
+
const newSym = fn.tag === IRNativeTag.headList ? hSym : tSym;
|
|
86
|
+
const parent = t.parent;
|
|
87
|
+
if (parent !== undefined) {
|
|
88
|
+
_modifyChildFromTo(parent, t, new IRVar(newSym));
|
|
89
|
+
}
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
stack.push(...t.children());
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TirBoolT, TirIntT } from "../../../compiler/tir/types/TirNativeType/index.js";
|
|
2
2
|
import { equalIrHash } from "../../IRHash.js";
|
|
3
3
|
import { _ir_apps } from "../../IRNodes/IRApp.js";
|
|
4
|
+
import { IRCase } from "../../IRNodes/IRCase.js";
|
|
4
5
|
import { IRConst } from "../../IRNodes/IRConst.js";
|
|
5
6
|
import { IRFunc } from "../../IRNodes/IRFunc.js";
|
|
6
7
|
import { IRHoisted } from "../../IRNodes/IRHoisted.js";
|
|
@@ -125,8 +126,14 @@ export function rewriteNativesAppliedToConstantsAndReturnRoot(term) {
|
|
|
125
126
|
if (isListLength(eqZeroArgFunc)
|
|
126
127
|
&& eqZeroArgArgs.length === 1) {
|
|
127
128
|
const listTerm = eqZeroArgArgs[0];
|
|
128
|
-
//
|
|
129
|
-
|
|
129
|
+
// if( list.length() === 0 ) thenArg else elseArg
|
|
130
|
+
// → case list of cons _h _t -> elseArg ; nil -> thenArg
|
|
131
|
+
const dh = Symbol("_h");
|
|
132
|
+
const dt = Symbol("_t");
|
|
133
|
+
const newTerm = new IRCase(listTerm, [
|
|
134
|
+
new IRFunc([dh, dt], elseArg),
|
|
135
|
+
thenArg
|
|
136
|
+
]);
|
|
130
137
|
modifyTermAndPushToReprocess(current, newTerm);
|
|
131
138
|
continue;
|
|
132
139
|
}
|
|
@@ -137,8 +144,14 @@ export function rewriteNativesAppliedToConstantsAndReturnRoot(term) {
|
|
|
137
144
|
else if (isNullList(condFunc)
|
|
138
145
|
&& condArgs.length === 1) {
|
|
139
146
|
const listTerm = condArgs[0];
|
|
140
|
-
//
|
|
141
|
-
|
|
147
|
+
// if( nullList(list) ) thenArg else elseArg
|
|
148
|
+
// → case list of cons _h _t -> elseArg ; nil -> thenArg
|
|
149
|
+
const dh = Symbol("_h");
|
|
150
|
+
const dt = Symbol("_t");
|
|
151
|
+
const newTerm = new IRCase(listTerm, [
|
|
152
|
+
new IRFunc([dh, dt], elseArg),
|
|
153
|
+
thenArg
|
|
154
|
+
]);
|
|
142
155
|
modifyTermAndPushToReprocess(current, newTerm);
|
|
143
156
|
continue;
|
|
144
157
|
} // if( x.isEmpty() )
|
|
@@ -227,6 +240,24 @@ export function rewriteNativesAppliedToConstantsAndReturnRoot(term) {
|
|
|
227
240
|
continue;
|
|
228
241
|
}
|
|
229
242
|
}
|
|
243
|
+
else if (tag === IRNativeTag.strictChooseList
|
|
244
|
+
&& restArgs.length === 2) {
|
|
245
|
+
// strictChooseList list caseNil caseCons
|
|
246
|
+
// → case list of (λ_h _t → caseCons) | caseNil
|
|
247
|
+
// IRCase branches are naturally lazy, so wrapping caseNil/
|
|
248
|
+
// caseCons in delay/force is unnecessary at the call site.
|
|
249
|
+
const listTerm = fstArg;
|
|
250
|
+
const caseNil = restArgs[0];
|
|
251
|
+
const caseCons = restArgs[1];
|
|
252
|
+
const dh = Symbol("_h");
|
|
253
|
+
const dt = Symbol("_t");
|
|
254
|
+
const newTerm = new IRCase(listTerm, [
|
|
255
|
+
new IRFunc([dh, dt], caseCons),
|
|
256
|
+
caseNil
|
|
257
|
+
]);
|
|
258
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
230
261
|
}
|
|
231
262
|
// only optimizations if first argument is constant after this point
|
|
232
263
|
if (!(fstArg instanceof IRConst)) {
|
|
@@ -254,7 +285,7 @@ function isDropList(term) {
|
|
|
254
285
|
term = term.value;
|
|
255
286
|
}
|
|
256
287
|
return (term instanceof IRNative
|
|
257
|
-
&& term.tag === IRNativeTag.
|
|
288
|
+
&& term.tag === IRNativeTag.dropList);
|
|
258
289
|
}
|
|
259
290
|
function isId(term) {
|
|
260
291
|
while (term instanceof IRHoisted
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Case-over-Const lowering pass.
|
|
3
|
+
*
|
|
4
|
+
* The UPLC `Case` term accepts a constant scrutinee and reinterprets it
|
|
5
|
+
* as a tag-untagged constructor (bool → 0/1, int N → N, unit → 0,
|
|
6
|
+
* pair → constr 0 [fst, snd], list → constr 1 [] for `[]` or
|
|
7
|
+
* constr 0 [head, tail] for cons).
|
|
8
|
+
*
|
|
9
|
+
* This pass replaces canonical `strictIfThenElse(cond, then, else)`
|
|
10
|
+
* sequences with the equivalent `IRCase(cond, [else, then])` form. The
|
|
11
|
+
* machine resolves bool=false → constr 0, bool=true → constr 1.
|
|
12
|
+
* This subsumes the strict boolean helpers (`_not`, `_strictAnd`,
|
|
13
|
+
* `_strictOr`) whose hoisted bodies are themselves `strictIfThenElse`
|
|
14
|
+
* triple-apps — they get lowered inside their hoisted definitions.
|
|
15
|
+
*
|
|
16
|
+
* It also replaces the LAZY pattern emitted by `_ir_lazyIfThenElse`:
|
|
17
|
+
*
|
|
18
|
+
* IRForced( strictIfThenElse cond (delay t) (delay e) )
|
|
19
|
+
*
|
|
20
|
+
* — which is how `&&`, `||` and pebble `if/else` are encoded today —
|
|
21
|
+
* with `IRCase(cond, [e, t])`. Branches under `Case` are naturally
|
|
22
|
+
* lazy, so the surrounding `force`/`delay` indirection is dropped.
|
|
23
|
+
*
|
|
24
|
+
* It also prunes trailing IRError continuations: a missing branch is
|
|
25
|
+
* semantically equivalent to an evaluation-failure branch, so dropping a
|
|
26
|
+
* trailing `IRError` reduces script size while preserving meaning.
|
|
27
|
+
*
|
|
28
|
+
* NOTE: `getApplicationTerms` sees through both raw `IRApp` chains AND
|
|
29
|
+
* the case-constr-app encoding produced earlier in `performUplc…`
|
|
30
|
+
* (i.e. `IRCase(IRConstr(0, [args]), [func])`). We therefore check the
|
|
31
|
+
* app-pattern *before* the IRCase trailing-error pruning so that a case
|
|
32
|
+
* that's really a function call gets unwrapped first.
|
|
33
|
+
*/
|
|
34
|
+
import { IRTerm } from "../../IRTerm.js";
|
|
35
|
+
export declare function rewriteToCaseOverConstAndReturnRoot(term: IRTerm): IRTerm;
|