slige/compiler/resolver_syms.ts
2025-01-17 11:50:14 +01:00

133 lines
3.0 KiB
TypeScript

import type { Sym } from "./ast.ts";
export type SymMap = { [ident: string]: Sym };
type GetRes = { ok: true; sym: Sym } | { ok: false };
export interface Syms {
define(ident: string, sym: Sym): void;
definedLocally(ident: string): boolean;
get(ident: string): GetRes;
}
export class EntryModSyms implements Syms {
private syms: SymMap = {};
public constructor() {
this.syms["crate"] = {
type: "mod",
ident: "crate",
syms: this,
};
}
public define(ident: string, sym: Sym) {
if (sym.type === "let") {
this.define(ident, {
...sym,
type: "let_static",
});
return;
}
this.syms[ident] = sym;
}
public definedLocally(ident: string): boolean {
return ident in this.syms;
}
public get(ident: string): GetRes {
if (ident in this.syms) {
return { ok: true, sym: this.syms[ident] };
}
return { ok: false };
}
}
export class ModSyms implements Syms {
private syms: SymMap = {};
public constructor(private parent: Syms) {
this.syms["super"] = {
type: "mod",
ident: "super",
syms: this.parent,
};
}
public define(ident: string, sym: Sym) {
if (sym.type === "let") {
this.define(ident, {
...sym,
type: "let_static",
});
return;
}
this.syms[ident] = sym;
}
public definedLocally(ident: string): boolean {
return ident in this.syms;
}
public get(ident: string): GetRes {
if (ident === "crate") {
return this.parent.get(ident);
}
if (ident in this.syms) {
return { ok: true, sym: this.syms[ident] };
}
return { ok: false };
}
}
export class FnSyms implements Syms {
private syms: SymMap = {};
public constructor(private parent: Syms) {}
public define(ident: string, sym: Sym) {
if (sym.type === "let") {
this.define(ident, {
...sym,
type: "closure",
inner: sym,
});
return;
}
this.syms[ident] = sym;
}
public definedLocally(ident: string): boolean {
return ident in this.syms;
}
public get(ident: string): GetRes {
if (ident in this.syms) {
return { ok: true, sym: this.syms[ident] };
}
return this.parent.get(ident);
}
}
export class LeafSyms implements 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): GetRes {
if (ident in this.syms) {
return { ok: true, sym: this.syms[ident] };
}
return this.parent.get(ident);
}
}