116 lines
2.8 KiB
TypeScript
116 lines
2.8 KiB
TypeScript
import { Sym } from "./ast.ts";
|
|
|
|
export type SymMap = { [ident: string]: Sym };
|
|
|
|
export interface Syms {
|
|
define(ident: string, sym: Sym): void;
|
|
definedLocally(ident: string): boolean;
|
|
get(ident: string): { ok: true; sym: Sym } | { ok: false };
|
|
}
|
|
|
|
export class GlobalSyms implements Syms {
|
|
private syms: SymMap = {};
|
|
|
|
public constructor() {}
|
|
|
|
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): { ok: true; sym: Sym } | { ok: false } {
|
|
if (ident in this.syms) {
|
|
return { ok: true, sym: this.syms[ident] };
|
|
}
|
|
return { ok: false };
|
|
}
|
|
}
|
|
|
|
export class StaticSyms implements Syms {
|
|
private syms: SymMap = {};
|
|
|
|
public constructor(private parent: GlobalSyms) {}
|
|
|
|
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): { ok: true; sym: Sym } | { ok: false } {
|
|
if (ident in this.syms) {
|
|
return { ok: true, sym: this.syms[ident] };
|
|
}
|
|
return this.parent.get(ident);
|
|
}
|
|
}
|
|
|
|
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): { ok: true; sym: Sym } | { ok: false } {
|
|
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): { ok: true; sym: Sym } | { ok: false } {
|
|
if (ident in this.syms) {
|
|
return { ok: true, sym: this.syms[ident] };
|
|
}
|
|
return this.parent.get(ident);
|
|
}
|
|
}
|