Created
January 26, 2025 00:15
-
-
Save reverofevil/406ddd68c7f06c486e7ce6039b90f1d5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Example1 { | |
type Sig<I, O> = (input: I) => O; | |
declare const imm: (int: number) => Sig<[], [number]>; | |
declare const add: () => Sig<[number, number], [number]>; | |
interface Builder<Stack> { | |
$: <I extends any[], O extends any[]>( | |
instr: Stack extends [...I, ...any[]] ? Sig<I, O> : never | |
) => Builder<Stack extends [...I, ...infer R] ? [...O, ...R] : never> | |
} | |
declare const b: Builder<[]>; | |
const test = () => b | |
.$(imm(1)) | |
.$(imm(2)) | |
.$(add()) | |
.$(imm(4)) | |
.$(add()) | |
} | |
namespace Example2 { | |
type AddFn<Stack extends any[], N extends string, P extends any[], I extends any[], O extends any[]> = | |
Stack extends [...I, ...infer R] | |
? { [K in N]: (...args: P) => Builder<[...O, ...R]> } | |
: {} | |
type Builder<Stack extends any[]> = | |
& AddFn<Stack, 'imm', [number], [], [number]> | |
& AddFn<Stack, 'add', [], [number, number], [number]> | |
declare const b: Builder<[]>; | |
const test = () => b | |
.imm(1) | |
.imm(2) | |
.add() | |
.imm(3) | |
.add() | |
} | |
namespace Example3 { | |
type Unwrap<T> = T extends infer R ? {[K in keyof R]: R[K]} : never; | |
type Apply<F, R> = F extends { args: unknown; result: unknown; } ? (F & {args: R})["result"] : never | |
interface Arr { args: unknown; result: Unwrap<this["args"][]> } | |
type R1 = Apply<Arr, number> | |
interface Pair1<L> { args: unknown; result: [L, this["args"]] } | |
interface Pair { args: unknown; result: Pair1<this["args"]> } | |
type R2 = Apply<Apply<Pair, string>, number> | |
} | |
namespace Example4 { | |
interface A { a: this } | |
interface B { b: this } | |
declare const t: A & B; | |
const test1 = () => t.a.b.a.b; | |
type Builder<T extends string> = { [K in T]: Builder<T> } | |
declare const r: Builder<'o' | 'a' | 'c' | 'l'>; | |
const test2 = () => r.c.o.c.a.c.o.l.a; | |
type Builder2<T extends string> = { [K in T]: Builder2<T> } | |
interface Bibuilder<K extends string> { | |
end: Builder2<K>; | |
add: <L extends string>(l: L) => Bibuilder<K | L>; | |
} | |
declare const bb: Bibuilder<never>; | |
const b = bb.add('o').add('a').add('c').add('l').end; | |
const r2 = b.c.o.c.a.c.o.l.a; | |
} | |
namespace Example5 { | |
type Apply<F, R> = F extends { args: unknown; result: unknown; } ? (F & {args: R})["result"] : never | |
interface Args<T> { args: T } | |
interface Fix { | |
args: unknown; | |
// @ts-ignore | |
result: (this["args"] & Args<this>)["result"] | |
} | |
interface FooAux<T> { $: 'a', value: T } | |
// @ts-ignore | |
interface Foo { args: unknown; result: FooAux<this["args"]["result"]> } | |
// @ts-ignore | |
type R = Apply<Fix, Foo> | |
declare const r: R; | |
// only up to 32 | |
const a = r.value.value.value.value.value.value.value.value.value.value.value.value.value | |
.value.value.value.value.value.value.value.value.value.value.value.value.value | |
.value.value.value.value.value.x | |
} | |
namespace Example6 { | |
type Unwrap<T> = T extends infer R ? {[K in keyof R]: R[K]} : never; | |
type Presence<K, V, Stack> = V extends [[...infer I], ...any[]] | |
? Stack extends [...I, ...any[]] | |
? K | |
: never | |
: never | |
type Builder<Stack, T> = { | |
[K in keyof T as Presence<K, T[K], Stack>]: T[K] extends [[...infer I], [...infer O], [...infer P]] | |
? Stack extends [...I, ...infer R] | |
? (...args: P) => Builder<[...O, ...R], T> | |
: never | |
: never | |
} | |
interface Bibuilder<T> { | |
end: Builder<[], T>; | |
add: <N extends string>(key: N) => | |
<I extends any[], O extends any[]>() => | |
<P extends any[]>(handler: (...args: P) => string) => | |
Bibuilder<Unwrap<T & { [K in N]: [I, O, P] }>> | |
} | |
declare const make: <K>() => Bibuilder<K> | |
const defineAsm = make<{}>(); | |
const asm = defineAsm | |
.add('imm')<[], [number]>()<[number]>((p) => '') | |
.add('add')<[number, number], [number]>()<[]>(() => '') | |
.end; | |
const codegen = () => asm | |
.imm(1) | |
.imm(2) | |
.add() | |
.imm(3) | |
.add() | |
} | |
// type Unwrap<T> = T extends infer R ? {[K in keyof R]: R[K]} : never; | |
// type Apply<F, R> = F extends { args: unknown; result: unknown; } ? (F & {args: R})["result"] : never | |
// interface Fn<B, N extends string> { | |
// args: unknown; | |
// result: { [K in N]: B } | |
// } | |
// interface AddFn<R, N extends string, P extends any[], I extends any[], O extends any[]> { | |
// args: unknown; | |
// result: Fn<{}, N, P, I, O> | |
// } | |
// type Builder1 = AddFn<AddFn<{}, 'imm', [number], [], [number]>, 'add', [], [number, number], [number]> | |
// type Builder<Stack> = Apply<Builder1, Stack> | |
// declare const b: Builder<[]>; | |
// const res = b | |
// .imm(1) | |
// .imm(2) | |
// .add() | |
// .imm(3) | |
// .add() | |
// type AddFn<Stack extends any[], N extends string, P extends any[], I extends any[], O extends any[]> = | |
// Stack extends [...I, ...infer R] | |
// ? { [K in N]: (...args: P) => Builder<[...O, ...R]> } | |
// : {} | |
// interface Bibuilder<T> { | |
// end: T; | |
// add: <N extends string>(key: N) => | |
// <I extends any[], O extends any[]>() => | |
// <P extends any[]>(handler: (...args: P) => string) => | |
// Bibuilder<Unwrap<T & AddFn<>>> | |
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Unwrap<T> = T extends infer R ? {[K in keyof R]: R[K]} : never; | |
type Presence<K, V, Stack> = V extends [[...infer I], ...any[]] | |
? Stack extends [...I, ...any[]] | |
? K | |
: never | |
: never | |
type Builder<Stack, T> = { | |
[K in keyof T as Presence<K, T[K], Stack>]: T[K] extends [[...infer I], [...infer O], [...infer P]] | |
? Stack extends [...I, ...infer R] | |
? (...args: P) => Builder<[...O, ...R], T> | |
: never | |
: never | |
} & { | |
[K in "end" as (Stack extends [] ? "end" : never)]: () => string; | |
} | |
interface Bibuilder<T> { | |
end: <S extends any[] = []>() => Builder<S, T>; | |
add: <N extends string>(key: N) => | |
<I extends any[], O extends any[], P extends any[]>(handler: (...args: P) => string) => | |
Bibuilder<Unwrap<T & { [K in N]: [I, O, P] }>> | |
} | |
declare const make: <K>() => Bibuilder<K> | |
const defineAsm = make<{}>(); | |
const asm = defineAsm | |
.add('imm')<[], [number], [number]>((p) => `01${p}`) | |
.add('add')<[number, number], [number], []>(() => `10`) | |
.add('drop')<[any], [], []>(() => `11`) | |
.end; | |
const codegen = () => asm() | |
.imm(1) | |
.imm(2) | |
.add() | |
.imm(3) | |
.add() | |
.drop() | |
.end() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment