This commit is contained in:
Mikkel Kongsted 2024-12-10 09:03:03 +01:00
parent 6ab45ffbed
commit b9c174d96a

142
compiler/Lowerer.ts Normal file
View File

@ -0,0 +1,142 @@
import { Expr, Stmt } from "./ast.ts";
import { Ops } from "./mod.ts";
class Locals {
private localIdCounter = 0;
private symLocalMap: {[key: string]: number} = {}
constructor (private parent?: Locals) {}
defineSym(ident: string) {
this.symLocalMap[ident] = this.localIdCounter
this.localIdCounter++
}
symLocalId(ident: string): number {
if (ident in this.symLocalMap) {
return this.symLocalMap[ident]
}
if (!this.parent) {
throw new Error(`Could not find syn local id with ident ${ident}`)
}
else {
return this.parent.symLocalId(ident)
}
}
}
export class Lowerer {
private program: number[] = []
private locals = new Locals()
lower(stmts: Stmt[]) {
for(const stmt of stmts) {
this.lowerStmt(stmt)
}
}
lowerStmt(stmt: Stmt) {
switch (stmt.kind.type) {
case "error":
case "break":
case "return":
case "fn":
break;
case "let":
return this.lowerLetStmt(stmt);
case "assign":
case "expr":
}
throw new Error(`Unhandled stmt ${stmt.kind.type}`)
}
lowerLetStmt(stmt: Stmt) {
if (stmt.kind.type !== "let") {
throw new Error();
}
this.lowerExpr(stmt.kind.value)
this.locals.defineSym(stmt.kind.param.ident),
this.program.push(Ops.StoreLocal)
this.program.push(this.locals.symLocalId(stmt.kind.param.ident))
}
lowerExpr(expr: Expr) {
switch (expr.kind.type) {
case "string":
case "error":
break;
case "int":
return this.lowerInt(expr)
case "ident":
case "group":
case "field":
case "index":
case "call":
case "unary":
break;
case "binary":
return this.lowerBinaryExpr(expr)
case "if":
case "bool":
case "null":
case "loop":
case "block":
break;
case "sym":
return this.lowerSym(expr)
}
throw new Error(`Unhandled expr ${expr.kind.type}`)
}
lowerInt(expr: Expr) {
if (expr.kind.type !== "int") {
throw new Error();
}
this.program.push(Ops.PushInt)
this.program.push(expr.kind.value)
}
lowerSym(expr: Expr) {
if (expr.kind.type !== "sym") {
throw new Error();
}
if (expr.kind.defType == "let") {
this.program.push(Ops.LoadLocal)
this.program.push(this.locals.symLocalId(expr.kind.ident));
return;
}
throw new Error(`Unhandled sym deftype ${expr.kind.defType}`);
}
lowerBinaryExpr(expr: Expr) {
if (expr.kind.type !== "binary") {
throw new Error();
}
this.lowerExpr(expr.kind.left);
this.lowerExpr(expr.kind.right);
if (expr.vtype?.type == "int") {
switch (expr.kind.binaryType) {
case "+":
this.program.push(Ops.Add);
return
case "*":
this.program.push(Ops.Multiply);
return
case "==":
case "-":
case "/":
case "!=":
case "<":
case ">":
case "<=":
case ">=":
case "or":
case "and":
}
throw new Error("Unhandled binary type")
}
}
}