feat: Template implementations
This commit is contained in:
parent
1076c3c727
commit
fd3d6b2eb3
@ -1,5 +1,3 @@
|
|||||||
export * from './Types/bigint.mjs'
|
export * from './Types/bigint.mjs'
|
||||||
|
|
||||||
export const add = {
|
export const add = {'bigint,bigint': () => (a,b) => a+b}
|
||||||
'...bigint': () => addends => addends.reduce((x,y) => x+y, 0n)
|
|
||||||
}
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
export * from './Types/Complex.mjs'
|
export * from './Types/Complex.mjs'
|
||||||
|
|
||||||
export const add = {
|
export const add = {
|
||||||
'...Complex': ({self}) => addends => {
|
'Complex,number': ({
|
||||||
if (addends.length === 0) return {re:0, im:0}
|
'self(number,number)': addNum,
|
||||||
const seed = addends.shift()
|
'complex(any,any)': cplx
|
||||||
return addends.reduce(
|
}) => (z,x) => cplx(addNum(z.re, x), z.im),
|
||||||
(w,z) => ({re: self(w.re, z.re), im: self(w.im, z.im)}), seed)
|
'Complex,Complex': ({
|
||||||
}
|
self,
|
||||||
|
'complex(any,any)': cplx
|
||||||
|
}) => (w,z) => cplx(self(w.re, z.re), self(w.im, z.im))
|
||||||
}
|
}
|
||||||
|
@ -443,7 +443,26 @@ export default class PocomathInstance {
|
|||||||
for (const instType of behavior.instantiations) {
|
for (const instType of behavior.instantiations) {
|
||||||
const signature =
|
const signature =
|
||||||
substituteInSig(rawSignature, theTemplateParam, instType)
|
substituteInSig(rawSignature, theTemplateParam, instType)
|
||||||
this._addTFimplementation(tf_imps, signature, behavior, instType)
|
const uses = new Set()
|
||||||
|
for (const dep of behavior.uses) {
|
||||||
|
if (this._templateParam(dep)) continue
|
||||||
|
uses.add(substituteInSig(dep, theTemplateParam, instType))
|
||||||
|
}
|
||||||
|
const patch = (refs) => {
|
||||||
|
const innerRefs = {}
|
||||||
|
for (const dep of behavior.uses) {
|
||||||
|
if (this._templateParam(dep)) {
|
||||||
|
innerRefs[dep] = instType
|
||||||
|
} else {
|
||||||
|
const outerName = substituteInSig(
|
||||||
|
dep, theTemplateParam, instType)
|
||||||
|
innerRefs[dep] = refs[outerName]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const original = behavior.does(innerRefs)
|
||||||
|
return behavior.does(innerRefs)
|
||||||
|
}
|
||||||
|
this._addTFimplementation(tf_imps, signature, {uses, does: patch})
|
||||||
}
|
}
|
||||||
/* Now add the catchall signature */
|
/* Now add the catchall signature */
|
||||||
const signature = substituteInSig(rawSignature, theTemplateParam, 'any')
|
const signature = substituteInSig(rawSignature, theTemplateParam, 'any')
|
||||||
@ -464,13 +483,21 @@ export default class PocomathInstance {
|
|||||||
`Cannot find template parameter in ${rawSignature}`)
|
`Cannot find template parameter in ${rawSignature}`)
|
||||||
}
|
}
|
||||||
const self = this
|
const self = this
|
||||||
const patch = (refs) => {
|
const patch = (refs) => (...args) => {
|
||||||
const original = behavior.does(refs)
|
const example = args[exemplar]
|
||||||
return (...args) => {
|
const instantiateFor = self.typeOf(example)
|
||||||
const example = args[exemplar]
|
refs[theTemplateParam] = instantiateFor
|
||||||
console.log('Have to match template to', example)
|
const instCount = behavior.instantiations.size
|
||||||
return original(...args)
|
for (const earlier of self._priorTypes[instantiateFor]) {
|
||||||
|
behavior.instantiations.add(earlier)
|
||||||
}
|
}
|
||||||
|
behavior.instantiations.add(instantiateFor)
|
||||||
|
if (behavior.instantiations.size > instCount) {
|
||||||
|
self._invalidate(name)
|
||||||
|
}
|
||||||
|
// And for now, we have to rely on the "any" implementation. Hope
|
||||||
|
// it matches the instantiated one!
|
||||||
|
return behavior.does(refs)(...args)
|
||||||
}
|
}
|
||||||
this._addTFimplementation(
|
this._addTFimplementation(
|
||||||
tf_imps, signature, {uses: behavior.uses, does: patch})
|
tf_imps, signature, {uses: behavior.uses, does: patch})
|
||||||
@ -484,7 +511,7 @@ export default class PocomathInstance {
|
|||||||
* to typed-function implementations and inserts the result into plain object
|
* to typed-function implementations and inserts the result into plain object
|
||||||
* imps
|
* imps
|
||||||
*/
|
*/
|
||||||
_addTFimplementation(imps, signature, behavior, instType) {
|
_addTFimplementation(imps, signature, behavior) {
|
||||||
const {uses, does} = behavior
|
const {uses, does} = behavior
|
||||||
if (uses.length === 0) {
|
if (uses.length === 0) {
|
||||||
imps[signature] = does()
|
imps[signature] = does()
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
import {reducingOperation} from './reducingOperation.mjs'
|
||||||
|
|
||||||
export * from './Types/generic.mjs'
|
export * from './Types/generic.mjs'
|
||||||
|
|
||||||
|
export const add = reducingOperation
|
||||||
export {lcm} from './lcm.mjs'
|
export {lcm} from './lcm.mjs'
|
||||||
export {mod} from './mod.mjs'
|
export {mod} from './mod.mjs'
|
||||||
export {multiply} from './multiply.mjs'
|
export const multiply = reducingOperation
|
||||||
export {divide} from './divide.mjs'
|
export {divide} from './divide.mjs'
|
||||||
export {sign} from './sign.mjs'
|
export {sign} from './sign.mjs'
|
||||||
export {sqrt} from './sqrt.mjs'
|
export {sqrt} from './sqrt.mjs'
|
||||||
|
12
src/generic/reducingOperation.mjs
Normal file
12
src/generic/reducingOperation.mjs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export * from './Types/generic.mjs'
|
||||||
|
|
||||||
|
export const reducingOperation = {
|
||||||
|
'undefined': () => u => u,
|
||||||
|
'undefined,...any': () => (u, rest) => u,
|
||||||
|
'any,undefined': () => (x, u) => u,
|
||||||
|
any: () => x => x,
|
||||||
|
'any,any,...any': ({
|
||||||
|
self
|
||||||
|
}) => (a,b,rest) => [b, ...rest].reduce((x,y) => self(x,y), a)
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,3 @@
|
|||||||
export const subtract = {
|
export const subtract = {
|
||||||
'T,T': ({'add(T)': addT, 'negate(T)': negT}) => (x,y) => addT(x, negT(y))
|
'T,T': ({'add(T,T)': addT, 'negate(T)': negT}) => (x,y) => addT(x, negT(y))
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
export * from './Types/number.mjs'
|
export * from './Types/number.mjs'
|
||||||
|
|
||||||
export const add = {
|
export const add = {'number,number': () => (m,n) => m+n}
|
||||||
'...number': () => addends => addends.reduce((x,y) => x+y, 0),
|
|
||||||
}
|
|
||||||
|
@ -21,12 +21,14 @@ describe('The default full pocomath instance "math"', () => {
|
|||||||
|
|
||||||
it('can subtract numbers', () => {
|
it('can subtract numbers', () => {
|
||||||
assert.strictEqual(math.subtract(12, 5), 7)
|
assert.strictEqual(math.subtract(12, 5), 7)
|
||||||
|
//assert.strictEqual(math.subtract(3n, 1.5), 1.5)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can add numbers', () => {
|
it('can add numbers', () => {
|
||||||
assert.strictEqual(math.add(3, 4), 7)
|
assert.strictEqual(math.add(3, 4), 7)
|
||||||
assert.strictEqual(math.add(1.5, 2.5, 3.5), 7.5)
|
assert.strictEqual(math.add(1.5, 2.5, 3.5), 7.5)
|
||||||
assert.strictEqual(math.add(Infinity), Infinity)
|
assert.strictEqual(math.add(Infinity), Infinity)
|
||||||
|
assert.throws(() => math.add(3n, -1.5), TypeError)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can negate numbers', () => {
|
it('can negate numbers', () => {
|
||||||
@ -55,10 +57,10 @@ describe('The default full pocomath instance "math"', () => {
|
|||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
math.subtract(math.complex(1,1), math.complex(2,-2)),
|
math.subtract(math.complex(1,1), math.complex(2,-2)),
|
||||||
math.complex(-1,3))
|
math.complex(-1,3))
|
||||||
|
assert.strictEqual(math.negate(math.complex(3, 8)).im, -8)
|
||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
math.subtract(16, math.add(3, math.complex(0,4), 2)),
|
math.subtract(16, math.add(3, math.complex(0,4), 2)),
|
||||||
math.complex(11, -4))
|
math.complex(11, -4))
|
||||||
assert.strictEqual(math.negate(math.complex(3, 8)).im, -8)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('handles bigints', () => {
|
it('handles bigints', () => {
|
||||||
|
@ -3,6 +3,7 @@ import math from '../src/pocomath.mjs'
|
|||||||
import PocomathInstance from '../src/core/PocomathInstance.mjs'
|
import PocomathInstance from '../src/core/PocomathInstance.mjs'
|
||||||
import * as numbers from '../src/number/all.mjs'
|
import * as numbers from '../src/number/all.mjs'
|
||||||
import * as numberAdd from '../src/number/add.mjs'
|
import * as numberAdd from '../src/number/add.mjs'
|
||||||
|
import {add as genericAdd} from '../src/generic/arithmetic.mjs'
|
||||||
import * as complex from '../src/complex/all.mjs'
|
import * as complex from '../src/complex/all.mjs'
|
||||||
import * as complexAdd from '../src/complex/add.mjs'
|
import * as complexAdd from '../src/complex/add.mjs'
|
||||||
import * as complexNegate from '../src/complex/negate.mjs'
|
import * as complexNegate from '../src/complex/negate.mjs'
|
||||||
@ -66,6 +67,7 @@ describe('A custom instance', () => {
|
|||||||
const cherry = new PocomathInstance('cherry')
|
const cherry = new PocomathInstance('cherry')
|
||||||
cherry.install(numberAdd)
|
cherry.install(numberAdd)
|
||||||
await extendToComplex(cherry)
|
await extendToComplex(cherry)
|
||||||
|
cherry.install({add: genericAdd})
|
||||||
/* Now we have an instance that supports addition for number and complex
|
/* Now we have an instance that supports addition for number and complex
|
||||||
and little else:
|
and little else:
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user