slige/compiler/lowerer_locals.ts
2024-12-11 03:11:00 +01:00

76 lines
2.0 KiB
TypeScript

export interface Locals {
reserveAmount(id: number): void;
allocSym(ident: string): void;
symId(ident: string): number;
currentLocalIdCounter(): number;
}
export class LocalsFnRoot implements Locals {
private localsAmount = 0;
private symLocalMap: { [key: string]: number } = {};
private localIdCounter: number;
constructor(private parent?: Locals) {
this.localIdCounter = parent?.currentLocalIdCounter() ?? 0;
}
public reserveAmount(amount: number): void {
this.localsAmount = Math.max(amount, this.localsAmount);
}
public allocSym(ident: string) {
this.symLocalMap[ident] = this.localIdCounter;
this.localIdCounter++;
this.reserveAmount(this.localIdCounter);
}
public symId(ident: string): number {
if (ident in this.symLocalMap) {
return this.symLocalMap[ident];
}
if (this.parent) {
return this.parent.symId(ident);
}
throw new Error(`undefined symbol '${ident}'`);
}
public stackReserved(): number {
return this.localsAmount;
}
public currentLocalIdCounter(): number {
return this.localIdCounter;
}
}
export class LocalLeaf implements Locals {
private symLocalMap: { [key: string]: number } = {};
private localIdCounter: number;
constructor(private parent: Locals) {
this.localIdCounter = parent.currentLocalIdCounter();
}
public reserveAmount(amount: number): void {
this.parent.reserveAmount(amount);
}
public allocSym(ident: string) {
this.symLocalMap[ident] = this.localIdCounter;
this.localIdCounter++;
this.reserveAmount(this.localIdCounter);
}
public symId(ident: string): number {
if (ident in this.symLocalMap) {
return this.symLocalMap[ident];
}
return this.parent.symId(ident);
}
public currentLocalIdCounter(): number {
return this.localIdCounter;
}
}