From d4a4d8f331b25a8b1281a353c1b997a5374bb0d4 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Sun, 31 Jul 2022 00:17:36 -0700 Subject: [PATCH] refactor: track all the 'prior types' of a type as types are installed These are exactly the types that might match before the given type, and hence which require to have their template instantiations defined when an instantiation with the given type is made. --- src/core/PocomathInstance.mjs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) 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) }