Compare commits
2 Commits
main
...
dispatcher
Author | SHA1 | Date | |
---|---|---|---|
8dcf74c5d1 | |||
569079e908 |
@ -1,6 +1,9 @@
|
|||||||
import * as Complex from './native.js'
|
import * as Complex from './native.js'
|
||||||
import * as complex from './arithmetic.js'
|
import * as complex from './arithmetic.js'
|
||||||
|
import {$$typeMetadata} from 'ts-macros'
|
||||||
|
|
||||||
export { complex }
|
export { complex }
|
||||||
|
|
||||||
export {Complex}
|
export {Complex}
|
||||||
|
|
||||||
|
const tryit = $$typeMetadata!<typeof complex>(true, true)
|
||||||
|
@ -2,7 +2,7 @@ import {Complex} from './type.js'
|
|||||||
import type {
|
import type {
|
||||||
Dependencies, Signature, Returns, RealType, AliasOf
|
Dependencies, Signature, Returns, RealType, AliasOf
|
||||||
} from '../interfaces/type.js'
|
} from '../interfaces/type.js'
|
||||||
import {$reflect} from '../interfaces/type.js'
|
import {$reflectGen, GENERIC} from '../interfaces/type.js'
|
||||||
|
|
||||||
declare module "../interfaces/type" {
|
declare module "../interfaces/type" {
|
||||||
interface Signatures<T> {
|
interface Signatures<T> {
|
||||||
@ -98,7 +98,11 @@ export const sqrt =
|
|||||||
return dep.divideReal(num, denom)
|
return dep.divideReal(num, denom)
|
||||||
}
|
}
|
||||||
|
|
||||||
$reflect!([
|
export interface GenericImplementations<T> {
|
||||||
|
kilroy: "was here"
|
||||||
|
}
|
||||||
|
|
||||||
|
$reflectGen!(GENERIC, [
|
||||||
add, addReal, unaryMinus, conj, subtract, multiply, absquare, divideReal,
|
add, addReal, unaryMinus, conj, subtract, multiply, absquare, divideReal,
|
||||||
reciprocal, divide, sqrt
|
reciprocal, divide, sqrt
|
||||||
])
|
])
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {Complex} from './type.js'
|
import {Complex} from './type.js'
|
||||||
import type {Dependencies, Signature} from '../interfaces/type.js'
|
import type {Dependencies, Signature} from '../interfaces/type.js'
|
||||||
import {$reflect} from '../interfaces/type.js'
|
import {$reflectGen, GENERIC, CONCRETE} from '../interfaces/type.js'
|
||||||
|
|
||||||
export const isReal =
|
export const isReal =
|
||||||
<T>(dep: Dependencies<'add' | 'equal' | 'isReal', T>):
|
<T>(dep: Dependencies<'add' | 'equal' | 'isReal', T>):
|
||||||
@ -10,4 +10,5 @@ export const isReal =
|
|||||||
export const isSquare = (): Signature<'isSquare', Complex<unknown>> =>
|
export const isSquare = (): Signature<'isSquare', Complex<unknown>> =>
|
||||||
z => true // FIXME: not correct for Complex<bigint> once we get there
|
z => true // FIXME: not correct for Complex<bigint> once we get there
|
||||||
|
|
||||||
$reflect!([isReal, isSquare])
|
$reflectGen!(GENERIC, [isReal])
|
||||||
|
$reflectGen!(CONCRETE, [isSquare])
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {parseReflectedType, ImplementationDef} from './parseReflectedType.js'
|
import {parseReflectedType, ImplementationDef} from './parseReflectedType.js'
|
||||||
|
import type {ValueIntersectionByKeyUnion} from '../interfaces/type.js'
|
||||||
|
|
||||||
// First helper types and functions for the Dispatcher
|
// First helper types and functions for the Dispatcher
|
||||||
|
|
||||||
@ -35,32 +36,57 @@ type TypeSpecification = {
|
|||||||
infer?: (d: DependenciesType) => (z: unknown) => TypeName
|
infer?: (d: DependenciesType) => (z: unknown) => TypeName
|
||||||
}
|
}
|
||||||
|
|
||||||
type SpecObject = Record<string, Function | TypeSpecification>
|
type Callable = (...args: any) => any
|
||||||
|
type SpecObject = Record<string, Callable | TypeSpecification>
|
||||||
type SpecificationsGroup = Record<string, SpecObject>
|
type SpecificationsGroup = Record<string, SpecObject>
|
||||||
|
|
||||||
export class Dispatcher {
|
// Find all of the keys of an object that are functions but not aliases
|
||||||
installSpecification(
|
// to another operation
|
||||||
name: string,
|
type BaseOperations<Obj extends SpecObject> =
|
||||||
defn: ImplementationDef,
|
{[K in keyof Obj]:
|
||||||
behavior: Function // possible todo: constrain this type based
|
Obj[K] extends Callable
|
||||||
// on the signature, return type, and dependencies. Not sure if
|
? ReturnType<Obj[K]>['aliasOf'] extends (string | undefined)
|
||||||
// that's really possible, though.
|
? never
|
||||||
) {
|
: K extends string ? K : never
|
||||||
console.log('Pretending to install', name, 'with signatures')
|
: never
|
||||||
for (const signature of defn.fn.signatures) {
|
}[keyof Obj]
|
||||||
console.log(' ', signature.args, '=>', signature.returns)
|
// Gather all of the operations specified in a SpecificationsGroup
|
||||||
}
|
type DispatcherOperations<G extends SpecificationsGroup> =
|
||||||
if (defn.fn.aliasOf) {
|
{[K in keyof G]: BaseOperations<G[K]>}[keyof G]
|
||||||
console.log(' As an alias of', defn.fn.aliasOf)
|
// Get the type of a given operation in a SpecObject:
|
||||||
}
|
type BaseOperationSignature<
|
||||||
//TODO: implement me
|
Obj extends SpecObject,
|
||||||
}
|
Name extends BaseOperations<Obj>
|
||||||
installType(name: TypeName, typespec: TypeSpecification) {
|
> = ValueIntersectionByKeyUnion<
|
||||||
console.log('Pretending to install type', name, typespec)
|
{[K in keyof Obj]:
|
||||||
//TODO: implement me
|
Obj[K] extends Callable
|
||||||
}
|
? K extends Name
|
||||||
constructor(collection: SpecificationsGroup) {
|
? ReturnType<Obj[K]>
|
||||||
|
: ReturnType<Obj[K]>['aliasOf'] extends (Name | undefined)
|
||||||
|
? ReturnType<Obj[K]> : unknown
|
||||||
|
: unknown
|
||||||
|
},
|
||||||
|
keyof Obj>
|
||||||
|
// Get the type of a given operation in a SpecificationsGroup
|
||||||
|
type OperationSignature<
|
||||||
|
G extends SpecificationsGroup,
|
||||||
|
Name extends DispatcherOperations<G>
|
||||||
|
> = ValueIntersectionByKeyUnion<
|
||||||
|
{[K in keyof G]:
|
||||||
|
Name extends BaseOperations<G[K]>
|
||||||
|
? BaseOperationSignature<G[K], Name>
|
||||||
|
: unknown},
|
||||||
|
keyof G>
|
||||||
|
// Put it all together into the typing of the dispatcher
|
||||||
|
type DispatcherInterface<G extends SpecificationsGroup> =
|
||||||
|
{[Op in DispatcherOperations<G>]: OperationSignature<G, Op>}
|
||||||
|
|
||||||
|
export function createDispatcher<G extends SpecificationsGroup>(
|
||||||
|
collection: G): DispatcherInterface<G>
|
||||||
|
{
|
||||||
const implementations = []
|
const implementations = []
|
||||||
|
const types = {} // who knows what the type of this will be
|
||||||
|
const behaviors = {} // ditto
|
||||||
for (const key in collection) {
|
for (const key in collection) {
|
||||||
console.log('Working on', key)
|
console.log('Working on', key)
|
||||||
for (const identifier in collection[key]) {
|
for (const identifier in collection[key]) {
|
||||||
@ -69,16 +95,44 @@ export class Dispatcher {
|
|||||||
implementations.push([key, identifier, item])
|
implementations.push([key, identifier, item])
|
||||||
} else {
|
} else {
|
||||||
console.log('Handling type', key, ':', identifier)
|
console.log('Handling type', key, ':', identifier)
|
||||||
this.installType(
|
installType( // In this design, installType would modify
|
||||||
item.name, collection[key][identifier] as TypeSpecification)
|
// types by side effect; maybe Jos prefers some other
|
||||||
|
// factoring of this?
|
||||||
|
types, item.name,
|
||||||
|
collection[key][identifier] as TypeSpecification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const trio of implementations) {
|
for (const trio of implementations) {
|
||||||
const [k, id, imp] = trio
|
const [k, id, imp] = trio
|
||||||
console.log('Handling implementation', id, 'from', k)
|
console.log('Handling implementation', id, 'from', k)
|
||||||
this.installSpecification(
|
installSpecification(
|
||||||
id, parseReflectedType(id, imp.reflectedType), imp)
|
behaviors, id, parseReflectedType(id, imp.reflectedType), imp)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return {} as DispatcherInterface<G>
|
||||||
|
}
|
||||||
|
|
||||||
|
function installType(
|
||||||
|
types: Object, name: TypeName, typespec: TypeSpecification)
|
||||||
|
{
|
||||||
|
console.log('Pretending to install type', name, typespec)
|
||||||
|
//TODO: implement me
|
||||||
|
}
|
||||||
|
|
||||||
|
function installSpecification(
|
||||||
|
behaviors: Object, // Same issue as mentioned above with side effects...
|
||||||
|
name: string,
|
||||||
|
defn: ImplementationDef,
|
||||||
|
specification: 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
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
import {inspect} from 'node:util'
|
import {inspect} from 'node:util'
|
||||||
import {Dispatcher} from './core/Dispatcher.js'
|
import {createDispatcher} from './core/Dispatcher.js'
|
||||||
import * as Specifications from './all.js'
|
import * as Specifications from './all.js'
|
||||||
|
|
||||||
export default new Dispatcher(Specifications)
|
export Specifications
|
||||||
|
const math = createDispatcher(Specifications)
|
||||||
|
export default math
|
||||||
|
|
||||||
|
console.log('Made', math.add}
|
||||||
|
|
||||||
import {Complex} from './Complex/type.js'
|
import {Complex} from './Complex/type.js'
|
||||||
import {absquare as absquare_complex} from './Complex/arithmetic.js'
|
import {absquare as absquare_complex} from './Complex/arithmetic.js'
|
||||||
|
@ -15,7 +15,7 @@ import {$$typeToString} from 'ts-macros'
|
|||||||
* but that's OK, the generic parameter doesn't hurt in those cases.
|
* but that's OK, the generic parameter doesn't hurt in those cases.
|
||||||
****/
|
****/
|
||||||
|
|
||||||
type ValueIntersectionByKeyUnion<T, TKey extends keyof T> = {
|
export type ValueIntersectionByKeyUnion<T, TKey extends keyof T> = {
|
||||||
[P in TKey]: (k: T[P])=>void
|
[P in TKey]: (k: T[P])=>void
|
||||||
} [TKey] extends ((k: infer I)=>void) ? I : never
|
} [TKey] extends ((k: infer I)=>void) ? I : never
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ type SignatureKey<T> = keyof Signatures<T>
|
|||||||
export type Signature<Name extends SignatureKey<T>, T> = Signatures<T>[Name]
|
export type Signature<Name extends SignatureKey<T>, T> = Signatures<T>[Name]
|
||||||
export type Returns<Name extends SignatureKey<T>, T> =
|
export type Returns<Name extends SignatureKey<T>, T> =
|
||||||
ReturnType<Signatures<T>[Name]>
|
ReturnType<Signatures<T>[Name]>
|
||||||
type Deps<T> = T extends unknown ? { [K in keyof T]: T[K] } : never;
|
export type Deps<T> = T extends unknown ? { [K in keyof T]: T[K] } : never;
|
||||||
export type Dependencies<Name extends SignatureKey<T>, T> =
|
export type Dependencies<Name extends SignatureKey<T>, T> =
|
||||||
Deps<{[K in Name]: Signature<K, T>}>
|
Deps<{[K in Name]: Signature<K, T>}>
|
||||||
|
|
||||||
@ -88,3 +88,34 @@ export function $reflect<ImplTuple>(tup: ImplTuple) {
|
|||||||
+[[tup], <T>(elt: T) =>
|
+[[tup], <T>(elt: T) =>
|
||||||
elt.reflectedType = $$typeToString!<T>(true, false, true)]
|
elt.reflectedType = $$typeToString!<T>(true, false, true)]
|
||||||
}
|
}
|
||||||
|
export function $genImps<ImplTuple>(tup: ImplTuple) {
|
||||||
|
+[[tup], <U>(elt: U) => {
|
||||||
|
export interface GenericImplementations<T> {
|
||||||
|
[$$text!(elt)]: typeof elt
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function $genImpsT<ImplTuple>(tup: ImplTuple) {
|
||||||
|
+[[tup], <U>(elt: U) => {
|
||||||
|
export interface GenericImplementations<T> {
|
||||||
|
[$$text!(elt)]: typeof elt<T>
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
export const GENERIC = true
|
||||||
|
export const CONCRETE = false
|
||||||
|
export function $reflectGen<ImplTuple>(generic: boolean, tup: ImplTuple) {
|
||||||
|
+[[tup], <T>(elt: T) => {
|
||||||
|
elt.reflectedType = $$typeToString!<T>(true, false, true)
|
||||||
|
if (generic) {
|
||||||
|
export interface GenericImplementations<T> {
|
||||||
|
[$$text!(elt)]: typeof elt<T>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
export interface GenericImplementations<T> {
|
||||||
|
[$$text!(elt)]: typeof elt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
|
import {GenericImplementations} from './predicate.js'
|
||||||
|
import {$$typeToString} from 'ts-macros'
|
||||||
export * from './type.js'
|
export * from './type.js'
|
||||||
export * from './arithmetic.js'
|
export * from './arithmetic.js'
|
||||||
export * from './predicate.js'
|
export * from './predicate.js'
|
||||||
export * from './relational.js'
|
export * from './relational.js'
|
||||||
|
|
||||||
|
const test: ReturnType<GenericImplementations<unknown>['isReal']> =
|
||||||
|
(a: number) => true // = "oops" would fail as desired.
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
import type {Signature} from '../interfaces/type.js'
|
import type {Signature} from '../interfaces/type.js'
|
||||||
import {$reflect} from '../interfaces/type.js'
|
import {$reflectGen, CONCRETE} from '../interfaces/type.js'
|
||||||
|
import {$$typeToString} from 'ts-macros'
|
||||||
export const isReal = (): Signature<'isReal', number> => (a) => true
|
export const isReal = (): Signature<'isReal', number> => (a) => true
|
||||||
export const isSquare = (): Signature<'isSquare', number> => (a) => a >= 0
|
export const isSquare = (): Signature<'isSquare', number> => (a) => a >= 0
|
||||||
|
|
||||||
$reflect!([isReal, isSquare])
|
export interface GenericImplementations<T> {
|
||||||
|
kilroy: "was here"
|
||||||
|
}
|
||||||
|
|
||||||
|
$reflectGen!(CONCRETE, [isReal, isSquare])
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
"outDir": "./build",
|
"outDir": "./build",
|
||||||
"moduleResolution": "nodenext",
|
"moduleResolution": "nodenext",
|
||||||
|
"declaration": true,
|
||||||
"plugins": [ {
|
"plugins": [ {
|
||||||
"transform": "ts-macros/dist/type-resolve",
|
"transform": "ts-macros/dist/type-resolve",
|
||||||
"transformProgram": true
|
"transformProgram": true
|
||||||
|
Loading…
Reference in New Issue
Block a user