diff --git a/src/core/PocomathInstance.mjs b/src/core/PocomathInstance.mjs index 215ef74..9f9520b 100644 --- a/src/core/PocomathInstance.mjs +++ b/src/core/PocomathInstance.mjs @@ -2,7 +2,7 @@ import typed from 'typed-function' import {makeChain} from './Chain.mjs' import {dependencyExtractor, generateTypeExtractor} from './extractors.mjs' -import {R_, isReturnAnnotated} from './returns.mjs' +import R_ from './returns.mjs' import {typeListOfSignature, typesOfSignature, subsetOfKeys} from './utils.mjs' const anySpec = {} // fixed dummy specification of 'any' type @@ -693,7 +693,7 @@ export default class PocomathInstance { } /* Now build the catchall implementation */ const self = this - /* For return-type annotation, we will have to fix this to + /* For return type annotation, we may have to fix this to propagate the return type. At the moment we are just bagging */ const patch = (refs) => (...args) => { @@ -815,12 +815,9 @@ export default class PocomathInstance { } } // Finally ready to make the call. - let returnSpec = behavior.does(innerRefs) - if (isReturnAnnotated(returnSpec)) { - // for now just drop return type information - returnSpec = returnSpec.via - } - return returnSpec(...args) + const implementation = behavior.does(innerRefs) + // Could do something with return type information here + return implementation(...args) } // The actual uses value needs to be a set: const outerUses = new Set(Object.values(simplifiedUses)) @@ -862,12 +859,9 @@ export default class PocomathInstance { _addTFimplementation(imps, signature, behavior) { const {uses, does} = behavior if (uses.length === 0) { - let returnSpec = does() - if (isReturnAnnotated(returnSpec)) { - // for now just dump the return information - returnSpec = returnSpec.via - } - imps[signature] = returnSpec + const implementation = does() + // could do something with return type information here + imps[signature] = implementation return } const refs = {} @@ -927,13 +921,9 @@ export default class PocomathInstance { if (full_self_referential) { imps[signature] = this._typed.referToSelf(self => { refs.self = self - let returnSpec = does(refs) - if (isReturnAnnotated(returnSpec)) { - // What are we going to do with the return type info in here? - // Anyhow, drop it for now - returnSpec = returnSpec.via - } - return returnSpec + const implementation = does(refs) + // What are we going to do with the return type info in here? + return implementation }) return } @@ -953,12 +943,9 @@ export default class PocomathInstance { } return } - let returnSpec = does(refs) - if (isReturnAnnotated(returnSpec)) { - // drop return type for now - returnSpec = returnSpec.via - } - imps[signature] = returnSpec + const implementation = does(refs) + // could do something with return type information here + imps[signature] = implementation } _correctPartialSelfRefs(name, imps) { @@ -993,13 +980,9 @@ export default class PocomathInstance { for (let i = 0; i < part_self_references.length; ++i) { refs[`self(${part_self_references[i]})`] = impls[i] } - let returnSpec = does(refs) - if (isReturnAnnotated(returnSpec)) { - // What will we do with the return type info in here? - // anyhow, drop it for now - returnSpec = returnSpec.via - } - return returnSpec + const implementation = does(refs) + // What will we do with the return type info in here? + return implementation } ) } diff --git a/src/core/returns.mjs b/src/core/returns.mjs index d51e667..1c236c4 100644 --- a/src/core/returns.mjs +++ b/src/core/returns.mjs @@ -1,10 +1,28 @@ /* Annotate a function with its return type */ -export function R_(type, fn) { - return {returns: type, via: fn} + +/* Unfortunately JavaScript is missing a way to cleanly clone a function + * object, see https://stackoverflow.com/questions/1833588 + */ + +const clonedFrom = Symbol('the original function this one was cloned from') +function cloneFunction(fn) { + const behavior = fn[clonedFrom] || fn // don't nest clones + const theClone = function () { return behavior.apply(this, arguments) } + Object.assign(theClone, fn) + theClone[clonedFrom] = body + Object.defineProperty( + theClone, 'name', {value: fn.name, configurable: true }) + return theClone } -export function isReturnAnnotated(x) { - return x && typeof x === 'object' && 'returns' in x && 'via' in x +export function R_(type, fn) { + if ('returns' in fn) fn = cloneFunction(fn) + fn.returns = type + return fn +} + +export function returnTypeOf(fn) { + return fn.returns || 'any' } export default R_