@harmoniclabs/pebble 0.2.0 → 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.
Files changed (116) hide show
  1. package/dist/IR/CompilationCtx.d.ts +40 -0
  2. package/dist/IR/CompilationCtx.js +54 -0
  3. package/dist/IR/IRHash.d.ts +23 -2
  4. package/dist/IR/IRHash.js +10 -60
  5. package/dist/IR/IRNodes/IRConst.js +22 -2
  6. package/dist/IR/IRNodes/IRHoisted.d.ts +0 -1
  7. package/dist/IR/IRNodes/IRHoisted.js +4 -6
  8. package/dist/IR/IRNodes/IRLetted.d.ts +0 -1
  9. package/dist/IR/IRNodes/IRLetted.js +4 -6
  10. package/dist/IR/IRNodes/IRNative/IRNativeTag.d.ts +22 -2
  11. package/dist/IR/IRNodes/IRNative/IRNativeTag.js +26 -2
  12. package/dist/IR/IRNodes/IRNative/index.d.ts +16 -1
  13. package/dist/IR/IRNodes/IRNative/index.js +27 -2
  14. package/dist/IR/IRNodes/utils/hashVarSym.d.ts +0 -1
  15. package/dist/IR/IRNodes/utils/hashVarSym.js +27 -33
  16. package/dist/IR/toUPLC/CompilerOptions.d.ts +12 -0
  17. package/dist/IR/toUPLC/CompilerOptions.js +14 -9
  18. package/dist/IR/toUPLC/compileIRToUPLC.js +39 -3
  19. package/dist/IR/toUPLC/subRoutines/inlineSingleUseLetBindingsAndReturnRoot.d.ts +23 -0
  20. package/dist/IR/toUPLC/subRoutines/inlineSingleUseLetBindingsAndReturnRoot.js +263 -0
  21. package/dist/IR/toUPLC/subRoutines/introduceCaseForDualHeadTailAndReturnRoot.d.ts +35 -0
  22. package/dist/IR/toUPLC/subRoutines/introduceCaseForDualHeadTailAndReturnRoot.js +169 -0
  23. package/dist/IR/toUPLC/subRoutines/replaceHoistedWithLetted.d.ts +0 -1
  24. package/dist/IR/toUPLC/subRoutines/replaceHoistedWithLetted.js +6 -6
  25. package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.d.ts +2 -3
  26. package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.js +106 -65
  27. package/dist/IR/toUPLC/subRoutines/rewriteHeadTailInCaseConsAndReturnRoot.d.ts +30 -0
  28. package/dist/IR/toUPLC/subRoutines/rewriteHeadTailInCaseConsAndReturnRoot.js +95 -0
  29. package/dist/IR/toUPLC/subRoutines/rewriteNativesAppliedToConstantsAndReturnRoot.js +36 -5
  30. package/dist/IR/toUPLC/subRoutines/rewriteToCaseOverConstAndReturnRoot.d.ts +35 -0
  31. package/dist/IR/toUPLC/subRoutines/rewriteToCaseOverConstAndReturnRoot.js +169 -0
  32. package/dist/IR/tree_utils/_ir_caseList.d.ts +15 -0
  33. package/dist/IR/tree_utils/_ir_caseList.js +19 -0
  34. package/dist/ast/nodes/statements/declarations/StructDecl.d.ts +16 -2
  35. package/dist/ast/nodes/statements/declarations/StructDecl.js +15 -1
  36. package/dist/compiler/AstCompiler/AstCompiler.d.ts +1 -0
  37. package/dist/compiler/AstCompiler/AstCompiler.js +41 -4
  38. package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +3 -3
  39. package/dist/compiler/AstCompiler/internal/exprs/_compileCaseExpr.js +31 -0
  40. package/dist/compiler/AstCompiler/internal/exprs/_compileIsExpr.js +12 -0
  41. package/dist/compiler/AstCompiler/internal/exprs/_compilePropAccessExpr.js +36 -0
  42. package/dist/compiler/AstCompiler/internal/exprs/_compileUnaryPrefixExpr.js +13 -1
  43. package/dist/compiler/AstCompiler/internal/exprs/binary/_compileAddExpr.js +18 -5
  44. package/dist/compiler/AstCompiler/internal/exprs/binary/_compileEqualExpr.js +3 -1
  45. package/dist/compiler/AstCompiler/internal/exprs/binary/_compileGreaterThanEqualExpr.js +2 -1
  46. package/dist/compiler/AstCompiler/internal/exprs/binary/_compileGreaterThanExpr.js +2 -1
  47. package/dist/compiler/AstCompiler/internal/exprs/binary/_compileLessThanEqualExpr.js +2 -1
  48. package/dist/compiler/AstCompiler/internal/exprs/binary/_compileLessThanExpr.js +2 -1
  49. package/dist/compiler/AstCompiler/internal/exprs/binary/_compileMultExpr.js +24 -6
  50. package/dist/compiler/AstCompiler/internal/exprs/binary/_compileNotEqualExpr.js +2 -1
  51. package/dist/compiler/AstCompiler/internal/exprs/binary/_compileSubExpr.js +16 -5
  52. package/dist/compiler/AstCompiler/internal/statements/_compileMatchStmt.js +33 -20
  53. package/dist/compiler/AstCompiler/utils/getPropAccessReturnType.js +11 -0
  54. package/dist/compiler/Compiler.js +20 -27
  55. package/dist/compiler/TirCompiler/expressify/ExpressifyCtx.js +1 -1
  56. package/dist/compiler/TirCompiler/expressify/expressify.js +30 -2
  57. package/dist/compiler/TirCompiler/expressify/expressifyForStmt.d.ts +2 -1
  58. package/dist/compiler/TirCompiler/expressify/expressifyForStmt.js +45 -7
  59. package/dist/compiler/TirCompiler/expressify/expressifyVars.d.ts +0 -1
  60. package/dist/compiler/TirCompiler/expressify/expressifyVars.js +23 -8
  61. package/dist/compiler/tir/expressions/TirCaseExpr.d.ts +9 -0
  62. package/dist/compiler/tir/expressions/TirCaseExpr.js +144 -122
  63. package/dist/compiler/tir/expressions/TirElemAccessExpr.js +2 -2
  64. package/dist/compiler/tir/expressions/TirFromDataExpr.js +102 -67
  65. package/dist/compiler/tir/expressions/TirIsExpr.js +14 -1
  66. package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +1 -2
  67. package/dist/compiler/tir/expressions/TirNativeFunc.js +2 -12
  68. package/dist/compiler/tir/expressions/TirToDataExpr.js +3 -0
  69. package/dist/compiler/tir/expressions/TirTypeConversionExpr.js +10 -0
  70. package/dist/compiler/tir/expressions/TirVariableAccessExpr.d.ts +2 -3
  71. package/dist/compiler/tir/expressions/TirVariableAccessExpr.js +1 -4
  72. package/dist/compiler/tir/expressions/ToIRTermCtx.d.ts +20 -3
  73. package/dist/compiler/tir/expressions/ToIRTermCtx.js +48 -3
  74. package/dist/compiler/tir/expressions/binary/TirBinaryExpr.d.ts +2 -2
  75. package/dist/compiler/tir/expressions/binary/TirBinaryExpr.js +45 -8
  76. package/dist/compiler/tir/expressions/litteral/TirLitEnumMemberExpr.d.ts +19 -0
  77. package/dist/compiler/tir/expressions/litteral/TirLitEnumMemberExpr.js +24 -0
  78. package/dist/compiler/tir/expressions/litteral/TirLitteralExpr.d.ts +2 -1
  79. package/dist/compiler/tir/expressions/litteral/TirLitteralExpr.js +2 -0
  80. package/dist/compiler/tir/expressions/unary/TirUnaryMinus.js +4 -1
  81. package/dist/compiler/tir/program/stdScope/populateStdNamespace.js +49 -4
  82. package/dist/compiler/tir/program/stdScope/prelude/preludeTypesSrc.js +35 -2
  83. package/dist/compiler/tir/program/stdScope/stdScope.d.ts +7 -0
  84. package/dist/compiler/tir/program/stdScope/stdScope.js +83 -40
  85. package/dist/compiler/tir/types/TirEnumType.d.ts +21 -0
  86. package/dist/compiler/tir/types/TirEnumType.js +36 -0
  87. package/dist/compiler/tir/types/TirNativeType/TirNativeType.d.ts +4 -2
  88. package/dist/compiler/tir/types/TirNativeType/TirNativeType.js +5 -0
  89. package/dist/compiler/tir/types/TirNativeType/native/array.d.ts +16 -0
  90. package/dist/compiler/tir/types/TirNativeType/native/array.js +38 -0
  91. package/dist/compiler/tir/types/TirNativeType/native/index.d.ts +2 -0
  92. package/dist/compiler/tir/types/TirNativeType/native/index.js +2 -0
  93. package/dist/compiler/tir/types/TirNativeType/native/value.d.ts +18 -0
  94. package/dist/compiler/tir/types/TirNativeType/native/value.js +17 -0
  95. package/dist/compiler/tir/types/TirStructType.js +6 -1
  96. package/dist/compiler/tir/types/TirType.d.ts +3 -2
  97. package/dist/compiler/tir/types/TirType.js +4 -1
  98. package/dist/compiler/tir/types/utils/canAssignTo.js +28 -0
  99. package/dist/compiler/tir/types/utils/canCastTo.js +14 -1
  100. package/dist/compiler/tir/types/utils/getDeconstructableType.d.ts +2 -1
  101. package/dist/compiler/tir/types/utils/getDeconstructableType.js +2 -0
  102. package/dist/compiler/tir/types/utils/inferTypeArgs.js +4 -0
  103. package/dist/compiler/tir/types/utils/normalizeEnumToInt.d.ts +10 -0
  104. package/dist/compiler/tir/types/utils/normalizeEnumToInt.js +17 -0
  105. package/dist/compiler/tir/types/utils/substituteTypeParams.js +5 -0
  106. package/dist/diagnostics/diagnosticMessages.generated.d.ts +5 -0
  107. package/dist/diagnostics/diagnosticMessages.generated.js +10 -0
  108. package/dist/parser/Parser.js +29 -13
  109. package/dist/tokenizer/Token.d.ts +8 -7
  110. package/dist/tokenizer/Token.js +8 -7
  111. package/dist/tokenizer/utils/tokenFromKeyword.js +2 -0
  112. package/dist/version.generated.d.ts +1 -1
  113. package/dist/version.generated.js +1 -1
  114. package/package.json +3 -3
  115. package/dist/IR/tree_utils/_ir_lazyChooseList.d.ts +0 -3
  116. 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
