From cc3d00c2c40a4a3045320f190bd8bdab62a15ab7 Mon Sep 17 00:00:00 2001 From: Mikkel Troels Kongsted Date: Tue, 26 Nov 2024 19:37:21 +0100 Subject: [PATCH] resolver stuff --- compiler/Syms.ts | 134 ++++++++++++++++++++++++++++++++++ compiler/ast.ts | 1 + compiler/example-no-types.slg | 18 ++--- compiler/example.slg | 2 - 4 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 compiler/Syms.ts diff --git a/compiler/Syms.ts b/compiler/Syms.ts new file mode 100644 index 0000000..a2ed8da --- /dev/null +++ b/compiler/Syms.ts @@ -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}`); + } + + +} \ No newline at end of file diff --git a/compiler/ast.ts b/compiler/ast.ts index 30d46bf..49029f0 100644 --- a/compiler/ast.ts +++ b/compiler/ast.ts @@ -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 = { diff --git a/compiler/example-no-types.slg b/compiler/example-no-types.slg index 019c744..aafec18 100644 --- a/compiler/example-no-types.slg +++ b/compiler/example-no-types.slg @@ -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!" diff --git a/compiler/example.slg b/compiler/example.slg index 19ea8fc..4eac52e 100755 --- a/compiler/example.slg +++ b/compiler/example.slg @@ -19,8 +19,6 @@ else { println(":o"); } -oopjoipjioj - loop { let i = 0;