UNPKG

@harmoniclabs/plu-ts-onchain

Version:

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

152 lines (151 loc) 5.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.typeExtends = exports.sopDefExtends = void 0; var isTaggedAsAlias_1 = require("./kinds/isTaggedAsAlias.js"); var isWellFormedType_1 = require("./kinds/isWellFormedType.js"); var tyArgs_1 = require("./tyArgs/index.js"); var unwrapAlias_1 = require("./tyArgs/unwrapAlias.js"); var types_1 = require("./types.js"); function isSymbol(stuff) { return typeof stuff === "symbol"; } /** * * @param a extending ctor * @param b extended ctor * @returns */ function ctorDefExtends(a, b, subs) { if (subs === void 0) { subs = []; } var aFields = Object.keys(a); var bFields = Object.keys(b); if (aFields.length !== bFields.length) return false; function findSym(tVar) { return subs.find(function (pair) { return pair.tyVar === tVar; }); } for (var i = 0; i < aFields.length; i++) { // fields have to have the same order; // oterwhise it would imply a different order in the `Data` onchain if (aFields[i] !== bFields[i]) return false; var field = aFields[i]; if (isSymbol(b[field][0])) { var tyVar = b[field][0]; var tyArg = a[field]; var thisTyParam = findSym(tyVar); if (thisTyParam === undefined) { subs.push({ tyVar: tyVar, tyArg: tyArg }); continue; } if (isSymbol(tyArg[0])) { if (tyArg[0] === thisTyParam.tyArg[0]) continue; else return false; } // type argument corresponding to type var doesn't match some of the argument previously found // covers case of generic 'tyArg' if (!typeExtends(tyArg, thisTyParam.tyArg /*, subs */)) return false; if (!typeExtends(thisTyParam.tyArg, tyArg /*, subs */)) { // this type arument is more general than the previous registered thisTyParam.tyArg = tyArg; continue; } continue; } if (!typeExtends(a[field], b[field] /*, subs */)) return false; } return true; } function sopDefExtends(extendingDef, sDef, subs) { if (subs === void 0) { subs = []; } var ctorNames = Object.keys(sDef); var extendingCtors = Object.keys(extendingDef); if (ctorNames.length !== extendingCtors.length) return false; // first check the names only in order // not to do useless (potentially expensive) // ctor definiton extension checks for (var i = 0; i < ctorNames.length; i++) { if ( // ctors have to be in the same position; otherwhise is a different struct; ctorNames[i] !== extendingCtors[i]) return false; } for (var i = 0; i < ctorNames.length; i++) { if ( // check for the same fields and the extending types to extend the given struct ones !ctorDefExtends(extendingDef[extendingCtors[i]], sDef[ctorNames[i]], subs)) return false; } return true; } exports.sopDefExtends = sopDefExtends; /* * equivalent to ```A extends B``` but at plu-ts level */ function typeExtends(extending, extended) { if (!((0, isWellFormedType_1.isWellFormedType)(extending) && (0, isWellFormedType_1.isWellFormedGenericType)(extended))) return false; return uncheckedTypeExtends(extending, extended); } exports.typeExtends = typeExtends; function uncheckedTypeExtends(a, b) { if ((0, isTaggedAsAlias_1.isTaggedAsAlias)(b)) return uncheckedTypeExtends(a, (0, unwrapAlias_1.unwrapAlias)(b)); if ((0, isTaggedAsAlias_1.isTaggedAsAlias)(a)) return uncheckedTypeExtends((0, unwrapAlias_1.unwrapAlias)(a), b); if (typeof b[0] === "symbol") return true; if (b[0] === types_1.PrimType.Data) { return (a[0] === types_1.PrimType.Data || a[0] === types_1.PrimType.Struct || a[0] === types_1.PrimType.AsData); } if (b[0] === types_1.PrimType.AsData) { return ((a[0] === types_1.PrimType.AsData && uncheckedTypeExtends(a[1], b[1])) || a[0] === types_1.PrimType.Struct || a[0] === types_1.PrimType.Data); } if (b[0] === types_1.PrimType.Pair) { // `getFstT` and `getSndT` unwraps `alias`es and `asData`s return (a[0] === types_1.PrimType.Pair && (uncheckedTypeExtends((0, tyArgs_1.getFstT)(a), (0, tyArgs_1.getFstT)(b))) && (uncheckedTypeExtends((0, tyArgs_1.getSndT)(a), (0, tyArgs_1.getSndT)(b)))); } if (a[0] === types_1.PrimType.AsData) { // checked above // if( b[0] === PrimType.Data ) return true; // if( b[0] === PrimType.AsData ) return uncheckedTypeExtends( a[1], b[1] ); return b[0] === types_1.PrimType.Struct; } if (b[0] === types_1.PrimType.Sop) return (0, isWellFormedType_1.isSopType)(a) && sopDefExtends(a[1], b[1]); if (a[0] === types_1.PrimType.Sop) return false; // b must have been a SoP too if (b[0] === types_1.PrimType.Struct) return (0, isWellFormedType_1.isStructType)(a) && sopDefExtends(a[1], b[1]); // if a is a sturct but b is not // make sure b extends `data` at least if ((0, isWellFormedType_1.isStructType)(a)) return uncheckedTypeExtends(b, types_1.data); var bTyArgs = b.slice(1); var aTyArgs = a.slice(1); return ( // any other prim type that requires parameters a[0] === b[0] && // same n parameters aTyArgs.length === bTyArgs.length && // must have correct parameters following aTyArgs.every(function (aTyArg, idx) { return uncheckedTypeExtends(aTyArg, bTyArgs[idx]); })); }