resolver stuff

This commit is contained in:
Mikkel Troels Kongsted 2024-11-26 19:37:21 +01:00
parent e9c70f71b7
commit cc3d00c2c4
4 changed files with 144 additions and 11 deletions

134
compiler/Syms.ts Normal file
View File

@ -0,0 +1,134 @@
import { Expr, Stmt, Sym } from "./ast.ts";
import { Pos } from "./Token.ts";
type Ident = string
type SymMap = { [ident: string]: Sym }
class Syms {
private syms: SymMap = {};
public constructor(private parent?: Syms) {}
public define(ident: string, sym: Sym) {
this.syms[ident] = sym;
}
public definedLocally(ident: string): boolean {
return 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)
return this.parent.get(ident);
return { ok: false };
}
}
// Chapter 7 is generally fucked, remember to give feedback to Simon
class Resolver {
private root = new Syms();
private resolveIdentExpr(expr: Expr, syms: Syms) {
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
expr.kind = {
type: "sym",
ident: ident.value,
defType: sym.type,
};
if (sym.stmt)
expr.kind.stmt = sym.stmt;
if (sym.param)
expr.kind.param = sym.param;
}
private resolveExpr(expr: Expr, syms: Syms) {
if (expr.kind.type === "error") {
return;
}
if (expr.kind.type === "ident") {
this.resolveIdentexpr(expr, syms);
return;
}
// ...
if (expr.kind.type === "binary") {
this.resolveExpr(expr.kind.left, syms);
this.resolveExpr(expr.kind.right, syms);
return;
}
// ...
if (expr.kind.type === "block") {
const childSyms = new Syms(syms);
for (const stmt of expr.kind.stmts) {
this.resolveStmt(stmt, childSyms);
}
if (expr.kind.expr) {
this.resolveExpr(expr.kind.expr, childSyms);
}
return;
}
// ...
throw new Error(`unknown expression ${expr.kind.type}`);
}
private resolveIdentexpr(expr: Expr, syms: Syms) {
}
private resolveStmt(stmt: Stmt, syms: Syms) {
if (stmt.kind.type === "error") {
return;
}
if (stmt.kind.type === "let") {
this.resolveLetStmt(stmt, syms);
return;
}
if (stmt.kind.type === "fn") {
this.resolveFnStmt(stmt, syms);
return;
}
if (stmt.kind.type === "return") {
if (stmt.kind.expr)
this.resolveExpr(stmt.kind.expr, syms);
return;
}
// ...
throw new Error(`unknown statement ${stmt.kind.type}`);
}
private resolveLetStmt(stmt: Stmt, syms: Syms) {
}
private resolveFnStmt(stmt: Stmt, syms: Syms) {
}
private reportUseOfUndefined(ident: Ident, pos: Pos, syms: Syms) {
console.error(`use of undefined symbol '${ident}' at ${pos.line}${pos.col}`);
}
private reportAlreadyDefined(ident: Ident, pos: Pos, syms: Syms) {
console.error(`symbol already defined '${ident}', at ${pos.line}${pos.col}`);
const prev = syms.get(ident);
if (!prev.ok)
throw new Error("expected to be defined");
if (!prev.sym.pos)
return;
const { line: prevLine, col: prevCol } = prev.sym.pos;
console.error(`previous definition of '${ident}' at ${prevLine}:${prevCol}`);
}
}

View File

@ -46,6 +46,7 @@ export type ExprKind =
| { type: "null"} | { type: "null"}
| { type: "loop", body: Expr } | { type: "loop", body: Expr }
| { type: "block", stmts: Stmt[], expr?: Expr } | { type: "block", stmts: Stmt[], expr?: Expr }
| { type: "sym", ident: string, defType: "let" | "fn" | "fn_param" | "builtin", stmt?: Stmt, param?: Param }
; ;
export type Sym = { export type Sym = {

View File

@ -1,13 +1,13 @@
//fn sum(a, b) { fn sum(a, b) {
// + a b; + a b;
//} }
//
//add(2,3); // -> 5 add(2,3); // -> 5
//
//let a = "Hello"; let a = "Hello";
//
//let b = "world"; let b = "world";
println(+ + + a " " b "!"); // -> "Hello world!" println(+ + + a " " b "!"); // -> "Hello world!"

View File

@ -19,8 +19,6 @@ else {
println(":o"); println(":o");
} }
oopjoipjioj
loop { loop {
let i = 0; let i = 0;