mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 10:56:30 +00:00
193 lines
4.4 KiB
TypeScript
193 lines
4.4 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): Sym;
|
|
definedLocally(ident: string): boolean;
|
|
get(ident: string): GetRes;
|
|
getPub(ident: string): GetRes;
|
|
rootMod(): Sym;
|
|
pathString(): string;
|
|
}
|
|
|
|
export class EntryModSyms implements Syms {
|
|
private syms: SymMap = {};
|
|
|
|
public constructor(private modName: string) {}
|
|
|
|
public define(ident: string, sym: Sym): Sym {
|
|
if (sym.type === "let") {
|
|
return this.define(ident, {
|
|
...sym,
|
|
type: "let_static",
|
|
});
|
|
}
|
|
this.syms[ident] = sym;
|
|
return 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 };
|
|
}
|
|
|
|
public getPub(ident: string): GetRes {
|
|
if (ident in this.syms) {
|
|
return { ok: true, sym: this.syms[ident] };
|
|
}
|
|
return { ok: false };
|
|
}
|
|
|
|
public rootMod(): Sym {
|
|
return {
|
|
type: "mod",
|
|
ident: this.modName,
|
|
fullPath: this.modName,
|
|
syms: this,
|
|
};
|
|
}
|
|
|
|
public pathString(): string {
|
|
return this.modName;
|
|
}
|
|
}
|
|
|
|
export class ModSyms implements Syms {
|
|
private syms: SymMap = {};
|
|
|
|
public constructor(private parent: Syms, private modName: string) {
|
|
this.syms["super"] = {
|
|
type: "mod",
|
|
ident: "super",
|
|
fullPath: this.pathString(),
|
|
syms: this.parent,
|
|
};
|
|
}
|
|
|
|
public define(ident: string, sym: Sym): Sym {
|
|
if (sym.type === "let") {
|
|
return 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 };
|
|
}
|
|
|
|
public getPub(ident: string): GetRes {
|
|
if (ident in this.syms) {
|
|
return { ok: true, sym: this.syms[ident] };
|
|
}
|
|
return { ok: false };
|
|
}
|
|
|
|
public rootMod(): Sym {
|
|
return this.parent.rootMod();
|
|
}
|
|
|
|
public pathString(): string {
|
|
return `${this.parent.pathString()}::${this.modName}`;
|
|
}
|
|
}
|
|
|
|
export class FnSyms implements Syms {
|
|
private syms: SymMap = {};
|
|
|
|
public constructor(private parent: Syms) {}
|
|
|
|
public define(ident: string, sym: Sym): Sym {
|
|
if (sym.type === "let") {
|
|
return this.define(ident, {
|
|
...sym,
|
|
type: "closure",
|
|
inner: sym,
|
|
});
|
|
}
|
|
this.syms[ident] = sym;
|
|
return 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);
|
|
}
|
|
|
|
public getPub(ident: string): GetRes {
|
|
if (ident in this.syms) {
|
|
return { ok: true, sym: this.syms[ident] };
|
|
}
|
|
return { ok: false };
|
|
}
|
|
|
|
public rootMod(): Sym {
|
|
return this.parent.rootMod();
|
|
}
|
|
|
|
public pathString(): string {
|
|
return this.parent.pathString();
|
|
}
|
|
}
|
|
|
|
export class LeafSyms implements Syms {
|
|
private syms: SymMap = {};
|
|
|
|
public constructor(private parent: Syms) {}
|
|
|
|
public define(ident: string, sym: Sym): Sym {
|
|
this.syms[ident] = sym;
|
|
return 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);
|
|
}
|
|
|
|
public getPub(ident: string): GetRes {
|
|
if (ident in this.syms) {
|
|
return { ok: true, sym: this.syms[ident] };
|
|
}
|
|
return { ok: false };
|
|
}
|
|
|
|
public rootMod(): Sym {
|
|
return this.parent.rootMod();
|
|
}
|
|
|
|
public pathString(): string {
|
|
return this.parent.pathString();
|
|
}
|
|
}
|