feat: Template operations #41

Merged
glen merged 10 commits from template_operations into main 2022-08-01 10:09:32 +00:00
Showing only changes of commit d4a4d8f331 - Show all commits

View File

@ -31,6 +31,13 @@ export default class PocomathInstance {
*/ */
this.Types = {any: anySpec, T: anySpec} this.Types = {any: anySpec, T: anySpec}
this._subtypes = {} // For each type, gives all of its (in)direct subtypes 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.
* This is important because if we instantiate a template, we must
* instantiate it for all prior types as well, or else the wrong instance
* might match.
*/
this._priorTypes = {}
this._usedTypes = new Set() // all types that have occurred in a signature this._usedTypes = new Set() // all types that have occurred in a signature
this._doomed = new Set() // for detecting circular reference this._doomed = new Set() // for detecting circular reference
this._config = {predictable: false} this._config = {predictable: false}
@ -170,7 +177,12 @@ export default class PocomathInstance {
const mod = await import(modName) const mod = await import(modName)
this.install(mod) this.install(mod)
} catch (err) { } catch (err) {
// No such module, but that's OK if (!(err.message.includes('find'))) {
// Not just a error because module doesn't exist
// So take it seriously
throw err
}
// We don't care if a module doesn't exist, so merely proceed
} }
} }
doneSet.add(name) doneSet.add(name)
@ -235,6 +247,7 @@ export default class PocomathInstance {
} }
this._typed.addTypes([{name: type, test: testFn}], beforeType) this._typed.addTypes([{name: type, test: testFn}], beforeType)
this.Types[type] = spec this.Types[type] = spec
this._priorTypes[type] = new Set()
/* Now add conversions to this type */ /* Now add conversions to this type */
for (const from in (spec.from || {})) { for (const from in (spec.from || {})) {
if (from in this.Types) { if (from in this.Types) {
@ -243,6 +256,7 @@ export default class PocomathInstance {
while (nextSuper) { while (nextSuper) {
this._typed.addConversion( this._typed.addConversion(
{from, to: nextSuper, convert: spec.from[from]}) {from, to: nextSuper, convert: spec.from[from]})
this._priorTypes[nextSuper].add(from)
nextSuper = this.Types[nextSuper].refines nextSuper = this.Types[nextSuper].refines
} }
} }
@ -261,21 +275,24 @@ export default class PocomathInstance {
to: nextSuper, to: nextSuper,
convert: this.Types[to].from[type] convert: this.Types[to].from[type]
}) })
this._priorTypes[nextSuper].add(type)
nextSuper = this.Types[nextSuper].refines nextSuper = this.Types[nextSuper].refines
} }
} }
} }
if (spec.refines) { // Update all the subtype sets of supertypes up the chain, and
this._typed.addConversion( // while we are at it add trivial conversions from subtypes to supertypes
{from: type, to: spec.refines, convert: x => x}) // to help typed-function match signatures properly:
}
this._subtypes[type] = new Set() this._subtypes[type] = new Set()
// Update all the subtype sets of supertypes up the chain:
let nextSuper = spec.refines let nextSuper = spec.refines
while (nextSuper) { while (nextSuper) {
this._typed.addConversion(
{from: type, to: nextSuper, convert: x => x})
this._priorTypes[nextSuper].add(type)
this._subtypes[nextSuper].add(type) this._subtypes[nextSuper].add(type)
nextSuper = this.Types[nextSuper].refines nextSuper = this.Types[nextSuper].refines
} }
// rebundle anything that uses the new type: // rebundle anything that uses the new type:
this._invalidateDependents(':' + type) this._invalidateDependents(':' + type)
} }