Glen Whitney
d9d7af961f
Merging of Pocomath modules is eased by allowing one PocomathInstance to be merged into another. That allows types, for example, to be exported as a PocomathInstance (so there is no need for a special identifier convention for types; they can be directly added with an installType method). Also, larger modules can just be exported as an instance, since there is more flexibility and more checking in merging PocomathInstances than raw modules.
99 lines
3.9 KiB
JavaScript
99 lines
3.9 KiB
JavaScript
import assert from 'assert'
|
|
import math from '../src/pocomath.mjs'
|
|
import PocomathInstance from '../src/core/PocomathInstance.mjs'
|
|
import * as numbers from '../src/number/all.mjs'
|
|
import * as numberAdd from '../src/number/add.mjs'
|
|
import * as complex from '../src/complex/all.mjs'
|
|
import * as complexAdd from '../src/complex/add.mjs'
|
|
import * as complexNegate from '../src/complex/negate.mjs'
|
|
import * as complexComplex from '../src/complex/complex.mjs'
|
|
import * as concreteSubtract from '../src/generic/subtract.concrete.mjs'
|
|
import * as genericSubtract from '../src/generic/subtract.mjs'
|
|
import extendToComplex from '../src/complex/extendToComplex.mjs'
|
|
|
|
const bw = new PocomathInstance('backwards')
|
|
describe('A custom instance', () => {
|
|
it("works when partially assembled", () => {
|
|
bw.install(complex)
|
|
// Not much we can call without any number types:
|
|
assert.deepStrictEqual(bw.complex(0, 3), {re: 0, im: 3})
|
|
// Don't have a way to negate things, for example:
|
|
assert.throws(() => bw.negate(2), TypeError)
|
|
})
|
|
|
|
it("can be assembled in any order", () => {
|
|
bw.install(numbers)
|
|
bw.installType('string', {test: s => typeof s === 'string'})
|
|
assert.strictEqual(bw.subtract(16, bw.add(3,4,2)), 7)
|
|
assert.strictEqual(bw.negate('8'), -8)
|
|
assert.deepStrictEqual(bw.add(bw.complex(1,3), 1), {re: 2, im: 3})
|
|
assert.deepStrictEqual(
|
|
bw.subtract(16, bw.add(3, bw.complex(0,4), 2)),
|
|
math.complex(11, -4)) // note both instances coexist
|
|
assert.deepStrictEqual(bw.negate(math.complex(3, '8')).im, -8)
|
|
})
|
|
|
|
it("can be assembled piecemeal", () => {
|
|
const pm = new PocomathInstance('piecemeal')
|
|
pm.install(numbers)
|
|
assert.strictEqual(pm.subtract(5, 10), -5)
|
|
pm.install(complexAdd)
|
|
pm.install(complexNegate)
|
|
// Should be enough to allow complex subtraction, as subtract is generic:
|
|
assert.deepStrictEqual(
|
|
pm.subtract({re:5, im:0}, {re:10, im:1}), {re:-5, im: -1})
|
|
})
|
|
|
|
it("can defer definition of (even used) types", () => {
|
|
const dt = new PocomathInstance('Deferred Types')
|
|
dt.install(numberAdd)
|
|
dt.install({times: {
|
|
'number,number': () => (m,n) => m*n,
|
|
'Complex,Complex': ({complex}) => (w,z) => {
|
|
return complex(w.re*z.re - w.im*z.im, w.re*z.im + w.im*z.re)
|
|
}
|
|
}})
|
|
// complex type not present but should still be able to add numbers:
|
|
assert.strictEqual(dt.times(3,5), 15)
|
|
dt.install(complexComplex)
|
|
// times should now rebundle to allow complex:
|
|
assert.deepStrictEqual(
|
|
dt.times(dt.complex(2,3), dt.complex(2,-3)), dt.complex(13))
|
|
})
|
|
|
|
it("can selectively import in cute ways", async function () {
|
|
const cherry = new PocomathInstance('cherry')
|
|
cherry.install(numberAdd)
|
|
await extendToComplex(cherry)
|
|
/* Now we have an instance that supports addition for number and complex
|
|
and little else:
|
|
*/
|
|
assert.strictEqual(cherry.add(3, 4, 2), 9)
|
|
assert.deepStrictEqual(
|
|
cherry.add(cherry.complex(3, 3), 4, cherry.complex(2, 2)),
|
|
math.complex(9,5))
|
|
assert.strictEqual('subtract' in cherry, false)
|
|
assert.strictEqual('negate' in cherry, false)
|
|
})
|
|
|
|
it("can use bundles that are closed under dependency", () => {
|
|
const ok = new PocomathInstance('concrete')
|
|
ok.install(concreteSubtract)
|
|
assert.strictEqual(ok.subtract(7, 5), 2)
|
|
})
|
|
|
|
it("can load generics and then import their dependences", async function () {
|
|
const chase = new PocomathInstance('Chase Dependencies')
|
|
chase.install(genericSubtract)
|
|
chase.install(complexComplex) // for convenience to build complex numbers
|
|
await chase.importDependencies(['bigint', 'complex'])
|
|
/* Now we have an instance that supports subtraction for Gaussian
|
|
integers.
|
|
*/
|
|
assert.deepStrictEqual(
|
|
chase.subtract(chase.complex(3n, 2n), chase.complex(2n, 5n)),
|
|
math.complex(1n, -3n))
|
|
})
|
|
|
|
})
|