From 8dcf74c5d129e2a33be315cc1009076acbda3d4c Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Fri, 20 Oct 2023 09:05:02 -0700 Subject: [PATCH] refactor: Demonstrate macro generating a generic implementations interface I swapped in the new macro in source files numbers/predicate.ts, Complex/arithmetic.ts, and Complex/predicate.ts. Note that you have to specify whether you are reflecting the generic or concrete implementations, which in some cases will mean two separate macro calls (as in Complex/predicate.ts). Also tried out the $$typeMetadata macro in Complex/all.ts; you can see the result by building and looking at build/Complex/all.js. It splits things up somewhat but we would still need to do a bunch of parsing, so probably not worth switching. --- src/Complex/all.ts | 3 +++ src/Complex/arithmetic.ts | 8 ++++++-- src/Complex/predicate.ts | 5 +++-- src/core/Dispatcher.ts | 12 ++++++------ src/interfaces/type.ts | 33 ++++++++++++++++++++++++++++++++- src/numbers/native.ts | 5 +++++ src/numbers/predicate.ts | 10 +++++++--- 7 files changed, 62 insertions(+), 14 deletions(-) diff --git a/src/Complex/all.ts b/src/Complex/all.ts index 3ff6311..320bb2a 100644 --- a/src/Complex/all.ts +++ b/src/Complex/all.ts @@ -1,6 +1,9 @@ import * as Complex from './native.js' import * as complex from './arithmetic.js' +import {$$typeMetadata} from 'ts-macros' export { complex } export {Complex} + +const tryit = $$typeMetadata!(true, true) diff --git a/src/Complex/arithmetic.ts b/src/Complex/arithmetic.ts index 0f11f2e..11a2d7e 100644 --- a/src/Complex/arithmetic.ts +++ b/src/Complex/arithmetic.ts @@ -2,7 +2,7 @@ import {Complex} from './type.js' import type { Dependencies, Signature, Returns, RealType, AliasOf } from '../interfaces/type.js' -import {$reflect} from '../interfaces/type.js' +import {$reflectGen, GENERIC} from '../interfaces/type.js' declare module "../interfaces/type" { interface Signatures { @@ -98,7 +98,11 @@ export const sqrt = return dep.divideReal(num, denom) } -$reflect!([ +export interface GenericImplementations { + kilroy: "was here" +} + +$reflectGen!(GENERIC, [ add, addReal, unaryMinus, conj, subtract, multiply, absquare, divideReal, reciprocal, divide, sqrt ]) diff --git a/src/Complex/predicate.ts b/src/Complex/predicate.ts index fe26906..625b6d2 100644 --- a/src/Complex/predicate.ts +++ b/src/Complex/predicate.ts @@ -1,6 +1,6 @@ import {Complex} from './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 = (dep: Dependencies<'add' | 'equal' | 'isReal', T>): @@ -10,4 +10,5 @@ export const isReal = export const isSquare = (): Signature<'isSquare', Complex> => z => true // FIXME: not correct for Complex once we get there -$reflect!([isReal, isSquare]) +$reflectGen!(GENERIC, [isReal]) +$reflectGen!(CONCRETE, [isSquare]) diff --git a/src/core/Dispatcher.ts b/src/core/Dispatcher.ts index 1485160..3dab510 100644 --- a/src/core/Dispatcher.ts +++ b/src/core/Dispatcher.ts @@ -59,12 +59,12 @@ type BaseOperationSignature< Name extends BaseOperations > = ValueIntersectionByKeyUnion< {[K in keyof Obj]: - K extends Name - ? Obj[K] - : Obj[K] extends Callable - ? ReturnType['aliasOf'] extends (Name | undefined) - ? Obj[K] : unknown - : unknown + Obj[K] extends Callable + ? K extends Name + ? ReturnType + : ReturnType['aliasOf'] extends (Name | undefined) + ? ReturnType : unknown + : unknown }, keyof Obj> // Get the type of a given operation in a SpecificationsGroup diff --git a/src/interfaces/type.ts b/src/interfaces/type.ts index 55a36a9..da776d8 100644 --- a/src/interfaces/type.ts +++ b/src/interfaces/type.ts @@ -77,7 +77,7 @@ type SignatureKey = keyof Signatures export type Signature, T> = Signatures[Name] export type Returns, T> = ReturnType[Name]> -type Deps = T extends unknown ? { [K in keyof T]: T[K] } : never; +export type Deps = T extends unknown ? { [K in keyof T]: T[K] } : never; export type Dependencies, T> = Deps<{[K in Name]: Signature}> @@ -88,3 +88,34 @@ export function $reflect(tup: ImplTuple) { +[[tup], (elt: T) => elt.reflectedType = $$typeToString!(true, false, true)] } +export function $genImps(tup: ImplTuple) { + +[[tup], (elt: U) => { + export interface GenericImplementations { + [$$text!(elt)]: typeof elt + } + }] +} + +export function $genImpsT(tup: ImplTuple) { + +[[tup], (elt: U) => { + export interface GenericImplementations { + [$$text!(elt)]: typeof elt + } + }] +} +export const GENERIC = true +export const CONCRETE = false +export function $reflectGen(generic: boolean, tup: ImplTuple) { + +[[tup], (elt: T) => { + elt.reflectedType = $$typeToString!(true, false, true) + if (generic) { + export interface GenericImplementations { + [$$text!(elt)]: typeof elt + } + } else { + export interface GenericImplementations { + [$$text!(elt)]: typeof elt + } + } + }] +} diff --git a/src/numbers/native.ts b/src/numbers/native.ts index ea2f66b..50c97f0 100644 --- a/src/numbers/native.ts +++ b/src/numbers/native.ts @@ -1,4 +1,9 @@ +import {GenericImplementations} from './predicate.js' +import {$$typeToString} from 'ts-macros' export * from './type.js' export * from './arithmetic.js' export * from './predicate.js' export * from './relational.js' + +const test: ReturnType['isReal']> = + (a: number) => true // = "oops" would fail as desired. diff --git a/src/numbers/predicate.ts b/src/numbers/predicate.ts index 0a51d65..e0a4907 100644 --- a/src/numbers/predicate.ts +++ b/src/numbers/predicate.ts @@ -1,7 +1,11 @@ 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 isSquare = (): Signature<'isSquare', number> => (a) => a >= 0 -$reflect!([isReal, isSquare]) +export interface GenericImplementations { + kilroy: "was here" +} + +$reflectGen!(CONCRETE, [isReal, isSquare])