@harmoniclabs/pebble 0.1.2 → 0.1.3-dev1
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/IRNodes/IRConst.js +4 -6
- package/dist/IR/toUPLC/compileIRToUPLC.js +2 -0
- package/dist/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/ensureProperlyForcedBuiltinsAndReturnRoot.d.ts +2 -0
- package/dist/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/ensureProperlyForcedBuiltinsAndReturnRoot.js +163 -0
- package/dist/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/performUplcOptimizationsAndReturnRoot.js +12 -2
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.d.ts +1 -0
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.js +26 -10
- package/dist/compiler/AstCompiler/AstCompiler.js +6 -0
- package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +5 -1
- package/dist/compiler/Compiler.d.ts +1 -0
- package/dist/compiler/Compiler.js +5 -11
- package/dist/compiler/TirCompiler/expressify/ExpressifyCtx.js +7 -3
- package/dist/compiler/tir/expressions/TirNativeFunc.js +3 -3
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/parser/Parser.js +7 -0
- package/dist/parser/parseFile.d.ts +4 -2
- package/dist/parser/parseFile.js +8 -1
- package/package.json +7 -10
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Pair } from "@harmoniclabs/pair";
|
|
2
1
|
import { isData, dataToCbor } from "@harmoniclabs/plutus-data";
|
|
3
2
|
import { fromUtf8, toHex } from "@harmoniclabs/uint8array-utils";
|
|
4
3
|
import { BasePlutsError } from "../../utils/BasePlutsError.js";
|
|
@@ -11,7 +10,7 @@ import { TirAliasType } from "../../compiler/tir/types/TirAliasType.js";
|
|
|
11
10
|
import { TirDataStructType, TirSoPStructType } from "../../compiler/tir/types/TirStructType.js";
|
|
12
11
|
import { getListTypeArg } from "../../compiler/tir/types/utils/getListTypeArg.js";
|
|
13
12
|
import { TirTypeParam } from "../../compiler/tir/types/TirTypeParam.js";
|
|
14
|
-
import { constT, UPLCConst } from "@harmoniclabs/uplc";
|
|
13
|
+
import { constT, isPair, UPLCConst } from "@harmoniclabs/uplc";
|
|
15
14
|
import { TirPairDataT, TirUnConstrDataResultT } from "../../compiler/tir/types/TirNativeType/index.js";
|
|
16
15
|
import { TirBoolT } from "../../compiler/tir/types/TirNativeType/native/bool.js";
|
|
17
16
|
import { TirBytesT } from "../../compiler/tir/types/TirNativeType/native/bytes.js";
|
|
@@ -25,10 +24,9 @@ import { TirSopOptT } from "../../compiler/tir/types/TirNativeType/native/Option
|
|
|
25
24
|
import { TirStringT } from "../../compiler/tir/types/TirNativeType/native/string.js";
|
|
26
25
|
import { TirVoidT } from "../../compiler/tir/types/TirNativeType/native/void.js";
|
|
27
26
|
import { hashIrData, isIRHash } from "../IRHash.js";
|
|
28
|
-
import { ByteString } from "@harmoniclabs/bytestring";
|
|
29
27
|
import { UPLCFlatUtils } from "../../utils/UPLCFlatUtils/index.js";
|
|
30
28
|
export function isIRConstPair(value) {
|
|
31
|
-
return (value
|
|
29
|
+
return (isPair(value) &&
|
|
32
30
|
isIRConstValue(value.fst) &&
|
|
33
31
|
isIRConstValue(value.snd));
|
|
34
32
|
}
|
|
@@ -65,7 +63,7 @@ export class IRConst {
|
|
|
65
63
|
const type = getUnaliased(this.type);
|
|
66
64
|
if (type instanceof TirBytesT && this.value instanceof Uint8Array) {
|
|
67
65
|
// make a copy to prevent external mutation
|
|
68
|
-
return new UPLCConst(tirTypeToUplcType(type),
|
|
66
|
+
return new UPLCConst(tirTypeToUplcType(type), this.value);
|
|
69
67
|
}
|
|
70
68
|
return new UPLCConst(tirTypeToUplcType(type), this.value);
|
|
71
69
|
}
|
|
@@ -215,7 +213,7 @@ function serializeIRConstValue(value, type) {
|
|
|
215
213
|
if (type instanceof TirDataT
|
|
216
214
|
|| type instanceof TirDataOptT
|
|
217
215
|
|| type instanceof TirDataStructType)
|
|
218
|
-
return dataToCbor(value)
|
|
216
|
+
return dataToCbor(value);
|
|
219
217
|
if (type instanceof TirFuncT
|
|
220
218
|
|| type instanceof TirSopOptT
|
|
221
219
|
|| type instanceof TirSoPStructType
|
|
@@ -20,6 +20,7 @@ import { _debug_assertClosedIR } from "../utils/index.js";
|
|
|
20
20
|
import { ToUplcCtx } from "./ctx/ToUplcCtx.js";
|
|
21
21
|
import { removeUnusedVarsAndReturnRoot } from "./subRoutines/removeUnusuedVarsAndReturnRoot/removeUnusuedVarsAndReturnRoot.js";
|
|
22
22
|
import { IRRecursive } from "../IRNodes/IRRecursive.js";
|
|
23
|
+
import { ensureProperlyForcedBuiltinsAndReturnRoot } from "./subRoutines/performUplcOptimizationsAndReturnRoot/ensureProperlyForcedBuiltinsAndReturnRoot.js";
|
|
23
24
|
export function compileIRToUPLC(term, paritalOptions = defaultOptions) {
|
|
24
25
|
// most of the time we are just compiling small
|
|
25
26
|
// pre-execuded terms (hence constants)
|
|
@@ -144,6 +145,7 @@ export function compileIRToUPLC(term, paritalOptions = defaultOptions) {
|
|
|
144
145
|
// }
|
|
145
146
|
term = removeUnusedVarsAndReturnRoot(term);
|
|
146
147
|
term = performUplcOptimizationsAndReturnRoot(term, options);
|
|
148
|
+
term = ensureProperlyForcedBuiltinsAndReturnRoot(term);
|
|
147
149
|
if (options.addMarker &&
|
|
148
150
|
options.targetUplcVersion.major >= 1 &&
|
|
149
151
|
options.targetUplcVersion.minor >= 1 &&
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { IRConstr, IRNative } from "../../../IRNodes/index.js";
|
|
2
|
+
import { IRApp } from "../../../IRNodes/IRApp.js";
|
|
3
|
+
import { IRCase } from "../../../IRNodes/IRCase.js";
|
|
4
|
+
import { IRForced } from "../../../IRNodes/IRForced.js";
|
|
5
|
+
import { IRFunc } from "../../../IRNodes/IRFunc.js";
|
|
6
|
+
import { IRHoisted } from "../../../IRNodes/IRHoisted.js";
|
|
7
|
+
import { IRLetted } from "../../../IRNodes/IRLetted.js";
|
|
8
|
+
import { IRRecursive } from "../../../IRNodes/IRRecursive.js";
|
|
9
|
+
import { IRSelfCall } from "../../../IRNodes/IRSelfCall.js";
|
|
10
|
+
import { IRVar } from "../../../IRNodes/IRVar.js";
|
|
11
|
+
import { _modifyChildFromTo } from "../../_internal/_modifyChildFromTo.js";
|
|
12
|
+
import { getApplicationTerms } from "../../utils/getApplicationTerms.js";
|
|
13
|
+
import { getUnboundedVars } from "../handleLetted/groupByScope.js";
|
|
14
|
+
import { getNRequiredForces } from "@harmoniclabs/uplc";
|
|
15
|
+
export function ensureProperlyForcedBuiltinsAndReturnRoot(root) {
|
|
16
|
+
// const opts = options.uplcOptimizations;
|
|
17
|
+
// if( isDebugUplcOptimizations( opts ) ) return root;
|
|
18
|
+
// const {
|
|
19
|
+
// groupApplications,
|
|
20
|
+
// inlineSingleUse: shouldInlineSingleUse,
|
|
21
|
+
// simplifyWrappedPartialFuncApps,
|
|
22
|
+
// removeForceDelay
|
|
23
|
+
// } = opts;
|
|
24
|
+
const stack = [root];
|
|
25
|
+
let t = root;
|
|
26
|
+
while (t = stack.pop()) {
|
|
27
|
+
if (t instanceof IRNative) {
|
|
28
|
+
const expectedForces = getNRequiredForces(t.tag);
|
|
29
|
+
if (expectedForces <= 0)
|
|
30
|
+
continue;
|
|
31
|
+
let newNode = t;
|
|
32
|
+
let nDirectForces = 0;
|
|
33
|
+
// save the original parent before walking up through existing forces
|
|
34
|
+
// and before creating new IRForced wrappers (whose constructors
|
|
35
|
+
// overwrite the child's parent pointer)
|
|
36
|
+
const originalParent = t.parent;
|
|
37
|
+
while (t.parent instanceof IRForced) {
|
|
38
|
+
nDirectForces++;
|
|
39
|
+
t = t.parent;
|
|
40
|
+
}
|
|
41
|
+
if (nDirectForces === expectedForces)
|
|
42
|
+
continue;
|
|
43
|
+
// when nDirectForces > 0, t has walked up to the topmost IRForced;
|
|
44
|
+
// save its parent before wrapping overwrites parent pointers
|
|
45
|
+
const replaceInParent = nDirectForces > 0 ? t.parent : originalParent;
|
|
46
|
+
for (let i = 0; i < expectedForces - nDirectForces; i++) {
|
|
47
|
+
newNode = new IRForced(newNode);
|
|
48
|
+
}
|
|
49
|
+
if (replaceInParent)
|
|
50
|
+
_modifyChildFromTo(replaceInParent, t, newNode);
|
|
51
|
+
else
|
|
52
|
+
root = newNode;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (t instanceof IRRecursive ||
|
|
56
|
+
t instanceof IRHoisted ||
|
|
57
|
+
t instanceof IRLetted ||
|
|
58
|
+
t instanceof IRSelfCall)
|
|
59
|
+
throw new Error("Unexpected term while performing uplc optimizations");
|
|
60
|
+
stack.push(...t.children());
|
|
61
|
+
}
|
|
62
|
+
return root;
|
|
63
|
+
}
|
|
64
|
+
function isIdLike(term) {
|
|
65
|
+
return (term instanceof IRFunc &&
|
|
66
|
+
term.params.length === 1 &&
|
|
67
|
+
term.body instanceof IRVar &&
|
|
68
|
+
term.body.name === term.params[0]);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
*
|
|
72
|
+
* @returns either an object containing the new root, sorted args and next body
|
|
73
|
+
* or undefined if grouping wasnt possible (root is the same)
|
|
74
|
+
*/
|
|
75
|
+
function groupIndependentApplications(root) {
|
|
76
|
+
const parent = root.parent;
|
|
77
|
+
let applicaitonTerms = getApplicationTerms(root);
|
|
78
|
+
if (!applicaitonTerms)
|
|
79
|
+
return undefined;
|
|
80
|
+
let { func, args } = applicaitonTerms;
|
|
81
|
+
if (!(func instanceof IRFunc))
|
|
82
|
+
return undefined;
|
|
83
|
+
const params = func.params.slice();
|
|
84
|
+
while (true) {
|
|
85
|
+
applicaitonTerms = getApplicationTerms(func.body);
|
|
86
|
+
if (!applicaitonTerms)
|
|
87
|
+
break;
|
|
88
|
+
if (!(applicaitonTerms.func instanceof IRFunc))
|
|
89
|
+
break;
|
|
90
|
+
func = applicaitonTerms.func;
|
|
91
|
+
params.push(...func.params);
|
|
92
|
+
args.push(...applicaitonTerms.args);
|
|
93
|
+
if (params.length !== args.length)
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
const len = Math.min(params.length, args.length);
|
|
97
|
+
const finalParams = params.slice(len);
|
|
98
|
+
const finalArgs = args.slice(len);
|
|
99
|
+
params.length = len;
|
|
100
|
+
args.length = len;
|
|
101
|
+
const paramToArg = {};
|
|
102
|
+
for (let i = 0; i < len; i++) {
|
|
103
|
+
const p = params[i];
|
|
104
|
+
paramToArg[p] = args[i];
|
|
105
|
+
}
|
|
106
|
+
const globalUnbound = getUnboundedVars(root);
|
|
107
|
+
const groups = [[]];
|
|
108
|
+
for (let i = 0; i < len; i++) {
|
|
109
|
+
const p = params[i];
|
|
110
|
+
const arg = args[i];
|
|
111
|
+
const unbound = getUnboundedVars(arg, globalUnbound);
|
|
112
|
+
let highestIdx = -1;
|
|
113
|
+
for (let j = groups.length - 1; j >= 0; j--) {
|
|
114
|
+
const group = groups[j];
|
|
115
|
+
if (group.some(sym => unbound.has(sym))) {
|
|
116
|
+
highestIdx = j;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (highestIdx === groups.length - 1) {
|
|
121
|
+
groups.push([p]);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
groups[highestIdx + 1].push(p);
|
|
125
|
+
}
|
|
126
|
+
groups[groups.length - 1].push(...finalParams);
|
|
127
|
+
const sortedArgs = new Array(len);
|
|
128
|
+
const soretedParams = groups.flat();
|
|
129
|
+
for (let i = 0; i < len; i++) {
|
|
130
|
+
const p = soretedParams[i];
|
|
131
|
+
sortedArgs[i] = paramToArg[p];
|
|
132
|
+
}
|
|
133
|
+
let nextBody = func.body;
|
|
134
|
+
if (finalArgs.length > 0) {
|
|
135
|
+
if (finalArgs.length === 1) {
|
|
136
|
+
nextBody = new IRApp(nextBody, finalArgs[0]);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
nextBody = new IRCase(new IRConstr(0, finalArgs), [nextBody]);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
let newTerm = nextBody;
|
|
143
|
+
for (let i = groups.length - 1; i >= 0; i--) {
|
|
144
|
+
const group = groups[i];
|
|
145
|
+
if (group.length === 1) {
|
|
146
|
+
newTerm = new IRApp(new IRFunc(group, newTerm), paramToArg[group[0]]);
|
|
147
|
+
}
|
|
148
|
+
else if (group.length <= 0)
|
|
149
|
+
continue;
|
|
150
|
+
else {
|
|
151
|
+
newTerm = new IRCase(new IRConstr(0, group.map(p => paramToArg[p])), [new IRFunc(group, newTerm)]);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (parent)
|
|
155
|
+
_modifyChildFromTo(parent, root, newTerm);
|
|
156
|
+
else
|
|
157
|
+
root = newTerm;
|
|
158
|
+
return {
|
|
159
|
+
newRoot: !parent ? root : undefined,
|
|
160
|
+
args: sortedArgs,
|
|
161
|
+
nextBody
|
|
162
|
+
};
|
|
163
|
+
}
|
|
@@ -89,6 +89,10 @@ function groupIndependentApplications(root) {
|
|
|
89
89
|
if (!(func instanceof IRFunc))
|
|
90
90
|
return undefined;
|
|
91
91
|
const params = func.params.slice();
|
|
92
|
+
// Separate excess outer args: getApplicationTerms may return more args
|
|
93
|
+
// than func.params (e.g. `(λp. body)(arg1)(arg2)` → 2 args, 1 param).
|
|
94
|
+
// Excess args are trailing applications applied after all param bindings.
|
|
95
|
+
const trailingArgs = args.splice(params.length);
|
|
92
96
|
while (true) {
|
|
93
97
|
applicaitonTerms = getApplicationTerms(func.body);
|
|
94
98
|
if (!applicaitonTerms)
|
|
@@ -96,14 +100,20 @@ function groupIndependentApplications(root) {
|
|
|
96
100
|
if (!(applicaitonTerms.func instanceof IRFunc))
|
|
97
101
|
break;
|
|
98
102
|
func = applicaitonTerms.func;
|
|
103
|
+
const nNewParams = func.params.length;
|
|
104
|
+
const innerArgs = applicaitonTerms.args;
|
|
99
105
|
params.push(...func.params);
|
|
100
|
-
args.push(...
|
|
106
|
+
args.push(...innerArgs.slice(0, nNewParams));
|
|
107
|
+
// Inner excess args are applied before outer excess args
|
|
108
|
+
if (innerArgs.length > nNewParams) {
|
|
109
|
+
trailingArgs.unshift(...innerArgs.slice(nNewParams));
|
|
110
|
+
}
|
|
101
111
|
if (params.length !== args.length)
|
|
102
112
|
break;
|
|
103
113
|
}
|
|
104
114
|
const len = Math.min(params.length, args.length);
|
|
105
115
|
const finalParams = params.slice(len);
|
|
106
|
-
const finalArgs = args.slice(len);
|
|
116
|
+
const finalArgs = [...args.slice(len), ...trailingArgs];
|
|
107
117
|
params.length = len;
|
|
108
118
|
args.length = len;
|
|
109
119
|
const paramToArg = {};
|
|
@@ -11,6 +11,7 @@ export declare const hoisted_isTwo: IRHoisted;
|
|
|
11
11
|
export declare const hoisted_isThree: IRHoisted;
|
|
12
12
|
export declare const hoisted_addOne: IRHoisted;
|
|
13
13
|
export declare const hoisted_subOne: IRHoisted;
|
|
14
|
+
export declare const hoisted_negateInteger: IRHoisted;
|
|
14
15
|
export declare const hoisted_isPositive: IRHoisted;
|
|
15
16
|
export declare const hoisted_isNonNegative: IRHoisted;
|
|
16
17
|
export declare const hoisted_matchList: IRHoisted;
|
|
@@ -17,6 +17,7 @@ import { _ir_lazyChooseList } from "../../../tree_utils/_ir_lazyChooseList.js";
|
|
|
17
17
|
import { _ir_lazyIfThenElse } from "../../../tree_utils/_ir_lazyIfThenElse.js";
|
|
18
18
|
import { hoisted_drop4, hoisted_drop2, hoisted_drop3 } from "../_comptimeDropN.js";
|
|
19
19
|
import { IRConstr } from "../../../IRNodes/index.js";
|
|
20
|
+
import { _ir_and, _ir_or } from "../../../../compiler/tir/expressions/binary/TirBinaryExpr.js";
|
|
20
21
|
function _ir_strictAnd(left, right) {
|
|
21
22
|
return _ir_apps(IRNative.strictIfThenElse, left, right, IRConst.bool(false));
|
|
22
23
|
}
|
|
@@ -43,6 +44,8 @@ export const hoisted_addOne = new IRHoisted(new IRApp(IRNative.addInteger, IRCon
|
|
|
43
44
|
hoisted_addOne.hash;
|
|
44
45
|
export const hoisted_subOne = new IRHoisted(new IRApp(IRNative.addInteger, IRConst.int(-1)));
|
|
45
46
|
hoisted_subOne.hash;
|
|
47
|
+
export const hoisted_negateInteger = new IRHoisted(new IRApp(IRNative.subtractInteger, IRConst.int(0)));
|
|
48
|
+
hoisted_negateInteger.hash;
|
|
46
49
|
export const hoisted_isPositive = new IRHoisted(new IRApp(IRNative.lessThanInteger, IRConst.int(0)));
|
|
47
50
|
hoisted_isPositive.hash;
|
|
48
51
|
export const hoisted_isNonNegative = new IRHoisted(new IRApp(IRNative.lessThanEqualInteger, IRConst.int(0)));
|
|
@@ -54,6 +57,7 @@ export const hoisted_matchList = new IRHoisted((() => {
|
|
|
54
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))))))));
|
|
55
58
|
})());
|
|
56
59
|
hoisted_matchList.hash;
|
|
60
|
+
//*
|
|
57
61
|
// hoisted_recursiveList (needed by hoisted_foldr)
|
|
58
62
|
const recList_matchNil = Symbol("matchNil");
|
|
59
63
|
const recList_matchCons = Symbol("matchCons");
|
|
@@ -61,14 +65,15 @@ const recList_self = Symbol("recursiveList_self");
|
|
|
61
65
|
const recList_lst = Symbol("lst");
|
|
62
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))))));
|
|
63
67
|
hoisted_recursiveList.hash;
|
|
68
|
+
//*/
|
|
64
69
|
// hoisted_foldr
|
|
65
|
-
const
|
|
70
|
+
const foldr_reducer = Symbol("reduceFunc");
|
|
66
71
|
const foldr_acc = Symbol("accumulator");
|
|
67
72
|
const foldr__dummy = Symbol("_self");
|
|
68
73
|
const foldr_self = Symbol("self");
|
|
69
74
|
const foldr_head = Symbol("head");
|
|
70
75
|
const foldr_tail = Symbol("tail");
|
|
71
|
-
export const hoisted_foldr = new IRHoisted(new IRFunc([
|
|
76
|
+
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)))))));
|
|
72
77
|
hoisted_foldr.hash;
|
|
73
78
|
export const hosited_lazyChooseList = new IRHoisted((() => {
|
|
74
79
|
const list = Symbol("list");
|
|
@@ -142,19 +147,25 @@ export const hoisted_strictOr = new IRHoisted(new IRFunc([strictOr_a, strictOr_b
|
|
|
142
147
|
hoisted_strictOr.hash;
|
|
143
148
|
// hoisted _some
|
|
144
149
|
const some_pred = Symbol("predicate");
|
|
145
|
-
const
|
|
150
|
+
const some_lst = Symbol("lst");
|
|
146
151
|
const some_self = Symbol("self");
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
152
|
+
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
|
|
153
|
+
_ir_or(
|
|
154
|
+
// either predicate(head) is true
|
|
155
|
+
_ir_apps(new IRVar(some_pred), new IRApp(IRNative.headList, new IRVar(some_lst))),
|
|
156
|
+
// or self(tail) is true
|
|
157
|
+
_ir_apps(new IRSelfCall(some_self), new IRApp(IRNative.tailList, new IRVar(some_lst)))))))));
|
|
150
158
|
hoisted_some.hash;
|
|
151
159
|
// hoisted _every
|
|
152
160
|
const every_pred = Symbol("predicate");
|
|
153
|
-
const every_dummy = Symbol("_self");
|
|
154
161
|
const every_self = Symbol("self");
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
|
|
162
|
+
const every_lst = Symbol("lst");
|
|
163
|
+
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
|
|
164
|
+
_ir_and(
|
|
165
|
+
// both predicate(head) is true
|
|
166
|
+
_ir_apps(new IRVar(every_pred), new IRApp(IRNative.headList, new IRVar(every_lst))),
|
|
167
|
+
// AND self(tail) is true
|
|
168
|
+
_ir_apps(new IRSelfCall(every_self), new IRApp(IRNative.tailList, new IRVar(every_lst)))))))));
|
|
158
169
|
hoisted_every.hash;
|
|
159
170
|
// hoisted _filter
|
|
160
171
|
const filt_pred = Symbol("predicate");
|
|
@@ -249,6 +260,11 @@ export function nativeToIR(native) {
|
|
|
249
260
|
case IRNativeTag._mkMapList: return hoisted_mkMapList.clone();
|
|
250
261
|
case IRNativeTag._increment: return hoisted_addOne.clone();
|
|
251
262
|
case IRNativeTag._decrement: return hoisted_subOne.clone();
|
|
263
|
+
// case IRNativeTag._bytesToIntBE: ;
|
|
264
|
+
// case IRNativeTag._equalBoolean: ;
|
|
265
|
+
// case IRNativeTag._equalPairData: ;
|
|
266
|
+
case IRNativeTag._mkEqualsList: return hoisted_mkEqualsList.clone();
|
|
267
|
+
case IRNativeTag._negateInt: return hoisted_negateInteger.clone();
|
|
252
268
|
// case IRNativeTag._mkEqualsList: return hoisted_mkEqualsList.clone();
|
|
253
269
|
default:
|
|
254
270
|
throw new Error("unknown (negative) native calling 'nativeToIR'; " +
|
|
@@ -333,9 +333,15 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
333
333
|
if (!funcExpr)
|
|
334
334
|
return undefined;
|
|
335
335
|
this.program.functions.set(tirFuncName, funcExpr);
|
|
336
|
+
this.program.functions.set(astFuncName, funcExpr);
|
|
336
337
|
if (topLevelScope.functions.has(astFuncName))
|
|
337
338
|
return this.error(DiagnosticCode._0_is_already_defined, astFuncExpr.name.range, astFuncName);
|
|
338
339
|
topLevelScope.functions.set(astFuncName, tirFuncName);
|
|
340
|
+
topLevelScope.defineValue({
|
|
341
|
+
isConstant: true,
|
|
342
|
+
name: astFuncName,
|
|
343
|
+
type: funcExpr.type,
|
|
344
|
+
});
|
|
339
345
|
if (exportRange && srcExports) {
|
|
340
346
|
if (srcExports.functions.has(astFuncName)
|
|
341
347
|
|| srcExports.variables.has(astFuncName))
|
|
@@ -32,6 +32,7 @@ import { StructConstrDecl, StructDecl, StructDeclAstFlags } from "../../../../as
|
|
|
32
32
|
import { NamedDeconstructVarDecl } from "../../../../ast/nodes/statements/declarations/VarDecl/NamedDeconstructVarDecl.js";
|
|
33
33
|
import { SimpleVarDecl } from "../../../../ast/nodes/statements/declarations/VarDecl/SimpleVarDecl.js";
|
|
34
34
|
import { SingleDeconstructVarDecl } from "../../../../ast/nodes/statements/declarations/VarDecl/SingleDeconstructVarDecl.js";
|
|
35
|
+
import { isVarDecl } from "../../../../ast/nodes/statements/declarations/VarDecl/VarDecl.js";
|
|
35
36
|
import { EmptyStmt } from "../../../../ast/nodes/statements/EmptyStmt.js";
|
|
36
37
|
import { FailStmt } from "../../../../ast/nodes/statements/FailStmt.js";
|
|
37
38
|
import { ForOfStmt } from "../../../../ast/nodes/statements/ForOfStmt.js";
|
|
@@ -379,7 +380,9 @@ renamedVariables = {}) {
|
|
|
379
380
|
function _getMatchedRedeemerBlockStatements(compiler, stmts, paramsInternalNamesMap, contextVarsMapping, renamedVariables) {
|
|
380
381
|
const result = stmts.slice();
|
|
381
382
|
for (let i = 0; i < result.length; i++) {
|
|
382
|
-
|
|
383
|
+
let stmt = result[i];
|
|
384
|
+
if (isVarDecl(stmt))
|
|
385
|
+
stmt = new VarStmt([stmt], stmt.range);
|
|
383
386
|
if (stmt instanceof VarStmt) {
|
|
384
387
|
if (stmt.declarations.length !== 1) {
|
|
385
388
|
for (const varDecl of stmt.declarations) {
|
|
@@ -587,6 +590,7 @@ function _getMatchedRedeemerBlockStatements(compiler, stmts, paramsInternalNames
|
|
|
587
590
|
continue;
|
|
588
591
|
}
|
|
589
592
|
const tsEnsureExhaustiveCheck = stmt;
|
|
593
|
+
console.error(stmt);
|
|
590
594
|
throw new Error("unreachable::_getMatchedRedeemerBlockStatements::stmt::");
|
|
591
595
|
}
|
|
592
596
|
return result;
|
|
@@ -8,6 +8,7 @@ export declare class Compiler extends DiagnosticEmitter {
|
|
|
8
8
|
constructor(io?: CompilerIoApi, cfg?: CompilerOptions, diagnostics?: DiagnosticMessage[]);
|
|
9
9
|
compile(config?: Partial<CompilerOptions>): Promise<Uint8Array>;
|
|
10
10
|
export(config: Partial<ExportOptions> & HasFuncitonName): Promise<Uint8Array>;
|
|
11
|
+
private _compileBackend;
|
|
11
12
|
}
|
|
12
13
|
interface HasFuncitonName {
|
|
13
14
|
functionName: string;
|
|
@@ -34,16 +34,7 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
34
34
|
}
|
|
35
35
|
throw new Error("compilation failed with " + nDiags + " diagnostic messages; first message: " + fstErrorMsg);
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
const ir = compileTypedProgram(cfg, program);
|
|
39
|
-
const uplc = compileIRToUPLC(ir);
|
|
40
|
-
const serialized = compileUPLC(new UPLCProgram(cfg.targetUplcVersion, uplc)).toBuffer().buffer;
|
|
41
|
-
const outDir = cfg.outDir;
|
|
42
|
-
const outPath = outDir + (outDir.endsWith("/") ? "" : "/") + "out.flat";
|
|
43
|
-
this.io.writeFile(outPath, serialized, cfg.root);
|
|
44
|
-
this.io.stdout.write(`compiled program written to ${outPath}\n`);
|
|
45
|
-
__VERY_UNSAFE_FORGET_IRHASH_ONLY_USE_AT_END_OF_UPLC_COMPILATION();
|
|
46
|
-
return serialized;
|
|
37
|
+
return this._compileBackend(cfg, program);
|
|
47
38
|
}
|
|
48
39
|
async export(config) {
|
|
49
40
|
const cfg = {
|
|
@@ -67,10 +58,13 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
67
58
|
}
|
|
68
59
|
throw new Error("compilation failed with " + nDiags + " diagnostic messages; first message: " + fstErrorMsg);
|
|
69
60
|
}
|
|
61
|
+
return this._compileBackend(cfg, program);
|
|
62
|
+
}
|
|
63
|
+
_compileBackend(cfg, program) {
|
|
70
64
|
// backend starts here
|
|
71
65
|
const ir = compileTypedProgram(cfg, program);
|
|
72
66
|
const uplc = compileIRToUPLC(ir, cfg);
|
|
73
|
-
const serialized = compileUPLC(new UPLCProgram(cfg.targetUplcVersion, uplc))
|
|
67
|
+
const serialized = compileUPLC(new UPLCProgram(cfg.targetUplcVersion, uplc));
|
|
74
68
|
const outDir = cfg.outDir;
|
|
75
69
|
const outPath = outDir + (outDir.endsWith("/") ? "" : "/") + "out.flat";
|
|
76
70
|
this.io.writeFile(outPath, serialized, cfg.root);
|
|
@@ -51,12 +51,16 @@ export class ExpressifyCtx {
|
|
|
51
51
|
this.properties = properties;
|
|
52
52
|
this.hoisted = (hoisted
|
|
53
53
|
?? this.parent?.hoisted
|
|
54
|
-
?? new Map([...program.constants.entries()]
|
|
54
|
+
?? new Map([...program.constants.entries()]
|
|
55
|
+
.map(([name, decl]) => {
|
|
55
56
|
if (!decl.initExpr)
|
|
56
57
|
throw new Error(`expected init expr in hoisted constant '${name}'`);
|
|
57
58
|
const expr = decl.initExpr instanceof TirHoistedExpr ? decl.initExpr : new TirHoistedExpr(name, decl.initExpr);
|
|
58
59
|
return [name, expr];
|
|
59
|
-
})
|
|
60
|
+
})
|
|
61
|
+
.concat([...program.functions.entries()].map(([name, func]) => {
|
|
62
|
+
return [name, new TirHoistedExpr(name, func)];
|
|
63
|
+
}))));
|
|
60
64
|
}
|
|
61
65
|
allVariablesNoLetted() {
|
|
62
66
|
return (this.parent?.allVariablesNoLetted() ?? []).concat(...this.variables.keys());
|
|
@@ -119,7 +123,7 @@ export class ExpressifyCtx {
|
|
|
119
123
|
const result = (this._getNonHoistedVariable(name)
|
|
120
124
|
?? this.hoisted.get(name));
|
|
121
125
|
if (!result) {
|
|
122
|
-
console.log("[error log]: allVariables", this.allVariables());
|
|
126
|
+
console.log("[error log]: allVariables", this.allVariables(), "; get:", name);
|
|
123
127
|
throw new Error(`variable '${name}' not found in the context`);
|
|
124
128
|
}
|
|
125
129
|
return result;
|
|
@@ -117,7 +117,7 @@ export class TirNativeFunc {
|
|
|
117
117
|
int_t
|
|
118
118
|
], bool_t));
|
|
119
119
|
}
|
|
120
|
-
//
|
|
120
|
+
// bytes operations
|
|
121
121
|
static get appendByteString() {
|
|
122
122
|
return new TirNativeFunc(IRNativeTag.appendByteString, new TirFuncT([
|
|
123
123
|
// left
|
|
@@ -512,7 +512,7 @@ export class TirNativeFunc {
|
|
|
512
512
|
bytes_t
|
|
513
513
|
], bytes_t));
|
|
514
514
|
}
|
|
515
|
-
//
|
|
515
|
+
// bytes manipulation
|
|
516
516
|
static get integerToByteString() {
|
|
517
517
|
return new TirNativeFunc(IRNativeTag.integerToByteString, new TirFuncT([
|
|
518
518
|
// flag
|
|
@@ -585,7 +585,7 @@ export class TirNativeFunc {
|
|
|
585
585
|
bool_t
|
|
586
586
|
], bytes_t));
|
|
587
587
|
}
|
|
588
|
-
// Additional
|
|
588
|
+
// Additional bytes operations
|
|
589
589
|
static get replicateByte() {
|
|
590
590
|
return new TirNativeFunc(IRNativeTag.replicateByte, new TirFuncT([
|
|
591
591
|
// count
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
export * from "@harmoniclabs/bytestring";
|
|
2
1
|
export * from "@harmoniclabs/cbor";
|
|
3
2
|
export * from "@harmoniclabs/obj-utils";
|
|
4
|
-
export * from "@harmoniclabs/pair";
|
|
5
3
|
export * from "@harmoniclabs/plutus-data";
|
|
6
4
|
export * from "@harmoniclabs/plutus-machine";
|
|
7
5
|
export * from "@harmoniclabs/uint8array-utils";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
export * from "@harmoniclabs/bytestring";
|
|
2
1
|
export * from "@harmoniclabs/cbor";
|
|
3
2
|
export * from "@harmoniclabs/obj-utils";
|
|
4
|
-
export * from "@harmoniclabs/pair";
|
|
5
3
|
export * from "@harmoniclabs/plutus-data";
|
|
6
4
|
export * from "@harmoniclabs/plutus-machine";
|
|
7
5
|
export * from "@harmoniclabs/uint8array-utils";
|
package/dist/parser/Parser.js
CHANGED
|
@@ -72,6 +72,7 @@ import { Precedence, determinePrecedence } from "./Precedence.js";
|
|
|
72
72
|
import { LitFailExpr } from "../ast/nodes/expr/litteral/LitFailExpr.js";
|
|
73
73
|
import { ContractDecl } from "../ast/nodes/statements/declarations/ContractDecl.js";
|
|
74
74
|
import { LitContextExpr } from "../ast/nodes/expr/litteral/LitContextExpr.js";
|
|
75
|
+
import { tokenIsAlsoIdentifier } from "../tokenizer/utils/tokenIsAlsoIdentifier.js";
|
|
75
76
|
export class Parser extends DiagnosticEmitter {
|
|
76
77
|
tn;
|
|
77
78
|
constructor(tokenizer, diagnostics = undefined) {
|
|
@@ -833,6 +834,12 @@ export class Parser extends DiagnosticEmitter {
|
|
|
833
834
|
_parseVarDecl(flags, skipTypeAndInitializer = false) {
|
|
834
835
|
const tn = this.tn;
|
|
835
836
|
// ConstrName{ ... } || renamed
|
|
837
|
+
const identifierToken = tn.peek();
|
|
838
|
+
if (identifierToken !== Token.Identifier
|
|
839
|
+
&& identifierToken !== Token.OpenBrace // valid var destructuring (single constr obj)
|
|
840
|
+
&& identifierToken !== Token.OpenBracket // valid var destructuring (array-like)
|
|
841
|
+
&& !tokenIsAlsoIdentifier(identifierToken))
|
|
842
|
+
return this.error(DiagnosticCode._0_keyword_cannot_be_used_here, tn.range(tn.nextTokenPos, tn.nextToken), Token[identifierToken]);
|
|
836
843
|
const renamedField = this.parseIdentifier();
|
|
837
844
|
if (tn.skip(Token.OpenBrace)) // ConstrName{ ... } || { ... }
|
|
838
845
|
{
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { Source } from "../ast/Source/Source.js";
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
2
|
+
import { DiagnosticMessage } from "../diagnostics/DiagnosticMessage.js";
|
|
3
|
+
export declare function parseFilePure(path: string, src: string, getUid?: () => string, isEntry?: boolean): [Source, DiagnosticMessage[]];
|
|
4
|
+
export declare function parseFile(path: string, src: string, getUid?: () => string, isEntry?: boolean): Source;
|
|
5
|
+
export declare function parseSource(src: Source): DiagnosticMessage[];
|
package/dist/parser/parseFile.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { defaultSymbolForge } from "../compiler/internalVar.js";
|
|
2
2
|
import { Parser } from "./Parser.js";
|
|
3
|
-
export function
|
|
3
|
+
export function parseFilePure(path, src, getUid = defaultSymbolForge.getUid.bind(defaultSymbolForge), isEntry = false) {
|
|
4
4
|
return Parser.parseFile(path, src, getUid, isEntry);
|
|
5
5
|
}
|
|
6
|
+
export function parseFile(path, src, getUid = defaultSymbolForge.getUid.bind(defaultSymbolForge), isEntry = false) {
|
|
7
|
+
const [source, diagnostics] = Parser.parseFile(path, src, getUid, isEntry);
|
|
8
|
+
if (diagnostics.length > 0) {
|
|
9
|
+
throw new Error(`Parsing errors:\n${diagnostics.map(d => d.toString()).join("\n")}`);
|
|
10
|
+
}
|
|
11
|
+
return source;
|
|
12
|
+
}
|
|
6
13
|
export function parseSource(src) {
|
|
7
14
|
return Parser.parseSource(src);
|
|
8
15
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harmoniclabs/pebble",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3-dev1",
|
|
4
4
|
"description": "A simple, yet rock solid, functional language with an imperative bias, targeting UPLC",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -51,25 +51,22 @@
|
|
|
51
51
|
"homepage": "https://github.com/HarmonicLabs/pebble#readme",
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@harmoniclabs/bigint-utils": "^1.0.0",
|
|
54
|
-
"@harmoniclabs/
|
|
55
|
-
"@harmoniclabs/cbor": "^
|
|
54
|
+
"@harmoniclabs/cardano-costmodels-ts": "^1.4.0",
|
|
55
|
+
"@harmoniclabs/cbor": "^2.0.1",
|
|
56
56
|
"@harmoniclabs/crypto": "^0.3.0",
|
|
57
57
|
"@harmoniclabs/obj-utils": "^1.0.0",
|
|
58
|
-
"@harmoniclabs/
|
|
59
|
-
"@harmoniclabs/plutus-
|
|
60
|
-
"@harmoniclabs/plutus-machine": "^2.1.1",
|
|
58
|
+
"@harmoniclabs/plutus-data": "^2.0.1",
|
|
59
|
+
"@harmoniclabs/plutus-machine": "^3.0.0",
|
|
61
60
|
"@harmoniclabs/uint8array-utils": "^1.0.4",
|
|
62
|
-
"@harmoniclabs/uplc": "^
|
|
61
|
+
"@harmoniclabs/uplc": "^2.0.5"
|
|
63
62
|
},
|
|
64
63
|
"devDependencies": {
|
|
65
64
|
"@babel/preset-env": "^7.18.6",
|
|
66
65
|
"@babel/preset-typescript": "^7.18.6",
|
|
67
|
-
"@harmoniclabs/cardano-costmodels-ts": "^1.3.0",
|
|
68
|
-
"@harmoniclabs/cardano-ledger-ts": "^0.3.2",
|
|
69
66
|
"@types/jest": "^28.1.4",
|
|
70
67
|
"@types/node": "^18.14.6",
|
|
71
68
|
"jest": "^29.4.3",
|
|
72
|
-
"jest-environment-jsdom": "^
|
|
69
|
+
"jest-environment-jsdom": "^30.3.0",
|
|
73
70
|
"tsc-alias": "^1.7.1",
|
|
74
71
|
"typescript": "^4.6.3"
|
|
75
72
|
},
|