@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
JavaScript
"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;