mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 18:36:31 +00:00
resolver stuff
This commit is contained in:
parent
03d68fa562
commit
c44c4fb9a7
@ -12,8 +12,8 @@ export class Lexer {
|
||||
if (this.done())
|
||||
return null;
|
||||
const pos = this.pos();
|
||||
if (this.test(/[ \t\n]/)) {
|
||||
while (!this.done() && this.test(/[ \t\n]/))
|
||||
if (this.test(/[ \t\n\r]/)) {
|
||||
while (!this.done() && this.test(/[ \t\n\r]/))
|
||||
this.step();
|
||||
return this.next();
|
||||
}
|
||||
|
124
compiler/Syms.ts
124
compiler/Syms.ts
@ -1,10 +1,6 @@
|
||||
import { Expr, Stmt, Sym } from "./ast.ts";
|
||||
import { Pos } from "./Token.ts";
|
||||
|
||||
|
||||
type Ident = string
|
||||
|
||||
|
||||
type SymMap = { [ident: string]: Sym }
|
||||
|
||||
class Syms {
|
||||
@ -29,10 +25,43 @@ class Syms {
|
||||
}
|
||||
}
|
||||
|
||||
// Chapter 7 is generally fucked, remember to give feedback to Simon
|
||||
class Resolver {
|
||||
export class Resolver {
|
||||
private root = new Syms();
|
||||
|
||||
public resolve(stmts: Stmt[]) {
|
||||
const scopeSyms = new Syms(this.root);
|
||||
for (const stmt of stmts) {
|
||||
this.resolveStmt(stmt, scopeSyms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
if (expr.kind.type !== "ident")
|
||||
throw new Error("expected ident");
|
||||
@ -54,39 +83,6 @@ class Resolver {
|
||||
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;
|
||||
@ -104,22 +100,62 @@ class Resolver {
|
||||
this.resolveExpr(stmt.kind.expr, syms);
|
||||
return;
|
||||
}
|
||||
// ...
|
||||
throw new Error(`unknown statement ${stmt.kind.type}`);
|
||||
}
|
||||
private resolveLetStmt(stmt: Stmt, syms: Syms) {
|
||||
|
||||
private resolveLetStmt(stmt: Stmt, syms: Syms) {
|
||||
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)) {
|
||||
this.reportAlreadyDefined(ident, stmt.pos, syms);
|
||||
return;
|
||||
}
|
||||
syms.define(ident, {
|
||||
ident,
|
||||
type: "let",
|
||||
pos: stmt.kind.param.pos,
|
||||
stmt,
|
||||
param: stmt.kind.param,
|
||||
});
|
||||
}
|
||||
|
||||
private resolveFnStmt(stmt: Stmt, syms: Syms) {
|
||||
|
||||
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;
|
||||
}
|
||||
const ident = stmt.kind.ident;
|
||||
syms.define(ident, {
|
||||
ident: stmt.kind.ident,
|
||||
type: "fn",
|
||||
pos: stmt.pos,
|
||||
stmt,
|
||||
});
|
||||
const fnScopeSyms = new Syms(syms);
|
||||
for (const param of stmt.kind.params) {
|
||||
if (fnScopeSyms.definedLocally(param.ident)) {
|
||||
this.reportAlreadyDefined(param.ident, param.pos, syms);
|
||||
continue;
|
||||
}
|
||||
fnScopeSyms.define(param.ident, {
|
||||
ident: param.ident,
|
||||
type: "fn_param",
|
||||
pos: param.pos,
|
||||
param,
|
||||
});
|
||||
}
|
||||
this.resolveExpr(stmt.kind.body, fnScopeSyms);
|
||||
}
|
||||
|
||||
private reportUseOfUndefined(ident: Ident, pos: Pos, syms: Syms) {
|
||||
private reportUseOfUndefined(ident: string, pos: Pos, syms: Syms) {
|
||||
console.error(`use of undefined symbol '${ident}' at ${pos.line}${pos.col}`);
|
||||
}
|
||||
|
||||
private reportAlreadyDefined(ident: Ident, pos: Pos, syms: Syms) {
|
||||
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)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Pos } from "./Token.ts";
|
||||
|
||||
type UnaryType = "not";
|
||||
export type UnaryType = "not";
|
||||
export type BinaryType = "+" | "*" | "==" | "-" | "/" | "!=" | "<" | ">" | "<=" | ">=" | "or" | "and";
|
||||
|
||||
export type Param = {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Lexer } from "./Lexer.ts";
|
||||
import { Parser } from "./Parser.ts";
|
||||
import { Resolver } from "./Syms.ts";
|
||||
|
||||
const text = await Deno.readTextFile("example-no-types.slg");
|
||||
// const text = await Deno.readTextFile("example.slg");
|
||||
@ -13,5 +14,7 @@ const lexer = new Lexer(text);
|
||||
// }
|
||||
|
||||
const parser = new Parser(lexer)
|
||||
const result = parser.parseStmts()
|
||||
console.log(JSON.stringify(result, null, 4))
|
||||
const ast = parser.parseStmts()
|
||||
// const resolver = new Resolver()
|
||||
// const resolvedAst = resolver.resolve(ast)
|
||||
console.log(JSON.stringify(ast, null, 4))
|
||||
|
Loading…
Reference in New Issue
Block a user