Last active
September 12, 2019 21:42
-
-
Save jack-williams/53b3c5c53f8cef5a4bd856ef4ce0f167 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
interface Lit<K> { | |
kind: 'lit'; | |
value: K; | |
} | |
interface BinOp<T> { | |
kind: 'binop'; | |
l: T; | |
r: T; | |
} | |
type Expr<T, K> = Lit<K> | BinOp<TaggedExpr<T, K>>; | |
type TaggedExpr<T, K> = Expr<T, K> & T; | |
type Basic<K> = TaggedExpr<unknown, K>; | |
type WithDepth<K> = TaggedExpr<{ depth: number }, K>; | |
interface Annotator<T, K> { | |
lit: (k: K) => T; | |
binop: (l: T, r: T) => T; | |
} | |
function annotateExpr<T, U, K>(annotate: Annotator<U, K>, node: TaggedExpr<T, K>): TaggedExpr<T & U, K> { | |
switch (node.kind) { | |
case 'lit': | |
return { ...node, ...annotate.lit(node.value) }; | |
case 'binop': | |
const l = annotateExpr(annotate, node.l); | |
const r = annotateExpr(annotate, node.r); | |
return { ...node, l, r, ...annotate.binop(l, r) }; | |
} | |
} | |
const addDepth = <T, K>(node: TaggedExpr<T, K>) => annotateExpr<T, { depth: number }, K>( | |
{ | |
lit: () => ({ depth: 0 }), | |
binop: (l: { depth: number }, r: { depth: number }) => ({ depth: Math.max(l.depth, r.depth) + 1 }) | |
}, | |
node | |
); | |
const addType = <T, K>(node: TaggedExpr<T, K>) => annotateExpr<T, { type: string }, K>( | |
{ | |
lit: (k: K) => ({ type: typeof k }), | |
binop: (l: { type: string }, r: { type: string }) => ({ type: l.type === r.type ? l.type : "any" }) | |
}, | |
node | |
); | |
const node: Basic<number | string | boolean> = { kind: 'binop', l: { kind: 'lit', value: 3 }, r: { kind: 'lit', value: 10 } }; | |
const transformed: TaggedExpr<{ depth: number, type: string }, number | string | boolean> = addType(addDepth(node)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment