@harmoniclabs/plu-ts-onchain
Version:
An embedded DSL for Cardano smart contracts creation coupled with a library for Cardano transactions, all in Typescript
207 lines (206 loc) • 9.73 kB
JavaScript
;
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.pmatchStruct = void 0;
var obj_utils_1 = require("@harmoniclabs/obj-utils");
var plutus_data_1 = require("@harmoniclabs/plutus-data");
var old_1 = require("../plet/old.js");
var types_1 = require("../../type_system/types.js");
var Term_1 = require("../../Term/index.js");
var minimal_1 = require("../plet/minimal.js");
var minimal_2 = require("../punsafeConvertType/minimal.js");
var fromData_minimal_1 = require("../std/data/conversion/fromData_minimal.js");
var isWellFormedType_1 = require("../../type_system/kinds/isWellFormedType.js");
var papp_1 = require("../papp.js");
var matchSingleCtorStruct_1 = require("./matchSingleCtorStruct.js");
var IRConst_1 = require("../../../IR/IRNodes/IRConst.js");
var plam_1 = require("../plam.js");
var matchNCtors_1 = require("./matchNCtors.js");
var addUtilityForType_1 = require("../std/UtilityTerms/addUtilityForType.js");
var getElemAtTerm_1 = require("./getElemAtTerm.js");
var utils_1 = require("../../type_system/utils.js");
var capitalize_1 = require("../../../utils/capitalize.js");
var punsafeConvertType_1 = require("../punsafeConvertType/index.js");
var IR_1 = require("../../../IR/index.js");
function getReturnTypeFromContinuation(cont, ctorDef) {
return cont(
// mock the fields
// we are not really interested in the result here; only in the type
new Term_1.Term((0, types_1.list)(types_1.data), function (_dbn) {
return IRConst_1.IRConst.listOf(types_1.data)((new Array(Object.keys(ctorDef).length))
.fill(new plutus_data_1.DataI(0)));
})).type;
}
/**
*
* @param structData
* @param sDef
* @param ctorCbs
*
* @returns the term that matches the ctor
*/
function hoistedMatchCtors(structData, sDef, ctorCbs, cbsReturnT) {
var _a;
var length = ctorCbs.length;
if (length <= 0)
throw new Error("trying to match ill formed struct");
// const returnT = tyVar("single_ctor_match_return_type");
var ctors = Object.keys(sDef);
if (length === 1) {
var cont_1 = ctorCbs[0];
if (cont_1 instanceof Term_1.Term) {
if (cont_1.type[0] !== types_1.PrimType.Lambda) {
// todo: add proper error
throw new Error("pmatch continuation was not a lambda");
}
return (0, papp_1.papp)(cont_1, (0, papp_1.papp)(matchSingleCtorStruct_1.getFields, structData));
}
var thisCtorDef_1 = sDef[ctors[0]];
var returnT_1 = cbsReturnT !== null && cbsReturnT !== void 0 ? cbsReturnT : getReturnTypeFromContinuation(cont_1, thisCtorDef_1);
return (0, papp_1.papp)((0, plam_1.plam)((0, types_1.list)(types_1.data), returnT_1)(cont_1), (0, papp_1.papp)(matchSingleCtorStruct_1.getFields, structData));
}
// multiple ctors struct case
var ctorIdx = 0;
var cont = (_a = ctorCbs.find(function (cb, i) {
if (typeof cb === "function") {
ctorIdx = i;
return true;
}
return false;
})) !== null && _a !== void 0 ? _a : ctorCbs[0];
var thisCtorDef = sDef[Object.keys(sDef)[ctorIdx]];
var returnT = cbsReturnT !== null && cbsReturnT !== void 0 ? cbsReturnT : (cont instanceof Term_1.Term ?
cont.type[2] :
getReturnTypeFromContinuation(cont, thisCtorDef));
var result = (0, papp_1.papp)((0, matchNCtors_1.matchNCtorsIdxs)(ctors.length, returnT), structData);
for (var i = ctors.length - 1; i >= 0; i--) {
var thisCont = ctorCbs[i];
var thisCtorDef_2 = sDef[ctors[i]];
result = (0, papp_1.papp)(result, thisCont instanceof Term_1.Term ? thisCont :
(0, plam_1.plam)((0, types_1.list)(types_1.data), returnT !== null && returnT !== void 0 ? returnT : getReturnTypeFromContinuation(thisCont, thisCtorDef_2))(thisCont));
}
return result;
}
function getStructInstance(fieldsList, ctorDef) {
var instance = {};
var fieldNames = Object.keys(ctorDef);
for (var i = 0; i < fieldNames.length; i++) {
var fieldName = fieldNames[i];
var fieldType = ctorDef[fieldName];
Object.defineProperty(instance, fieldName, {
value: (0, addUtilityForType_1.addUtilityForType)(fieldType)((0, minimal_2._punsafeConvertType)((0, minimal_1._plet)((0, fromData_minimal_1._fromData)(fieldType)((0, getElemAtTerm_1.getElemAtTerm)(i).$(fieldsList))), fieldType)),
writable: false,
enumerable: true,
configurable: false
});
}
return instance;
}
function pmatchStruct(struct) {
var sDef = struct.type[1];
if (!(0, isWellFormedType_1.isStructDefinition)(sDef)) {
/**
* @todo add proper error
*/
throw new Error("unexpected struct type while running 'pmatch'; " +
"\ntype expected to be a 'ConstantableStructDefiniton' was: " + (0, utils_1.termTypeToString)(struct.type));
}
var ctors = Object.keys(sDef);
var ctorCbs = ctors.map(function (_) { return undefined; });
// console.log("matching", ctors);
// if( ctors[0] === "PoolStateRef" )
// {
// console.log( getCallStackAt( 4 )?.__line__ );
// }
function indexOfCtor(ctor) {
var res = ctors.indexOf(ctor);
if (res < 0) {
throw new Error("internal function 'indexOfCtor' in 'definePMatchPermutations' couldn't find the constructor \"" + ctor +
"\" between [" + ctors.map(function (c) { return c.toString(); }).join(',') + ']');
}
return res;
}
function permutations(missingCtors) {
if (missingCtors.length <= 0)
return {};
// last permutation
// returns the final expression
if (missingCtors.length === 1) {
var ctor_1 = missingCtors[0];
var idx_1 = indexOfCtor(ctor_1);
var matcher = "on" + (0, capitalize_1.capitalize)(ctor_1);
var result = {};
(0, obj_utils_1.defineReadOnlyProperty)(result, matcher, function (cb) {
// build the `StructInstance` input from the struct fields
var callback = function (mathcedCtorsFields) {
return cb(getStructInstance(mathcedCtorsFields, sDef[ctor_1]));
};
var returnT = cb(getStructInstance(new Term_1.Term((0, types_1.list)(types_1.data), function (_) { return new IR_1.IRVar(0); }), sDef[ctor_1])).type;
// same stuff of previous ctors
ctorCbs[idx_1] = callback;
return hoistedMatchCtors(struct, sDef, ctorCbs, returnT);
});
return (0, obj_utils_1.defineReadOnlyProperty)(result, "_", result[matcher]);
}
var remainingCtorsObj = {};
// here add all the missing ctors contiunuations
missingCtors.forEach(function (ctor) {
var idx = indexOfCtor(ctor);
(0, obj_utils_1.defineReadOnlyProperty)(remainingCtorsObj, "on" + (0, capitalize_1.capitalize)(ctor), function (cb) {
ctorCbs[idx] = function (fieldsList) { return cb(getStructInstance(fieldsList, sDef[ctor])); };
return permutations(missingCtors.filter(function (c) { return c !== ctor; }));
});
});
return (0, obj_utils_1.defineReadOnlyProperty)(remainingCtorsObj, "_", function (cb) {
var maxLengthFound = Math.max.apply(Math, __spreadArray([], __read(ctors
.map(function (ctor, i) {
// only get length if a function was specified
return typeof ctorCbs[i] === "function" ?
Object.keys(sDef[ctor]).length :
-1;
})), false));
// .reduce( (prev, curr, i ) => Math.max( prev, curr ) , 0 );
var returnT = getReturnTypeFromContinuation(cb, sDef[ctors[ctors.findIndex(function (ctor) { return Object.keys(sDef[ctor]).length === maxLengthFound; })]]);
return (0, old_1._old_plet)((0, plam_1.plam)((0, types_1.list)(types_1.data), returnT)(cb)).in(function (othCtorsContinuation) {
for (var i = 0; i < ctorCbs.length; i++) {
if (typeof ctorCbs[i] !== "function") {
ctorCbs[i] = othCtorsContinuation;
}
}
var res = hoistedMatchCtors(
/*
Argument of type 'Term<PStruct<SDef>>' is not assignable to parameter of type 'Term<PStruct<StructDefinition>>'.
Type 'PStruct<SDef>' is not assignable to type 'PStruct<StructDefinition>'.
*/
struct, sDef, ctorCbs, returnT);
return (0, punsafeConvertType_1.punsafeConvertType)(res, returnT);
});
});
}
return permutations(ctors);
}
exports.pmatchStruct = pmatchStruct;