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.
This commit is contained in:
Glen Whitney 2023-10-20 09:05:02 -07:00
parent 569079e908
commit 8dcf74c5d1
7 changed files with 62 additions and 14 deletions

View File

@ -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)

View File

@ -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
]) ])

View File

@ -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])

View File

@ -59,11 +59,11 @@ type BaseOperationSignature<
Name extends BaseOperations<Obj> Name extends BaseOperations<Obj>
> = ValueIntersectionByKeyUnion< > = ValueIntersectionByKeyUnion<
{[K in keyof Obj]: {[K in keyof Obj]:
K extends Name Obj[K] extends Callable
? Obj[K] ? K extends Name
: Obj[K] extends Callable ? ReturnType<Obj[K]>
? ReturnType<Obj[K]>['aliasOf'] extends (Name | undefined) : ReturnType<Obj[K]>['aliasOf'] extends (Name | undefined)
? Obj[K] : unknown ? ReturnType<Obj[K]> : unknown
: unknown : unknown
}, },
keyof Obj> keyof Obj>

View File

@ -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
}
}
}]
}

View File

@ -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.

View File

@ -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])