refactor(core): Resolve partial self-references at Pocomath level

This commit is contained in:
Glen Whitney 2022-11-30 09:00:39 -05:00
parent c4b1ac9045
commit 269b9f5fc6

View File

@ -1147,7 +1147,6 @@ export default class PocomathInstance {
behavior) behavior)
behavior.resolved = true behavior.resolved = true
} }
this._correctPartialSelfRefs(name, tf_imps)
// Make sure we have all of the needed (template) types; and if they // Make sure we have all of the needed (template) types; and if they
// can't be added (because they have been instantiated too deep), // can't be added (because they have been instantiated too deep),
// ditch the signature: // ditch the signature:
@ -1306,7 +1305,6 @@ export default class PocomathInstance {
} }
const refs = {} const refs = {}
let full_self_referential = false let full_self_referential = false
let part_self_references = []
for (const dep of uses) { for (const dep of uses) {
let [func, needsig] = dep.split(/[()]/) let [func, needsig] = dep.split(/[()]/)
/* Safety check that can perhaps be removed: /* Safety check that can perhaps be removed:
@ -1322,18 +1320,13 @@ export default class PocomathInstance {
} }
if (func === 'self') { if (func === 'self') {
if (needsig) { if (needsig) {
/* Maybe we can resolve the self reference without troubling /* We now resolve all specific-signature self references
* typed-function: * here, without resorting to the facility in typed-function:
*/ */
if (needsig in imps && typeof imps[needsig] == 'function') { if (needsig in imps && typeof imps[needsig] == 'function') {
refs[dep] = imps[needsig] refs[dep] = imps[needsig]
continue continue
} }
if (full_self_referential) {
throw new SyntaxError(
'typed-function does not support mixed full and '
+ 'partial self-reference')
}
const needTypes = typesOfSignature(needsig) const needTypes = typesOfSignature(needsig)
const mergedTypes = Object.assign( const mergedTypes = Object.assign(
{}, this.Types, this.Templates) {}, this.Types, this.Templates)
@ -1348,11 +1341,6 @@ export default class PocomathInstance {
continue continue
} }
} else { } else {
if (part_self_references.length) {
throw new SyntaxError(
'typed-function does not support mixed full and '
+ 'partial self-reference')
}
full_self_referential = true full_self_referential = true
continue continue
} }
@ -1411,34 +1399,11 @@ export default class PocomathInstance {
return implementation return implementation
}) })
imps[signature].uses = uses imps[signature].uses = uses
if (!uses) {
throw new ReferenceError(`NANH uses for ${signature} from ${fromImp}`)
}
imps[signature].fromInstance = this imps[signature].fromInstance = this
imps[signature].instance = asInstance imps[signature].instance = asInstance
imps[signature].fromBehavior = fromImp imps[signature].fromBehavior = fromImp
return return
} }
if (part_self_references.length) {
/* There is an obstruction here. The list part_self_references
* might contain a signature that requires conversion for self to
* handle. But I advocated this not be allowed in typed.referTo, which
* made sense for human-written functions, but is unfortunate now.
* So we have to defer creating these and correct them later, at
* least until we can add an option to typed-function.
*/
imps[signature] = {
deferred: true,
builtRefs: refs,
sigDoes: does,
sigUses: uses,
fromInstance: this,
fromBehavior: fromImp,
instance: asInstance,
psr: part_self_references
}
return
}
const implementation = does(refs) const implementation = does(refs)
implementation.fromInstance = this implementation.fromInstance = this
implementation.fromBehavior = fromImp implementation.fromBehavior = fromImp
@ -1448,96 +1413,6 @@ export default class PocomathInstance {
imps[signature] = implementation imps[signature] = implementation
} }
_correctPartialSelfRefs(name, imps) {
let sawDeferral = true
while (sawDeferral) {
// We might generate some new partial self references in resolving
// the previously existing ones, so looping through the signatures
// once is not enough; we have to keep looping until there are no
// more deferrals
sawDeferral = false
for (const aSignature in imps) {
if (!(imps[aSignature].deferred)) continue
sawDeferral = true
const deferral = imps[aSignature]
const part_self_references = deferral.psr
const corrected_self_references = []
const remaining_self_references = []
const refs = deferral.builtRefs
for (const neededSig of part_self_references) {
// Have to find a match for neededSig among the other signatures
// of this function. That's a job for typed-function, but we will
// try here:
if (neededSig in imps) { // the easy case
corrected_self_references.push(neededSig)
remaining_self_references.push(neededSig)
continue
}
// No exact match, try to get one that matches with
// subtypes since the whole conversion thing in typed-function
// is too complicated to reproduce
let foundSig = this._findSubtypeImpl(name, imps, neededSig)
if (foundSig) {
corrected_self_references.push(foundSig)
remaining_self_references.push(neededSig)
} else {
// Maybe it's a template instance we don't yet have
foundSig = this._findSubtypeImpl(
name, this._imps[name], neededSig)
if (foundSig) {
const match = this._pocoFindSignature(name, neededSig)
const neededTemplate = match.fn._pocoSignature
const neededInstance = whichSigInstance(
neededSig, neededTemplate)
const neededImplementation =
this._instantiateTemplateImplementation(
name, neededTemplate, neededInstance)
if (!neededImplementation) {
refs[`self(${neededSig})`] = match.implementation
} else {
if (typeof neededImplementation === 'function') {
refs[`self(${neededSig})`] = neededImplementation
} else {
corrected_self_references.push(neededSig)
remaining_self_references.push(neededSig)
}
}
} else {
throw new Error(
'Implement inexact self-reference in typed-function for '
+ `${name}(${neededSig})`)
}
}
}
const does = deferral.sigDoes
if (remaining_self_references.length > 0) {
imps[aSignature] = this._typed.referTo(
...corrected_self_references, (...impls) => {
for (let i = 0; i < remaining_self_references.length; ++i) {
refs[`self(${remaining_self_references[i]})`] = impls[i]
}
const implementation = does(refs)
implementation.fromInstance = deferral.fromInstance
implementation.fromBehavior = deferral.fromBehavior
implementation.instance = deferral.instance
implementation.uses = deferral.sigUses
// What will we do with the return type info in here?
return implementation
}
)
} else {
imps[aSignature] = does(refs)
}
imps[aSignature]._pocoSignature = deferral._pocoSignature
imps[aSignature]._pocoInstance = deferral._pocoInstance
imps[aSignature].fromInstance = deferral.fromInstance
imps[aSignature].fromBehavior = deferral.fromBehavior
imps[aSignature].instance = deferral.instance
imps[aSignature].uses = deferral.sigUses
}
}
}
/* This function analyzes the template and makes sure the /* This function analyzes the template and makes sure the
* instantiations of it for type and all prior types of type are present * instantiations of it for type and all prior types of type are present
* in the instance. * in the instance.