UNPKG

@harmoniclabs/plu-ts-onchain

Version:

An embedded DSL for Cardano smart contracts creation coupled with a library for Cardano transactions, all in Typescript

289 lines (288 loc) 11 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; 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.cloneHoistedSetEntry = exports.getHoistedTerms = exports.getSortedHoistedSet = exports.IRHoisted = void 0; var IRDelayed_1 = require("./IRDelayed.js"); var showIR_1 = require("../utils/showIR.js"); var obj_utils_1 = require("@harmoniclabs/obj-utils"); var BasePlutsError_1 = require("../../utils/BasePlutsError.js"); var concatUint8Arr_1 = require("../utils/concatUint8Arr.js"); var isClosedIRTerm_1 = require("../utils/isClosedIRTerm.js"); var IRApp_1 = require("./IRApp.js"); var IRForced_1 = require("./IRForced.js"); var IRFunc_1 = require("./IRFunc.js"); var IRLetted_1 = require("./IRLetted.js"); var isIRParentTerm_1 = require("../utils/isIRParentTerm.js"); var IRConstr_1 = require("./IRConstr.js"); var IRCase_1 = require("./IRCase.js"); var IRHash_1 = require("../IRHash.js"); var equalIRTerm_1 = require("../utils/equalIRTerm.js"); var IRNodeKind_1 = require("../IRNodeKind.js"); var IRRecursive_1 = require("./IRRecursive.js"); var defaultHoistedMeta = (0, obj_utils_1.freezeAll)({ forceHoist: false }); var IRHoisted = /** @class */ (function () { function IRHoisted(hoisted, metadata, _unsafeHash) { if (metadata === void 0) { metadata = {}; } var _a, _b; // unwrap // !!! IMPORTANT !!! while (hoisted instanceof IRHoisted) hoisted = hoisted.hoisted; if (!(0, isClosedIRTerm_1.isClosedIRTerm)(hoisted)) { console.log((0, showIR_1.prettyIRJsonStr)(hoisted)); throw new BasePlutsError_1.BasePlutsError("only closed terms can be hoisted"); } // initialize without calling "set" this._hoisted = hoisted; this._hoisted.parent = this; this._deps = undefined; this._hash = (0, IRHash_1.isIRHash)(_unsafeHash) ? _unsafeHash : undefined; this._parent = undefined; this.meta = __assign(__assign(__assign({}, defaultHoistedMeta), metadata), { name: (_b = (_a = this._hoisted.meta) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : metadata.name }); } Object.defineProperty(IRHoisted, "kind", { get: function () { return IRNodeKind_1.IRNodeKind.Hoisted; }, enumerable: false, configurable: true }); Object.defineProperty(IRHoisted.prototype, "kind", { get: function () { return IRHoisted.kind; }, enumerable: false, configurable: true }); Object.defineProperty(IRHoisted, "tag", { get: function () { return new Uint8Array([IRHoisted.kind]); }, enumerable: false, configurable: true }); Object.defineProperty(IRHoisted.prototype, "hash", { get: function () { if (!(0, IRHash_1.isIRHash)(this._hash)) { this._hash = (0, IRHash_1.hashIrData)((0, concatUint8Arr_1.concatUint8Arr)(IRHoisted.tag, this.hoisted.hash)); } return this._hash; }, enumerable: false, configurable: true }); IRHoisted.prototype.markHashAsInvalid = function () { var _a; this._hash = undefined; this._deps = undefined; (_a = this.parent) === null || _a === void 0 ? void 0 : _a.markHashAsInvalid(); }; IRHoisted.prototype.isHashPresent = function () { return (0, IRHash_1.isIRHash)(this._hash); }; Object.defineProperty(IRHoisted.prototype, "hoisted", { get: function () { return this._hoisted; }, set: function (newHoisted) { if (!(0, isClosedIRTerm_1.isClosedIRTerm)(newHoisted)) throw new BasePlutsError_1.BasePlutsError("only closed terms can be hoisted"); if (!(0, equalIRTerm_1.shallowEqualIRTermHash)(this._hoisted, newHoisted)) this.markHashAsInvalid(); // dependencies need to be updated EVEN if hash is the same // since the terms might be the same but maybe cloned this._deps = undefined; // keep the parent reference in the old child, useful for compilation // _hoisted.parent = undefined; this._hoisted = newHoisted; this._hoisted.parent = this; }, enumerable: false, configurable: true }); Object.defineProperty(IRHoisted.prototype, "dependencies", { get: function () { if (this._deps === undefined) this._deps = getSortedHoistedSet(getHoistedTerms(this._hoisted)); return this._deps; }, enumerable: false, configurable: true }); Object.defineProperty(IRHoisted.prototype, "parent", { get: function () { return this._parent; }, set: function (newParent) { if (!( // assert // new parent value is different than current this._parent !== newParent && ( // and the new parent value is valid newParent === undefined || (0, isIRParentTerm_1.isIRParentTerm)(newParent)))) return; this._parent = newParent; }, enumerable: false, configurable: true }); IRHoisted.prototype.clone = function () { return new IRHoisted(this.hoisted.clone(), __assign({}, this.meta), this.isHashPresent() ? this.hash : undefined); }; IRHoisted.prototype.toJSON = function () { return this.toJson(); }; IRHoisted.prototype.toJson = function () { return { type: "IRHoisted", hash: (0, IRHash_1.irHashToHex)(this.hash), hoisted: this.hoisted.toJson() }; }; return IRHoisted; }()); exports.IRHoisted = IRHoisted; /** * basically an insertion sort; * * @param {HoistedSetEntry[]} hoistedTerms * @returns {HoistedSetEntry[]} a **new** array with ```IRHoisted```s with no dependencies first, followed by the dependents */ function getSortedHoistedSet(hoistedTerms) { var set = []; var hashesSet = []; /** * **O((n * m) * d)** * * where * * n = length of set * m = number of terms passed * d = number of unique dependencies among the passed terms */ function addToSet() { var _terms = []; for (var _i = 0; _i < arguments.length; _i++) { _terms[_i] = arguments[_i]; } var _loop_1 = function (i) { var thisHoistedEntry = _terms[i]; var thisHash = thisHoistedEntry.hoisted.hash; var idxInSet = hashesSet.findIndex(function (hash) { return (0, IRHash_1.equalIrHash)(hash, thisHash); }); // if( !hashesSet.includes( compiled ) ) // "includes" uses standard equality (===) if (idxInSet < 0) // not present { // add dependencies first addToSet.apply(void 0, __spreadArray([], __read(_terms[i].hoisted.dependencies), false)); hashesSet.push(thisHash); set.push(thisHoistedEntry); } else { var entry = set[idxInSet]; entry.nReferences += thisHoistedEntry.nReferences; entry.hoisted.meta.forceHoist = entry.hoisted.meta.forceHoist || thisHoistedEntry.hoisted.meta.forceHoist; } }; for (var i = 0; i < _terms.length; i++) { _loop_1(i); } } addToSet.apply(void 0, __spreadArray([], __read(hoistedTerms), false)); return set; } exports.getSortedHoistedSet = getSortedHoistedSet; function getHoistedTerms(irTerm) { var hoisteds = []; function searchIn(term) { if (term instanceof IRHoisted) { // only push direct hoisteds // dependencies are counted calling `getSortedHoistedSet` hoisteds.push({ hoisted: term, nReferences: 1 }); return; } if (term instanceof IRApp_1.IRApp) { searchIn(term.fn); searchIn(term.arg); return; } if (term instanceof IRConstr_1.IRConstr) { for (var i = 0; i < term.fields.length; i++) { searchIn(term.fields[i]); } return; } if (term instanceof IRCase_1.IRCase) { searchIn(term.constrTerm); for (var i = 0; i < term.continuations.length; i++) { searchIn(term.continuations[i]); } return; } if (term instanceof IRFunc_1.IRFunc) { searchIn(term.body); return; } if (term instanceof IRRecursive_1.IRRecursive) { searchIn(term.body); return; } if (term instanceof IRLetted_1.IRLetted) { // useless // term.dependencies.forEach( searchIn ) // dependecies are still in the body anyway (hoisted are closed) searchIn(term.value); return; } if (term instanceof IRForced_1.IRForced) { searchIn(term.forced); return; } if (term instanceof IRDelayed_1.IRDelayed) { searchIn(term.delayed); return; } // if( term instanceof IRNative ) return; // if( term instanceof IRVar ) return; // if( term instanceof IRConst ) return; // if( term instanceof IRError ) return; } searchIn(irTerm); return hoisteds; } exports.getHoistedTerms = getHoistedTerms; function cloneHoistedSetEntry(_a) { var hoisted = _a.hoisted, nReferences = _a.nReferences; return { hoisted: hoisted.clone(), nReferences: nReferences }; } exports.cloneHoistedSetEntry = cloneHoistedSetEntry;