Skip to content

Instantly share code, notes, and snippets.

@SimonFJ20
Last active September 12, 2023 12:51
Show Gist options
  • Save SimonFJ20/1bbfd17c323acb78ad46fef2af12d968 to your computer and use it in GitHub Desktop.
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
// 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