mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 18:16:31 +00:00
resolver stuff
This commit is contained in:
parent
e9c70f71b7
commit
cc3d00c2c4
134
compiler/Syms.ts
Normal file
134
compiler/Syms.ts
Normal 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}`);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -46,6 +46,7 @@ export type ExprKind =
|
||||
| { type: "null"}
|
||||
| { type: "loop", body: Expr }
|
||||
| { type: "block", stmts: Stmt[], expr?: Expr }
|
||||
| { type: "sym", ident: string, defType: "let" | "fn" | "fn_param" | "builtin", stmt?: Stmt, param?: Param }
|
||||
;
|
||||
|
||||
export type Sym = {
|
||||
|
@ -1,13 +1,13 @@
|
||||
|
||||
//fn sum(a, b) {
|
||||
// + a b;
|
||||
//}
|
||||
//
|
||||
//add(2,3); // -> 5
|
||||
//
|
||||
//let a = "Hello";
|
||||
//
|
||||
//let b = "world";
|
||||
fn sum(a, b) {
|
||||
+ a b;
|
||||
}
|
||||
|
||||
add(2,3); // -> 5
|
||||
|
||||
let a = "Hello";
|
||||
|
||||
let b = "world";
|
||||
|
||||
println(+ + + a " " b "!"); // -> "Hello world!"
|
||||
|
||||
|
@ -19,8 +19,6 @@ else {
|
||||
println(":o");
|
||||
}
|
||||
|
||||
oopjoipjioj
|
||||
|
||||
loop {
|
||||
let i = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user