import { IdentId, idKey, Key } from "../ctx.ts"; type Ident = Key; export class Ribs { private tyRibs: Rib[] = []; private valRibs: Rib[] = []; private constructor() {} public static withRootMod(): Ribs { const ribs = new Ribs(); ribs.pushRib({ tag: "mod", mod: { items: new Map() } }); return ribs; } public pushRib(kind: RibKind) { this.tyRibs.push({ bindings: new Map(), kind }); this.valRibs.push({ bindings: new Map(), kind }); } public hasTy(ident: IdentId): boolean { return this.tyRibs.at(-1)!.bindings.has(idKey(ident)); } public defTy(ident: IdentId, res: Res) { this.tyRibs.at(-1)!.bindings.set(idKey(ident), res); } public hasVal(ident: IdentId): boolean { return this.valRibs.at(-1)!.bindings.has(idKey(ident)); } public defVal(ident: IdentId, res: Res) { this.valRibs.at(-1)!.bindings.set(idKey(ident), res); } public checkpoint(): number { return this.tyRibs.length; } public returnToCheckpoint(checkpoint: number) { this.tyRibs = this.tyRibs.slice(checkpoint, this.tyRibs.length); this.valRibs = this.valRibs.slice(checkpoint, this.valRibs.length); } public nearestMod(): Mod { return [ this.tyRibs .toReversed() .find((r) => r.kind.tag === "mod")!, ] .map((r) => (r.kind.tag === "mod" && r.kind.mod) as Mod)[0]; } } export type Mod = { parent?: Mod; items: Map; }; export type Rib = { bindings: Map; kind: RibKind; }; export type RibKind = | { tag: "normal" } | { tag: "fn" } | { tag: "item" } | { tag: "mod"; mod: Mod }; export type Res = | { tag: "def"; def: Def } | { tag: "local"; id: number }; export type Def = { type: DefType; id: number; }; export type DefType = | "mod" | "enum" | "struct" | "variant" | "ty_alias" | "ty_param" | "fn" | "use" | "field";