rest
This commit is contained in:
parent
27ec81441b
commit
b2a59de1b2
69
compiler.ts
69
compiler.ts
@ -2,8 +2,9 @@ import { Expr } from "./parsed";
|
||||
|
||||
export type Register = "acc" | "op";
|
||||
export type Value = number;
|
||||
export type Location = number;
|
||||
|
||||
export type Instruction = {
|
||||
export type Instruction = ({
|
||||
type: "push" | "pop",
|
||||
register: Register,
|
||||
} | {
|
||||
@ -19,7 +20,14 @@ export type Instruction = {
|
||||
type: "negate",
|
||||
src: Register,
|
||||
dest: Register,
|
||||
}
|
||||
} | {
|
||||
type: "jump_zero",
|
||||
register: Register,
|
||||
location: Location,
|
||||
} | {
|
||||
type: "jump",
|
||||
location: Location,
|
||||
}) & ({ jumpedTo: true, label: number } | { jumpedTo?: false });
|
||||
|
||||
export class Compiler {
|
||||
public result: Instruction[] = [];
|
||||
@ -70,6 +78,33 @@ export class Compiler {
|
||||
this.result.push({ type: binaryType, left: "acc", right: "op", dest: "acc" });
|
||||
break;
|
||||
}
|
||||
case "if": {
|
||||
this.compileExpr(expr.condition);
|
||||
|
||||
const jumpToFalsyIndex = this.result.length;
|
||||
this.result.push({ type: "jump_zero", register: "acc", location: 0 });
|
||||
|
||||
this.compileExpr(expr.truthy);
|
||||
|
||||
const skipFalsyIndex = this.result.length;
|
||||
this.result.push({ type: "jump", location: 0 });
|
||||
|
||||
let jumpToFalsyRef = this.result[jumpToFalsyIndex];
|
||||
if (jumpToFalsyRef.type !== "jump_zero") throw new Error("unreachable");
|
||||
jumpToFalsyRef.location = this.result.length;
|
||||
|
||||
this.compileExpr(expr.falsy);
|
||||
|
||||
let skipFalsyRef = this.result[skipFalsyIndex];
|
||||
if (skipFalsyRef.type !== "jump") throw new Error("unreachable");
|
||||
skipFalsyRef.location = this.result.length;
|
||||
|
||||
break;
|
||||
}
|
||||
case "block": {
|
||||
this.compileExpr(expr.expr);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const exhaustiveCheck: never = expr;
|
||||
throw new Error(`Unhandled color case: ${exhaustiveCheck}`);
|
||||
@ -78,17 +113,35 @@ export class Compiler {
|
||||
}
|
||||
}
|
||||
|
||||
export function locateAndSetJumpedToInstructions(instructions: Instruction[]) {
|
||||
let nextLabel = 0;
|
||||
for (const ins of instructions) {
|
||||
if (ins.type === "jump_zero" || ins.type === "jump") {
|
||||
instructions[ins.location] = {
|
||||
...instructions[ins.location],
|
||||
jumpedTo: true,
|
||||
label: nextLabel,
|
||||
};
|
||||
nextLabel += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class X86Generator {
|
||||
public generate(instructions: Instruction[]): string {
|
||||
return this.asmWithHeaders(instructions.map((ins) => this.generateInstruction(ins)).join(""));
|
||||
}
|
||||
|
||||
private generateInstruction(ins: Instruction): string {
|
||||
let result = "";
|
||||
if (ins.jumpedTo) {
|
||||
|
||||
}
|
||||
switch (ins.type) {
|
||||
case "load": {
|
||||
return `
|
||||
mov ${this.reg64(ins.register)}, ${this.value(ins.value)}
|
||||
`;
|
||||
result += ` ; load`
|
||||
result += ` mov ${this.reg64(ins.register)}, ${this.value(ins.value)}\n`;
|
||||
break;
|
||||
}
|
||||
case "push": {
|
||||
return `
|
||||
@ -141,6 +194,12 @@ export class X86Generator {
|
||||
mov ${this.reg64(ins.dest)}, rax
|
||||
`;
|
||||
}
|
||||
case "jump_zero": {
|
||||
return `
|
||||
; jump_zero
|
||||
|
||||
`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
22
grammar.ne
22
grammar.ne
@ -30,11 +30,29 @@ unary -> "+" _ unary
|
||||
({ exprType: "unary", unaryType: "negate", subject }) %}
|
||||
| operand {% id %}
|
||||
|
||||
operand -> "(" _ expr _ ")" {% ([_0, _1, expr]): Expr => expr %}
|
||||
| [0-9]:+
|
||||
operand -> int {% id %}
|
||||
| group {% id %}
|
||||
| block {% id %}
|
||||
| if {% id %}
|
||||
|
||||
int -> [0-9]:+
|
||||
{% ([token]): Expr =>
|
||||
({ exprType: "int", value: parseInt(token.join("")) }) %}
|
||||
|
||||
group -> "(" _ expr _ ")" {% (v): Expr => v[2] %}
|
||||
|
||||
block -> "{" _ expr _ "}" {% (v): Expr => ({ exprType: "block", expr: v[2] }) %}
|
||||
|
||||
if -> "if" __ expr _ block _ "else" _ block
|
||||
{%
|
||||
(v): Expr => ({
|
||||
exprType: "if",
|
||||
condition: v[2],
|
||||
truthy: v[4],
|
||||
falsy: v[8]
|
||||
})
|
||||
%}
|
||||
|
||||
_ -> __:?
|
||||
__ -> ws:+
|
||||
|
||||
|
6
main.ts
6
main.ts
@ -1,6 +1,6 @@
|
||||
import { Parser, Grammar } from "nearley"
|
||||
import compiledGrammar from "./grammar.out"
|
||||
import { Compiler, Instruction, Register, Value, X86Generator as X8664Generator } from "./compiler";
|
||||
import { Compiler, Instruction, Register, Value, X86Generator as X8664Generator, locateAndSetJumpedToInstructions } from "./compiler";
|
||||
import fs from "fs/promises";
|
||||
import { exec } from "child_process";
|
||||
|
||||
@ -37,7 +37,9 @@ async function main(args: string[]) {
|
||||
|
||||
const compiler = new Compiler();
|
||||
compiler.compileExpr(ast);
|
||||
const ir = compiler.result;
|
||||
let ir = compiler.result;
|
||||
console.log(ir);
|
||||
locateAndSetJumpedToInstructions(ir);
|
||||
console.log(ir);
|
||||
|
||||
const generator = new X8664Generator();
|
||||
|
Loading…
Reference in New Issue
Block a user