feat(Tuple): Stub for a template type

This adds the target initial definition of a homogeneous Tuple<T>
  type, and just enough processing that the type can be defined and
  non-template methods that deal with the generic base type Tuple can
  be called. Still has no actual template instantiation.
This commit is contained in:
Glen Whitney 2022-08-03 11:27:40 -07:00
parent 21ce098f98
commit 27bf23db54
9 changed files with 176 additions and 3 deletions

View file

@ -45,6 +45,8 @@ export default class PocomathInstance {
*/
this.Types = {any: anySpec}
this.Types[theTemplateParam] = anySpec
// All the template types that have been defined
this._templateTypes = {}
this._subtypes = {} // For each type, gives all of its (in)direct subtypes
/* The following gives for each type, a set of all types that could
* match in typed-function's dispatch algorithm before the given type.
@ -263,10 +265,15 @@ export default class PocomathInstance {
* the corresponding changes to the _typed object immediately
*/
installType(type, spec) {
if (this._templateParam(type)) {
const parts = type.split(/[<,>]/)
if (this._templateParam(parts[0])) {
throw new SyntaxError(
`Type name '${type}' reserved for template parameter`)
}
if (parts.some(this._templateParam.bind(this))) {
// It's a template, deal with it separately
return this._installTemplateType(type, spec)
}
if (type in this.Types) {
if (spec !== this.Types[type]) {
throw new SyntaxError(`Conflicting definitions of type ${type}`)
@ -353,7 +360,6 @@ export default class PocomathInstance {
// update the typeOf function
const imp = {}
imp[type] = {uses: new Set(), does: () => () => type}
console.log('Adding', type, 'to typeOf')
this._installFunctions({typeOf: imp})
}
@ -393,6 +399,7 @@ export default class PocomathInstance {
}
return 'any'
}
/* Returns a list of all types that have been mentioned in the
* signatures of operations, but which have not actually been installed:
*/
@ -400,6 +407,23 @@ export default class PocomathInstance {
return Array.from(this._usedTypes).filter(t => !(t in this.Types))
}
/* Used internally to install a template type */
_installTemplateType(type, spec) {
const base = type.split('<')[0]
/* For now, just allow a single template per base type; that
* might need to change later:
*/
if (base in this._templateTypes) {
if (spec !== this._templateTypes[base].spec) {
throw new SyntaxError(
`Conflicting definitions of template type ${type}`)
}
return
}
// Nothing actually happens until we match a template parameter
this._templateTypes[base] = {type, spec}
}
/* Used internally by install, see the documentation there */
_installFunctions(functions) {
for (const [name, spec] of Object.entries(functions)) {
@ -509,6 +533,7 @@ export default class PocomathInstance {
`Every implementation for ${name} uses an undefined type;\n`
+ ` signatures: ${Object.keys(imps)}`)
}
// Mark this method as being in the midst of being reassembled
Object.defineProperty(this, name, {configurable: true, value: 'limbo'})
const tf_imps = {}
for (const [rawSignature, behavior] of usableEntries) {