@harmoniclabs/plu-ts-onchain
Version:
An embedded DSL for Cardano smart contracts creation coupled with a library for Cardano transactions, all in Typescript
126 lines (125 loc) • 7.27 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.compileIRToUPLC = void 0;
var IRLetted_1 = require("../IRNodes/IRLetted.js");
var IRHoisted_1 = require("../IRNodes/IRHoisted.js");
var IRConst_1 = require("../IRNodes/IRConst.js");
var _irToUplc_1 = require("./_internal/_irToUplc.js");
var includesNode_1 = require("./_internal/includesNode.js");
var handleLetted_1 = require("./subRoutines/handleLetted/index.js");
var handleHoistedAndReturnRoot_1 = require("./subRoutines/handleHoistedAndReturnRoot/index.js");
var replaceNatives_1 = require("./subRoutines/replaceNatives/index.js");
var replaceClosedLettedWithHoisted_1 = require("./subRoutines/replaceClosedLettedWithHoisted.js");
var hoistForcedNatives_1 = require("./subRoutines/hoistForcedNatives.js");
var handleRecursiveTerms_1 = require("./subRoutines/handleRecursiveTerms.js");
var CompilerOptions_1 = require("./CompilerOptions.js");
var replaceHoistedWithLetted_1 = require("./subRoutines/replaceHoistedWithLetted.js");
var IRNodes_1 = require("../IRNodes/index.js");
var replaceForcedNativesWithHoisted_1 = require("./subRoutines/replaceForcedNativesWithHoisted.js");
var performUplcOptimizationsAndReturnRoot_1 = require("./subRoutines/performUplcOptimizationsAndReturnRoot/index.js");
function compileIRToUPLC(term, paritalOptions) {
if (paritalOptions === void 0) { paritalOptions = CompilerOptions_1.defaultOptions; }
// most of the time we are just compiling small
// pre-execuded terms (hence constants)
if (term instanceof IRConst_1.IRConst)
return (0, _irToUplc_1._irToUplc)(term).term;
///////////////////////////////////////////////////////////////////////////////
// ------------------------------------------------------------------------- //
// --------------------------------- init --------------------------------- //
// ------------------------------------------------------------------------- //
///////////////////////////////////////////////////////////////////////////////
var options = (0, CompilerOptions_1.completeCompilerOptions)(paritalOptions);
// unwrap top level letted and hoisted;
while (term instanceof IRLetted_1.IRLetted || term instanceof IRHoisted_1.IRHoisted) {
// replace with value
term = term instanceof IRLetted_1.IRLetted ? term.value : term.hoisted;
// forget the parent; this is the new root
term.parent = undefined;
}
// _makeAllNegativeNativesHoisted( term );
///////////////////////////////////////////////////////////////////////////////
// ------------------------------------------------------------------------- //
// ----------------------------- optimizations ----------------------------- //
// ------------------------------------------------------------------------- //
///////////////////////////////////////////////////////////////////////////////
// --------------------------- optimize natives --------------------------- //
// at constant -> head and tails
// --------------------- optimize recursive functions --------------------- //
// avoid passing whole structs
// take letted terms outside
// ----------------------- optimize normal functions ----------------------- //
// avoid passing whole structs
// reorganize function arguments to take advantage of partial applicaiton
///////////////////////////////////////////////////////////////////////////////
// ------------------------------------------------------------------------- //
// ------------------------------ final steps ------------------------------ //
// ------------------------------------------------------------------------- //
///////////////////////////////////////////////////////////////////////////////
term = (0, replaceNatives_1.replaceNativesAndReturnRoot)(term);
// unwrap top level letted and hoisted;
// some natives may be converted to hoisted;
// this is really just an edge case
while (term instanceof IRLetted_1.IRLetted || term instanceof IRHoisted_1.IRHoisted) {
// replace with value
term = term instanceof IRLetted_1.IRLetted ? term.value : term.hoisted;
// forget the parent; this is the new root
term.parent = undefined;
}
if (term instanceof IRNodes_1.IRNative ||
term instanceof IRConst_1.IRConst // while we are at it
)
return (0, _irToUplc_1._irToUplc)(term).term;
if (options.delayHoists)
(0, replaceForcedNativesWithHoisted_1.replaceForcedNativesWithHoisted)(term);
if (options.delayHoists)
(0, replaceHoistedWithLetted_1.replaceHoistedWithLetted)(term);
else
(0, replaceClosedLettedWithHoisted_1.replaceClosedLettedWithHoisted)(term);
// handle letted before hoisted because the tree is smaller
// and we also have less letted dependecies to handle
term = (0, handleLetted_1.handleLettedAndReturnRoot)(term);
term = (0, handleHoistedAndReturnRoot_1.handleHoistedAndReturnRoot)(term);
// replaced hoisted terms might include new letted terms
while ((0, includesNode_1.includesNode)(term, function (node) {
return node instanceof IRLetted_1.IRLetted ||
node instanceof IRHoisted_1.IRHoisted;
})) {
term = (0, handleLetted_1.handleLettedAndReturnRoot)(term);
term = (0, handleHoistedAndReturnRoot_1.handleHoistedAndReturnRoot)(term);
}
///////////////////////////////////////////////////////////////////////////////
// ------------------------------------------------------------------------- //
// --------------------------- translate to UPLC --------------------------- //
// ------------------------------------------------------------------------- //
///////////////////////////////////////////////////////////////////////////////
// introduces new hoisted terms
// however we cannot do this before
// because in order to hanlde letted at the best
// we need to know where the `IRRecursive` nodes are
term = (0, handleRecursiveTerms_1.handleRootRecursiveTerm)(term);
// if( options.delayHoists ) replaceHoistedWithLetted( term );
// handle new hoisted terms
term = (0, handleHoistedAndReturnRoot_1.handleHoistedAndReturnRoot)(term);
// strictly necessary to check the options
// otherwise forced natives where already hoisted
// will be re-hosited; causeing uselsess evaluations
if (!options.delayHoists)
term = (0, hoistForcedNatives_1.hoistForcedNatives)(term);
// at this point we expect the IR to be translable 1:1 to UPLC
term = (0, performUplcOptimizationsAndReturnRoot_1.performUplcOptimizationsAndReturnRoot)(term, options);
if (options.addMarker &&
options.targetUplcVersion.major >= 1 &&
options.targetUplcVersion.minor >= 1 &&
options.targetUplcVersion.patch >= 0) {
term = new IRNodes_1.IRCase(new IRNodes_1.IRConstr(0, []), [
term,
// never evaluated
IRConst_1.IRConst.int(42)
]);
}
var srcmap = {};
var uplc = (0, _irToUplc_1._irToUplc)(term, srcmap).term;
// console.log( "srcmap", srcmap );
return uplc;
}
exports.compileIRToUPLC = compileIRToUPLC;