From 883a351aa817ea26e4da5f4be1adc43ff04dcadf Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Sat, 30 Jul 2022 09:40:47 -0700 Subject: [PATCH] refactor: Add stubs for function templates The stubs are so far all no-ops so basically at the moment the only allowed template parameter 'T' is just a synonym for 'any'. But at least this allows us to put the definition of the generic `subtract` into the exact form we actually want to support. --- src/core/PocomathInstance.mjs | 30 ++++++++++++++++++++++++++---- src/generic/subtract.mjs | 2 +- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/core/PocomathInstance.mjs b/src/core/PocomathInstance.mjs index a6a2000..b1b865d 100644 --- a/src/core/PocomathInstance.mjs +++ b/src/core/PocomathInstance.mjs @@ -26,7 +26,10 @@ export default class PocomathInstance { this._affects = {} this._typed = typed.create() this._typed.clear() - this.Types = {any: anySpec} // dummy entry to track the default 'any' type + /* List of types installed in the instance. We start with just dummies + * for the 'any' type and for type parameters: + */ + this.Types = {any: anySpec, T: anySpec} this._subtypes = {} // For each type, gives all of its (in)direct subtypes this._usedTypes = new Set() // all types that have occurred in a signature this._doomed = new Set() // for detecting circular reference @@ -130,6 +133,7 @@ export default class PocomathInstance { _installInstance(other) { for (const [type, spec] of Object.entries(other.Types)) { + if (type === 'any' || this._templateParam(type)) continue this.installType(type, spec) } this._installFunctions(other._imps) @@ -200,6 +204,10 @@ export default class PocomathInstance { * the corresponding changes to the _typed object immediately */ installType(type, spec) { + if (this._templateParam(type)) { + throw new SyntaxError( + `Type name '${type}' reserved for template parameter`) + } if (type in this.Types) { if (spec !== this.Types[type]) { throw new SyntaxError(`Conflicting definitions of type ${type}`) @@ -295,10 +303,13 @@ export default class PocomathInstance { opImps[signature] = behavior for (const dep of behavior.uses) { const depname = dep.split('(', 1)[0] - if (depname === 'self') continue + if (depname === 'self' || this._templateParam(depname)) { + continue + } this._addAffect(depname, name) } for (const type of typesOfSignature(signature)) { + if (this._templateParam(type)) continue this._usedTypes.add(type) this._addAffect(':' + type, name) } @@ -307,6 +318,12 @@ export default class PocomathInstance { } } + /* returns a boolean indicating whether t denotes a template parameter. + * We will start this out very simply: the special string `T` is always + * a template parameter, and that's the only one + */ + _templateParam(t) { return t === 'T' } + _addAffect(dependency, dependent) { if (dependency in this._affects) { this._affects[dependency].add(dependent) @@ -366,7 +383,9 @@ export default class PocomathInstance { } Object.defineProperty(this, name, {configurable: true, value: 'limbo'}) const tf_imps = {} - for (const [signature, {uses, does}] of usableEntries) { + for (const [rawSignature, {uses, does}] of usableEntries) { + /* For now, replace 'T' with 'any' */ + const signature = rawSignature.replaceAll('T', 'any') if (uses.length === 0) { tf_imps[signature] = does() } else { @@ -374,7 +393,10 @@ export default class PocomathInstance { let full_self_referential = false let part_self_references = [] for (const dep of uses) { - const [func, needsig] = dep.split(/[()]/) + let [func, needsig] = dep.split(/[()]/) + const needTypes = needsig ? typesOfSignature(needsig) : new Set() + /* For now, punt on template parameters */ + if (needTypes.has('T')) needsig = '' if (func === 'self') { if (needsig) { if (full_self_referential) { diff --git a/src/generic/subtract.mjs b/src/generic/subtract.mjs index 96a27bf..1c93b39 100644 --- a/src/generic/subtract.mjs +++ b/src/generic/subtract.mjs @@ -1,3 +1,3 @@ export const subtract = { - 'any,any': ({add, negate}) => (x,y) => add(x, negate(y)) + 'T,T': ({'add(T)': addT, 'negate(T)': negT}) => (x,y) => addT(x, negT(y)) }