"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FormatadorDelegua = void 0;
const construtos_1 = require("../construtos");
const declaracoes_1 = require("../declaracoes");
const delegua_1 = __importDefault(require("../tipos-de-simbolos/delegua"));
/**
 * O formatador de código Delégua.
 * Normalmente usado por IDEs, mas pode ser usado por linha de comando ou programaticamente.
 */
class FormatadorDelegua {
    constructor(quebraLinha, tamanhoIndentacao = 4) {
        this.quebraLinha = quebraLinha;
        this.tamanhoIndentacao = tamanhoIndentacao;
        this.indentacaoAtual = 0;
        this.codigoFormatado = '';
        this.devePularLinha = true;
        this.deveIndentar = true;
    }
    /* istanbul ignore next */
    visitarExpressaoTuplaN(expressao) {
        throw new Error('Método não implementado.');
    }
    /* istanbul ignore next */
    visitarExpressaoAcessoIntervaloVariavel(expressao) {
        throw new Error('Método não implementado.');
    }
    /* istanbul ignore next */
    visitarDeclaracaoTextoDocumentacao(declaracao) {
        throw new Error('Método não implementado.');
    }
    /* istanbul ignore next */
    visitarExpressaoSeparador(expressao) {
        throw new Error('Método não implementado.');
    }
    /* istanbul ignore next */
    visitarExpressaoComentario(expressao) {
        throw new Error('Método não implementado.');
    }
    visitarExpressaoArgumentoReferenciaFuncao(expressao) {
        this.codigoFormatado += expressao.simboloFuncao.lexema;
    }
    visitarExpressaoReferenciaFuncao(expressao) {
        this.codigoFormatado += expressao.simboloFuncao.lexema;
    }
    visitarExpressaoAcessoMetodo(expressao) {
        this.formatarDeclaracaoOuConstruto(expressao.objeto);
        this.codigoFormatado += '.';
        this.codigoFormatado += expressao.nomeMetodo;
    }
    visitarExpressaoAcessoPropriedade(expressao) {
        this.formatarDeclaracaoOuConstruto(expressao.objeto);
        this.codigoFormatado += '.';
        this.codigoFormatado += expressao.nomePropriedade;
    }
    visitarDeclaracaoComentario(declaracao) {
        if (declaracao.multilinha) {
            this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}/* `;
            for (let linhaConteudo of declaracao.conteudo) {
                this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}  ${linhaConteudo.replace(/\s+/g, ' ')}${this.quebraLinha}`;
            }
            this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)} */${this.quebraLinha}`;
        }
        else {
            this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}// `;
            this.codigoFormatado += declaracao.conteudo.replace(/\s+/g, ' ');
            this.codigoFormatado += `${this.quebraLinha}`;
        }
    }
    visitarDeclaracaoTendoComo(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}tendo `;
        this.formatarDeclaracaoOuConstruto(declaracao.inicializacaoVariavel);
        this.codigoFormatado += ` como ${declaracao.simboloVariavel.lexema} `;
        this.formatarDeclaracaoOuConstruto(declaracao.corpo);
    }
    /* istanbul ignore next */
    visitarDeclaracaoInicioAlgoritmo(declaracao) {
        throw new Error('Método não implementado.');
    }
    /* istanbul ignore next */
    visitarDeclaracaoCabecalhoPrograma(declaracao) {
        throw new Error('Método não implementado.');
    }
    visitarExpressaoTupla(expressao) {
        return '';
    }
    visitarDeclaracaoClasse(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}classe ${declaracao.simbolo.lexema} {${this.quebraLinha}`;
        this.indentacaoAtual += this.tamanhoIndentacao;
        for (let propriedade of declaracao.propriedades) {
            this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}${propriedade.nome.lexema}: ${propriedade.tipo || 'qualquer'}${this.quebraLinha}`;
        }
        this.codigoFormatado += `${this.quebraLinha}`;
        for (let metodo of declaracao.metodos) {
            this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}${metodo.simbolo.lexema}`;
            this.visitarExpressaoFuncaoConstruto(metodo.funcao);
        }
        this.indentacaoAtual -= this.tamanhoIndentacao;
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}}${this.quebraLinha}`;
    }
    visitarDeclaracaoConst(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}constante ${declaracao.simbolo.lexema}`;
        if (declaracao.inicializador) {
            this.codigoFormatado += ` = `;
            this.formatarDeclaracaoOuConstruto(declaracao.inicializador);
        }
        if (this.devePularLinha) {
            this.codigoFormatado += this.quebraLinha;
        }
    }
    visitarDeclaracaoConstMultiplo(declaracao) {
        // TODO: Até então o código nunca passa por aqui, porque o avaliador sintático
        // converte `ConstMultiplo` em várias declarações `const`.
        // Talvez mudar a avaliação sintática para não fazer mais isso.
        console.log(declaracao);
    }
    visitarExpressaoDeAtribuicao(expressao) {
        if (expressao.valor instanceof construtos_1.Binario &&
            [
                delegua_1.default.MAIS_IGUAL,
                delegua_1.default.MENOS_IGUAL,
                delegua_1.default.MULTIPLICACAO_IGUAL,
                delegua_1.default.DIVISAO_IGUAL,
                delegua_1.default.DIVISAO_INTEIRA_IGUAL,
                delegua_1.default.MODULO_IGUAL,
            ].includes(expressao.valor.operador.tipo)) {
            this.visitarExpressaoBinaria(expressao.valor);
        }
        else {
            this.formatarDeclaracaoOuConstruto(expressao.alvo);
            this.codigoFormatado += ` = `;
            this.formatarDeclaracaoOuConstruto(expressao.valor);
        }
        if (this.devePularLinha) {
            this.codigoFormatado += `${this.quebraLinha}`;
        }
    }
    visitarDeclaracaoDeExpressao(declaracao) {
        this.codigoFormatado += ' '.repeat(this.indentacaoAtual);
        this.formatarDeclaracaoOuConstruto(declaracao.expressao);
    }
    visitarDeclaracaoDefinicaoFuncao(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}função `;
        if (declaracao.simbolo) {
            this.codigoFormatado += `${declaracao.simbolo.lexema}`;
        }
        this.formatarDeclaracaoOuConstruto(declaracao.funcao);
    }
    visitarDeclaracaoEnquanto(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}enquanto `;
        this.formatarDeclaracaoOuConstruto(declaracao.condicao);
        this.formatarDeclaracaoOuConstruto(declaracao.corpo);
    }
    visitarDeclaracaoEscolha(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}escolha `;
        this.formatarDeclaracaoOuConstruto(declaracao.identificadorOuLiteral);
        this.codigoFormatado += ` {${this.quebraLinha}`;
        this.indentacaoAtual += this.tamanhoIndentacao;
        for (let caminho of declaracao.caminhos) {
            for (let declaracoes of caminho.condicoes) {
                this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}caso `;
                this.formatarDeclaracaoOuConstruto(declaracoes);
                this.codigoFormatado += ':';
                this.codigoFormatado += this.quebraLinha;
            }
            for (let declaracoes of caminho.declaracoes) {
                this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}`;
                this.formatarDeclaracaoOuConstruto(declaracoes);
            }
        }
        for (let padrao of declaracao.caminhoPadrao.declaracoes) {
            this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}padrao:`;
            this.codigoFormatado += this.quebraLinha;
            this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}`;
            this.formatarDeclaracaoOuConstruto(padrao);
        }
        this.indentacaoAtual -= this.tamanhoIndentacao;
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}}${this.quebraLinha}`;
    }
    visitarDeclaracaoEscreva(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}escreva(`;
        for (let argumento of declaracao.argumentos) {
            this.formatarDeclaracaoOuConstruto(argumento);
            this.codigoFormatado += ', ';
        }
        if (declaracao.argumentos.length > 0) {
            this.codigoFormatado = this.codigoFormatado.slice(0, -2);
        }
        this.codigoFormatado += `)${this.quebraLinha}`;
    }
    visitarDeclaracaoFazer(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}fazer {${this.quebraLinha}`;
        this.indentacaoAtual += this.tamanhoIndentacao;
        for (let declaracaoBloco of declaracao.caminhoFazer.declaracoes) {
            this.formatarDeclaracaoOuConstruto(declaracaoBloco);
        }
        this.indentacaoAtual -= this.tamanhoIndentacao;
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}} enquanto `;
        this.formatarDeclaracaoOuConstruto(declaracao.condicaoEnquanto);
        this.codigoFormatado += `${this.quebraLinha}`;
    }
    visitarDeclaracaoImportar(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}importar(`;
        this.formatarDeclaracaoOuConstruto(declaracao.caminho);
        this.codigoFormatado += `)`;
    }
    visitarDeclaracaoPara(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}para `;
        this.devePularLinha = false;
        if (declaracao.inicializador) {
            if (Array.isArray(declaracao.inicializador)) {
                this.deveIndentar = false;
                for (let declaracaoInicializador of declaracao.inicializador) {
                    this.formatarDeclaracaoOuConstruto(declaracaoInicializador);
                }
                this.deveIndentar = true;
            }
            else {
                this.formatarDeclaracaoOuConstruto(declaracao.inicializador);
            }
        }
        this.codigoFormatado += `; `;
        this.formatarDeclaracaoOuConstruto(declaracao.condicao);
        this.codigoFormatado += `; `;
        this.formatarDeclaracaoOuConstruto(declaracao.incrementar);
        this.devePularLinha = true;
        this.codigoFormatado += ` {${this.quebraLinha}`;
        this.indentacaoAtual += this.tamanhoIndentacao;
        for (let declaracaoBloco of declaracao.corpo.declaracoes) {
            this.formatarDeclaracaoOuConstruto(declaracaoBloco);
        }
        this.indentacaoAtual -= this.tamanhoIndentacao;
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}}${this.quebraLinha}`;
    }
    visitarDeclaracaoParaCada(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}para cada ${declaracao.variavelIteracao} de `;
        this.formatarDeclaracaoOuConstruto(declaracao.vetorOuDicionario);
        this.visitarExpressaoBloco(declaracao.corpo);
    }
    visitarDeclaracaoSe(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}se `;
        this.formatarDeclaracaoOuConstruto(declaracao.condicao);
        this.codigoFormatado += ` {${this.quebraLinha}`;
        this.indentacaoAtual += this.tamanhoIndentacao;
        for (let declaracaoBloco of declaracao.caminhoEntao.declaracoes) {
            this.formatarDeclaracaoOuConstruto(declaracaoBloco);
        }
        this.indentacaoAtual -= this.tamanhoIndentacao;
        if (declaracao.caminhoSenao) {
            this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}} senão `;
            this.formatarDeclaracaoOuConstruto(declaracao.caminhoSenao);
        }
        else {
            this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}}${this.quebraLinha}`;
        }
    }
    visitarDeclaracaoTente(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}tente {${this.quebraLinha}`;
        this.indentacaoAtual += this.tamanhoIndentacao;
        for (let declaracaoBloco of declaracao.caminhoTente) {
            this.formatarDeclaracaoOuConstruto(declaracaoBloco);
        }
        this.indentacaoAtual -= this.tamanhoIndentacao;
        if (declaracao.caminhoPegue) {
            this.codigoFormatado += `} pegue {${this.quebraLinha}`;
            if (declaracao.caminhoPegue instanceof construtos_1.FuncaoConstruto) {
                // Se tem um parâmetro de erro.
            }
            else {
                // Se não tem um parâmetro de erro.
                this.indentacaoAtual += this.tamanhoIndentacao;
                for (let declaracaoBloco of declaracao.caminhoPegue) {
                    this.formatarDeclaracaoOuConstruto(declaracaoBloco);
                }
            }
        }
        this.indentacaoAtual -= this.tamanhoIndentacao;
        if (declaracao.caminhoFinalmente) {
            this.codigoFormatado += `} finalmente {${this.quebraLinha}`;
            this.indentacaoAtual += this.tamanhoIndentacao;
            for (let declaracaoBloco of declaracao.caminhoFinalmente) {
                this.formatarDeclaracaoOuConstruto(declaracaoBloco);
            }
        }
        this.indentacaoAtual -= this.tamanhoIndentacao;
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}}${this.quebraLinha}`;
    }
    visitarDeclaracaoVar(declaracao) {
        if (this.deveIndentar) {
            this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}`;
        }
        this.codigoFormatado += `var ${declaracao.simbolo.lexema}`;
        if (declaracao.tipoExplicito && declaracao.tipo) {
            this.codigoFormatado += `: ${declaracao.tipo}`;
        }
        if (declaracao.inicializador) {
            this.codigoFormatado += ` = `;
            this.formatarDeclaracaoOuConstruto(declaracao.inicializador);
        }
        if (this.devePularLinha) {
            this.codigoFormatado += this.quebraLinha;
        }
    }
    visitarDeclaracaoVarMultiplo(declaracao) {
        // TODO: Até então o código nunca passa por aqui, porque o avaliador sintático
        // converte `VarMultiplo` em várias declarações `var`.
        // Talvez mudar a avaliação sintática para não fazer mais isso.
        console.log(declaracao);
    }
    visitarExpressaoAcessoIndiceVariavel(expressao) {
        this.formatarDeclaracaoOuConstruto(expressao.entidadeChamada);
        this.codigoFormatado += `[`;
        this.formatarDeclaracaoOuConstruto(expressao.indice);
        this.codigoFormatado += `]`;
    }
    visitarExpressaoAcessoMetodoOuPropriedade(expressao) {
        this.formatarDeclaracaoOuConstruto(expressao.objeto);
        this.codigoFormatado += '.';
        this.codigoFormatado += expressao.simbolo.lexema;
    }
    visitarExpressaoAgrupamento(expressao) {
        this.codigoFormatado += '(';
        this.formatarDeclaracaoOuConstruto(expressao.expressao);
        this.codigoFormatado += ')';
    }
    visitarExpressaoAtribuicaoPorIndice(expressao) {
        this.formatarDeclaracaoOuConstruto(expressao.objeto);
        this.codigoFormatado += '[';
        this.formatarDeclaracaoOuConstruto(expressao.indice);
        this.codigoFormatado += '] = ';
        this.formatarDeclaracaoOuConstruto(expressao.valor);
        this.codigoFormatado += this.quebraLinha;
    }
    visitarExpressaoAtribuicaoPorIndicesMatriz(expressao) {
        // Implementar somente para VisuAlg que tem atribuição diferente de Delégua - matriz[1, 2] = 1
        throw new Error('Método não implementado.');
    }
    visitarExpressaoAcessoElementoMatriz(expressao) {
        // Implementar somente para VisuAlg que tem acesso ao elemento da matriz diferente de Delégua - var valor = matriz[1, 2]
        throw new Error('Método não implementado.');
    }
    visitarExpressaoBinaria(expressao) {
        this.formatarDeclaracaoOuConstruto(expressao.esquerda);
        switch (expressao.operador.tipo) {
            case delegua_1.default.ADICAO:
                this.codigoFormatado += ` + `;
                break;
            case delegua_1.default.DIFERENTE:
                this.codigoFormatado += ` != `;
                break;
            case delegua_1.default.DIVISAO:
                this.codigoFormatado += ` / `;
                break;
            case delegua_1.default.DIVISAO_IGUAL:
                this.codigoFormatado += ` /= `;
                break;
            case delegua_1.default.DIVISAO_INTEIRA:
                this.codigoFormatado += ` \\ `;
                break;
            case delegua_1.default.DIVISAO_INTEIRA_IGUAL:
                this.codigoFormatado += ` \\= `;
                break;
            case delegua_1.default.EXPONENCIACAO:
                this.codigoFormatado += ` ** `;
                break;
            case delegua_1.default.IGUAL_IGUAL:
                this.codigoFormatado += ` == `;
                break;
            case delegua_1.default.MAIOR:
                this.codigoFormatado += ` > `;
                break;
            case delegua_1.default.MAIOR_IGUAL:
                this.codigoFormatado += ` >= `;
                break;
            case delegua_1.default.MAIS_IGUAL:
                this.codigoFormatado += ` += `;
                break;
            case delegua_1.default.MENOR:
                this.codigoFormatado += ` < `;
                break;
            case delegua_1.default.MENOR_IGUAL:
                this.codigoFormatado += ` <= `;
                break;
            case delegua_1.default.MENOS_IGUAL:
                this.codigoFormatado += ` -= `;
                break;
            case delegua_1.default.MODULO:
                this.codigoFormatado += ` % `;
                break;
            case delegua_1.default.MODULO_IGUAL:
                this.codigoFormatado += ` %= `;
                break;
            case delegua_1.default.MULTIPLICACAO:
                this.codigoFormatado += ` * `;
                break;
            case delegua_1.default.MULTIPLICACAO_IGUAL:
                this.codigoFormatado += ` * `;
                break;
            case delegua_1.default.SUBTRACAO:
                this.codigoFormatado += ` - `;
                break;
        }
        this.formatarDeclaracaoOuConstruto(expressao.direita);
    }
    formatarBlocoOuVetorDeclaracoes(declaracoes) {
        this.codigoFormatado += `{${this.quebraLinha}`;
        this.indentacaoAtual += this.tamanhoIndentacao;
        for (let declaracaoBloco of declaracoes) {
            this.formatarDeclaracaoOuConstruto(declaracaoBloco);
        }
        this.indentacaoAtual -= this.tamanhoIndentacao;
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}}${this.quebraLinha}`;
    }
    visitarExpressaoBloco(declaracao) {
        this.formatarBlocoOuVetorDeclaracoes(declaracao.declaracoes);
    }
    visitarExpressaoContinua(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}continua${this.quebraLinha}`;
    }
    visitarExpressaoDeChamada(expressao) {
        this.formatarDeclaracaoOuConstruto(expressao.entidadeChamada);
        this.codigoFormatado += '(';
        for (let argumento of expressao.argumentos) {
            this.formatarDeclaracaoOuConstruto(argumento);
            this.codigoFormatado += ', ';
        }
        if (expressao.argumentos.length > 0) {
            this.codigoFormatado = this.codigoFormatado.slice(0, -2);
        }
        this.codigoFormatado += ')';
    }
    visitarExpressaoDefinirValor(expressao) {
        this.formatarDeclaracaoOuConstruto(expressao.objeto);
        this.codigoFormatado += `.${expressao.nome.lexema} = `;
        this.formatarDeclaracaoOuConstruto(expressao.valor);
        this.codigoFormatado += `${this.quebraLinha}`;
    }
    visitarExpressaoDeVariavel(expressao) {
        this.codigoFormatado += expressao.simbolo.lexema;
    }
    visitarExpressaoDicionario(expressao) {
        this.codigoFormatado += `{`;
        for (let i = 0; i < expressao.chaves.length; i++) {
            // Verificar se é spread
            if (expressao.esSpread && expressao.esSpread[i]) {
                this.codigoFormatado += `**`;
                this.formatarDeclaracaoOuConstruto(expressao.valores[i]);
            }
            else {
                this.formatarDeclaracaoOuConstruto(expressao.chaves[i]);
                this.codigoFormatado += `: `;
                this.formatarDeclaracaoOuConstruto(expressao.valores[i]);
            }
            this.codigoFormatado += `, `;
        }
        if (expressao.chaves.length > 0) {
            this.codigoFormatado = this.codigoFormatado.slice(0, -2);
        }
        this.codigoFormatado += `}`;
    }
    visitarExpressaoExpressaoRegular(expressao) {
        this.codigoFormatado += `||${expressao.valor}||`;
    }
    visitarDeclaracaoEscrevaMesmaLinha(declaracao) {
        throw new Error('Método não implementado.');
    }
    visitarExpressaoFalhar(expressao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}falhar`;
        if (expressao.explicacao) {
            this.codigoFormatado += ` `;
            this.formatarDeclaracaoOuConstruto(expressao.explicacao);
        }
        this.codigoFormatado += `${this.quebraLinha}`;
    }
    visitarExpressaoFimPara(declaracao) {
        throw new Error('Método não implementado.');
    }
    visitarExpressaoFormatacaoEscrita(declaracao) {
        throw new Error('Método não implementado.');
    }
    visitarExpressaoFuncaoConstruto(expressao) {
        this.codigoFormatado += `(`;
        for (let argumento of expressao.parametros) {
            this.codigoFormatado += `${argumento.nome.lexema}: ${argumento.tipoDado || 'qualquer'}, `;
        }
        if (expressao.parametros.length > 0) {
            this.codigoFormatado = this.codigoFormatado.slice(0, -2);
        }
        this.codigoFormatado += `)`;
        if (expressao.tipoExplicito && expressao.tipo) {
            this.codigoFormatado += `: ${expressao.tipo}`;
        }
        this.codigoFormatado += ' ';
        this.formatarBlocoOuVetorDeclaracoes(expressao.corpo);
    }
    visitarExpressaoImportar(expressao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}importar(`;
        this.formatarDeclaracaoOuConstruto(expressao.caminho);
        this.codigoFormatado += `)`;
    }
    visitarExpressaoIsto(expressao) {
        this.codigoFormatado += `isto`;
    }
    visitarExpressaoLeia(expressao) {
        this.codigoFormatado += `leia(`;
        for (let argumento of expressao.argumentos) {
            this.formatarDeclaracaoOuConstruto(argumento);
            this.codigoFormatado += `, `;
        }
        if (expressao.argumentos.length > 0) {
            this.codigoFormatado = this.codigoFormatado.slice(0, -2);
        }
        this.codigoFormatado += `)`;
    }
    visitarExpressaoLiteral(expressao) {
        if (typeof expressao.valor === 'string') {
            const valorStr = expressao.valor
                .replace(/\\/g, '\\\\')
                .replace(/\r/g, '\\r')
                .replace(/\n/g, '\\n')
                .replace(/\t/g, '\\t')
                .replace(/'/g, "\\'");
            this.codigoFormatado += `'${valorStr}'`;
            return;
        }
        if (['logico', 'lógico'].includes(expressao.tipo)) {
            this.codigoFormatado += `${expressao.valor ? 'verdadeiro' : 'falso'}`;
            return;
        }
        this.codigoFormatado += expressao.valor;
    }
    visitarExpressaoLogica(expressao) {
        this.formatarDeclaracaoOuConstruto(expressao.esquerda);
        switch (expressao.operador.tipo) {
            case delegua_1.default.E:
                this.codigoFormatado += ` e `;
                break;
            case delegua_1.default.EM:
                this.codigoFormatado += ` em `;
                break;
            case delegua_1.default.OU:
                this.codigoFormatado += ` ou `;
                break;
        }
        this.formatarDeclaracaoOuConstruto(expressao.direita);
    }
    visitarExpressaoRetornar(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}retorna`;
        if (declaracao.valor) {
            this.codigoFormatado += ` `;
            if (declaracao.valor.constructor === construtos_1.FuncaoConstruto) {
                this.codigoFormatado += `função`;
            }
            this.formatarDeclaracaoOuConstruto(declaracao.valor);
        }
        this.codigoFormatado += `${this.quebraLinha}`;
    }
    visitarExpressaoSuper(expressao) {
        this.codigoFormatado += `super`;
    }
    visitarExpressaoSustar(declaracao) {
        this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}sustar${this.quebraLinha}`;
    }
    visitarExpressaoTipoDe(expressao) {
        this.codigoFormatado += `tipo de `;
        this.formatarDeclaracaoOuConstruto(expressao.valor);
    }
    visitarExpressaoUnaria(expressao) {
        let operador;
        switch (expressao.operador.tipo) {
            case delegua_1.default.INCREMENTAR:
                operador = `++`;
                break;
            case delegua_1.default.DECREMENTAR:
                operador = `--`;
                break;
            case delegua_1.default.NEGACAO:
                operador = `!`;
                break;
            case delegua_1.default.SUBTRACAO:
                operador = `-`;
                break;
        }
        switch (expressao.incidenciaOperador) {
            case 'ANTES':
                this.codigoFormatado += operador;
                this.formatarDeclaracaoOuConstruto(expressao.operando);
                break;
            case 'DEPOIS':
                this.formatarDeclaracaoOuConstruto(expressao.operando);
                this.codigoFormatado += operador;
                break;
        }
        if (this.devePularLinha) {
            this.codigoFormatado += this.quebraLinha;
        }
    }
    visitarExpressaoVetor(expressao) {
        this.codigoFormatado += '[';
        for (let valor of expressao.valores) {
            this.formatarDeclaracaoOuConstruto(valor);
            this.codigoFormatado += ', ';
        }
        if (expressao.valores.length > 0) {
            this.codigoFormatado = this.codigoFormatado.slice(0, -2);
        }
        this.codigoFormatado += ']';
    }
    formatarDeclaracaoOuConstruto(declaracaoOuConstruto) {
        switch (declaracaoOuConstruto.constructor) {
            case construtos_1.AcessoIndiceVariavel:
                this.visitarExpressaoAcessoIndiceVariavel(declaracaoOuConstruto);
                break;
            case construtos_1.AcessoMetodoOuPropriedade:
                this.visitarExpressaoAcessoMetodoOuPropriedade(declaracaoOuConstruto);
                break;
            case construtos_1.Agrupamento:
                this.visitarExpressaoAgrupamento(declaracaoOuConstruto);
                break;
            case construtos_1.ArgumentoReferenciaFuncao:
                this.visitarExpressaoArgumentoReferenciaFuncao(declaracaoOuConstruto);
                break;
            case construtos_1.AtribuicaoPorIndice:
                this.visitarExpressaoAtribuicaoPorIndice(declaracaoOuConstruto);
                break;
            case construtos_1.Atribuir:
                this.visitarExpressaoDeAtribuicao(declaracaoOuConstruto);
                break;
            case construtos_1.Binario:
                this.visitarExpressaoBinaria(declaracaoOuConstruto);
                break;
            case declaracoes_1.Bloco:
                this.visitarExpressaoBloco(declaracaoOuConstruto);
                break;
            case construtos_1.Chamada:
                this.visitarExpressaoDeChamada(declaracaoOuConstruto);
                break;
            case declaracoes_1.Classe:
                this.visitarDeclaracaoClasse(declaracaoOuConstruto);
                break;
            case declaracoes_1.Continua:
                this.visitarExpressaoContinua(declaracaoOuConstruto);
                break;
            case construtos_1.DefinirValor:
                this.visitarExpressaoDefinirValor(declaracaoOuConstruto);
                break;
            case construtos_1.Dicionario:
                this.visitarExpressaoDicionario(declaracaoOuConstruto);
                break;
            case declaracoes_1.Escolha:
                this.visitarDeclaracaoEscolha(declaracaoOuConstruto);
                break;
            case declaracoes_1.Enquanto:
                this.visitarDeclaracaoEnquanto(declaracaoOuConstruto);
                break;
            case declaracoes_1.Escreva:
                this.visitarDeclaracaoEscreva(declaracaoOuConstruto);
                break;
            case declaracoes_1.Expressao:
                this.visitarDeclaracaoDeExpressao(declaracaoOuConstruto);
                break;
            case construtos_1.ExpressaoRegular:
                this.visitarExpressaoExpressaoRegular(declaracaoOuConstruto);
                break;
            case declaracoes_1.Falhar:
                this.visitarExpressaoFalhar(declaracaoOuConstruto);
                break;
            case declaracoes_1.Fazer:
                this.visitarDeclaracaoFazer(declaracaoOuConstruto);
                break;
            case construtos_1.FuncaoConstruto:
                this.visitarExpressaoFuncaoConstruto(declaracaoOuConstruto);
                break;
            case declaracoes_1.FuncaoDeclaracao:
                this.visitarDeclaracaoDefinicaoFuncao(declaracaoOuConstruto);
                break;
            case declaracoes_1.Importar:
                this.visitarDeclaracaoImportar(declaracaoOuConstruto);
                break;
            case construtos_1.ImportarComoConstruto:
                this.visitarExpressaoImportar(declaracaoOuConstruto);
                break;
            case construtos_1.Isto:
                this.visitarExpressaoIsto(declaracaoOuConstruto);
                break;
            case construtos_1.Leia:
                this.visitarExpressaoLeia(declaracaoOuConstruto);
                break;
            case construtos_1.Literal:
                this.visitarExpressaoLiteral(declaracaoOuConstruto);
                break;
            case construtos_1.Logico:
                this.visitarExpressaoLogica(declaracaoOuConstruto);
                break;
            case declaracoes_1.Para:
                this.visitarDeclaracaoPara(declaracaoOuConstruto);
                break;
            case declaracoes_1.ParaCada:
                this.visitarDeclaracaoParaCada(declaracaoOuConstruto);
                break;
            case construtos_1.ReferenciaFuncao:
                this.visitarExpressaoReferenciaFuncao(declaracaoOuConstruto);
                break;
            case declaracoes_1.Retorna:
                this.visitarExpressaoRetornar(declaracaoOuConstruto);
                break;
            case declaracoes_1.Se:
                this.visitarDeclaracaoSe(declaracaoOuConstruto);
                break;
            case construtos_1.Super:
                this.visitarExpressaoSuper(declaracaoOuConstruto);
                break;
            case declaracoes_1.Sustar:
                this.visitarExpressaoSustar(declaracaoOuConstruto);
                break;
            case declaracoes_1.TendoComo:
                this.visitarDeclaracaoTendoComo(declaracaoOuConstruto);
                break;
            case declaracoes_1.Tente:
                this.visitarDeclaracaoTente(declaracaoOuConstruto);
                break;
            case construtos_1.TipoDe:
                this.visitarExpressaoTipoDe(declaracaoOuConstruto);
                break;
            case construtos_1.Unario:
                this.visitarExpressaoUnaria(declaracaoOuConstruto);
                break;
            case declaracoes_1.Const:
                this.visitarDeclaracaoConst(declaracaoOuConstruto);
                break;
            case declaracoes_1.Var:
                this.visitarDeclaracaoVar(declaracaoOuConstruto);
                break;
            case construtos_1.Variavel:
                this.visitarExpressaoDeVariavel(declaracaoOuConstruto);
                break;
            case construtos_1.Vetor:
                this.visitarExpressaoVetor(declaracaoOuConstruto);
                break;
            default:
                console.log(declaracaoOuConstruto.constructor.name);
                break;
        }
    }
    /**
     * Devolve código formatado de acordo com os símbolos encontrados.
     * @param {Declaracao[]} declaracoes Um vetor de declarações.
     * @returns Código Delégua formatado.
     */
    formatar(declaracoes) {
        this.codigoFormatado = '';
        this.indentacaoAtual = 0;
        for (let declaracao of declaracoes) {
            this.formatarDeclaracaoOuConstruto(declaracao);
        }
        return this.codigoFormatado;
    }
}
exports.FormatadorDelegua = FormatadorDelegua;
//# sourceMappingURL=formatador-delegua.js.map