|
|
@ -2,7 +2,7 @@
|
|
|
|
import typed from 'typed-function'
|
|
|
|
import typed from 'typed-function'
|
|
|
|
import {makeChain} from './Chain.mjs'
|
|
|
|
import {makeChain} from './Chain.mjs'
|
|
|
|
import {dependencyExtractor, generateTypeExtractor} from './extractors.mjs'
|
|
|
|
import {dependencyExtractor, generateTypeExtractor} from './extractors.mjs'
|
|
|
|
import {R_, returnTypeOf} from './returns.mjs'
|
|
|
|
import {Returns, returnTypeOf} from './Returns.mjs'
|
|
|
|
import {typeListOfSignature, typesOfSignature, subsetOfKeys} from './utils.mjs'
|
|
|
|
import {typeListOfSignature, typesOfSignature, subsetOfKeys} from './utils.mjs'
|
|
|
|
|
|
|
|
|
|
|
|
const anySpec = {} // fixed dummy specification of 'any' type
|
|
|
|
const anySpec = {} // fixed dummy specification of 'any' type
|
|
|
@ -13,7 +13,9 @@ const templateFromParam = 'U' // For defining covariant conversions
|
|
|
|
/* Returns a new signature just like sig but with the parameter replaced by
|
|
|
|
/* Returns a new signature just like sig but with the parameter replaced by
|
|
|
|
* the type
|
|
|
|
* the type
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function substituteInSig(sig, parameter, type) {
|
|
|
|
const upperBounds = /\s*[(]=\s*(\w*)\s*/g
|
|
|
|
|
|
|
|
function substituteInSignature(signature, parameter, type) {
|
|
|
|
|
|
|
|
const sig = signature.replaceAll(upperBounds, '')
|
|
|
|
const pattern = new RegExp("\\b" + parameter + "\\b", 'g')
|
|
|
|
const pattern = new RegExp("\\b" + parameter + "\\b", 'g')
|
|
|
|
return sig.replaceAll(pattern, type)
|
|
|
|
return sig.replaceAll(pattern, type)
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -30,12 +32,14 @@ export default class PocomathInstance {
|
|
|
|
'install',
|
|
|
|
'install',
|
|
|
|
'installType',
|
|
|
|
'installType',
|
|
|
|
'instantiateTemplate',
|
|
|
|
'instantiateTemplate',
|
|
|
|
|
|
|
|
'isPriorTo',
|
|
|
|
'isSubtypeOf',
|
|
|
|
'isSubtypeOf',
|
|
|
|
'joinTypes',
|
|
|
|
'joinTypes',
|
|
|
|
'name',
|
|
|
|
'name',
|
|
|
|
'returnTypeOf',
|
|
|
|
'returnTypeOf',
|
|
|
|
'self',
|
|
|
|
'self',
|
|
|
|
'subtypesOf',
|
|
|
|
'subtypesOf',
|
|
|
|
|
|
|
|
'supertypesOf',
|
|
|
|
'Templates',
|
|
|
|
'Templates',
|
|
|
|
'typeOf',
|
|
|
|
'typeOf',
|
|
|
|
'Types',
|
|
|
|
'Types',
|
|
|
@ -88,7 +92,7 @@ export default class PocomathInstance {
|
|
|
|
|
|
|
|
|
|
|
|
this._installFunctions({
|
|
|
|
this._installFunctions({
|
|
|
|
typeOf: {
|
|
|
|
typeOf: {
|
|
|
|
ground: {uses: new Set(), does: () => R_('string', () => 'any')}
|
|
|
|
ground: {uses: new Set(), does: () => Returns('string', () => 'any')}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
@ -202,7 +206,7 @@ export default class PocomathInstance {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!(this._typed.isTypedFunction(operation))) return 'any'
|
|
|
|
if (!(this._typed.isTypedFunction(operation))) return 'any'
|
|
|
|
const details = this._typed.findSignature(operation, signature)
|
|
|
|
const details = this._typed.findSignature(operation, signature)
|
|
|
|
return returnTypeOf(details.fn)
|
|
|
|
return returnTypeOf(details.fn, signature, this)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Return a chain object for this instance with a given value: */
|
|
|
|
/* Return a chain object for this instance with a given value: */
|
|
|
@ -398,7 +402,7 @@ export default class PocomathInstance {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// update the typeOf function
|
|
|
|
// update the typeOf function
|
|
|
|
const imp = {}
|
|
|
|
const imp = {}
|
|
|
|
imp[type] = {uses: new Set(), does: () => R_('string', () => type)}
|
|
|
|
imp[type] = {uses: new Set(), does: () => Returns('string', () => type)}
|
|
|
|
this._installFunctions({typeOf: imp})
|
|
|
|
this._installFunctions({typeOf: imp})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -412,18 +416,36 @@ export default class PocomathInstance {
|
|
|
|
supSubs.splice(i, 0, sub)
|
|
|
|
supSubs.splice(i, 0, sub)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Returns true is typeA is a subtype of type B */
|
|
|
|
/* Returns true if typeA is a subtype of type B */
|
|
|
|
isSubtypeOf(typeA, typeB) {
|
|
|
|
isSubtypeOf(typeA, typeB) {
|
|
|
|
return this._subtypes[typeB].includes(typeA)
|
|
|
|
return this._subtypes[typeB].includes(typeA)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Returns true if typeA is a subtype of or converts to type B */
|
|
|
|
|
|
|
|
isPriorTo(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
|
|
|
|
/* 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).
|
|
|
|
* order (i.e, no type on the list contains one that comes after it).
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
subtypesOf(type) {
|
|
|
|
subtypesOf(type) {
|
|
|
|
// HERE! For this to work, have to maintain subtypes as a sorted list.
|
|
|
|
|
|
|
|
return this._subtypes[type] // should we clone?
|
|
|
|
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) {
|
|
|
|
|
|
|
|
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,
|
|
|
|
/* Returns the most refined type containing all the types in the array,
|
|
|
|
* with '' standing for the empty type for convenience. If the second
|
|
|
|
* with '' standing for the empty type for convenience. If the second
|
|
|
|
* argument `convert` is true, a convertible type is considered a
|
|
|
|
* argument `convert` is true, a convertible type is considered a
|
|
|
@ -488,7 +510,7 @@ export default class PocomathInstance {
|
|
|
|
const imp = {}
|
|
|
|
const imp = {}
|
|
|
|
imp[type] = {
|
|
|
|
imp[type] = {
|
|
|
|
uses: new Set(['T']),
|
|
|
|
uses: new Set(['T']),
|
|
|
|
does: ({T}) => R_('string', () => `${base}<${T}>`)
|
|
|
|
does: ({T}) => Returns('string', () => `${base}<${T}>`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this._installFunctions({typeOf: imp})
|
|
|
|
this._installFunctions({typeOf: imp})
|
|
|
|
|
|
|
|
|
|
|
@ -628,7 +650,7 @@ export default class PocomathInstance {
|
|
|
|
/* Check if it's an ordinary non-template signature */
|
|
|
|
/* Check if it's an ordinary non-template signature */
|
|
|
|
let explicit = true
|
|
|
|
let explicit = true
|
|
|
|
for (const type of typesOfSignature(rawSignature)) {
|
|
|
|
for (const type of typesOfSignature(rawSignature)) {
|
|
|
|
for (const word of type.split(/[<>]/)) {
|
|
|
|
for (const word of type.split(/[<>(=\s]/)) {
|
|
|
|
if (this._templateParam(word)) {
|
|
|
|
if (this._templateParam(word)) {
|
|
|
|
explicit = false
|
|
|
|
explicit = false
|
|
|
|
break
|
|
|
|
break
|
|
|
@ -640,14 +662,26 @@ export default class PocomathInstance {
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* It's a template, have to instantiate */
|
|
|
|
/* It's a template, have to instantiate */
|
|
|
|
|
|
|
|
/* First, find any upper bounds on the instantation */
|
|
|
|
|
|
|
|
/* TODO: handle multiple upper bounds */
|
|
|
|
|
|
|
|
upperBounds.lastIndex = 0
|
|
|
|
|
|
|
|
let ubType = upperBounds.exec(rawSignature)
|
|
|
|
|
|
|
|
if (ubType) {
|
|
|
|
|
|
|
|
ubType = ubType[1]
|
|
|
|
|
|
|
|
if (!ubType in this.Types) {
|
|
|
|
|
|
|
|
throw new TypeError(
|
|
|
|
|
|
|
|
`Unknown type upper bound '${ubType}' in '${rawSignature}'`)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
/* First, add the known instantiations, gathering all types needed */
|
|
|
|
/* First, add the known instantiations, gathering all types needed */
|
|
|
|
if (!('instantiations' in behavior)) {
|
|
|
|
if (!('instantiations' in behavior)) {
|
|
|
|
behavior.instantiations = new Set()
|
|
|
|
behavior.instantiations = new Set()
|
|
|
|
|
|
|
|
if (ubType) behavior.instantiations.add(ubType)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let instantiationSet = new Set()
|
|
|
|
let instantiationSet = new Set()
|
|
|
|
for (const instType of behavior.instantiations) {
|
|
|
|
for (const instType of behavior.instantiations) {
|
|
|
|
instantiationSet.add(instType)
|
|
|
|
instantiationSet.add(instType)
|
|
|
|
for (const other of this._priorTypes[instType]) {
|
|
|
|
for (const other of this.subtypesOf(instType)) {
|
|
|
|
instantiationSet.add(other)
|
|
|
|
instantiationSet.add(other)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -656,7 +690,7 @@ export default class PocomathInstance {
|
|
|
|
if (!(instType in this.Types)) continue
|
|
|
|
if (!(instType in this.Types)) continue
|
|
|
|
if (this.Types[instType] === anySpec) continue
|
|
|
|
if (this.Types[instType] === anySpec) continue
|
|
|
|
const signature =
|
|
|
|
const signature =
|
|
|
|
substituteInSig(rawSignature, theTemplateParam, instType)
|
|
|
|
substituteInSignature(rawSignature, theTemplateParam, instType)
|
|
|
|
/* Don't override an explicit implementation: */
|
|
|
|
/* Don't override an explicit implementation: */
|
|
|
|
if (signature in imps) continue
|
|
|
|
if (signature in imps) continue
|
|
|
|
/* Don't go too deep */
|
|
|
|
/* Don't go too deep */
|
|
|
@ -670,7 +704,7 @@ export default class PocomathInstance {
|
|
|
|
const uses = new Set()
|
|
|
|
const uses = new Set()
|
|
|
|
for (const dep of behavior.uses) {
|
|
|
|
for (const dep of behavior.uses) {
|
|
|
|
if (this._templateParam(dep)) continue
|
|
|
|
if (this._templateParam(dep)) continue
|
|
|
|
uses.add(substituteInSig(dep, theTemplateParam, instType))
|
|
|
|
uses.add(substituteInSignature(dep, theTemplateParam, instType))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const patch = (refs) => {
|
|
|
|
const patch = (refs) => {
|
|
|
|
const innerRefs = {}
|
|
|
|
const innerRefs = {}
|
|
|
@ -678,7 +712,7 @@ export default class PocomathInstance {
|
|
|
|
if (this._templateParam(dep)) {
|
|
|
|
if (this._templateParam(dep)) {
|
|
|
|
innerRefs[dep] = instType
|
|
|
|
innerRefs[dep] = instType
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
const outerName = substituteInSig(
|
|
|
|
const outerName = substituteInSignature(
|
|
|
|
dep, theTemplateParam, instType)
|
|
|
|
dep, theTemplateParam, instType)
|
|
|
|
innerRefs[dep] = refs[outerName]
|
|
|
|
innerRefs[dep] = refs[outerName]
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -689,11 +723,13 @@ export default class PocomathInstance {
|
|
|
|
tf_imps, signature, {uses, does: patch})
|
|
|
|
tf_imps, signature, {uses, does: patch})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Now add the catchall signature */
|
|
|
|
/* Now add the catchall signature */
|
|
|
|
|
|
|
|
/* (Not needed if if it's a bounded template) */
|
|
|
|
|
|
|
|
if (ubType) continue
|
|
|
|
let templateCall = `<${theTemplateParam}>`
|
|
|
|
let templateCall = `<${theTemplateParam}>`
|
|
|
|
/* Relying here that the base of 'Foo<T>' is 'Foo': */
|
|
|
|
/* Relying here that the base of 'Foo<T>' is 'Foo': */
|
|
|
|
let baseSignature = rawSignature.replaceAll(templateCall, '')
|
|
|
|
let baseSignature = rawSignature.replaceAll(templateCall, '')
|
|
|
|
/* Any remaining template params are top-level */
|
|
|
|
/* Any remaining template params are top-level */
|
|
|
|
const signature = substituteInSig(
|
|
|
|
const signature = substituteInSignature(
|
|
|
|
baseSignature, theTemplateParam, 'ground')
|
|
|
|
baseSignature, theTemplateParam, 'ground')
|
|
|
|
/* The catchall signature has to detect the actual type of the call
|
|
|
|
/* The catchall signature has to detect the actual type of the call
|
|
|
|
* and add the new instantiations.
|
|
|
|
* and add the new instantiations.
|
|
|
@ -718,7 +754,8 @@ export default class PocomathInstance {
|
|
|
|
for (const dep of behavior.uses) {
|
|
|
|
for (const dep of behavior.uses) {
|
|
|
|
let [func, needsig] = dep.split(/[()]/)
|
|
|
|
let [func, needsig] = dep.split(/[()]/)
|
|
|
|
if (needsig) {
|
|
|
|
if (needsig) {
|
|
|
|
const subsig = substituteInSig(needsig, theTemplateParam, '')
|
|
|
|
const subsig = substituteInSignature(
|
|
|
|
|
|
|
|
needsig, theTemplateParam, '')
|
|
|
|
if (subsig === needsig) {
|
|
|
|
if (subsig === needsig) {
|
|
|
|
simplifiedUses[dep] = dep
|
|
|
|
simplifiedUses[dep] = dep
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -789,7 +826,7 @@ export default class PocomathInstance {
|
|
|
|
self._maxDepthSeen = depth
|
|
|
|
self._maxDepthSeen = depth
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Generate the list of actual wanted types */
|
|
|
|
/* Generate the list of actual wanted types */
|
|
|
|
const wantTypes = parTypes.map(type => substituteInSig(
|
|
|
|
const wantTypes = parTypes.map(type => substituteInSignature(
|
|
|
|
type, theTemplateParam, instantiateFor))
|
|
|
|
type, theTemplateParam, instantiateFor))
|
|
|
|
/* Now we have to add any actual types that are relevant
|
|
|
|
/* Now we have to add any actual types that are relevant
|
|
|
|
* to this invocation. Namely, that would be every formal parameter
|
|
|
|
* to this invocation. Namely, that would be every formal parameter
|
|
|
@ -811,7 +848,7 @@ export default class PocomathInstance {
|
|
|
|
if (wantType.slice(0,3) === '...') {
|
|
|
|
if (wantType.slice(0,3) === '...') {
|
|
|
|
wantType = wantType.slice(3)
|
|
|
|
wantType = wantType.slice(3)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wantType = substituteInSig(
|
|
|
|
wantType = substituteInSignature(
|
|
|
|
wantType, theTemplateParam, instantiateFor)
|
|
|
|
wantType, theTemplateParam, instantiateFor)
|
|
|
|
if (wantType !== parTypes[i]) {
|
|
|
|
if (wantType !== parTypes[i]) {
|
|
|
|
args[j] = self._typed.convert(args[j], wantType)
|
|
|
|
args[j] = self._typed.convert(args[j], wantType)
|
|
|
@ -840,7 +877,7 @@ export default class PocomathInstance {
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
let [func, needsig] = dep.split(/[()]/)
|
|
|
|
let [func, needsig] = dep.split(/[()]/)
|
|
|
|
if (self._typed.isTypedFunction(refs[simplifiedDep])) {
|
|
|
|
if (self._typed.isTypedFunction(refs[simplifiedDep])) {
|
|
|
|
const subsig = substituteInSig(
|
|
|
|
const subsig = substituteInSignature(
|
|
|
|
needsig, theTemplateParam, instantiateFor)
|
|
|
|
needsig, theTemplateParam, instantiateFor)
|
|
|
|
let resname = simplifiedDep
|
|
|
|
let resname = simplifiedDep
|
|
|
|
if (resname == 'self') resname = name
|
|
|
|
if (resname == 'self') resname = name
|
|
|
@ -890,8 +927,8 @@ export default class PocomathInstance {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Adapts Pocomath-style behavior specification (uses, does) for signature
|
|
|
|
/* Adapts Pocomath-style behavior specification (uses, does) for signature
|
|
|
|
* to typed-function implementations and inserts the result into plain object
|
|
|
|
* to typed-function implementations and inserts the result into plain
|
|
|
|
* imps
|
|
|
|
* object imps
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
_addTFimplementation(imps, signature, behavior) {
|
|
|
|
_addTFimplementation(imps, signature, behavior) {
|
|
|
|
const {uses, does} = behavior
|
|
|
|
const {uses, does} = behavior
|
|
|
@ -910,7 +947,7 @@ export default class PocomathInstance {
|
|
|
|
* Verify that the desired signature has been fully grounded:
|
|
|
|
* Verify that the desired signature has been fully grounded:
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
if (needsig) {
|
|
|
|
if (needsig) {
|
|
|
|
const trysig = substituteInSig(needsig, theTemplateParam, '')
|
|
|
|
const trysig = substituteInSignature(needsig, theTemplateParam, '')
|
|
|
|
if (trysig !== needsig) {
|
|
|
|
if (trysig !== needsig) {
|
|
|
|
throw new Error(
|
|
|
|
throw new Error(
|
|
|
|
'Attempt to add a template implementation: ' +
|
|
|
|
'Attempt to add a template implementation: ' +
|
|
|
@ -1051,8 +1088,9 @@ export default class PocomathInstance {
|
|
|
|
return resultingTypes
|
|
|
|
return resultingTypes
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Maybe add the instantiation of template type base with argument tyoe
|
|
|
|
/* Maybe add the instantiation of template type base with argument type
|
|
|
|
* instantiator to the Types of this instance, if it hasn't happened already.
|
|
|
|
* instantiator to the Types of this instance, if it hasn't happened
|
|
|
|
|
|
|
|
* already.
|
|
|
|
* Returns the name of the type if added, false if it was already there,
|
|
|
|
* 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).
|
|
|
|
* and undefined if the type is declined (because of being nested too deep).
|
|
|
|
*/
|
|
|
|
*/
|
|
|
@ -1081,7 +1119,7 @@ export default class PocomathInstance {
|
|
|
|
if (template.before) {
|
|
|
|
if (template.before) {
|
|
|
|
for (const beforeTmpl of template.before) {
|
|
|
|
for (const beforeTmpl of template.before) {
|
|
|
|
beforeTypes.push(
|
|
|
|
beforeTypes.push(
|
|
|
|
substituteInSig(beforeTmpl, theTemplateParam, instantiator))
|
|
|
|
substituteInSignature(beforeTmpl, theTemplateParam, instantiator))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (beforeTypes.length > 0) {
|
|
|
|
if (beforeTypes.length > 0) {
|
|
|
@ -1090,7 +1128,7 @@ export default class PocomathInstance {
|
|
|
|
newTypeSpec.test = template.test(this._typeTests[instantiator])
|
|
|
|
newTypeSpec.test = template.test(this._typeTests[instantiator])
|
|
|
|
if (template.from) {
|
|
|
|
if (template.from) {
|
|
|
|
for (let source in template.from) {
|
|
|
|
for (let source in template.from) {
|
|
|
|
const instSource = substituteInSig(
|
|
|
|
const instSource = substituteInSignature(
|
|
|
|
source, theTemplateParam, instantiator)
|
|
|
|
source, theTemplateParam, instantiator)
|
|
|
|
let usesFromParam = false
|
|
|
|
let usesFromParam = false
|
|
|
|
for (const word of instSource.split(/[<>]/)) {
|
|
|
|
for (const word of instSource.split(/[<>]/)) {
|
|
|
@ -1101,14 +1139,14 @@ export default class PocomathInstance {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (usesFromParam) {
|
|
|
|
if (usesFromParam) {
|
|
|
|
for (const iFrom in instantiatorSpec.from) {
|
|
|
|
for (const iFrom in instantiatorSpec.from) {
|
|
|
|
const finalSource = substituteInSig(
|
|
|
|
const finalSource = substituteInSignature(
|
|
|
|
instSource, templateFromParam, iFrom)
|
|
|
|
instSource, templateFromParam, iFrom)
|
|
|
|
maybeFrom[finalSource] = template.from[source](
|
|
|
|
maybeFrom[finalSource] = template.from[source](
|
|
|
|
instantiatorSpec.from[iFrom])
|
|
|
|
instantiatorSpec.from[iFrom])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Assuming all templates are covariant here, I guess...
|
|
|
|
// Assuming all templates are covariant here, I guess...
|
|
|
|
for (const subType of this._subtypes[instantiator]) {
|
|
|
|
for (const subType of this._subtypes[instantiator]) {
|
|
|
|
const finalSource = substituteInSig(
|
|
|
|
const finalSource = substituteInSignature(
|
|
|
|
instSource, templateFromParam, subType)
|
|
|
|
instSource, templateFromParam, subType)
|
|
|
|
maybeFrom[finalSource] = template.from[source](x => x)
|
|
|
|
maybeFrom[finalSource] = template.from[source](x => x)
|
|
|
|
}
|
|
|
|
}
|
|
|
|