feat: Add a couple of ways to install generics safely. #18
@ -6,7 +6,7 @@ export default class PocomathInstance {
|
||||
* in that if a new top-level PocomathInstance method is added, its name
|
||||
* must be added to this list.
|
||||
*/
|
||||
static reserved = new Set(['install'])
|
||||
static reserved = new Set(['install', 'importDependencies'])
|
||||
|
||||
constructor(name) {
|
||||
this.name = name
|
||||
@ -52,6 +52,43 @@ export default class PocomathInstance {
|
||||
for (const key in ops) this._installOp(key, ops[key])
|
||||
}
|
||||
|
||||
/**
|
||||
* Import (and install) all dependencies of previously installed functions,
|
||||
* for the specified types.
|
||||
*
|
||||
* @param {string[]} types A list of type names
|
||||
*/
|
||||
async importDependencies(types) {
|
||||
const doneSet = new Set(['self']) // nothing to do for self dependencies
|
||||
while (true) {
|
||||
const requiredSet = new Set()
|
||||
/* Grab all of the known deps */
|
||||
for (const func in this._imps) {
|
||||
if (func === 'Types') continue
|
||||
for (const definition of Object.values(this._imps[func])) {
|
||||
for (const dependency of definition[0]) {
|
||||
const depName = dependency.split('(',1)[0]
|
||||
if (doneSet.has(depName)) continue
|
||||
requiredSet.add(depName)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (requiredSet.size === 0) break
|
||||
for (const name of requiredSet) {
|
||||
for (const type of types) {
|
||||
try {
|
||||
const modName = `../${type}/${name}.mjs`
|
||||
const mod = await import(modName)
|
||||
this.install(mod)
|
||||
} catch (err) {
|
||||
// No such module, but that's OK
|
||||
}
|
||||
}
|
||||
doneSet.add(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Used internally by install, see the documentation there */
|
||||
_installOp(name, implementations) {
|
||||
if (name.charAt(0) === '_') {
|
||||
|
@ -6,7 +6,9 @@ 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')
|
||||
@ -62,4 +64,18 @@ describe('A custom instance', () => {
|
||||
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))
|
||||
})
|
||||
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user