From 0950d7d585b4daedb6dc271be9fe823777ee63ee Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Wed, 24 Aug 2022 19:34:33 -0400 Subject: [PATCH] feat(PocomathInstance): Specify return types of all core methods --- src/core/PocomathInstance.mjs | 68 +++++++++++++++++++---------------- src/ops/floor.mjs | 4 +-- test/_pocomath.mjs | 4 +++ 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/src/core/PocomathInstance.mjs b/src/core/PocomathInstance.mjs index 936ccfb..041177c 100644 --- a/src/core/PocomathInstance.mjs +++ b/src/core/PocomathInstance.mjs @@ -164,7 +164,7 @@ export default class PocomathInstance { * instantiation can be accomplished by prefixin the signature with an * exclamation point. */ - install(ops) { + install = Returns('void', function(ops) { if (ops instanceof PocomathInstance) { return _installInstance(ops) } @@ -197,7 +197,7 @@ export default class PocomathInstance { } } this._installFunctions(stdFunctions) - } + }) /* Merge any number of PocomathInstances or modules: */ static merge(name, ...pieces) { @@ -209,7 +209,7 @@ export default class PocomathInstance { } /* Determine the return type of an operation given an input signature */ - returnTypeOf(operation, signature) { + returnTypeOf = Returns('string', function(operation, signature) { for (const type of typeListOfSignature(signature)) { this._maybeInstantiate(type) } @@ -217,13 +217,20 @@ export default class PocomathInstance { operation = operation.name } const details = this._pocoFindSignature(operation, signature) - return returnTypeOf(details.fn, signature, this) - } + if (details) { + return returnTypeOf(details.fn, signature, this) + } + console.log('Checking return type of', operation) + return returnTypeOf(this[operation], signature, this) + }) /* Return a chain object for this instance with a given value: */ - chain(value) { - return makeChain(value, this, this._chainRepository) - } + chain = Returns( + sig => `Chain<${sig}>`, + function(value) { + return makeChain(value, this, this._chainRepository) + } + ) _installInstance(other) { for (const [type, spec] of Object.entries(other.Types)) { @@ -272,9 +279,9 @@ export default class PocomathInstance { for (const name of requiredSet) { for (const type of typeSet) { try { - const modName = `../${type}/${name}.mjs` - const mod = await import(modName) - this.install(mod) + const moduleName = `../${type}/${name}.mjs` + const module = await import(moduleName) + this.install(module) } catch (err) { if (!(err.message.includes('find'))) { // Not just a error because module doesn't exist @@ -315,7 +322,7 @@ export default class PocomathInstance { * Implementation note: unlike _installFunctions below, we can make * the corresponding changes to the _typed object immediately */ - installType(type, spec) { + installType = Returns('void', function(type, spec) { const parts = type.split(/[<,>]/) if (this._templateParam(parts[0])) { throw new SyntaxError( @@ -415,7 +422,7 @@ export default class PocomathInstance { const imp = {} imp[type] = {uses: new Set(), does: () => Returns('string', () => type)} this._installFunctions({typeOf: imp}) - } + }) _addSubtypeTo(sup, sub) { if (this.isSubtypeOf(sub, sup)) return @@ -428,47 +435,48 @@ export default class PocomathInstance { } /* Returns true if typeA is a subtype of type B */ - isSubtypeOf(typeA, typeB) { + isSubtypeOf = Returns('boolean', function(typeA, typeB) { return this._subtypes[typeB].includes(typeA) - } + }) /* Returns true if typeA is a subtype of or converts to type B */ - isPriorTo(typeA, typeB) { + isPriorTo = Returns('boolean', function(typeA, typeB) { if (!(typeB in this._priorTypes)) return false return this._priorTypes[typeB].has(typeA) - } + }) - /* Returns a list of the subtypes of a given type, in topological sorted - * order (i.e, no type on the list contains one that comes after it). + /* Returns a list of the strict ubtypes of a given type, in topological + * sorted order (i.e, no type on the list contains one that comes after it). */ - subtypesOf(type) { + subtypesOf = Returns('Array', function(type) { return this._subtypes[type] // should we clone? - } + }) /* Returns a list of the supertypes of a given type, starting with itself, * in topological order */ - supertypesOf(type) { + supertypesOf = Returns('Array', function(type) { const supList = [] while (type) { supList.push(type) type = this.Types[type].refines } return supList - } + }) /* Returns the most refined type containing all the types in the array, * with '' standing for the empty type for convenience. If the second * argument `convert` is true, a convertible type is considered a * a subtype (defaults to false). */ - joinTypes(types, convert) { + joinTypes = Returns('string', function(types, convert) { let join = '' for (const type of types) { join = this._joinTypes(join, type, convert) } return join - } + }) + /* helper for above */ _joinTypes(typeA, typeB, convert) { if (!typeA) return typeB @@ -500,9 +508,9 @@ export default class PocomathInstance { /* Returns a list of all types that have been mentioned in the * signatures of operations, but which have not actually been installed: */ - undefinedTypes() { + undefinedTypes = Returns('Array', function() { return Array.from(this._seenTypes).filter(t => !(t in this.Types)) - } + }) /* Used internally to install a template type */ _installTemplateType(type, spec) { @@ -1137,7 +1145,7 @@ export default class PocomathInstance { * Returns the name of the type if added, false if it was already there, * and undefined if the type is declined (because of being nested too deep). */ - instantiateTemplate(base, instantiator) { + instantiateTemplate = Returns('void', function(base, instantiator) { const depth = instantiator.split('<').length if (depth > this._maxDepthSeen ) { // don't bother with types much deeper thant we have seen @@ -1204,7 +1212,7 @@ export default class PocomathInstance { } this.installType(wantsType, newTypeSpec) return wantsType - } + }) _findSubtypeImpl(name, imps, neededSig) { if (neededSig in imps) return neededSig @@ -1305,7 +1313,7 @@ export default class PocomathInstance { } return result } - + _pocoresolve(name, sig, typedFunction) { if (!this._typed.isTypedFunction(typedFunction)) { typedFunction = this[name] diff --git a/src/ops/floor.mjs b/src/ops/floor.mjs index c2a23fc..2fbe106 100644 --- a/src/ops/floor.mjs +++ b/src/ops/floor.mjs @@ -13,8 +13,8 @@ export const floor = { * be separately activated */ bigint: () => Returns('bigint', x => x), - NumInt: () => Returns('NumInt', x => x), - 'Complex': () => Returns('Complex', x => x), + NumInt: () => Returns('NumInt', x => x), + 'Complex': () => Returns('Complex', x => x), number: ({'equalTT(number,number)': eq}) => Returns('NumInt', n => { if (eq(n, Math.round(n))) return Math.round(n) diff --git a/test/_pocomath.mjs b/test/_pocomath.mjs index 4d471dc..eb0481b 100644 --- a/test/_pocomath.mjs +++ b/test/_pocomath.mjs @@ -34,6 +34,10 @@ describe('The default full pocomath instance "math"', () => { math.add(3, math.complex(2.5, 1)), math.complex(5.5, 1)) assert.strictEqual( math.returnTypeOf('add', 'Complex,NumInt'), 'Complex') + assert.strictEqual( + math.returnTypeOf('chain', 'bigint'), 'Chain') + assert.strictEqual( + math.returnTypeOf('returnTypeOf', 'string,string'), 'string') }) it('can subtract numbers', () => {