"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PilhaEscopos = void 0;
const elemento_montao_tipos_1 = require("./elemento-montao-tipos");
class PilhaEscopos {
    constructor() {
        this.pilha = [];
    }
    empilhar(item) {
        this.pilha.push(item);
    }
    eVazio() {
        return this.pilha.length === 0;
    }
    topoDaPilha() {
        if (this.eVazio())
            throw new Error('Pilha vazia.');
        return this.pilha[this.pilha.length - 1];
    }
    removerUltimo() {
        if (this.eVazio())
            throw new Error('Pilha vazia.');
        return this.pilha.pop();
    }
    obterBibliotecaGlobal(nome) {
        return this.pilha[0].elementosSintaticos[nome];
    }
    obterTipoVariavelPorNome(nome) {
        for (let i = 1; i <= this.pilha.length; i++) {
            const informacaoEscopo = this.pilha[this.pilha.length - i];
            if (informacaoEscopo.elementosSintaticos[nome] !== undefined) {
                return informacaoEscopo.elementosSintaticos[nome].tipo;
            }
        }
        throw new Error("Variável não definida: '" + nome + "'.");
    }
    obterElementoMontaoTipos(nome) {
        for (let i = 1; i <= this.pilha.length; i++) {
            const informacaoEscopo = this.pilha[this.pilha.length - i];
            if (informacaoEscopo.elementosSintaticos[nome] !== undefined) {
                const elementoMontaoTipos = informacaoEscopo.elementosSintaticos[nome];
                if (!(elementoMontaoTipos instanceof elemento_montao_tipos_1.ElementoMontaoTipos)) {
                    throw new Error(`Elemento não é um dicionário ou objeto por não pertencer ao montão de tipos: ${nome}`);
                }
                return elementoMontaoTipos;
            }
        }
        throw new Error("Elemento não existente no montão de tipos: '" + nome + "'.");
    }
    definirInformacoesVariavel(nomeVariavel, informacoes) {
        const topoDaPilha = this.topoDaPilha();
        topoDaPilha.elementosSintaticos[nomeVariavel] = informacoes;
    }
    registrarReferenciaFuncao(nome, definicao) {
        const topoDaPilha = this.topoDaPilha();
        topoDaPilha.referenciasFuncoes[nome] = definicao;
    }
    obterReferenciaFuncao(nome) {
        for (let i = 1; i <= this.pilha.length; i++) {
            const informacaoEscopo = this.pilha[this.pilha.length - i];
            if (informacaoEscopo.referenciasFuncoes[nome] !== undefined) {
                return informacaoEscopo.referenciasFuncoes[nome];
            }
        }
        return null;
    }
    variavelJaDefinida(nome) {
        for (let i = 1; i <= this.pilha.length; i++) {
            const informacaoEscopo = this.pilha[this.pilha.length - i];
            if (informacaoEscopo.elementosSintaticos[nome] !== undefined) {
                return true;
            }
        }
        return false;
    }
}
exports.PilhaEscopos = PilhaEscopos;
//# sourceMappingURL=pilha-escopos.js.map