From fa81c17c251d40f54c45be7c28c6b6de75317215 Mon Sep 17 00:00:00 2001 From: SimonFJ20 Date: Tue, 10 Dec 2024 10:39:12 +0100 Subject: [PATCH] rename syms --- compiler/Lowerer.ts | 115 ++++++++++++++++++++---------- compiler/{Syms.ts => Resolver.ts} | 91 +++++++++++++---------- compiler/main.ts | 10 +-- 3 files changed, 135 insertions(+), 81 deletions(-) rename compiler/{Syms.ts => Resolver.ts} (72%) diff --git a/compiler/Lowerer.ts b/compiler/Lowerer.ts index 87021bd..4d1aafb 100644 --- a/compiler/Lowerer.ts +++ b/compiler/Lowerer.ts @@ -1,38 +1,72 @@ -import { Expr, Stmt } from "./ast.ts"; +import { BinaryType, Expr, Stmt } from "./ast.ts"; import { Ops } from "./mod.ts"; +import { VType } from "./vtypes.ts"; -class Locals { +interface Locals { + reserveId(id: number): void; + allocSym(ident: string): void; + symId(ident: string): number; +} + +class LocalsFnRoot implements Locals { + private localsAmount = 0; private localIdCounter = 0; - private symLocalMap: {[key: string]: number} = {} + private symLocalMap: { [key: string]: number } = {}; - constructor (private parent?: Locals) {} - - defineSym(ident: string) { - this.symLocalMap[ident] = this.localIdCounter - this.localIdCounter++ + constructor(private parent?: Locals) { } - symLocalId(ident: string): number { + reserveId(id: number): void { + this.localsAmount = Math.max(id + 1, this.localsAmount); + } + + allocSym(ident: string) { + this.symLocalMap[ident] = this.localIdCounter; + this.localIdCounter++; + } + + symId(ident: string): number { if (ident in this.symLocalMap) { - return this.symLocalMap[ident] + return this.symLocalMap[ident]; } - if (!this.parent) { - throw new Error(`Could not find syn local id with ident ${ident}`) + if (this.parent) { + return this.parent.symId(ident); } - else { - return this.parent.symLocalId(ident) + throw new Error(`undefined symbol '${ident}'`); + } +} + +class LocalLeaf implements Locals { + private localIdCounter = 0; + private symLocalMap: { [key: string]: number } = {}; + + constructor(private parent: Locals) { + } + + reserveId(id: number): void { + this.parent.reserveId(id); + } + + allocSym(ident: string) { + this.symLocalMap[ident] = this.localIdCounter; + this.localIdCounter++; + } + + symId(ident: string): number { + if (ident in this.symLocalMap) { + return this.symLocalMap[ident]; } + return this.parent.symId(ident); } } export class Lowerer { - private program: number[] = [] - private locals = new Locals() - + private program: number[] = []; + private locals = new LocalsFnRoot(); lower(stmts: Stmt[]) { - for(const stmt of stmts) { - this.lowerStmt(stmt) + for (const stmt of stmts) { + this.lowerStmt(stmt); } } @@ -47,19 +81,18 @@ export class Lowerer { return this.lowerLetStmt(stmt); case "assign": case "expr": - } - throw new Error(`Unhandled stmt ${stmt.kind.type}`) - + } + 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)) + this.lowerExpr(stmt.kind.value); + this.locals.allocSym(stmt.kind.param.ident), + this.program.push(Ops.StoreLocal); + this.program.push(this.locals.symId(stmt.kind.param.ident)); } lowerExpr(expr: Expr) { @@ -68,7 +101,7 @@ export class Lowerer { case "error": break; case "int": - return this.lowerInt(expr) + return this.lowerInt(expr); case "ident": case "group": case "field": @@ -77,7 +110,7 @@ export class Lowerer { case "unary": break; case "binary": - return this.lowerBinaryExpr(expr) + return this.lowerBinaryExpr(expr); case "if": case "bool": case "null": @@ -85,17 +118,17 @@ export class Lowerer { case "block": break; case "sym": - return this.lowerSym(expr) + return this.lowerSym(expr); } - throw new Error(`Unhandled expr ${expr.kind.type}`) + 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) + this.program.push(Ops.PushInt); + this.program.push(expr.kind.value); } lowerSym(expr: Expr) { @@ -103,8 +136,8 @@ export class Lowerer { throw new Error(); } if (expr.kind.defType == "let") { - this.program.push(Ops.LoadLocal) - this.program.push(this.locals.symLocalId(expr.kind.ident)); + this.program.push(Ops.LoadLocal); + this.program.push(this.locals.symId(expr.kind.ident)); return; } throw new Error(`Unhandled sym deftype ${expr.kind.defType}`); @@ -116,14 +149,14 @@ export class Lowerer { } this.lowerExpr(expr.kind.left); this.lowerExpr(expr.kind.right); - if (expr.vtype?.type == "int") { + if (expr.vtype!.type === "int") { switch (expr.kind.binaryType) { case "+": this.program.push(Ops.Add); - return + return; case "*": this.program.push(Ops.Multiply); - return + return; case "==": case "-": case "/": @@ -135,8 +168,12 @@ export class Lowerer { case "or": case "and": } - throw new Error("Unhandled binary type") } + throw new Error( + `Unhandled vtype/binaryType '${ + expr.vtype!.type + }/${expr.kind.binaryType}'`, + ); } +} -} \ No newline at end of file diff --git a/compiler/Syms.ts b/compiler/Resolver.ts similarity index 72% rename from compiler/Syms.ts rename to compiler/Resolver.ts index 109888d..5442f09 100644 --- a/compiler/Syms.ts +++ b/compiler/Resolver.ts @@ -1,7 +1,7 @@ import { Expr, Stmt, Sym } from "./ast.ts"; import { Pos } from "./Token.ts"; -type SymMap = { [ident: string]: Sym } +type SymMap = { [ident: string]: Sym }; class Syms { private syms: SymMap = {}; @@ -16,11 +16,13 @@ class Syms { return ident in this.syms; } - public get(ident: string): { ok: true, sym: Sym } | { ok: false } { - if (ident in this.syms) + public get(ident: string): { ok: true; sym: Sym } | { ok: false } { + if (ident in this.syms) { return { ok: true, sym: this.syms[ident] }; - if (this.parent) + } + if (this.parent) { return this.parent.get(ident); + } return { ok: false }; } } @@ -35,7 +37,6 @@ export class Resolver { } } - private resolveExpr(expr: Expr, syms: Syms) { if (expr.kind.type === "error") { return; @@ -60,65 +61,72 @@ export class Resolver { return; } if (expr.kind.type === "group") { - this.resolveExpr(expr.kind.expr, syms) + this.resolveExpr(expr.kind.expr, syms); return; } if (expr.kind.type === "field") { - this.resolveExpr(expr.kind.subject, syms) + this.resolveExpr(expr.kind.subject, syms); return; } if (expr.kind.type === "index") { - this.resolveExpr(expr.kind.subject, syms) - this.resolveExpr(expr.kind.value, syms) + this.resolveExpr(expr.kind.subject, syms); + this.resolveExpr(expr.kind.value, syms); return; } if (expr.kind.type === "call") { - this.resolveExpr(expr.kind.subject, syms) + this.resolveExpr(expr.kind.subject, syms); for (const e of expr.kind.args) { - this.resolveExpr(e, syms) + this.resolveExpr(e, syms); } return; } if (expr.kind.type === "unary") { - this.resolveExpr(expr.kind.subject, syms) + this.resolveExpr(expr.kind.subject, syms); return; } if (expr.kind.type === "if") { - this.resolveExpr(expr.kind.cond, syms) - this.resolveExpr(expr.kind.truthy, syms) + this.resolveExpr(expr.kind.cond, syms); + this.resolveExpr(expr.kind.truthy, syms); if (expr.kind.falsy !== undefined) { - this.resolveExpr(expr.kind.falsy, syms) + this.resolveExpr(expr.kind.falsy, syms); } return; } if (expr.kind.type === "loop") { - this.resolveExpr(expr.kind.body, syms) + this.resolveExpr(expr.kind.body, syms); return; } - if (expr.kind.type === "int" || expr.kind.type === "bool" || expr.kind.type === "null" || expr.kind.type === "string" || expr.kind.type === "sym") { + if ( + expr.kind.type === "int" || expr.kind.type === "bool" || + expr.kind.type === "null" || expr.kind.type === "string" || + expr.kind.type === "sym" + ) { return; } } private resolveIdentExpr(expr: Expr, syms: Syms) { - if (expr.kind.type !== "ident") + if (expr.kind.type !== "ident") { throw new Error("expected ident"); + } const ident = expr.kind; const symResult = syms.get(ident.value); if (!symResult.ok) { this.reportUseOfUndefined(ident.value, expr.pos, syms); return; } - const sym = symResult.sym + const sym = symResult.sym; expr.kind = { type: "sym", ident: ident.value, defType: sym.type, }; - if (sym.stmt) + if (sym.stmt) { expr.kind.stmt = sym.stmt; - if (sym.param) + } + if (sym.param) { expr.kind.param = sym.param; + } } private resolveStmt(stmt: Stmt, syms: Syms) { @@ -134,30 +142,32 @@ export class Resolver { return; } if (stmt.kind.type === "return") { - if (stmt.kind.expr) + if (stmt.kind.expr) { this.resolveExpr(stmt.kind.expr, syms); + } return; } if (stmt.kind.type === "break") { if (stmt.kind.expr !== undefined) { - this.resolveExpr(stmt.kind.expr, syms) + this.resolveExpr(stmt.kind.expr, syms); } return; } if (stmt.kind.type === "assign") { - this.resolveExpr(stmt.kind.subject, syms) - this.resolveExpr(stmt.kind.value, syms) + this.resolveExpr(stmt.kind.subject, syms); + this.resolveExpr(stmt.kind.value, syms); return; } if (stmt.kind.type === "expr") { - this.resolveExpr(stmt.kind.expr, syms) + this.resolveExpr(stmt.kind.expr, syms); return; } } private resolveLetStmt(stmt: Stmt, syms: Syms) { - if (stmt.kind.type !== "let") + if (stmt.kind.type !== "let") { throw new Error("expected let statement"); + } this.resolveExpr(stmt.kind.value, syms); const ident = stmt.kind.param.ident; if (syms.definedLocally(ident)) { @@ -174,8 +184,9 @@ export class Resolver { } private resolveFnStmt(stmt: Stmt, syms: Syms) { - if (stmt.kind.type !== "fn") + if (stmt.kind.type !== "fn") { throw new Error("expected fn statement"); + } if (syms.definedLocally(stmt.kind.ident)) { this.reportAlreadyDefined(stmt.kind.ident, stmt.pos, syms); return; @@ -204,19 +215,25 @@ export class Resolver { } private reportUseOfUndefined(ident: string, pos: Pos, syms: Syms) { - console.error(`use of undefined symbol '${ident}' at ${pos.line}${pos.col}`); + console.error( + `use of undefined symbol '${ident}' at ${pos.line}${pos.col}`, + ); } - private reportAlreadyDefined(ident: string, pos: Pos, syms: Syms) { - console.error(`symbol already defined '${ident}', at ${pos.line}${pos.col}`); + private reportAlreadyDefined(ident: string, pos: Pos, syms: Syms) { + console.error( + `symbol already defined '${ident}', at ${pos.line}${pos.col}`, + ); const prev = syms.get(ident); - if (!prev.ok) + if (!prev.ok) { throw new Error("expected to be defined"); - if (!prev.sym.pos) + } + if (!prev.sym.pos) { return; + } const { line: prevLine, col: prevCol } = prev.sym.pos; - console.error(`previous definition of '${ident}' at ${prevLine}:${prevCol}`); + console.error( + `previous definition of '${ident}' at ${prevLine}:${prevCol}`, + ); } - - -} \ No newline at end of file +} diff --git a/compiler/main.ts b/compiler/main.ts index 1183ac6..81b2f42 100644 --- a/compiler/main.ts +++ b/compiler/main.ts @@ -1,7 +1,7 @@ import { Checker } from "./Checker.ts"; import { Lexer } from "./Lexer.ts"; import { Parser } from "./Parser.ts"; -import { Resolver } from "./Syms.ts"; +import { Resolver } from "./Resolver.ts"; const text = await Deno.readTextFile("example.slg"); // const text = await Deno.readTextFile("example.slg"); @@ -14,8 +14,8 @@ const lexer = new Lexer(text); // token = lexer.next(); // } -const parser = new Parser(lexer) -const ast = parser.parseStmts() -new Resolver().resolve(ast) -new Checker().check(ast) +const parser = new Parser(lexer); +const ast = parser.parseStmts(); +new Resolver().resolve(ast); +new Checker().check(ast); // console.log(JSON.stringify(ast, null, 4))