"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SymbolTable = void 0;
class SymbolTable {
    outer;
    store = new Map();
    numDefinitions = 0;
    freeSymbols = [];
    constructor(outer = null) {
        this.outer = outer;
    }
    define(name) {
        const symbol = {
            name,
            index: this.numDefinitions,
            scope: this.outer === null ? "GLOBAL" : "LOCAL",
        };
        this.store.set(name, symbol);
        this.numDefinitions++;
        return symbol;
    }
    defineBuiltin(index, name) {
        const symbol = { name, index, scope: "BUILTIN" };
        this.store.set(name, symbol);
        return symbol;
    }
    defineFunctionName(name) {
        const symbol = { name, index: 0, scope: "FUNCTION" };
        this.store.set(name, symbol);
        return symbol;
    }
    resolve(name) {
        const obj = this.store.get(name);
        if (obj) {
            return obj;
        }
        if (!this.outer) {
            return undefined;
        }
        const outer = this.outer.resolve(name);
        if (!outer) {
            return undefined;
        }
        if (outer.scope === "GLOBAL" || outer.scope === "BUILTIN") {
            return outer;
        }
        return this.defineFree(outer);
    }
    defineFree(original) {
        this.freeSymbols.push(original);
        const symbol = {
            name: original.name,
            index: this.freeSymbols.length - 1,
            scope: "FREE",
        };
        this.store.set(original.name, symbol);
        return symbol;
    }
}
exports.SymbolTable = SymbolTable;
//# sourceMappingURL=symbols.js.map