- const cached = _hoisted_cache.get(term.hash)?.deref();
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
- _hoisted_cache.set(term.hash, new WeakRef(letted));
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 { _ir_lazyChooseList } from "../../../tree_utils/_ir_lazyChooseList.js";
16
+ import { _ir_caseList } from "../../../tree_utils/_ir_caseList.js";
17
17
  import { _ir_lazyIfThenElse } from "../../../tree_utils/_ir_lazyIfThenElse.js";
18
- import { hoisted_drop4, hoisted_drop2, hoisted_drop3 } from "../_comptimeDropN.js";
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
- export const hoisted_recursiveList = new IRHoisted(new IRFunc([recList_matchNil, recList_matchCons], new IRRecursive(recList_self, new IRFunc([recList_lst], _ir_apps(hoisted_matchList.clone(), new IRApp(new IRVar(recList_matchNil), new IRSelfCall(recList_self)), new IRApp(new IRVar(recList_matchCons), new IRSelfCall(recList_self)), new IRVar(recList_lst))))));
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(new IRRecursive(self_length, new IRFunc([length_list_sym], _ir_lazyChooseList(new IRVar(length_list_sym), IRConst.int(0), _ir_apps(hoisted_incr.clone(), new IRApp(new IRSelfCall(self_length), // self
93
- new IRApp(IRNative.tailList, new IRVar(length_list_sym) // list
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
- // REPLACED hoisted_dropList (was numeric arity + dbn)
97
- const drop_self = Symbol("drop_self");
98
- const drop_n = Symbol("n");
99
- const drop_lst = Symbol("lst");
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], _ir_apps(hoisted_matchList.clone(), new IRDelayed(new IRVar(foldl_acc)), 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))))))));
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], _ir_lazyChooseList(new IRVar(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], _ir_lazyChooseList(new IRVar(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
- export const hoisted_mkFindDataOptional = new IRHoisted(new IRFunc([mkFind_elemToData, mkFind_pred], new IRRecursive(mkFind_self, new IRFunc([mkFind_list], new IRForced(_ir_apps(new IRApp(IRNative.strictChooseList, new IRVar(mkFind_list)), new IRDelayed(IRConst.data(new DataConstr(1, []))), new IRDelayed(new IRApp(new IRFunc([mkFind_head], new IRForced(_ir_apps(IRNative.strictIfThenElse, new IRApp(new IRVar(mkFind_pred), new IRVar(mkFind_head)), new IRDelayed(_ir_apps(IRNative.constrData, IRConst.int(0), new IRApp(new IRVar(mkFind_elemToData), new IRVar(mkFind_head)))), new IRDelayed(new IRApp(new IRSelfCall(mkFind_self), new IRApp(IRNative.tailList, new IRVar(mkFind_list))))))), new IRApp(IRNative.headList, new IRVar(mkFind_list))))))))));
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], _ir_lazyChooseList(new IRVar(some_lst), IRConst.bool(false), // case nil => false
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], _ir_lazyChooseList(new IRVar(every_lst), IRConst.bool(true), // case nil => true
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], _ir_lazyChooseList(new IRVar(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], _ir_lazyChooseList(new IRVar(eqList_listA),
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
- _ir_lazyChooseList(new IRVar(eqList_listB),
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], _ir_lazyChooseList(new IRVar(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
- new IRForced(_ir_apps(IRNative.strictChooseList, new IRVar(amount_value),
352
- // case nil: return (tokenName => 0)
353
- new IRDelayed(new IRFunc([amount_isTokenName], IRConst.int(0))),
354
- // case cons
355
- new IRDelayed(_ir_let(_ir_apps(IRNative.headList, new IRVar(amount_value)), pairDataSym => new IRForced(_ir_apps(IRNative.strictIfThenElse,
356
- // isPolicy( fst pairData as bytes )
357
- _ir_apps(new IRVar(amount_isPolicy), _ir_apps(IRNative.unBData, _ir_apps(IRNative.fstPair, new IRVar(pairDataSym)))),
358
- // then: build (tokenName => amount)
359
- new IRDelayed(new IRFunc([amount_isTokenName], _ir_apps(new IRRecursive(amount_tokenNameLoop, new IRFunc([amount_tokenMap], new IRForced(_ir_apps(IRNative.strictChooseList, new IRVar(amount_tokenMap),
360
- // token map empty => 0
361
- new IRDelayed(IRConst.int(0)),
362
- // token map cons
363
- new IRDelayed(_ir_let(_ir_apps(IRNative.headList, new IRVar(amount_tokenMap)), pairDataTokenSym => new IRForced(_ir_apps(IRNative.strictIfThenElse,
364
- // isTokenName( fst pairDataToken as bytes )
365
- _ir_apps(new IRVar(amount_isTokenName), _ir_apps(IRNative.unBData, _ir_apps(IRNative.fstPair, new IRVar(pairDataTokenSym)))),
366
- // then: return amount
367
- new IRDelayed(_ir_apps(IRNative.unIData, _ir_apps(IRNative.sndPair, new IRVar(pairDataTokenSym)))),
368
- // else: recurse tail
369
- new IRDelayed(_ir_apps(new IRSelfCall(amount_tokenNameLoop), _ir_apps(IRNative.tailList, new IRVar(amount_tokenMap) // tokenMap list
370
- ))))))))))),
371
- // pass token map (snd pairData)
372
- _ir_apps(IRNative.unMapData, _ir_apps(IRNative.sndPair, new IRVar(pairDataSym)))))),
373
- // else: recurse policyLoop on tail value list
374
- new IRDelayed(_ir_apps(new IRSelfCall(amount_policyLoop), _ir_apps(IRNative.tailList, new IRVar(amount_value))))))))))))));
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
- // replace with isNullList
129
- const newTerm = _ir_apps(IRNative.strictChooseList, listTerm, thenArg, elseArg);
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
- // replace with isListLength
141
- const newTerm = _ir_apps(IRNative.strictChooseList, listTerm, thenArg, elseArg);
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._dropList);
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;