UNPKG

@harmoniclabs/plu-ts-onchain

Version:

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

73 lines (72 loc) 3.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports._precursive = void 0; var IRFunc_1 = require("../../../IR/IRNodes/IRFunc.js"); var IRRecursive_1 = require("../../../IR/IRNodes/IRRecursive.js"); var IRSelfCall_1 = require("../../../IR/IRNodes/IRSelfCall.js"); var IRVar_1 = require("../../../IR/IRNodes/IRVar.js"); var _modifyChildFromTo_1 = require("../../../IR/toUPLC/_internal/_modifyChildFromTo.js"); var getChildren_1 = require("../../../IR/tree_utils/getChildren.js"); var assert_1 = require("../../../utils/assert.js"); var Term_1 = require("../../Term/index.js"); var type_system_1 = require("../../type_system/index.js"); /** * for reference the "Z combinator in js": https://medium.com/swlh/y-and-z-combinators-in-javascript-lambda-calculus-with-real-code-31f25be934ec * * ```js * const Zcombinator = ( * Z => ( * toMakeRecursive => Z( value => toMakeRecursive(toMakeRecursive)(value) ) * )( toMakeRecursive => Z( value => toMakeRecursive(toMakeRecursive)(value)) ) * ); * ``` * of type * ```js * Z => toMakeRecursive => value => result * ``` * and ```toMakeRecursive``` has to be of type * ```js * self => value => result * ``` */ function _precursive(fnBody) { var a = (0, type_system_1.tyVar)("recursive_fn_a"); var b = (0, type_system_1.tyVar)("recursive_fn_b"); (0, assert_1.assert)((0, type_system_1.typeExtends)(fnBody.type, (0, type_system_1.lam)((0, type_system_1.lam)(a, b), (0, type_system_1.lam)(a, b))), "passed function body cannot be recursive; " + "the first argument is not a lambda or it doesn't take any input"); var recursiveFn = new Term_1.Term(fnBody.type[2], function (cfg, dbn) { var fnBodyIr = assertArity2AndRemoveFirst(fnBody.toIR(cfg, dbn)); replaceSelfVars(fnBodyIr); return new IRRecursive_1.IRRecursive(fnBodyIr); // return new IRApp( // IRNative.z_comb, // fnBodyIr // ) }); return (recursiveFn); } exports._precursive = _precursive; function assertArity2AndRemoveFirst(term) { if (!(term instanceof IRFunc_1.IRFunc)) throw new Error("argument of precursive must be a function"); if (term.arity >= 2) { return new IRFunc_1.IRFunc(term.arity - 1, term.body); } // else term.arity === 1 if (!(term.body instanceof IRFunc_1.IRFunc)) throw new Error("argument of precursive must be a function with arity >= 2"); return term.body; } function replaceSelfVars(term, dbn) { if (dbn === void 0) { dbn = 0; } if (term instanceof IRVar_1.IRVar) { if (term.dbn === dbn) { (0, _modifyChildFromTo_1._modifyChildFromTo)(term.parent, term, new IRSelfCall_1.IRSelfCall(dbn)); } return; } if (term instanceof IRFunc_1.IRFunc || term instanceof IRRecursive_1.IRRecursive) return replaceSelfVars(term.body, dbn + term.arity); (0, getChildren_1.getChildren)(term).forEach(function (child) { return replaceSelfVars(child, dbn); }); }