typocomath/src/core/Dispatcher.ts

76 lines
2.5 KiB
TypeScript

/* A Dispatcher is a collection of operations that do run-time
* dispatch on the types of their arguments. Thus, every individual
* method is like a typed-function (from the library by that name),
* but they can depend on one another and on ona another's implementations
* for specific types (including their own).
*/
// First helper types and functions for the Dispatcher
type TypeName = string
type Parameter = TypeName
type Signature = Parameter[]
type DependenciesType = Record<string, Function>
// A "canned" dependency for a builtin function:
export type typeOfDependency = {typeOf: (x: unknown) => TypeName}
// Utility needed in type definitions
//dummy implementation for now
export function joinTypes(a: TypeName, b: TypeName) {
if (a === b) return a
return 'any'
}
// Now types used in the Dispatcher class itself
type TypeSpecification = {
before?: TypeName[],
test: ((x: unknown) => boolean)
| ((d: DependenciesType) => (x: unknown) => boolean),
from: Record<TypeName, Function>,
infer?: (d: DependenciesType) => (z: unknown) => TypeName
}
type SpecObject = Record<string, Function | TypeSpecification>
type SpecificationsGroup = Record<string, SpecObject>
export class Dispatcher {
installSpecification(
name: string,
signature: Signature,
returns: TypeName,
dependencies: Record<string, Signature>,
behavior: Function // possible todo: constrain this type based
// on the signature, return type, and dependencies. Not sure if
// that's really possible, though.
) {
console.log('Pretending to install', name, signature, '=>', returns)
//TODO: implement me
}
installType(name: TypeName, typespec: TypeSpecification) {
console.log('Pretending to install type', name, typespec)
//TODO: implement me
}
constructor(collection: SpecificationsGroup) {
for (const key in collection) {
console.log('Working on', key)
for (const identifier in collection[key]) {
console.log('Handling', key, ':', identifier)
const parts = identifier.split('_')
if (parts[parts.length - 1] === 'type') {
parts.pop()
const name = parts.join('_')
this.installType(
name, collection[key][identifier] as TypeSpecification)
} else {
const name = parts[0]
this.installSpecification(
name, ['dunno'], 'unsure', {},
collection[key][identifier] as Function)
}
}
}
}
}