summaryrefslogtreecommitdiff
path: root/src/interpreter/SymbolTable.ts
blob: df88d8f201f796750ed726892fa8baf45e0e2512 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
export class UndefinedSymbolError extends Error {}

export class SymbolTable {
  private knownSymbols: Set<string>;
  private parent: SymbolTable | null;
  private depth: number;

  constructor(parent: SymbolTable | null = null) {
    this.knownSymbols = new Set();
    this.parent = parent;
    this.depth = parent ? parent.getDepth() + 1 : 0;
  }

  public getDepth() {
    return this.depth;
  }

  public add(name: string) {
    this.knownSymbols.add(name);
  }

  public get(name: string): number {
    if (this.knownSymbols.has(name)) {
      return 1;
    }

    if (this.parent) {
      return 1 + this.parent.get(name);
    }

    throw new UndefinedSymbolError(`Undefined variable: ${name}`);
  }

  public has(name: string): boolean {
    if (this.knownSymbols.has(name)) {
      return true;
    }

    if (this.parent) {
      return this.parent.has(name);
    }

    return false;
  }

  public createChild(): SymbolTable {
    return new SymbolTable(this);
  }

  public static from(collection: Array<string> | Set<string>): SymbolTable {
    const table = new SymbolTable();
    collection.forEach((symbol) => table.add(symbol));
    return table;
  }
}