feat: Runtime type reflection #17

Merged
glen merged 21 commits from ts-macros-issues into main 2023-10-17 22:02:18 +00:00
5 changed files with 42 additions and 37 deletions
Showing only changes of commit ebe7cf831e - Show all commits

View File

@ -2,7 +2,7 @@ import {Complex} from './type.js'
import type {
Dependencies, Signature, Returns, RealType, AliasOf
} from '../interfaces/type.js'
import {$reflecType} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
declare module "../interfaces/type" {
interface Signatures<T> {
@ -82,8 +82,7 @@ export const sqrt =
addTR: Signature<'addReal', T>,
addRR: Signature<'add', RealType<T>>,
addCR: Signature<'addReal', Complex<T>>
}):
Signature<'sqrt', Complex<T>> =>
}): Signature<'sqrt', Complex<T>> =>
z => {
const myabs = dep.conservativeSqrt(dep.absquare(z))
const r = dep.re(z)
@ -98,4 +97,4 @@ export const sqrt =
const denom = dep.conservativeSqrt(denomsq)
return dep.divideReal(num, denom)
}
$reflecType!(sqrt)
$reflect!([sqrt])

View File

@ -1,7 +1,9 @@
import type {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const square = $reflect!('square',
<T>(dep: Dependencies<'multiply', T>) => (z:T) => dep.multiply(z, z))
export const square =
<T>(dep: Dependencies<'multiply', T>): Signature<'square', T> =>
z => dep.multiply(z, z)
// z => dep.fooBar(z, z) // fails as desired
// z => dep.multiply(z, 'foo') // still fails as desired
$reflect!([square])

View File

@ -1,12 +1,20 @@
import { inspect} from 'node:util'
import {inspect} from 'node:util'
import {Dispatcher} from './core/Dispatcher.js'
import {Signatures, Deps} from './interfaces/type.js'
import {$$typeToString} from 'ts-macros'
import * as Specifications from './all.js'
class Placeholder {}
const allSignatures =
$$typeToString!<Deps<Signatures<Placeholder>>>(true, false, true)
console.log('Found signatures', allSignatures)
export default new Dispatcher(Specifications)
import {Complex} from './Complex/type.js'
import {absquare as absquare_complex} from './Complex/arithmetic.js'
import { parseReflectedType, split } from './core/parseReflectedType.js'
import {parseReflectedType} from './core/parseReflectedType.js'
const mockRealAdd = (a: number, b: number) => a+b
const mockComplexAbsquare = (z: Complex<number>) => z.re*z.re + z.im*z.im
@ -36,7 +44,11 @@ console.log('Result of sqrt(-4)=', sqrt(-4))
console.log()
console.log('1) NUMBER SQRT')
console.log(`1.1) REFLECTED TYPE: "${Specifications.numbers.sqrt.reflectedType}"`)
console.log('1.2) PARSED TYPE:', inspect(parseReflectedType('sqrt', Specifications.numbers.sqrt.reflectedType), { depth: null, colors: true }))
console.log(
'1.2) PARSED TYPE:',
inspect(
parseReflectedType('sqrt', Specifications.numbers.sqrt.reflectedType),
{ depth: null, colors: true }))
console.log()
console.log('2) GENERIC SQUARE')
@ -47,9 +59,3 @@ console.log()
console.log('3) COMPLEX SQRT')
console.log(`1.1) REFLECTED TYPE: "${Specifications.complex.sqrt.reflectedType}"`)
console.log('3.2) PARSED TYPE:', inspect(parseReflectedType('sqrt', Specifications.complex.sqrt.reflectedType), { depth: null, colors: true }))
// FIXME: cleanup
// console.log()
// console.log('split', split('hello**world**how**are**you', '**'))
// console.log('split', split('hello(test**world)**how**are**you', '**'))
// console.log('split', split('<T>(dep: { multiply: (a: T, b: T) => T; }) => (z: T) => T', '=>'))

View File

@ -1,4 +1,4 @@
import {$$typeToString, $$ident, $$define} from 'ts-macros'
import {$$typeToString} from 'ts-macros'
/*****
* Every typocomath type has some associated types; they need
@ -74,25 +74,23 @@ export interface Signatures<T> {
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 DSignature<Name extends SignatureKey<T>, T> =
Signatures<T>[Name] & {reflectedType?: string, actualType?: Signatures<T>[Name]}
export type Returns<Name extends SignatureKey<T>, T> = 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> = Deps<{[K in Name]: Signature<K, T>}>
export type AliasOf<Name extends string, T> = T & {aliasOf?: Name}
// For defining implementations with type reflection
export function $reflect<Impl>(name: string, expr: Impl) : Impl & { reflectedType: string} {
$$define!(name, expr, false, false);
$$ident!(name).reflectedType = $$typeToString!<Impl>(true, false, true);
return $$ident!(name)
}
export function $reflecType<Impl>(expr: Impl) {
expr.reflectedType = $$typeToString!<Impl>(true, false, true);
}
export function $reflecTypes<ImplTuple>(tup: ImplTuple) {
export function $reflect<ImplTuple>(tup: ImplTuple) {
+[[tup], <T>(elt: T) =>
elt.reflectedType = $$typeToString!<T>(true, false, true)]
elt.reflectedType = $$typeToString!<T>(true, false, true)]
}
export function $Dreflect<ImplTuple>(tup: ImplTuple) {
+[[tup], <T>(elt: T) =>
elt.reflectedType = $$typeToString!<T['actualType']>(true, false, true)]
}
export type RTT = {reflectedType?: string}

View File

@ -1,11 +1,11 @@
import type {configDependency} from '../core/Config.js'
import type {Dependencies, Signature} from '../interfaces/type.js'
import { $reflecType, $reflecTypes } from '../interfaces/type.js'
import type {Dependencies, Signature, RTT, DSignature} from '../interfaces/type.js'
import {$reflect, $Dreflect} from '../interfaces/type.js'
export const add /*: Signature<'add', number>*/ = (a, b) => a + b
export const add: Signature<'add', number> & RTT = (a, b) => a + b
export const unaryMinus: Signature<'unaryMinus', number> = a => -a
export const conj /*: Signature<'conj', number>*/ = a => a
export const subtract /*: Signature<'subtract', number>*/ = (a, b) => a - b
export const conj: DSignature<'conj', number> = a => a
export const subtract = (): Signature<'subtract', number> => (a, b) => a - b
export const multiply: Signature<'multiply', number> = (a, b) => a * b
export const absquare: Signature<'absquare', number> = a => a * a
export const reciprocal: Signature<'reciprocal', number> = a => 1 / a
@ -26,5 +26,5 @@ export const sqrt =
return dep.complex(0, Math.sqrt(unaryMinus(a)))
}
}
$reflecType!(sqrt)
$reflecTypes!([add, conj, subtract])
$reflect!([add, sqrt, subtract])
$Dreflect!([conj])