feat: Add a couple of ways to install generics safely. (#18)
Resolves #10. Co-authored-by: Glen Whitney <glen@studioinfinity.org> Reviewed-on: #18
This commit is contained in:
parent
2a60cc0989
commit
4fdafc751e
@ -6,7 +6,7 @@ export default class PocomathInstance {
|
|||||||
* in that if a new top-level PocomathInstance method is added, its name
|
* in that if a new top-level PocomathInstance method is added, its name
|
||||||
* must be added to this list.
|
* must be added to this list.
|
||||||
*/
|
*/
|
||||||
static reserved = new Set(['install'])
|
static reserved = new Set(['install', 'importDependencies'])
|
||||||
|
|
||||||
constructor(name) {
|
constructor(name) {
|
||||||
this.name = name
|
this.name = name
|
||||||
@ -52,6 +52,43 @@ export default class PocomathInstance {
|
|||||||
for (const key in ops) this._installOp(key, ops[key])
|
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 */
|
/* Used internally by install, see the documentation there */
|
||||||
_installOp(name, implementations) {
|
_installOp(name, implementations) {
|
||||||
if (name.charAt(0) === '_') {
|
if (name.charAt(0) === '_') {
|
||||||
|
3
src/generic/subtract.concrete.mjs
Normal file
3
src/generic/subtract.concrete.mjs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export {subtract} from './subtract.mjs'
|
||||||
|
export * from '../number/add.mjs'
|
||||||
|
export * from '../number/negate.mjs'
|
@ -6,6 +6,9 @@ import * as numberAdd from '../src/number/add.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'
|
||||||
|
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'
|
import extendToComplex from '../src/complex/extendToComplex.mjs'
|
||||||
|
|
||||||
const bw = new PocomathInstance('backwards')
|
const bw = new PocomathInstance('backwards')
|
||||||
@ -55,4 +58,24 @@ describe('A custom instance', () => {
|
|||||||
assert.strictEqual('subtract' in cherry, false)
|
assert.strictEqual('subtract' in cherry, false)
|
||||||
assert.strictEqual('negate' 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))
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user