feat: Additional notations for specifying dependencies and implementations

Allow just a plain function for when there are no dependencies,
  and allow an object with 'uses' and 'does' properties for the
  dependencies (optional) and implementation, respectively.
This commit is contained in:
Glen Whitney 2022-07-22 21:48:06 -07:00
parent 2ef0b5b263
commit 81ff04f88f
6 changed files with 39 additions and 15 deletions

View File

@ -1,10 +1,13 @@
export {Types} from './Types/Complex.mjs' export {Types} from './Types/Complex.mjs'
export const add = { export const add = {
'...Complex': [['self'], ref => addends => { '...Complex': {
if (addends.length === 0) return {re:0, im:0} uses: ['self'],
const seed = addends.shift() does: ref => addends => {
return addends.reduce((w,z) => if (addends.length === 0) return {re:0, im:0}
({re: ref.self(w.re, z.re), im: ref.self(w.im, z.im)}), seed) const seed = addends.shift()
}] return addends.reduce((w,z) =>
({re: ref.self(w.re, z.re), im: ref.self(w.im, z.im)}), seed)
}
}
} }

View File

@ -5,7 +5,7 @@ export const complex = {
* have a numeric/scalar type, e.g. by implementing subtypes in * have a numeric/scalar type, e.g. by implementing subtypes in
* typed-function * typed-function
*/ */
'any, any': [[], (x, y) => ({re: x, im: y})], 'any, any': {does: (x, y) => ({re: x, im: y})},
/* Take advantage of conversions in typed-function */ /* Take advantage of conversions in typed-function */
Complex: [[], z => z] Complex: {does: z => z}
} }

View File

@ -1,7 +1,10 @@
export {Types} from './Types/Complex.mjs' export {Types} from './Types/Complex.mjs'
export const negate = { export const negate = {
Complex: [['self'], ref => z => { Complex: {
return {re: ref.self(z.re), im: ref.self(z.im)} uses: ['self'],
}] does: ref => z => {
return {re: ref.self(z.re), im: ref.self(z.im)}
}
}
} }

View File

@ -70,7 +70,12 @@ export default class PocomathInstance {
for (const func in this._imps) { for (const func in this._imps) {
if (func === 'Types') continue if (func === 'Types') continue
for (const definition of Object.values(this._imps[func])) { for (const definition of Object.values(this._imps[func])) {
for (const dependency of definition[0]) { let deps = []
if (Array.isArray(definition)) deps = definition[0]
else if (typeof definition === 'object') {
deps = definition.uses || deps
}
for (const dependency of deps) {
const depName = dependency.split('(',1)[0] const depName = dependency.split('(',1)[0]
if (doneSet.has(depName)) continue if (doneSet.has(depName)) continue
requiredSet.add(depName) requiredSet.add(depName)
@ -158,7 +163,20 @@ export default class PocomathInstance {
this._ensureTypes() this._ensureTypes()
const tf_imps = {} const tf_imps = {}
for (const signature in imps) { for (const signature in imps) {
const [deps, imp] = imps[signature] const specifier = imps[signature]
let deps = []
let imp
if (typeof specifier === 'function') {
imp = specifier
} else if (Array.isArray(specifier)) {
[deps, imp] = specifier
} else if (typeof specifier === 'object') {
deps = specifier.uses || deps
imp = specifier.does
} else {
throw new SyntaxError(
`Cannot interpret signature definition ${specifier}`)
}
if (deps.length === 0) { if (deps.length === 0) {
tf_imps[signature] = imp tf_imps[signature] = imp
} else { } else {

View File

@ -1,5 +1,5 @@
export {Types} from './Types/number.mjs' export {Types} from './Types/number.mjs'
export const add = { export const add = {
'...number': [[], addends => addends.reduce((x,y) => x+y, 0)], '...number': addends => addends.reduce((x,y) => x+y, 0),
} }

View File

@ -1,3 +1,3 @@
export { Types } from './Types/number.mjs' export { Types } from './Types/number.mjs'
export const negate = {number: [[], n => -n]} export const negate = {number: n => -n}