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.
This commit is contained in:
Glen Whitney 2022-07-30 09:40:47 -07:00
parent 2609310b8e
commit 883a351aa8
2 changed files with 27 additions and 5 deletions

View File

@ -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) {

View File

@ -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))
}