UNPKG

@harmoniclabs/plu-ts-onchain

Version:

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

191 lines (190 loc) 8.66 kB
"use strict"; 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.handleHoistedAndReturnRoot = void 0; var IRApp_1 = require("../../../IRNodes/IRApp.js"); var IRDelayed_1 = require("../../../IRNodes/IRDelayed.js"); var IRForced_1 = require("../../../IRNodes/IRForced.js"); var IRFunc_1 = require("../../../IRNodes/IRFunc.js"); var IRHoisted_1 = require("../../../IRNodes/IRHoisted.js"); var IRLetted_1 = require("../../../IRNodes/IRLetted.js"); var IRVar_1 = require("../../../IRNodes/IRVar.js"); var _modifyChildFromTo_1 = require("../../_internal/_modifyChildFromTo.js"); var showIR_1 = require("../../../utils/showIR.js"); var markRecursiveHoistsAsForced_1 = require("../markRecursiveHoistsAsForced.js"); var IRHash_1 = require("../../../IRHash.js"); var mapArrayLike_1 = require("../../../IRNodes/utils/mapArrayLike.js"); var IRCase_1 = require("../../../IRNodes/IRCase.js"); var IRConstr_1 = require("../../../IRNodes/IRConstr.js"); var stringify_1 = require("../../../../utils/stringify.js"); var IRRecursive_1 = require("../../../IRNodes/IRRecursive.js"); function handleHoistedAndReturnRoot(term) { // unwrap; // if( term instanceof IRHoisted ) while (term instanceof IRHoisted_1.IRHoisted) { // we know `handleHoistedAndReturnRoot` modifies the term // so we are probably ok not cloning here // top level hoisted terms should be handled in `compileIRToUPLC` anyway term = term.hoisted; // we still need to remove this parent otherhwise there will be an unknown hoisted to handle term.parent = undefined; // return handleHoistedAndReturnRoot( // theTerm // ); } // TODO: should probably merge `markRecursiveHoistsAsForced` inside `getHoistedTerms` to iter once (0, markRecursiveHoistsAsForced_1.markRecursiveHoistsAsForced)(term); var directHoisteds = (0, IRHoisted_1.getHoistedTerms)(term); var allHoisteds = (0, IRHoisted_1.getSortedHoistedSet)(directHoisteds); var n = allHoisteds.length; // evaluating constants if (n === 0) { return term; } // nothing to do; shortcut. if (n === 0) return term; var a = 0; var b = 0; var toHoist = new Array(n); var toInline = new Array(n); // filter out hoisted terms with single reference for (var i = 0; i < n; i++) { var thisHoistedEntry = allHoisteds[i]; if (thisHoistedEntry.hoisted.meta.forceHoist === true) { toHoist[a++] = thisHoistedEntry.hoisted; continue; } if (thisHoistedEntry.nReferences === 1 && thisHoistedEntry.hoisted.parent) { // inline hoisted with single reference toInline[b++] = thisHoistedEntry.hoisted; } else toHoist[a++] = thisHoistedEntry.hoisted; } // drop unused space toHoist.length = a; toInline.length = b; var hoistedsToInlineHashes = toInline.map(function (h) { return h.hash; }); // console.log( "toHoist", toHoist.map( h => ({ ...showIR( h.hoisted ), hash: toHex( h.hash ) }) ) ); // console.log( "toInline", toInline.map( h => ({ ...showIR( h.hoisted ), hash: toHex( h.hash ) }) ) ); var root = term; while (root.parent !== undefined) root = root.parent; function getIRVarForHoistedAtLevel(_hoistedHash, level) { var levelOfTerm = toHoist.findIndex(function (sortedH) { return (0, IRHash_1.equalIrHash)(sortedH.hash, _hoistedHash); }); if (levelOfTerm < 0) { throw new Error("missing hoisted with hash ".concat((0, IRHash_1.irHashToHex)(_hoistedHash), " between toHoist [\n\t").concat(toHoist.map(function (h) { return (0, IRHash_1.irHashToHex)(h.hash); }) .join(",\n\t"), "\n]; can't replace with IRVar")); } return new IRVar_1.IRVar(level - (levelOfTerm + 1)); } // adds the actual terms // from last to first for (var i = toHoist.length - 1; i >= 0; i--) { var thisHoisted = toHoist[i]; root = new IRApp_1.IRApp(new IRFunc_1.IRFunc(1, root), thisHoisted.hoisted.clone()); } // replace hoisted references with variables var stack = [{ irTerm: root, dbn: 0 }]; var _loop_1 = function () { var _a = stack.pop(), irTerm = _a.irTerm, dbn = _a.dbn; var irTermHash = irTerm.hash; var isHoistedToinline = hoistedsToInlineHashes.some(function (h) { return (0, IRHash_1.equalIrHash)(h, irTermHash); }); if ( // is hoiseted irTerm instanceof IRHoisted_1.IRHoisted && // is not one to be inlined !isHoistedToinline) { var irvar = getIRVarForHoistedAtLevel(irTermHash, dbn); if (irvar.dbn >= dbn) { throw new Error("out of bound hoisted term; hash: ".concat((0, IRHash_1.irHashToHex)(irTerm.hash), "; var's DeBruijn: ").concat(irvar.dbn, " (starts from 0); tot hoisted in scope: ").concat(dbn)); } // console.log( // showIRText( irTerm.parent as IRTerm ), // "\n\n", // showIRText( irTerm ), // ) (0, _modifyChildFromTo_1._modifyChildFromTo)(irTerm.parent, irTerm, irvar); Object.defineProperty(irTerm.meta, "handled", { value: true, writable: true, enumerable: true, configurable: true }); return "continue"; } else if (irTerm instanceof IRHoisted_1.IRHoisted) { if (!isHoistedToinline) { throw new Error("unexpected hoisted term found with hash: " + (0, IRHash_1.irHashToHex)(irTermHash) + "\n showIR of the term: " + (0, stringify_1.stringify)((0, showIR_1.showIR)(irTerm), undefined, 2)); } var toInline_1 = irTerm.hoisted; (0, _modifyChildFromTo_1._modifyChildFromTo)(irTerm.parent, irTerm, toInline_1); stack.push({ irTerm: toInline_1, dbn: dbn }); return "continue"; } if (irTerm instanceof IRApp_1.IRApp) { stack.push({ irTerm: irTerm.fn, dbn: dbn }, { irTerm: irTerm.arg, dbn: dbn }); return "continue"; } if (irTerm instanceof IRCase_1.IRCase) { stack.push.apply(stack, __spreadArray([{ irTerm: irTerm.constrTerm, dbn: dbn }], __read((0, mapArrayLike_1.mapArrayLike)(irTerm.continuations, function (continuation) { return ({ irTerm: continuation, dbn: dbn }); })), false)); return "continue"; } if (irTerm instanceof IRConstr_1.IRConstr) { stack.push.apply(stack, __spreadArray([], __read((0, mapArrayLike_1.mapArrayLike)(irTerm.fields, function (field) { return ({ irTerm: field, dbn: dbn }); })), false)); return "continue"; } if (irTerm instanceof IRDelayed_1.IRDelayed) { stack.push({ irTerm: irTerm.delayed, dbn: dbn }); return "continue"; } if (irTerm instanceof IRForced_1.IRForced) { stack.push({ irTerm: irTerm.forced, dbn: dbn }); return "continue"; } if (irTerm instanceof IRFunc_1.IRFunc) { stack.push({ irTerm: irTerm.body, dbn: dbn + irTerm.arity }); return "continue"; } if (irTerm instanceof IRRecursive_1.IRRecursive) { stack.push({ irTerm: irTerm.body, dbn: dbn + irTerm.arity }); return "continue"; } if (irTerm instanceof IRLetted_1.IRLetted) { stack.push({ irTerm: irTerm.value, dbn: dbn }); return "continue"; } }; while (stack.length > 0) { _loop_1(); } return root; } exports.handleHoistedAndReturnRoot = handleHoistedAndReturnRoot;