Last active
September 12, 2023 12:51
-
-
Save SimonFJ20/1bbfd17c323acb78ad46fef2af12d968 to your computer and use it in GitHub Desktop.
A PEMDAS Compliant Math Parser implemented entirely in Typescript's Type System, also includes AST Evaluator, IR Compiler, IR Evaluator and X86-64 Generator
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
// utils | |
type Ok<T> = { ok: true, value: T }; | |
type Err<E> = { ok: false, error: E }; | |
type Result<T, E> = Ok<T> | Err<E>; | |
type NumericIndices<T> = T extends unknown[] ? Extract<keyof T, `${number}`> : never | |
type StringToNumber<S> = S extends `${infer N extends number}` ? N : never; | |
type NumberToString<N> = N extends infer N extends number ? `${N}` : never; | |
// unsigned integer arithmetic | |
type Not<V> = V extends true ? false : true; | |
type And<Left, Right> = [Left, Right] extends [true, true] ? true : false; | |
type Nand<Left, Right> = [Left, Right] extends [true, true] ? false : true; | |
type Or<Left, Right> = [Left, Right] extends [false, false] ? false : true; | |
type Nor<Left, Right> = [Left, Right] extends [false, false] ? true: false; | |
type Xor<Left, Right> = [Left, Right] extends [false, false] ? false : [Left, Right] extends [true, true] ? false : true; | |
type Xnor<Left, Right> = [Left, Right] extends [false, false] ? true : [Left, Right] extends [true, true] ? true : false; | |
type UInt = any[]; | |
type NumberToUInt<Value, Acc = []> = | |
[Value, Acc] extends [infer Value extends number, infer Acc extends UInt] | |
? Acc extends { length: Value } | |
? Acc | |
: NumberToUInt<Value, [...Acc, unknown]> | |
: never; | |
type UIntToNumber<Value> = Value extends { length: infer L } ? L : never; | |
type UEqual<Left, Right> = | |
[Left, Right] extends [{ length: infer LL }, { length: infer RL }] | |
? LL extends RL ? true : false | |
: never; | |
type UInequal<Left, Right> = | |
[Left, Right] extends [{ length: infer LL }, { length: infer RL }] | |
? LL extends RL ? false : true | |
: never; | |
type ULT<Left, Right> = | |
[Left, Right] extends [infer Left extends UInt, infer Right extends UInt] | |
? Left extends [...Right, ...any] ? false : true | |
: never; | |
type UGTE<Left, Right> = | |
[Left, Right] extends [infer Left extends UInt, infer Right extends UInt] | |
? Left extends [...Right, ...any] ? true : false | |
: never; | |
type UGT<Left, Right> = | |
[Left, Right] extends [infer Left extends UInt, infer Right extends UInt] | |
? Right extends [...Left, ...any] ? false : true | |
: never; | |
type ULTE<Left, Right> = | |
[Left, Right] extends [infer Left extends UInt, infer Right extends UInt] | |
? Right extends [...Left, ...any] ? true : false | |
: never; | |
type UAdd<Left, Right> = | |
[Left, Right] extends [infer Left extends UInt, infer Right extends UInt] | |
? [...Left, ...Right] | |
: never; | |
type USub<Left, Right> = | |
[Left, Right] extends [infer Left extends UInt, infer Right extends UInt] | |
? Left extends [...Right, ...infer LRest] | |
? LRest | |
: never | |
: never; | |
type UMul<Left, Right, Acc = []> = | |
[Left, Right, Acc] extends [infer Left extends UInt, infer Right extends UInt, infer Acc extends UInt] | |
? Right extends [any, ...infer RTail] | |
? UMul<Left, RTail, [...Acc, ...Left]> | |
: Acc | |
: never; | |
type UDivMod<Left, Right, Acc = []> = | |
[Left, Right, Acc] extends [infer Left extends UInt, infer Right extends UInt, infer Acc extends UInt] | |
? ULT<Left, Right> extends false | |
? Left extends [...Right, ...infer LRest] | |
? UDivMod<LRest, Right, [...Acc, unknown]> | |
: never | |
: { div: Acc, mod: Left } | |
: never; | |
type UDiv<Left, Right> = | |
[Left, Right] extends [infer Left extends UInt, infer Right extends UInt] | |
? UDivMod<Left, Right> extends { div: infer Div extends UInt } ? Div : never | |
: never; | |
type UMod<Left, Right> = | |
[Left, Right] extends [infer Left extends UInt, infer Right extends UInt] | |
? UDivMod<Left, Right> extends { mod: infer Mod extends UInt } ? Mod : never | |
: never; | |
type UPow<Left, Right, Acc = [any]> = | |
[Left, Right, Acc] extends [infer Left extends UInt, infer Right extends UInt, infer Acc extends UInt] | |
? Right extends [any, ...infer RRest] | |
? UPow<Left, RRest, UMul<Acc, Left>> | |
: Acc | |
: never; | |
// signed integer arithmetic | |
const NegativeSymbol = Symbol(); | |
type Negative<N> = N extends UInt ? [typeof NegativeSymbol, N] : never; | |
type Int = UInt | Negative<UInt>; | |
type Negate<Value> = | |
Value extends Int | |
? Value extends Negative<infer UValue extends UInt> | |
? UValue | |
: Negative<Value> | |
: never; | |
type NumberToInt<Value> = | |
Value extends infer Value extends number | |
? `${Value}` extends `-${infer UValue extends number}` | |
? Negate<NumberToUInt<UValue>> | |
: NumberToUInt<Value> | |
: never; | |
type IntToNumber<Value> = | |
Value extends infer Value extends Int | |
? Value extends Negative<infer N extends UInt> | |
? N extends [] | |
? -0 | |
: `-${UIntToNumber<N>}` extends `${infer Result extends number}` ? Result : never | |
: UIntToNumber<Value> | |
: never; | |
type Equal<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer URight extends UInt> | |
? UEqual<ULeft, URight> extends true ? true : false | |
: false | |
: Right extends Negative<UInt> | |
? false | |
: UEqual<Left, Right> extends true ? true : false | |
: never; | |
type Inequal<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer URight extends UInt> | |
? UInequal<ULeft, URight> extends true ? true : false | |
: true | |
: Right extends Negative<UInt> | |
? true | |
: UInequal<Left, Right> extends true ? true : false | |
: never; | |
type LT<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer URight extends UInt> | |
? ULT<ULeft, URight> extends true ? true : false | |
: true | |
: Right extends Negative<UInt> | |
? false | |
: ULT<Left, Right> extends true ? true : false | |
: never; | |
type GTE<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer URight extends UInt> | |
? UGTE<ULeft, URight> extends true ? true : false | |
: false | |
: Right extends Negative<UInt> | |
? true | |
: UGTE<Left, Right> extends true ? true : false | |
: never; | |
type GT<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer URight extends UInt> | |
? UGT<ULeft, URight> extends true ? true : false | |
: false | |
: Right extends Negative<UInt> | |
? true | |
: UGT<Left, Right> extends true ? true : false | |
: never; | |
type LTE<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer URight extends UInt> | |
? ULTE<ULeft, URight> extends true ? true : false | |
: true | |
: Right extends Negative<UInt> | |
? false | |
: ULTE<Left, Right> extends true ? true : false | |
: never; | |
type Add<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer URight extends UInt> | |
? UGTE<ULeft, URight> extends true | |
? Negate<UAdd<ULeft, URight>> | |
: Negate<UAdd<URight, ULeft>> | |
: UGTE<ULeft, Right> extends true | |
? Negate<USub<ULeft, Right>> | |
: USub<Right, ULeft> | |
: Right extends Negative<infer URight extends UInt> | |
? UGTE<URight, Left> extends true | |
? Negate<USub<URight, Left>> | |
: USub<Left, URight> | |
: UAdd<Left, Right> | |
: never; | |
type Sub<Left, Right> = Add<Left, Negate<Right>>; | |
type Mul<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer URight extends UInt> | |
? UMul<ULeft, URight> | |
: Negate<UMul<ULeft, Right>> | |
: Right extends Negative<infer URight extends UInt> | |
? Negate<UMul<Left, URight>> | |
: UMul<Left, Right> | |
: never; | |
type Div<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer URight extends UInt> | |
? UDiv<ULeft, URight> | |
: Negate<UDiv<ULeft, Right>> | |
: Right extends Negative<infer URight extends UInt> | |
? Negate<UDiv<Left, URight>> | |
: UDiv<Left, Right> | |
: never; | |
type Mod<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer URight extends UInt> | |
? Negate<UMod<ULeft, URight>> | |
: Negate<UMod<ULeft, Right>> | |
: Right extends Negative<infer URight extends UInt> | |
? UMod<Left, URight> | |
: UMod<Left, Right> | |
: never; | |
type Pow<Left, Right> = | |
[Left, Right] extends [infer Left extends Int, infer Right extends Int] | |
? Left extends Negative<infer ULeft extends UInt> | |
? Right extends Negative<infer _ extends UInt> | |
? never | |
: Negate<UPow<ULeft, Right>> | |
: Right extends Negative<infer _ extends UInt> | |
? never | |
: UPow<Left, Right> | |
: never; | |
// tokens, tokenizer, lexer | |
type TokenType = "error" | "int" | "+" | "-" | "*" | "/" | "^" | "(" | ")"; | |
type Token<T, V> = | |
[T, V] extends [infer T extends TokenType, infer V extends string] | |
? { tokenType: T, value: V } | |
: never; | |
type WhitespaceChar = " " | "\t" | "\r" | "\n"; | |
type IntChar = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"; | |
type StaticChar = "+" | "-" | "*" | "/" | "^" | "(" | ")"; | |
type TokenizeInt<IntValue, Text> = | |
[IntValue, Text] extends [infer IntValue extends string, infer Text extends string] | |
? Text extends `${infer Char extends IntChar}${infer Rest}` | |
? TokenizeInt<`${IntValue}${Char}`, Rest> | |
: { token: Token<"int", IntValue>, rest: Text } | |
: never; | |
type Tokenize<Text> = | |
Text extends infer Text extends string | |
? Text extends "" | |
? [] | |
: | |
Text extends `${WhitespaceChar}${infer Rest}` | |
? Tokenize<Rest> | |
: Text extends `${infer Char extends IntChar}${infer Rest}` | |
? TokenizeInt<Char, Rest> extends { token: infer TokenResult, rest: infer Rest extends string } | |
? [TokenResult, ...Tokenize<Rest>] | |
: never | |
: Text extends `${infer Char extends StaticChar}${infer Rest extends string}` | |
? [Token<Char, Char>, ...Tokenize<Rest>] | |
: [Token<"error", "invalid char">] | |
: never; | |
// ast, expr, parsed | |
type UnaryTypes = "negate"; | |
type BinaryTypes = "add" | "subtract" | "multiply" | "divide" | "power"; | |
type Expr = { | |
exprType: "error", | |
message: string, | |
} | { | |
exprType: "int", | |
value: number, | |
} | { | |
exprType: "unary", | |
unaryType: UnaryTypes, | |
subject: Expr, | |
} | { | |
exprType: "binary", | |
binaryType: BinaryTypes, | |
left: Expr, | |
right: Expr, | |
} | |
// parser | |
type ParseGroup<Tokens> = | |
Tokens extends infer Tokens extends any[] | |
? ParseExpr<Tokens> extends { expr: infer InnerExpr, rest: infer Rest extends any[] } | |
? Rest extends [Token<")", any>, ...infer Rest extends any[]] | |
? { expr: InnerExpr, rest: Rest } | |
: { expr: { exprType: "error", message: "expected ')'" }, rest: Rest } | |
: never | |
: never; | |
type ParseOperand<Tokens> = | |
Tokens extends infer Tokens extends any[] | |
? Tokens extends [] | |
? { exprType: "error", message: "unexpected eof" } | |
: | |
Tokens extends [{ tokenType: "int", value: infer Value extends string}, ...infer Rest extends any[]] | |
? { expr: { exprType: "int", value: StringToNumber<Value> }, rest: Rest } | |
: Tokens extends [Token<"(", any>, ...infer Rest extends any[]] | |
? ParseGroup<Rest> | |
: { exprType: "error", message: "expected operand" } | |
: never; | |
type ParsePower<Tokens> = | |
Tokens extends infer Tokens extends any[] | |
? ParseOperand<Tokens> extends { expr: infer Left extends Expr, rest: infer Rest0 extends any[] } | |
? Rest0 extends [Token<"^", any>, ...infer Rest1 extends any[]] | |
? ParsePower<Rest1> extends { expr: infer Right extends Expr, rest: infer Rest2 extends any[] } | |
? { expr: { exprType: "binary", binaryType: "power", left: Left, right: Right }, rest: Rest2 } | |
: never | |
: { expr: Left, rest: Rest0 } | |
: never | |
: never; | |
type ParseUnary<Tokens> = | |
Tokens extends infer Tokens extends any[] | |
? Tokens extends [Token<"-", any>, ...infer Rest] | |
? ParseUnary<Rest> extends { expr: infer Subject, rest: infer Rest } | |
? { expr: { exprType: "unary", unaryType: "negate", subject: Subject }, rest: Rest } | |
: never | |
: ParsePower<Tokens> | |
: never; | |
type ParseFactor<Tokens, Left = null> = | |
Tokens extends infer Tokens extends any[] | |
? Left extends null | |
? ParseUnary<Tokens> extends { expr: infer Left, rest: infer Rest extends any[] } | |
? ParseFactor<Rest, Left> | |
: never | |
: | |
Tokens extends [Token<"*", any>, ...infer Rest] | |
? ParseUnary<Rest> extends { expr: infer Right, rest: infer Rest extends any[] } | |
? ParseFactor<Rest, { exprType: "binary", binaryType: "multiply", left: Left, right: Right }> | |
: never | |
: Tokens extends [Token<"/", any>, ...infer Rest] | |
? ParseUnary<Rest> extends { expr: infer Right, rest: infer Rest extends any[] } | |
? ParseFactor<Rest, { exprType: "binary", binaryType: "divide", left: Left, right: Right }> | |
: never | |
: { expr: Left, rest: Tokens } | |
: never; | |
type ParseTerm<Tokens, Left = null> = | |
Tokens extends infer Tokens extends any[] | |
? Left extends null | |
? ParseFactor<Tokens> extends { expr: infer Left, rest: infer Rest extends any[] } | |
? ParseTerm<Rest, Left> | |
: never | |
: | |
Tokens extends [Token<"+", any>, ...infer Rest] | |
? ParseFactor<Rest> extends { expr: infer Right, rest: infer Rest extends any[] } | |
? ParseTerm<Rest, { exprType: "binary", binaryType: "add", left: Left, right: Right }> | |
: never | |
: Tokens extends [Token<"-", any>, ...infer Rest] | |
? ParseFactor<Rest> extends { expr: infer Right, rest: infer Rest extends any[] } | |
? ParseTerm<Rest, { exprType: "binary", binaryType: "minus", left: Left, right: Right }> | |
: never | |
: { expr: Left, rest: Tokens } | |
: never; | |
type ParseExpr<Tokens> = | |
Tokens extends infer Tokens extends any[] | |
? ParseTerm<Tokens> | |
: never; | |
type Parse<Text> = | |
Text extends infer Text extends string | |
? ParseExpr<Tokenize<Text>> extends { expr: infer Ast, rest: infer Rest } | |
? Rest extends [] | |
? Ast | |
: Rest | |
: never | |
: never; | |
// ast evaluator | |
type EvalExpr<E> = | |
E extends infer E extends Expr | |
? | |
E extends { exprType: "error", message: infer Message extends string } | |
? never & Message | |
: E extends { exprType: "int", value: infer Value extends number } | |
? NumberToUInt<Value> | |
: E extends { | |
exprType: "unary", | |
unaryType: infer UnaryType extends UnaryTypes, | |
subject: infer Subject extends Expr, | |
} | |
? UnaryType extends "negate" | |
? Negate<EvalExpr<Subject>> | |
: never | |
: E extends { | |
exprType: "binary", | |
binaryType: infer BinaryType extends BinaryTypes, | |
left: infer Left extends Expr, | |
right: infer Right extends Expr, | |
} | |
? | |
BinaryType extends "add" | |
? Add<EvalExpr<Left>, EvalExpr<Right>> | |
: BinaryType extends "subtract" | |
? Sub<EvalExpr<Left>, EvalExpr<Right>> | |
: BinaryType extends "multiply" | |
? Mul<EvalExpr<Left>, EvalExpr<Right>> | |
: BinaryType extends "divide" | |
? Div<EvalExpr<Left>, EvalExpr<Right>> | |
: BinaryType extends "power" | |
? Pow<EvalExpr<Left>, EvalExpr<Right>> | |
: never | |
: never | |
: never; | |
// ir instructions | |
type Register = "r0" | "r1"; | |
type Ins = { | |
insType: "push", | |
source: Register, | |
} | { | |
insType: "pop", | |
dest: Register, | |
} | { | |
insType: "loadInt", | |
dest: Register, | |
value: number, | |
} | { | |
insType: UnaryTypes, | |
subject: Register, | |
} | { | |
insType: BinaryTypes, | |
subject: Register, | |
operand: Register, | |
} | |
type IrPush<Source> = | |
Source extends infer Source extends Register | |
? { insType: "push", source: Source } | |
: never; | |
type IrPop<Dest> = | |
Dest extends infer Dest extends Register | |
? { insType: "pop", dest: Dest } | |
: never; | |
type IrLoadInt<Dest, Value> = | |
[Dest, Value] extends [infer Dest extends Register, infer Value extends number] | |
? { insType: "loadInt", dest: Dest, value: Value } | |
: never; | |
type IrUnary<InsType, Subject> = | |
[InsType, Subject] extends [infer InsType extends UnaryTypes, infer Subject extends Register] | |
? { insType: InsType, subject: Subject } | |
: never; | |
type IrBinary<InsType, Subject, Operand> = | |
[InsType, Subject, Operand] extends [ | |
infer InsType extends BinaryTypes, | |
infer Subject extends Register, | |
infer Operand extends Register, | |
] | |
? { insType: InsType, subject: Subject, operand: Operand } | |
: never; | |
// ir compiler | |
type Compile<E, Acc> = | |
[E, Acc] extends [infer E extends Expr, infer Acc extends Ins[]] | |
? | |
E extends { exprType: "error", message: infer Message } | |
? Err<Message> | |
: E extends { exprType: "int", value: infer Value extends number } | |
? Ok<[...Acc, IrLoadInt<"r0", Value>]> | |
: E extends { exprType: "unary", unaryType: infer UnaryType extends UnaryTypes, subject: infer Subject extends Expr } | |
? Compile<Subject, Acc> extends infer Result extends Err<any> | |
? Result | |
: Compile<Subject, Acc> extends Ok<infer Acc extends Ins[]> | |
? Ok<[...Acc, IrUnary<UnaryType, "r0">]> | |
: never | |
: E extends { exprType: "binary", binaryType: infer BinaryType extends BinaryTypes, left: infer Left extends Expr, right: infer Right extends Expr } | |
? Compile<Left, Acc> extends infer Result extends Err<any> | |
? Result | |
: Compile<Left, Acc> extends Ok<infer Acc extends Ins[]> | |
? Compile<Right, [...Acc, IrPush<"r0">]> extends infer Result extends Err<any> | |
? Result | |
: Compile<Right, [...Acc, IrPush<"r0">]> extends Ok<infer Acc extends Ins[]> | |
? Ok<[...Acc, IrPush<"r0">, IrPop<"r1">, IrPop<"r0">, IrBinary<BinaryType, "r0", "r1">]> | |
: never | |
: never | |
: Err<"unimplemented expr type"> | |
: never; | |
// ir vm evaluator | |
type IrRegisters = { r0: Int, r1: Int } | |
type SetRegister<Registers, Dest, Value> = | |
[Registers, Dest, Value] extends [ | |
infer Registers extends IrRegisters, | |
infer Dest extends Register, | |
infer Value extends Int, | |
] | |
? | |
Dest extends "r0" | |
? { r0: Value, r1: Registers["r1"] } | |
: Dest extends "r1" | |
? { r0: Registers["r0"], r1: Value } | |
: never | |
: never; | |
type EvalIr<Ir, Registers = { r0: [], r1: [] }, Stack = []> = | |
[Ir, Registers, Stack] extends [ | |
infer Ir extends Ins[], | |
infer Registers extends IrRegisters, | |
infer Stack extends Int[], | |
] | |
? Ir extends [] | |
? { registers: Registers, stack: Stack } | |
: | |
Ir extends [{ insType: "push", source: infer Source extends Register }, ...infer Rest extends Ins[]] | |
? EvalIr<Rest, Registers, [...Stack, Registers[Source]]> | |
: Ir extends [{ insType: "pop", dest: infer Dest extends Register }, ...infer Rest extends Ins[]] | |
? Stack extends [...infer Stack, infer Value] | |
? EvalIr<Rest, SetRegister<Registers, Dest, Value>, Stack> | |
: never | |
: Ir extends [{ | |
insType: "loadInt", | |
dest: infer Dest extends Register, | |
value: infer Value extends number, | |
}, ...infer Rest extends Ins[]] | |
? EvalIr<Rest, SetRegister<Registers, Dest, NumberToInt<Value>>, Stack> | |
: Ir extends [{ | |
insType: infer UnaryType extends UnaryTypes, | |
subject: infer Subject extends Register, | |
}, ...infer Rest extends Ins[]] | |
? | |
UnaryType extends "negate" | |
? EvalIr<Rest, SetRegister<Registers, Subject, Negate<Registers[Subject]>>, Stack> | |
: never | |
: Ir extends [{ | |
insType: infer BinaryType extends BinaryTypes, | |
subject: infer Subject extends Register, | |
operand: infer Operand extends Register, | |
}, ...infer Rest extends Ins[]] | |
? | |
BinaryType extends "add" | |
? EvalIr<Rest, SetRegister<Registers, Subject, Add<Registers[Subject], Registers[Operand]>>, Stack> | |
: BinaryType extends "subtract" | |
? EvalIr<Rest, SetRegister<Registers, Subject, Sub<Registers[Subject], Registers[Operand]>>, Stack> | |
: BinaryType extends "multiply" | |
? EvalIr<Rest, SetRegister<Registers, Subject, Mul<Registers[Subject], Registers[Operand]>>, Stack> | |
: BinaryType extends "divide" | |
? EvalIr<Rest, SetRegister<Registers, Subject, Div<Registers[Subject], Registers[Operand]>>, Stack> | |
: BinaryType extends "power" | |
? EvalIr<Rest, SetRegister<Registers, Subject, Pow<Registers[Subject], Registers[Operand]>>, Stack> | |
: never | |
: never | |
: never; | |
// x86-64 asm assembly generator | |
type X8664Reg<R> = | |
R extends infer R extends Register | |
? { "r0": "rax", "r1": "rdi" }[R] | |
: never; | |
type ConcatLines<Acc, Lines> = | |
[Acc, Lines] extends [infer Acc extends string, infer Lines extends string[]] | |
? Lines extends [infer Line extends string, ...infer Rest extends string[]] | |
? ConcatLines<`${Acc}${Line}`, Rest> | |
: Acc | |
: never; | |
type X8664Headers<Asm> = | |
Asm extends infer Asm extends string | |
? ConcatLines<"", [ | |
"bits 64", | |
"\nglobal _start", | |
"\n_start:", | |
Asm, | |
"\nexit:", | |
"\n mov rdi, rax", | |
"\n mov rax, 60", | |
"\n syscall", | |
]> | |
: never; | |
type GenerateX8664<Ir, Acc> = | |
[Ir, Acc] extends [infer Ir extends Ins[], infer Acc extends string] | |
? | |
Ir extends [] | |
? X8664Headers<Acc> | |
: Ir extends [{ insType: "push", source: infer Source }, ...infer Rest extends Ins[]] | |
? GenerateX8664<Rest, `${Acc}\n push ${X8664Reg<Source>}`> | |
: Ir extends [{ insType: "pop", dest: infer Dest }, ...infer Rest extends Ins[]] | |
? GenerateX8664<Rest, `${Acc}\n pop ${X8664Reg<Dest>}`> | |
: Ir extends [{ | |
insType: "loadInt", | |
dest: infer Dest, | |
value: infer Value extends number, | |
}, ...infer Rest extends Ins[]] | |
? GenerateX8664<Rest, `${Acc}\n mov ${X8664Reg<Dest>}, ${Value}`> | |
: Ir extends [{ | |
insType: infer UnaryType extends UnaryTypes, | |
subject: infer Subject, | |
}, ...infer Rest extends Ins[]] | |
? UnaryType extends "negate" | |
? GenerateX8664<Rest, `${Acc}\n neg ${X8664Reg<Subject>}`> | |
: never | |
: Ir extends [{ | |
insType: infer BinaryType extends BinaryTypes, | |
subject: infer Subject, | |
operand: infer Operand, | |
}, ...infer Rest extends Ins[]] | |
? | |
BinaryType extends "add" | |
? GenerateX8664<Rest, `${Acc}\n add ${X8664Reg<Subject>}, ${X8664Reg<Operand>}`> | |
: BinaryType extends "subtract" | |
? GenerateX8664<Rest, `${Acc}\n sub ${X8664Reg<Subject>}, ${X8664Reg<Operand>}`> | |
: BinaryType extends "multiply" | |
? GenerateX8664<Rest, `${Acc}\n imul ${X8664Reg<Subject>}, ${X8664Reg<Operand>}`> | |
: BinaryType extends "divide" | |
? GenerateX8664<Rest, ConcatLines<Acc, [ | |
`\n push rdx`, | |
`\n xor rdx, rdx`, | |
`\n mov rax, ${X8664Reg<Subject>}`, | |
`\n cqo`, | |
`\n idiv ${X8664Reg<Operand>}`, | |
`\n mov ${X8664Reg<Subject>}, rax`, | |
`\n pop rdx`, | |
]>> | |
: BinaryType extends "power" | |
? GenerateX8664<Rest, ConcatLines<Acc, [ | |
`\n push rsi`, | |
`\n push rdi`, | |
`\n mov rsi, ${X8664Reg<Subject>}`, | |
`\n mov rdi, ${X8664Reg<Operand>}`, | |
`\n call pow`, | |
`\n pop rdi`, | |
`\n pop rsi`, | |
`\n mov ${X8664Reg<Subject>}, rax`, | |
]>> | |
: never | |
: never | |
: never; | |
type Ast = Parse<"-6^2">; | |
type AstEvalResult = IntToNumber<EvalExpr<Ast>>; | |
type Ir = Compile<Ast, []>["value"]; | |
type IrEvalResult = IntToNumber<EvalIr<Ir> extends { registers: { r0: infer R0 } } ? R0 : never>; | |
type X8664Asm = GenerateX8664<Ir, "">; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment