slige-mirror/compiler/resolve/cx.ts
2025-01-31 13:16:45 +01:00

92 lines
2.0 KiB
TypeScript

import { IdentId, idKey, Key } from "../ctx.ts";
type Ident = Key<IdentId>;
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<Ident, Res>;
};
export type Rib = {
bindings: Map<Ident, Res>;
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";