From d95e5ad930e16ff535377a28a3ca428840b92779 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Fri, 25 Mar 2022 14:40:57 -0700 Subject: [PATCH] feat: Allow reconfiguration of an existing picomath instance Keeps track of which operations depend on the configuration and invalidates them for lazy reconfiguration when the config changes. --- complex/add.js | 3 ++- picomathInstance.js | 52 +++++++++++++++++++++++++++++++-------------- test/custom.js | 6 ++++++ 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/complex/add.js b/complex/add.js index fc07a9c..a831574 100644 --- a/complex/add.js +++ b/complex/add.js @@ -13,6 +13,7 @@ export default function create(pmath) { } if (resolve && Math.abs(sum.im/sum.re) < 1e-10) return sum.re return sum - }]) + }], + create, pmath) // register ourselves for invalidation and reconfiguration } diff --git a/picomathInstance.js b/picomathInstance.js index 759d215..90e4041 100644 --- a/picomathInstance.js +++ b/picomathInstance.js @@ -2,23 +2,43 @@ import poortf from './poortf.js' export default function picomathInstance (instName, config) { - /* Since we have to do it all the time, when we call a picomath instance - * as a function, it takes a name and 0 or more implementations add adds - * them to its poortf property named name, returning that property value. - */ - function fn (name, imps, author, data) { - if (name in fn) { - fn[name].addImps(imps, author, data) - } else { - fn[name] = poortf(name, imps, author, data) - } - return fn[name] - } + /* Since we have to do it all the time, when we call a picomath instance + * as a function, it takes a name and 0 or more implementations add adds + * them to its poortf property named name, returning that property value. + */ + function fn (name, imps, author, data) { + if (name in fn) { + fn[name].addImps(imps, author, data) + } else { + fn[name] = poortf(name, imps, author, data) + } + /* For PoC, just assume only reason to provide author info + * is to be invalidated when config changes + */ + if (author) { + if (!fn.configUsers.has(author)) { + fn.configUsers.set(author, new Set()) + } + fn.configUsers.get(author).add(name) + } + return fn[name] + } - Object.defineProperty(fn, 'name', {value: instName}) - fn.config = config || { resolveComplex: false } // primitive default for POC - - return fn + Object.defineProperty(fn, 'name', {value: instName}) + // There is an issue below of possible collision between the following + // property names and operation names. Since it would not be too hard to + // solve, we won't worry about it in this PoC. + fn.config = config || { resolveComplex: false } // primitive default for POC + fn.configUsers = new Map() + fn.reconfigure = config => { + for (const [author, names] of fn.configUsers.entries()) { + for (const name of names) { + fn[name].invalidate(author) + } + } + fn.config = config + } + return fn } diff --git a/test/custom.js b/test/custom.js index 69ac993..1107800 100644 --- a/test/custom.js +++ b/test/custom.js @@ -46,4 +46,10 @@ describe('Custom instances', () => { assert.deepStrictEqual(math.add(math.complex(2,3), math.complex(2,-3)), math.complex(4,0)) }) + + it("can be reconfigured", () => { + res.reconfigure({resolveComplex: false}) + assert.deepStrictEqual(math.add(math.complex(2,3), math.complex(2,-3)), + math.complex(4,0)) + }) })