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:
parent
2609310b8e
commit
883a351aa8
@ -26,7 +26,10 @@ export default class PocomathInstance {
|
|||||||
this._affects = {}
|
this._affects = {}
|
||||||
this._typed = typed.create()
|
this._typed = typed.create()
|
||||||
this._typed.clear()
|
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._subtypes = {} // For each type, gives all of its (in)direct subtypes
|
||||||
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
|
||||||
@ -130,6 +133,7 @@ export default class PocomathInstance {
|
|||||||
|
|
||||||
_installInstance(other) {
|
_installInstance(other) {
|
||||||
for (const [type, spec] of Object.entries(other.Types)) {
|
for (const [type, spec] of Object.entries(other.Types)) {
|
||||||
|
if (type === 'any' || this._templateParam(type)) continue
|
||||||
this.installType(type, spec)
|
this.installType(type, spec)
|
||||||
}
|
}
|
||||||
this._installFunctions(other._imps)
|
this._installFunctions(other._imps)
|
||||||
@ -200,6 +204,10 @@ export default class PocomathInstance {
|
|||||||
* the corresponding changes to the _typed object immediately
|
* the corresponding changes to the _typed object immediately
|
||||||
*/
|
*/
|
||||||
installType(type, spec) {
|
installType(type, spec) {
|
||||||
|
if (this._templateParam(type)) {
|
||||||
|
throw new SyntaxError(
|
||||||
|
`Type name '${type}' reserved for template parameter`)
|
||||||
|
}
|
||||||
if (type in this.Types) {
|
if (type in this.Types) {
|
||||||
if (spec !== this.Types[type]) {
|
if (spec !== this.Types[type]) {
|
||||||
throw new SyntaxError(`Conflicting definitions of type ${type}`)
|
throw new SyntaxError(`Conflicting definitions of type ${type}`)
|
||||||
@ -295,10 +303,13 @@ export default class PocomathInstance {
|
|||||||
opImps[signature] = behavior
|
opImps[signature] = behavior
|
||||||
for (const dep of behavior.uses) {
|
for (const dep of behavior.uses) {
|
||||||
const depname = dep.split('(', 1)[0]
|
const depname = dep.split('(', 1)[0]
|
||||||
if (depname === 'self') continue
|
if (depname === 'self' || this._templateParam(depname)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
this._addAffect(depname, name)
|
this._addAffect(depname, name)
|
||||||
}
|
}
|
||||||
for (const type of typesOfSignature(signature)) {
|
for (const type of typesOfSignature(signature)) {
|
||||||
|
if (this._templateParam(type)) continue
|
||||||
this._usedTypes.add(type)
|
this._usedTypes.add(type)
|
||||||
this._addAffect(':' + type, name)
|
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) {
|
_addAffect(dependency, dependent) {
|
||||||
if (dependency in this._affects) {
|
if (dependency in this._affects) {
|
||||||
this._affects[dependency].add(dependent)
|
this._affects[dependency].add(dependent)
|
||||||
@ -366,7 +383,9 @@ export default class PocomathInstance {
|
|||||||
}
|
}
|
||||||
Object.defineProperty(this, name, {configurable: true, value: 'limbo'})
|
Object.defineProperty(this, name, {configurable: true, value: 'limbo'})
|
||||||
const tf_imps = {}
|
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) {
|
if (uses.length === 0) {
|
||||||
tf_imps[signature] = does()
|
tf_imps[signature] = does()
|
||||||
} else {
|
} else {
|
||||||
@ -374,7 +393,10 @@ export default class PocomathInstance {
|
|||||||
let full_self_referential = false
|
let full_self_referential = false
|
||||||
let part_self_references = []
|
let part_self_references = []
|
||||||
for (const dep of uses) {
|
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 (func === 'self') {
|
||||||
if (needsig) {
|
if (needsig) {
|
||||||
if (full_self_referential) {
|
if (full_self_referential) {
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export const subtract = {
|
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))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user