diff --git a/src/core/PocomathInstance.mjs b/src/core/PocomathInstance.mjs index b1b865d..8cb572b 100644 --- a/src/core/PocomathInstance.mjs +++ b/src/core/PocomathInstance.mjs @@ -31,6 +31,13 @@ export default class PocomathInstance { */ this.Types = {any: anySpec, T: anySpec} 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._doomed = new Set() // for detecting circular reference this._config = {predictable: false} @@ -170,7 +177,12 @@ export default class PocomathInstance { const mod = await import(modName) this.install(mod) } 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) @@ -235,6 +247,7 @@ export default class PocomathInstance { } this._typed.addTypes([{name: type, test: testFn}], beforeType) this.Types[type] = spec + this._priorTypes[type] = new Set() /* Now add conversions to this type */ for (const from in (spec.from || {})) { if (from in this.Types) { @@ -243,6 +256,7 @@ export default class PocomathInstance { while (nextSuper) { this._typed.addConversion( {from, to: nextSuper, convert: spec.from[from]}) + this._priorTypes[nextSuper].add(from) nextSuper = this.Types[nextSuper].refines } } @@ -261,21 +275,24 @@ export default class PocomathInstance { to: nextSuper, convert: this.Types[to].from[type] }) + this._priorTypes[nextSuper].add(type) nextSuper = this.Types[nextSuper].refines } } } - if (spec.refines) { - this._typed.addConversion( - {from: type, to: spec.refines, convert: x => x}) - } + // Update all the subtype sets of supertypes up the chain, and + // while we are at it add trivial conversions from subtypes to supertypes + // to help typed-function match signatures properly: this._subtypes[type] = new Set() - // Update all the subtype sets of supertypes up the chain: let nextSuper = spec.refines while (nextSuper) { + this._typed.addConversion( + {from: type, to: nextSuper, convert: x => x}) + this._priorTypes[nextSuper].add(type) this._subtypes[nextSuper].add(type) nextSuper = this.Types[nextSuper].refines } + // rebundle anything that uses the new type: this._invalidateDependents(':' + type) }