UNPKG

@harmoniclabs/plu-ts-onchain

Version:

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

190 lines (188 loc) 8.3 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.psop = void 0; var addUtilityForType_1 = require("../../lib/std/UtilityTerms/addUtilityForType.js"); var utils_1 = require("../../type_system/utils.js"); var types_1 = require("../../type_system/types.js"); var type_system_1 = require("../../type_system/index.js"); var Term_1 = require("../../Term/index.js"); var PType_1 = require("../../PType/index.js"); var obj_utils_1 = require("@harmoniclabs/obj-utils"); var assert_1 = require("../../../utils/assert.js"); var IRConstr_1 = require("../../../IR/IRNodes/IRConstr.js"); /** * intermediate class useful to reconise structs form primitives */ var _PSop = /** @class */ (function (_super) { __extends(_PSop, _super); function _PSop() { return _super.call(this) || this; } return _PSop; }(PType_1.PType)); function isSopInstanceOfDefinition(structInstance, definition) { var jsSopFieldsNames = Object.keys(structInstance); var defKeys = Object.keys(definition); return (jsSopFieldsNames.length === defKeys.length && defKeys.every(function (defFieldName) { return jsSopFieldsNames.includes(defFieldName); }) && jsSopFieldsNames.every(function (fieldKey) { return definition[fieldKey] !== undefined && // every field's value is a Term structInstance[fieldKey] instanceof Term_1.Term /*thisCtorDef[fieldKey]*/ && (0, type_system_1.typeExtends)(structInstance[fieldKey].type, definition[fieldKey]); })); } var RESERVED_STRUCT_KEYS = Object.freeze([ "eq", "peq", "extract", "in", "raw" ]); /** * * @param {SopDef} def data-type definition of the sop * * each property of the object is a possible constructor for the sop; * * each constructor is defined by specifiying the fields that constructor expects and relative types * * @example * ```ts * const Shape = pstruct({ * Circle: { * radius: int * }, * Rectangle: { * fstSide: int, * sndSide: int * } * }); * ``` * * @param {( self_t: SopT<SopDef,{}> ) => Methods} getMethods (optional) function to implement arbitrary methods on a given sop. * * the function takes as first argument the type of this same sop and expects an object with various methods to be implemented on a sop instance * * @example * ```ts * const Shape = pstruct({ * Circle: { * radius: int * }, * Rectangle: { * fstSide: int, * sndSide: int * } * }, ( self_t ) => { * * return { * largestSide: pfn([ self_t ], int ) * ( self => * pmatch( self ) * .onCircle(({ radius }) => radius ) * .onRectangle({ fstSide, sndSide } => * pif( int ).$( fstSide.gt( sndSide ) ) * .then( fstSide ) * .else( sndSide ) * ) * ) * }; * }); * * const isLargeShape = pfn([ Shape.type ], int ) * ( shape => shape.largestSide.gtEq( 100 ) ) * ``` */ function psop(def, getMethods) { (0, assert_1.assert)((0, type_system_1.isSopDefinition)(def), "cannot construct 'PSop' type; sop definition is not constant: " + (0, utils_1.structDefToString)(def)); getMethods = typeof getMethods === "function" ? getMethods : function (_self_t) { return {}; }; var PSopExt = /** @class */ (function (_super) { __extends(PSopExt, _super); // private constructors are not a thing at js runtime // in any case constructing an instance is useless // private allows the typescript LSP to rise errors (not runtime) whet trying to extend the class function PSopExt() { return _super.call(this) || this; } PSopExt._isPType = true; return PSopExt; }(_PSop)); var noMethodsType = (0, types_1.sop)(def); var methods = getMethods(noMethodsType); var thisSopType = (0, types_1.sop)(def, methods); (0, obj_utils_1.defineReadOnlyProperty)(PSopExt, "type", thisSopType); (0, obj_utils_1.defineReadOnlyProperty)(PSopExt, "termType", thisSopType); var constructors = Object.keys(def); (0, assert_1.assert)(constructors.length >= 1, "sop definition requires at least 1 constructor"); var _loop_1 = function (i) { var ctorName = constructors[i]; (0, obj_utils_1.defineReadOnlyProperty)(PSopExt.prototype, ctorName, function (jsSop) { var e_1, _a; (0, assert_1.assert)((0, obj_utils_1.isObject)(jsSop), "cannot build a plu-ts structure if the input is not an object with named fields"); var thisCtorDef = def[ctorName]; // const jsSopFieldsNames = Object.keys( jsSop ); // order of fields in the 'jsSop' migth be different than the order of the definiton // to preserve the order we need to use the keys got form the ctor definition var ctorDefFieldsNames = Object.keys(thisCtorDef); try { for (var ctorDefFieldsNames_1 = (e_1 = void 0, __values(ctorDefFieldsNames)), ctorDefFieldsNames_1_1 = ctorDefFieldsNames_1.next(); !ctorDefFieldsNames_1_1.done; ctorDefFieldsNames_1_1 = ctorDefFieldsNames_1.next()) { var fieldName = ctorDefFieldsNames_1_1.value; if (RESERVED_STRUCT_KEYS.includes(fieldName)) { throw new Error("\"".concat(fieldName, "\" is a reserved sop key; it can't be used as custom sop property.")); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (ctorDefFieldsNames_1_1 && !ctorDefFieldsNames_1_1.done && (_a = ctorDefFieldsNames_1.return)) _a.call(ctorDefFieldsNames_1); } finally { if (e_1) throw e_1.error; } } if (ctorDefFieldsNames.length === 0) { return (0, addUtilityForType_1.addUtilityForType)(thisSopType)(new Term_1.Term(thisSopType, function (_dbn) { return new IRConstr_1.IRConstr(0, []); })); } // still we must be sure that the jsSop has at least all the fields (0, assert_1.assert)(isSopInstanceOfDefinition(jsSop, thisCtorDef), "the fields passed do not match the sop definition for constructor: " + ctorName); return (0, addUtilityForType_1.addUtilityForType)(thisSopType)(new Term_1.Term(thisSopType, function (cfg, dbn) { return new IRConstr_1.IRConstr(i, ctorDefFieldsNames.map(function (fieldKey) { return jsSop[fieldKey].toIR(cfg, dbn); })); })); }); (0, obj_utils_1.defineReadOnlyProperty)(PSopExt, ctorName, PSopExt.prototype[ctorName]); }; // define constructors for (var i = 0; i < constructors.length; i++) { _loop_1(i); } /* Type 'typeof PSopExt' is not assignable to type 'PSop<SopDef>' Why is this? */ return PSopExt; } exports.psop = psop;