diff --git a/PocomathInstance.mjs b/PocomathInstance.mjs index 59e6e2f..facdfb4 100644 --- a/PocomathInstance.mjs +++ b/PocomathInstance.mjs @@ -5,6 +5,7 @@ export default class PocomathInstance { constructor(name) { this.name = name this._imps = {} + this._affects = {} } /** @@ -46,6 +47,14 @@ export default class PocomathInstance { `Conflicting definitions of ${signature} for ${name}`) } else { opImps[signature] = implementations[signature] + for (const dep of implementations[signature][0]) { + const depname = dep.split('(', 1)[0] + if (depname === 'self') continue + if (!(depname in this._affects)) { + this._affects[depname] = new Set() + } + this._affects[depname].add(name) + } } } } @@ -62,6 +71,11 @@ export default class PocomathInstance { if (!(name in this._imps)) { this._imps[name] = {} } + if (name in this._affects) { + for (const ancestor of this._affects[name]) { + this._invalidate(ancestor) + } + } } /** diff --git a/complex/negate.mjs b/complex/negate.mjs index 1b8a189..429a575 100644 --- a/complex/negate.mjs +++ b/complex/negate.mjs @@ -1,4 +1,8 @@ -import './Complex.mjs' +import {numComplex} from './Complex.mjs' export const negate = { - Complex: [['self'], ref => z => ({re: ref.self(z.re), im: ref.self(z.im)})] + /* need a "base case" to avoid infinite self-reference */ + Complex: [['self'], ref => z => { + if (numComplex(z)) return {re: -z.re, im: -z.im} + return {re: ref.self(z.re), im: ref.self(z.im)} + }] } diff --git a/test/custom.mjs b/test/custom.mjs index 807fefc..78dd8db 100644 --- a/test/custom.mjs +++ b/test/custom.mjs @@ -4,12 +4,16 @@ import typed from 'typed-function' import PocomathInstance from '../PocomathInstance.mjs' import * as numbers from '../number/all.mjs' import * as complex from '../complex/all.mjs' +import * as complexAdd from '../complex/add.mjs' +import * as complexNegate from '../complex/negate.mjs' const bw = new PocomathInstance('backwards') describe('A custom instance', () => { it("works when partially assembled", () => { bw.install(complex) assert.deepStrictEqual(bw.add(2, bw.complex(0, 3)), {re: 2, im: 3}) + assert.deepStrictEqual(bw.negate(2), bw.complex(-2,-0)) + assert.deepStrictEqual(bw.subtract(2, bw.complex(0, 3)), {re: 2, im: -3}) }) it("can be assembled in any order", () => { @@ -23,4 +27,15 @@ describe('A custom instance', () => { 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}) + }) })