/* 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). */ import {parseReflectedType, ImplementationDef} from './parseReflectedType.js' // First helper types and functions for the Dispatcher type TypeName = string type Parameter = TypeName type Signature = Parameter[] type DependenciesType = Record // 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 = { name: string, // just until we get reflection, then we can remove this property before?: TypeName[], test: ((x: unknown) => boolean) | ((d: DependenciesType) => (x: unknown) => boolean), from: Record, infer?: (d: DependenciesType) => (z: unknown) => TypeName } type SpecObject = Record type SpecificationsGroup = Record export class Dispatcher { installSpecification( name: string, defn: ImplementationDef, 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, 'with signatures') for (const signature of defn.fn.signatures) { console.log(' ', signature.args, '=>', signature.returns) } if (defn.fn.aliasOf) { console.log(' As an alias of', defn.fn.aliasOf) } //TODO: implement me } installType(name: TypeName, typespec: TypeSpecification) { console.log('Pretending to install type', name, typespec) //TODO: implement me } constructor(collection: SpecificationsGroup) { const implementations = [] for (const key in collection) { console.log('Working on', key) for (const identifier in collection[key]) { const item = collection[key][identifier] if (typeof item === 'function') { implementations.push([key, identifier, item]) } else { console.log('Handling type', key, ':', identifier) this.installType( item.name, collection[key][identifier] as TypeSpecification) } } } for (const trio of implementations) { const [k, id, imp] = trio console.log('Handling implementation', id, 'from', k) this.installSpecification( id, parseReflectedType(id, imp.reflectedType), imp) } } }