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 const add = {
'...Complex': [['self'], ref => addends => {
'...Complex': {
uses: ['self'],
does: ref => addends => {
if (addends.length === 0) return {re:0, im:0}
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
* 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 */
Complex: [[], z => z]
Complex: {does: z => z}
}

View File

@ -1,7 +1,10 @@
export {Types} from './Types/Complex.mjs'
export const negate = {
Complex: [['self'], ref => z => {
Complex: {
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) {
if (func === 'Types') continue
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]
if (doneSet.has(depName)) continue
requiredSet.add(depName)
@ -158,7 +163,20 @@ export default class PocomathInstance {
this._ensureTypes()
const tf_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) {
tf_imps[signature] = imp
} else {

View File

@ -1,5 +1,5 @@
export {Types} from './Types/number.mjs'
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 const negate = {number: [[], n => -n]}
export const negate = {number: n => -n}