"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TradutorAssemblyScript = void 0;
const construtos_1 = require("../construtos");
const declaracoes_1 = require("../declaracoes");
const delegua_1 = __importDefault(require("../tipos-de-simbolos/delegua"));
class TradutorAssemblyScript {
    constructor() {
        this.indentacao = 0;
        this.dicionarioConstrutos = {
            AcessoIndiceVariavel: this.traduzirConstrutoAcessoIndiceVariavel.bind(this),
            AcessoMetodo: this.traduzirConstrutoAcessoMetodo.bind(this),
            AcessoMetodoOuPropriedade: this.traduzirConstrutoAcessoMetodo.bind(this),
            AcessoPropriedade: this.traduzirConstrutoAcessoPropriedade.bind(this),
            Agrupamento: this.traduzirConstrutoAgrupamento.bind(this),
            ArgumentoReferenciaFuncao: this.traduzirConstrutoArgumentoReferenciaFuncao.bind(this),
            AtribuicaoPorIndice: this.traduzirConstrutoAtribuicaoPorIndice.bind(this),
            Atribuir: this.traduzirConstrutoAtribuir.bind(this),
            Binario: this.traduzirConstrutoBinario.bind(this),
            Chamada: this.traduzirConstrutoChamada.bind(this),
            ComentarioComoConstruto: this.traduzirConstrutoComentario.bind(this),
            Deceto: this.traduzirConstrutoDeceto.bind(this),
            DefinirValor: this.traduzirConstrutoDefinirValor.bind(this),
            Dicionario: this.traduzirConstrutoDicionario.bind(this),
            Dupla: this.traduzirConstrutoDupla.bind(this),
            Elvis: this.traduzirConstrutoElvis.bind(this),
            ExpressaoRegular: this.traduzirConstrutoExpressaoRegular.bind(this),
            FuncaoConstruto: this.traduzirFuncaoConstruto.bind(this),
            Isto: () => 'this',
            Literal: this.traduzirConstrutoLiteral.bind(this),
            Logico: this.traduzirConstrutoLogico.bind(this),
            Noneto: this.traduzirConstrutoNoneto.bind(this),
            Octeto: this.traduzirConstrutoOcteto.bind(this),
            Quarteto: this.traduzirConstrutoQuarteto.bind(this),
            Quinteto: this.traduzirConstrutoQuinteto.bind(this),
            ReferenciaFuncao: this.traduzirConstrutoReferenciaFuncao.bind(this),
            Separador: this.traduzirConstrutoSeparador.bind(this),
            SeTernario: this.traduzirConstrutoSeTernario.bind(this),
            Sexteto: this.traduzirConstrutoSexteto.bind(this),
            Septeto: this.traduzirConstrutoSepteto.bind(this),
            TipoDe: this.traduzirConstrutoTipoDe.bind(this),
            Trio: this.traduzirConstrutoTrio.bind(this),
            TuplaN: this.traduzirConstrutoTuplaN.bind(this),
            Unario: this.traduzirConstrutoUnario.bind(this),
            Variavel: this.traduzirConstrutoVariavel.bind(this),
            Vetor: this.traduzirConstrutoVetor.bind(this),
        };
        this.dicionarioDeclaracoes = {
            Ajuda: this.traduzirDeclaracaoAjuda.bind(this),
            Bloco: this.traduzirDeclaracaoBloco.bind(this),
            Enquanto: this.traduzirDeclaracaoEnquanto.bind(this),
            Comentario: this.traduzirConstrutoComentario.bind(this),
            Continua: () => 'continue',
            Escolha: this.traduzirDeclaracaoEscolha.bind(this),
            Expressao: this.traduzirDeclaracaoExpressao.bind(this),
            Fazer: this.traduzirDeclaracaoFazer.bind(this),
            Falhar: this.traduzirDeclaracaoFalhar.bind(this),
            FuncaoDeclaracao: this.traduzirDeclaracaoFuncao.bind(this),
            Importar: this.traduzirDeclaracaoImportar.bind(this),
            Leia: this.traduzirDeclaracaoLeia.bind(this),
            Para: this.traduzirDeclaracaoPara.bind(this),
            ParaCada: this.traduzirDeclaracaoParaCada.bind(this),
            Retorna: this.traduzirDeclaracaoRetorna.bind(this),
            Se: this.traduzirDeclaracaoSe.bind(this),
            Sustar: () => 'break',
            Classe: this.traduzirDeclaracaoClasse.bind(this),
            Tente: this.traduzirDeclaracaoTente.bind(this),
            Const: this.traduzirDeclaracaoConst.bind(this),
            ConstMultiplo: this.traduzirDeclaracaoConstMultiplo.bind(this),
            Var: this.traduzirDeclaracaoVar.bind(this),
            VarMultiplo: this.traduzirDeclaracaoVarMultiplo.bind(this),
            Escreva: this.traduzirDeclaracaoEscreva.bind(this),
            EscrevaMesmaLinha: this.traduzirDeclaracaoEscrevaMesmaLinha.bind(this),
            TendoComo: this.traduzirDeclaracaoTendoComo.bind(this),
            TextoDocumentacao: this.traduzirDeclaracaoTextoDocumentacao.bind(this),
        };
    }
    traduzirSimboloOperador(operador) {
        switch (operador.tipo) {
            case delegua_1.default.ADICAO:
                return '+';
            case delegua_1.default.BIT_AND:
                return '&';
            case delegua_1.default.BIT_OR:
                return '|';
            case delegua_1.default.CIRCUMFLEXO:
                return '^';
            case delegua_1.default.BIT_NOT:
                return '~';
            case delegua_1.default.DIFERENTE:
                return '!=';
            case delegua_1.default.DIVISAO:
                return '/';
            case delegua_1.default.E:
                return '&&';
            case delegua_1.default.EXPONENCIACAO:
                return '**';
            case delegua_1.default.IGUAL:
                return '=';
            case delegua_1.default.IGUAL_IGUAL:
                return '==';
            case delegua_1.default.MAIOR:
                return '>';
            case delegua_1.default.MAIOR_IGUAL:
                return '>=';
            case delegua_1.default.MENOR:
                return '<';
            case delegua_1.default.MENOR_IGUAL:
                return '<=';
            case delegua_1.default.MODULO:
                return '%';
            case delegua_1.default.MULTIPLICACAO:
                return '*';
            case delegua_1.default.OU:
                return '||';
            case delegua_1.default.SUBTRACAO:
                return '-';
        }
    }
    traduzirFuncoesNativas(metodo) {
        switch (metodo.toLowerCase()) {
            // Array methods
            case 'adicionar':
            case 'empilhar':
                return 'push';
            case 'concatenar':
                return 'concat';
            case 'fatiar':
                return 'slice';
            case 'inclui':
            case 'incluido':
                return 'includes';
            case 'inverter':
                return 'reverse';
            case 'juntar':
                return 'join';
            case 'ordenar':
                return 'sort';
            case 'removerprimeiro':
                return 'shift';
            case 'removerultimo':
                return 'pop';
            case 'tamanho':
                return 'length';
            case 'indice':
            case 'indiceode':
                return 'indexOf';
            // String methods
            case 'maiusculo':
                return 'toUpperCase';
            case 'minusculo':
                return 'toLowerCase';
            case 'substituir':
                return 'replace';
            case 'trimcomeco':
                return 'trimStart';
            case 'trimfim':
                return 'trimEnd';
            case 'trim':
                return 'trim';
            case 'comeca':
                return 'startsWith';
            case 'termina':
                return 'endsWith';
            case 'contém':
            case 'contem':
                return 'includes';
            // Math constants and methods (would need Math. prefix in AS)
            case 'abs':
            case 'absoluto':
                return 'Math.abs';
            case 'ceil':
            case 'teto':
                return 'Math.ceil';
            case 'floor':
            case 'piso':
                return 'Math.floor';
            case 'round':
            case 'arredondar':
                return 'Math.round';
            case 'sqrt':
            case 'raizquadrada':
                return 'Math.sqrt';
            case 'pow':
            case 'potencia':
                return 'Math.pow';
            case 'max':
            case 'maximo':
                return 'Math.max';
            case 'min':
            case 'minimo':
                return 'Math.min';
            case 'sin':
            case 'seno':
                return 'Math.sin';
            case 'cos':
            case 'cosseno':
                return 'Math.cos';
            case 'tan':
            case 'tangente':
                return 'Math.tan';
            case 'pi':
                return 'Math.PI';
            case 'e':
                return 'Math.E';
            default:
                return metodo;
        }
    }
    traduzirFuncaoNativaGlobal(nomeFuncao, argumentos) {
        switch (nomeFuncao.toLowerCase()) {
            // Math functions
            case 'aleatorio':
                return `Math.random()`;
            case 'aleatorioEntre':
            case 'aleatorioente':
                if (argumentos.length >= 2) {
                    return `(Math.random() * (${argumentos[1]} - ${argumentos[0]}) + ${argumentos[0]})`;
                }
                return null;
            case 'arredondar':
                return argumentos.length > 0 ? `Math.round(${argumentos[0]})` : null;
            case 'inteiro':
                return argumentos.length > 0 ? `Math.trunc(${argumentos[0]})` : null;
            case 'numero':
                return argumentos.length > 0 ? `Number(${argumentos[0]})` : null;
            case 'texto':
                return argumentos.length > 0 ? `String(${argumentos[0]})` : null;
            case 'longo':
                return argumentos.length > 0 ? `parseInt(${argumentos[0]})` : null;
            case 'real':
                return argumentos.length > 0 ? `parseFloat(${argumentos[0]})` : null;
            // Array functions
            case 'tamanho':
                return argumentos.length > 0 ? `(${argumentos[0]}).length` : null;
            case 'intervalo':
                // intervalo(inicio, fim, passo?) - returns array of numbers
                if (argumentos.length >= 2) {
                    if (argumentos.length >= 3) {
                        return `Array.from({length: (${argumentos[1]} - ${argumentos[0]}) / ${argumentos[2]}}, (_, i) => ${argumentos[0]} + i * ${argumentos[2]})`;
                    }
                    return `Array.from({length: ${argumentos[1]} - ${argumentos[0]}}, (_, i) => ${argumentos[0]} + i)`;
                }
                return null;
            case 'maximo':
                return argumentos.length > 0 ? `Math.max(...${argumentos[0]})` : null;
            case 'minimo':
                return argumentos.length > 0 ? `Math.min(...${argumentos[0]})` : null;
            // These need custom implementation or are too complex for Phase 5
            case 'mapear':
            case 'filtrarPor':
            case 'reduzir':
            case 'ordenar':
            case 'encontrar':
            case 'encontrarIndice':
            case 'incluido':
            case 'todos':
            case 'algum':
                // These would require closures/lambda support - not easily translated
                return null;
            default:
                return null;
        }
    }
    traduzirConstrutoArgumentoReferenciaFuncao(argumentoReferenciaFuncao, argumentos) {
        const argumentosResolvidos = [];
        for (const argumento of argumentos) {
            const argumentoResolvido = this.dicionarioConstrutos[argumento.constructor.name](argumento);
            argumentosResolvidos.push(argumentoResolvido);
        }
        let textoArgumentos = argumentosResolvidos.reduce((atual, proximo) => (atual += proximo + ', '), '');
        textoArgumentos = textoArgumentos.slice(0, -2);
        return `${argumentoReferenciaFuncao.simboloFuncao.lexema}(${textoArgumentos})`;
    }
    traduzirConstrutoReferenciaFuncao(referenciaFuncao, argumentos) {
        const argumentosResolvidos = [];
        for (const argumento of argumentos) {
            const argumentoResolvido = this.dicionarioConstrutos[argumento.constructor.name](argumento);
            argumentosResolvidos.push(argumentoResolvido);
        }
        let textoArgumentos = argumentosResolvidos.reduce((atual, proximo) => (atual += proximo + ', '), '');
        textoArgumentos = textoArgumentos.slice(0, -2);
        return `${referenciaFuncao.simboloFuncao.lexema}(${textoArgumentos})`;
    }
    traduzirConstrutoSeparador(separador) {
        return `${separador.conteudo} `;
    }
    traduzirDeclaracaoEscreva(declaracaoEscreva) {
        let resultado = 'trace(';
        for (const argumento of declaracaoEscreva.argumentos) {
            const valor = this.dicionarioConstrutos[argumento.constructor.name](argumento);
            resultado += valor + ', ';
        }
        resultado = resultado.slice(0, -2);
        resultado += ')';
        return resultado;
    }
    traduzirConstrutoLiteral(literal) {
        if (typeof literal.valor === 'string')
            return `"${literal.valor}"`;
        return String(literal.valor);
    }
    resolveTipoDeclaracaoVarEContante(tipo) {
        switch (tipo) {
            case 'texto':
                return ': string';
            case 'inteiro':
                return ': i32';
            case 'longo':
                return ': i64';
            case 'inteiro_curto':
            case 'inteiroCurto':
                return ': i16';
            case 'byte':
                return ': i8';
            case 'numero':
            case 'número':
            case 'real':
                return ': f64';
            case 'real_curto':
            case 'realCurto':
                return ': f32';
            case 'logico':
            case 'lógico':
                return ': bool';
            case 'vazio':
            case 'nada':
                return ': void';
            case 'nulo':
                throw new Error(`Tipo 'nulo' não é válido no AssemblyScript. Use 'Type | null' para tipos anuláveis.`);
            case 'inteiro[]':
                return ': i32[]';
            case 'longo[]':
                return ': i64[]';
            case 'real[]':
            case 'numero[]':
            case 'número[]':
                return ': f64[]';
            case 'texto[]':
                return ': string[]';
            case 'logico[]':
            case 'lógico[]':
                return ': bool[]';
            case 'dicionario':
            case 'dicionário':
                return ': Map<string, i32>';
            case 'dupla':
                return ': i32[]';
            case 'trio':
                return ': i32[]';
            case 'quarteto':
                return ': i32[]';
            case 'quinteto':
                return ': i32[]';
            case 'sexteto':
                return ': i32[]';
            case 'septeto':
                return ': i32[]';
            case 'octeto':
                return ': i32[]';
            case 'noneto':
                return ': i32[]';
            case 'deceto':
                return ': i32[]';
            case 'tupla':
                return ': i32[]';
            default:
                throw new Error(`Tipo não reconhecido ou não suportado no AssemblyScript: '${tipo}'. AssemblyScript requer anotações de tipo explícitas.`);
        }
    }
    traduzirDeclaracaoVar(declaracaoVar) {
        let resultado = 'let ';
        resultado += declaracaoVar.simbolo.lexema;
        resultado += this.resolveTipoDeclaracaoVarEContante(declaracaoVar.tipo);
        if (!(declaracaoVar === null || declaracaoVar === void 0 ? void 0 : declaracaoVar.inicializador))
            resultado += ';';
        else {
            resultado += ' = ';
            if (this.dicionarioConstrutos[declaracaoVar.inicializador.constructor.name]) {
                resultado += this.dicionarioConstrutos[declaracaoVar.inicializador.constructor.name](declaracaoVar.inicializador);
            }
            else {
                resultado += this.dicionarioDeclaracoes[declaracaoVar.inicializador.constructor.name](declaracaoVar.inicializador);
            }
            resultado += ';';
        }
        return resultado;
    }
    traduzirDeclaracaoConst(declaracaoConst) {
        let resultado = 'const ';
        resultado += declaracaoConst.simbolo.lexema;
        resultado += this.resolveTipoDeclaracaoVarEContante(declaracaoConst.tipo);
        if (!(declaracaoConst === null || declaracaoConst === void 0 ? void 0 : declaracaoConst.inicializador))
            resultado += ';';
        else {
            resultado += ' = ';
            if (this.dicionarioConstrutos[declaracaoConst.inicializador.constructor.name]) {
                resultado += this.dicionarioConstrutos[declaracaoConst.inicializador.constructor.name](declaracaoConst.inicializador);
            }
            else {
                resultado += this.dicionarioDeclaracoes[declaracaoConst.inicializador.constructor.name](declaracaoConst.inicializador);
            }
            resultado += ';';
        }
        return resultado;
    }
    traduzirDeclaracaoTente(declaracaoTente) {
        let resultado = '/* AVISO: AssemblyScript não suporta try/catch/finally. Este código pode não funcionar como esperado. */\n';
        resultado += 'try {\n';
        this.indentacao += 4;
        resultado += ' '.repeat(this.indentacao);
        for (let condicao of declaracaoTente.caminhoTente) {
            resultado += this.dicionarioDeclaracoes[condicao.constructor.name](condicao) + '\n';
            resultado += ' '.repeat(this.indentacao);
        }
        resultado += '}';
        if (declaracaoTente.caminhoPegue !== null) {
            resultado += '\ncatch {\n';
            resultado += ' '.repeat(this.indentacao);
            if (Array.isArray(declaracaoTente.caminhoPegue)) {
                for (let declaracao of declaracaoTente.caminhoPegue) {
                    resultado +=
                        this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao) + '\n';
                }
            }
            else {
                for (let corpo of declaracaoTente.caminhoPegue.corpo) {
                    resultado += this.dicionarioDeclaracoes[corpo.constructor.name](corpo) + '\n';
                }
            }
            resultado += ' '.repeat(this.indentacao);
            resultado += '}';
        }
        if (declaracaoTente.caminhoFinalmente !== null) {
            resultado += '\nfinally {\n';
            for (let finalmente of declaracaoTente.caminhoFinalmente) {
                resultado +=
                    this.dicionarioDeclaracoes[finalmente.constructor.name](finalmente) + '\n';
            }
            resultado += ' '.repeat(this.indentacao);
            resultado += '}';
        }
        return resultado;
    }
    traduzirDeclaracaoVarMultiplo(declaracaoVarMultiplo) {
        const variaveis = declaracaoVarMultiplo.simbolos.map((s) => s.lexema).join(', ');
        let resultado = 'let ';
        resultado += variaveis;
        resultado += this.resolveTipoDeclaracaoVarEContante(declaracaoVarMultiplo.tipo);
        if (!(declaracaoVarMultiplo === null || declaracaoVarMultiplo === void 0 ? void 0 : declaracaoVarMultiplo.inicializador))
            resultado += ';';
        else {
            resultado += ' = ';
            if (this.dicionarioConstrutos[declaracaoVarMultiplo.inicializador.constructor.name]) {
                resultado += this.dicionarioConstrutos[declaracaoVarMultiplo.inicializador.constructor.name](declaracaoVarMultiplo.inicializador);
            }
            else {
                resultado += this.dicionarioDeclaracoes[declaracaoVarMultiplo.inicializador.constructor.name](declaracaoVarMultiplo.inicializador);
            }
            resultado += ';';
        }
        return resultado;
    }
    traduzirDeclaracaoConstMultiplo(declaracaoConstMultiplo) {
        const constantes = declaracaoConstMultiplo.simbolos.map((s) => s.lexema).join(', ');
        let resultado = 'const ';
        resultado += constantes;
        resultado += this.resolveTipoDeclaracaoVarEContante(declaracaoConstMultiplo.tipo);
        if (!(declaracaoConstMultiplo === null || declaracaoConstMultiplo === void 0 ? void 0 : declaracaoConstMultiplo.inicializador))
            resultado += ';';
        else {
            resultado += ' = ';
            if (this.dicionarioConstrutos[declaracaoConstMultiplo.inicializador.constructor.name]) {
                resultado += this.dicionarioConstrutos[declaracaoConstMultiplo.inicializador.constructor.name](declaracaoConstMultiplo.inicializador);
            }
            else {
                resultado += this.dicionarioDeclaracoes[declaracaoConstMultiplo.inicializador.constructor.name](declaracaoConstMultiplo.inicializador);
            }
            resultado += ';';
        }
        return resultado;
    }
    traduzirDeclaracaoEscrevaMesmaLinha(declaracaoEscrevaMesmaLinha) {
        let resultado = 'trace(';
        for (const argumento of declaracaoEscrevaMesmaLinha.argumentos) {
            const valor = this.dicionarioConstrutos[argumento.constructor.name](argumento);
            resultado += valor + ', ';
        }
        resultado = resultado.slice(0, -2);
        resultado += ')';
        return resultado;
    }
    traduzirDeclaracaoTendoComo(declaracaoTendoComo) {
        // TendoComo is a resource management pattern (like try-with-resources in Java)
        // AssemblyScript doesn't have built-in support, so we'll just treat it as a scope
        let resultado = `// tendo ${declaracaoTendoComo.simboloVariavel.lexema} como recurso\n`;
        resultado += ' '.repeat(this.indentacao);
        resultado += `let ${declaracaoTendoComo.simboloVariavel.lexema} = `;
        if (this.dicionarioConstrutos[declaracaoTendoComo.inicializacaoVariavel.constructor.name]) {
            resultado += this.dicionarioConstrutos[declaracaoTendoComo.inicializacaoVariavel.constructor.name](declaracaoTendoComo.inicializacaoVariavel);
        }
        else {
            resultado += this.dicionarioDeclaracoes[declaracaoTendoComo.inicializacaoVariavel.constructor.name](declaracaoTendoComo.inicializacaoVariavel);
        }
        resultado += ';\n';
        resultado += ' '.repeat(this.indentacao);
        resultado += this.dicionarioDeclaracoes[declaracaoTendoComo.corpo.constructor.name](declaracaoTendoComo.corpo);
        return resultado;
    }
    traduzirDeclaracaoAjuda(declaracaoAjuda) {
        // Ajuda is a help/documentation statement
        // In AssemblyScript, we'll just comment it out
        return '// ajuda' + '\n';
    }
    traduzirDeclaracaoTextoDocumentacao(declaracaoTextoDoc) {
        // TextoDocumentacao is documentation text
        // We'll convert it to a comment
        return `/** ${declaracaoTextoDoc} */\n`;
    }
    logicaComumBlocoEscopo(declaracoes) {
        let resultado = '{\n';
        this.indentacao += 4;
        if (typeof declaracoes[Symbol.iterator] === 'function') {
            for (const declaracaoOuConstruto of declaracoes) {
                resultado += ' '.repeat(this.indentacao);
                const nomeConstrutor = declaracaoOuConstruto.constructor.name;
                if (this.dicionarioConstrutos.hasOwnProperty(nomeConstrutor)) {
                    resultado += this.dicionarioConstrutos[nomeConstrutor](declaracaoOuConstruto);
                }
                else {
                    resultado += this.dicionarioDeclaracoes[nomeConstrutor](declaracaoOuConstruto);
                }
                resultado += '\n';
            }
        }
        this.indentacao -= 4;
        resultado += ' '.repeat(this.indentacao) + '}\n';
        return resultado;
    }
    logicaTraducaoMetodoClasse(metodoClasse) {
        this.indentacao += 4;
        let resultado = ' '.repeat(this.indentacao);
        resultado +=
            metodoClasse.simbolo.lexema === 'construtor'
                ? 'constructor('
                : metodoClasse.simbolo.lexema + '(';
        for (let parametro of metodoClasse.funcao.parametros) {
            resultado += parametro.nome.lexema + ', ';
        }
        if (metodoClasse.funcao.parametros.length > 0) {
            resultado = resultado.slice(0, -2);
        }
        resultado += ') ';
        resultado += this.logicaComumBlocoEscopo(metodoClasse.funcao.corpo);
        resultado += ' '.repeat(this.indentacao) + '\n';
        this.indentacao -= 4;
        return resultado;
    }
    traduzirDeclaracaoClasse(declaracaoClasse) {
        let resultado = 'export class ';
        if (declaracaoClasse.superClasse)
            resultado += `${declaracaoClasse.simbolo.lexema} extends ${declaracaoClasse.superClasse.simbolo.lexema} {\n`;
        else
            resultado += declaracaoClasse.simbolo.lexema + ' {\n';
        for (let metodo of declaracaoClasse.metodos) {
            resultado += this.logicaTraducaoMetodoClasse(metodo);
        }
        resultado += '}';
        return resultado;
    }
    traduzirDeclaracaoSe(declaracaoSe) {
        let resultado = 'if (';
        const condicao = this.dicionarioConstrutos[declaracaoSe.condicao.constructor.name](declaracaoSe.condicao);
        resultado += condicao;
        resultado += ')';
        resultado += this.dicionarioDeclaracoes[declaracaoSe.caminhoEntao.constructor.name](declaracaoSe.caminhoEntao);
        if (declaracaoSe.caminhoSenao !== null) {
            resultado += ' '.repeat(this.indentacao);
            resultado += 'else ';
            const se = declaracaoSe === null || declaracaoSe === void 0 ? void 0 : declaracaoSe.caminhoSenao;
            if (se === null || se === void 0 ? void 0 : se.caminhoEntao) {
                resultado += 'if (';
                resultado += this.dicionarioConstrutos[se.condicao.constructor.name](se.condicao);
                resultado += ')';
                resultado += this.dicionarioDeclaracoes[se.caminhoEntao.constructor.name](se.caminhoEntao);
                resultado += ' '.repeat(this.indentacao);
                if (se === null || se === void 0 ? void 0 : se.caminhoSenao) {
                    resultado += 'else ';
                    resultado += this.dicionarioDeclaracoes[se.caminhoSenao.constructor.name](se.caminhoSenao);
                    return resultado;
                }
            }
            resultado += this.dicionarioDeclaracoes[declaracaoSe.caminhoSenao.constructor.name](declaracaoSe.caminhoSenao);
        }
        return resultado;
    }
    traduzirDeclaracaoRetorna(declaracaoRetorna) {
        let resultado = 'return ';
        const nomeConstrutor = declaracaoRetorna.valor.constructor.name;
        return (resultado += this.dicionarioConstrutos[nomeConstrutor](declaracaoRetorna === null || declaracaoRetorna === void 0 ? void 0 : declaracaoRetorna.valor));
    }
    traduzirDeclaracaoParaCada(declaracaoParaCada) {
        // AssemblyScript não suporta for...of. Convertendo para loop baseado em índice.
        if (declaracaoParaCada.variavelIteracao.constructor.name !== 'Variavel') {
            throw new Error('Desestruturação em paraCada não é suportada no AssemblyScript. Use uma variável simples.');
        }
        const nomeVariavel = declaracaoParaCada.variavelIteracao.simbolo.lexema;
        const nomeVetor = `__arr_${nomeVariavel}`;
        let resultado = `const ${nomeVetor} = `;
        resultado +=
            this.dicionarioConstrutos[declaracaoParaCada.vetorOuDicionario.constructor.name](declaracaoParaCada.vetorOuDicionario) + ';';
        resultado += '\n';
        resultado += ' '.repeat(this.indentacao);
        resultado += `for (let __i_${nomeVariavel} = 0; __i_${nomeVariavel} < ${nomeVetor}.length; __i_${nomeVariavel}++) `;
        // Injeta a atribuição da variável de iteração no início do corpo do bloco
        const corpoBloco = declaracaoParaCada.corpo;
        const declaracoesCorpo = corpoBloco.declaracoes || [];
        let resultadoCorpo = '{\n';
        this.indentacao += 4;
        resultadoCorpo +=
            ' '.repeat(this.indentacao) +
                `const ${nomeVariavel} = ${nomeVetor}[__i_${nomeVariavel}];\n`;
        for (const declaracaoOuConstruto of declaracoesCorpo) {
            resultadoCorpo += ' '.repeat(this.indentacao);
            const nomeConstrutor = declaracaoOuConstruto.constructor.name;
            if (this.dicionarioConstrutos.hasOwnProperty(nomeConstrutor)) {
                resultadoCorpo += this.dicionarioConstrutos[nomeConstrutor](declaracaoOuConstruto);
            }
            else {
                resultadoCorpo += this.dicionarioDeclaracoes[nomeConstrutor](declaracaoOuConstruto);
            }
            resultadoCorpo += '\n';
        }
        this.indentacao -= 4;
        resultadoCorpo += ' '.repeat(this.indentacao) + '}\n';
        resultado += resultadoCorpo;
        return resultado;
    }
    traduzirDeclaracaoPara(declaracaoPara) {
        let resultado = 'for (';
        if (declaracaoPara.inicializador.constructor.name === 'Array') {
            resultado +=
                this.dicionarioDeclaracoes[declaracaoPara.inicializador[0].constructor.name](declaracaoPara.inicializador[0]) + ' ';
        }
        else {
            resultado +=
                this.dicionarioDeclaracoes[declaracaoPara.inicializador.constructor.name](declaracaoPara.inicializador) + ' ';
        }
        resultado += !resultado.includes(';') ? ';' : '';
        resultado +=
            this.dicionarioConstrutos[declaracaoPara.condicao.constructor.name](declaracaoPara.condicao) + '; ';
        resultado +=
            this.dicionarioConstrutos[declaracaoPara.incrementar.constructor.name](declaracaoPara.incrementar) + ') ';
        resultado += this.dicionarioDeclaracoes[declaracaoPara.corpo.constructor.name](declaracaoPara.corpo);
        return resultado;
    }
    traduzirDeclaracaoImportar(declaracaoImportar) {
        return `'importar() não é suportado por este padrão de JavaScript'`;
    }
    traduzirDeclaracaoLeia(declaracaoLeia) {
        return `'leia() não é suportado por este padrão de JavaScript.'`;
    }
    traduzirDeclaracaoFuncao(declaracaoFuncao) {
        let resultado = 'function ';
        resultado += declaracaoFuncao.simbolo.lexema + '(';
        // Adiciona parâmetros com tipos
        for (const parametro of declaracaoFuncao.funcao.parametros) {
            resultado += parametro.nome.lexema;
            // Adiciona tipo do parâmetro se disponível
            if (parametro.tipoDado) {
                try {
                    resultado += this.resolveTipoDeclaracaoVarEContante(parametro.tipoDado);
                }
                catch (e) {
                    // Se não conseguir resolver o tipo, lança erro mais específico
                    throw new Error(`Parâmetro '${parametro.nome.lexema}' da função '${declaracaoFuncao.simbolo.lexema}' tem tipo não suportado: '${parametro.tipoDado}'`);
                }
            }
            else {
                // AssemblyScript requer tipos explícitos em todos os parâmetros
                throw new Error(`Parâmetro '${parametro.nome.lexema}' da função '${declaracaoFuncao.simbolo.lexema}' não tem tipo definido. AssemblyScript requer tipos explícitos.`);
            }
            resultado += ', ';
        }
        if (declaracaoFuncao.funcao.parametros.length > 0) {
            resultado = resultado.slice(0, -2);
        }
        resultado += ')';
        // Adiciona tipo de retorno
        const tipoRetorno = this.inferirTipoRetornoFuncao(declaracaoFuncao.funcao);
        resultado += tipoRetorno;
        resultado += ' ';
        resultado += this.logicaComumBlocoEscopo(declaracaoFuncao.funcao.corpo);
        return resultado;
    }
    inferirTipoRetornoFuncao(funcao) {
        // Se a função tem tipo de retorno explícito, usa ele
        if (funcao.tipo && funcao.tipo !== 'qualquer') {
            try {
                return this.resolveTipoDeclaracaoVarEContante(funcao.tipo);
            }
            catch (e) {
                // Se não conseguir resolver, retorna void por padrão
                return ': void';
            }
        }
        // Procura por declarações de retorno no corpo e infere tipo a partir delas
        const tipoInferido = this.inferirTipoDeRetorno(funcao.corpo);
        if (tipoInferido) {
            try {
                return this.resolveTipoDeclaracaoVarEContante(tipoInferido);
            }
            catch (e) {
                return ': void';
            }
        }
        return ': void';
    }
    inferirTipoDeRetorno(corpo) {
        if (!corpo)
            return null;
        for (const declaracao of corpo) {
            if (declaracao.constructor.name === 'Retorna') {
                const retorna = declaracao;
                if (retorna.tipo && retorna.tipo !== 'vazio') {
                    return retorna.tipo;
                }
            }
            // Verifica recursivamente em blocos aninhados
            if (declaracao.corpo) {
                const corpoInterno = declaracao.corpo;
                if (Array.isArray(corpoInterno)) {
                    const tipo = this.inferirTipoDeRetorno(corpoInterno);
                    if (tipo)
                        return tipo;
                }
                else if (corpoInterno.declaracoes) {
                    const tipo = this.inferirTipoDeRetorno(corpoInterno.declaracoes);
                    if (tipo)
                        return tipo;
                }
            }
        }
        return null;
    }
    traduzirDeclaracaoFalhar(falhar) {
        return `abort('${falhar.explicacao.valor}')`;
    }
    traduzirDeclaracaoFazer(declaracaoFazer) {
        let resultado = 'do ';
        resultado += this.dicionarioDeclaracoes[declaracaoFazer.caminhoFazer.constructor.name](declaracaoFazer.caminhoFazer);
        resultado +=
            'while (' +
                this.dicionarioConstrutos[declaracaoFazer.condicaoEnquanto.constructor.name](declaracaoFazer.condicaoEnquanto) +
                ') ';
        return resultado;
    }
    traduzirDeclaracaoExpressao(declaracaoExpressao) {
        return this.dicionarioConstrutos[declaracaoExpressao.expressao.constructor.name](declaracaoExpressao.expressao);
    }
    logicaComumCaminhosEscolha(caminho) {
        let resultado = '';
        this.indentacao += 4;
        resultado += ' '.repeat(this.indentacao);
        for (let condicao of caminho.condicoes) {
            resultado +=
                'case ' + this.dicionarioConstrutos[condicao.constructor.name](condicao) + ':\n';
            resultado += ' '.repeat(this.indentacao);
        }
        for (let declaracao of caminho.declaracoes) {
            resultado += ' '.repeat(this.indentacao + 4);
            switch (declaracao.constructor.name) {
                case 'Retorna':
                    const declaracaoRetorna = declaracao;
                    resultado +=
                        'return ' +
                            this.dicionarioConstrutos[declaracaoRetorna.valor.constructor.name](declaracaoRetorna.valor);
                    break;
                default:
                    resultado +=
                        this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao) + '\n';
                    break;
            }
            resultado += ' '.repeat(this.indentacao + 4);
            resultado += 'break' + '\n';
        }
        this.indentacao -= 4;
        return resultado;
    }
    traduzirDeclaracaoEscolha(declaracaoEscolha) {
        let resultado = 'switch (';
        resultado +=
            this.dicionarioConstrutos[declaracaoEscolha.identificadorOuLiteral.constructor.name](declaracaoEscolha.identificadorOuLiteral) + ') {\n';
        for (let caminho of declaracaoEscolha.caminhos) {
            resultado += this.logicaComumCaminhosEscolha(caminho);
        }
        if (declaracaoEscolha.caminhoPadrao) {
            resultado += ' '.repeat(4);
            resultado += 'default:\n';
            resultado += this.logicaComumCaminhosEscolha(declaracaoEscolha.caminhoPadrao);
        }
        resultado += '}\n';
        return resultado;
    }
    traduzirDeclaracaoEnquanto(declaracaoEnquanto) {
        let resultado = 'while (';
        resultado +=
            this.dicionarioConstrutos[declaracaoEnquanto.condicao.constructor.name](declaracaoEnquanto.condicao) + ') ';
        resultado += this.dicionarioDeclaracoes[declaracaoEnquanto.corpo.constructor.name](declaracaoEnquanto.corpo);
        return resultado;
    }
    traduzirDeclaracaoBloco(declaracaoBloco) {
        return this.logicaComumBlocoEscopo(declaracaoBloco.declaracoes);
    }
    traduzirConstrutoVetor(vetor) {
        if (!vetor.valores.length) {
            return '[]';
        }
        let resultado = '[';
        for (let valor of vetor.valores) {
            resultado += `${this.dicionarioConstrutos[valor.constructor.name](valor)}`;
        }
        resultado += ']';
        return resultado;
    }
    traduzirConstrutoDicionario(dicionario) {
        // AssemblyScript Maps são inicializados via construtor
        // Map<K, V>() requer: new Map<string, ValueType>()
        if (!dicionario.chaves.length) {
            return 'new Map<string, i32>()';
        }
        // AssemblyScript não suporta literal syntax para Map, precisa usar constructor
        // Gerar algo como: { let m = new Map<string, i32>(); m.set("key", value); ... return m; }
        let resultado = '(() => { let m = new Map<string, i32>(); ';
        for (let i = 0; i < dicionario.chaves.length; i++) {
            const chave = dicionario.chaves[i];
            const valor = dicionario.valores[i];
            // A chave pode ser um Construto (como Literal) ou um valor simples
            let chaveStr;
            if (typeof chave === 'string') {
                chaveStr = `"${chave}"`;
            }
            else if (chave &&
                chave.constructor &&
                this.dicionarioConstrutos[chave.constructor.name]) {
                // Se for um Construto, traduzi-lo
                chaveStr = this.dicionarioConstrutos[chave.constructor.name](chave);
            }
            else {
                // Fallback: converter para string
                chaveStr = `"${String(chave)}"`;
            }
            resultado += `m.set(${chaveStr}, ${this.dicionarioConstrutos[valor.constructor.name](valor)}); `;
        }
        resultado += 'return m; })()';
        return resultado;
    }
    traduzirConstrutoDupla(dupla) {
        const primeiro = this.dicionarioConstrutos[dupla.primeiro.constructor.name](dupla.primeiro);
        const segundo = this.dicionarioConstrutos[dupla.segundo.constructor.name](dupla.segundo);
        return `[${primeiro}, ${segundo}]`;
    }
    traduzirConstrutoTrio(trio) {
        const primeiro = this.dicionarioConstrutos[trio.primeiro.constructor.name](trio.primeiro);
        const segundo = this.dicionarioConstrutos[trio.segundo.constructor.name](trio.segundo);
        const terceiro = this.dicionarioConstrutos[trio.terceiro.constructor.name](trio.terceiro);
        return `[${primeiro}, ${segundo}, ${terceiro}]`;
    }
    traduzirConstrutoQuarteto(quarteto) {
        const primeiro = this.dicionarioConstrutos[quarteto.primeiro.constructor.name](quarteto.primeiro);
        const segundo = this.dicionarioConstrutos[quarteto.segundo.constructor.name](quarteto.segundo);
        const terceiro = this.dicionarioConstrutos[quarteto.terceiro.constructor.name](quarteto.terceiro);
        const quarto = this.dicionarioConstrutos[quarteto.quarto.constructor.name](quarteto.quarto);
        return `[${primeiro}, ${segundo}, ${terceiro}, ${quarto}]`;
    }
    traduzirConstrutoQuinteto(quinteto) {
        const primeiro = this.dicionarioConstrutos[quinteto.primeiro.constructor.name](quinteto.primeiro);
        const segundo = this.dicionarioConstrutos[quinteto.segundo.constructor.name](quinteto.segundo);
        const terceiro = this.dicionarioConstrutos[quinteto.terceiro.constructor.name](quinteto.terceiro);
        const quarto = this.dicionarioConstrutos[quinteto.quarto.constructor.name](quinteto.quarto);
        const quinto = this.dicionarioConstrutos[quinteto.quinto.constructor.name](quinteto.quinto);
        return `[${primeiro}, ${segundo}, ${terceiro}, ${quarto}, ${quinto}]`;
    }
    traduzirConstrutoSexteto(sexteto) {
        const primeiro = this.dicionarioConstrutos[sexteto.primeiro.constructor.name](sexteto.primeiro);
        const segundo = this.dicionarioConstrutos[sexteto.segundo.constructor.name](sexteto.segundo);
        const terceiro = this.dicionarioConstrutos[sexteto.terceiro.constructor.name](sexteto.terceiro);
        const quarto = this.dicionarioConstrutos[sexteto.quarto.constructor.name](sexteto.quarto);
        const quinto = this.dicionarioConstrutos[sexteto.quinto.constructor.name](sexteto.quinto);
        const sexto = this.dicionarioConstrutos[sexteto.sexto.constructor.name](sexteto.sexto);
        return `[${primeiro}, ${segundo}, ${terceiro}, ${quarto}, ${quinto}, ${sexto}]`;
    }
    traduzirConstrutoSepteto(septeto) {
        const primeiro = this.dicionarioConstrutos[septeto.primeiro.constructor.name](septeto.primeiro);
        const segundo = this.dicionarioConstrutos[septeto.segundo.constructor.name](septeto.segundo);
        const terceiro = this.dicionarioConstrutos[septeto.terceiro.constructor.name](septeto.terceiro);
        const quarto = this.dicionarioConstrutos[septeto.quarto.constructor.name](septeto.quarto);
        const quinto = this.dicionarioConstrutos[septeto.quinto.constructor.name](septeto.quinto);
        const sexto = this.dicionarioConstrutos[septeto.sexto.constructor.name](septeto.sexto);
        const setimo = this.dicionarioConstrutos[septeto.setimo.constructor.name](septeto.setimo);
        return `[${primeiro}, ${segundo}, ${terceiro}, ${quarto}, ${quinto}, ${sexto}, ${setimo}]`;
    }
    traduzirConstrutoOcteto(octeto) {
        const primeiro = this.dicionarioConstrutos[octeto.primeiro.constructor.name](octeto.primeiro);
        const segundo = this.dicionarioConstrutos[octeto.segundo.constructor.name](octeto.segundo);
        const terceiro = this.dicionarioConstrutos[octeto.terceiro.constructor.name](octeto.terceiro);
        const quarto = this.dicionarioConstrutos[octeto.quarto.constructor.name](octeto.quarto);
        const quinto = this.dicionarioConstrutos[octeto.quinto.constructor.name](octeto.quinto);
        const sexto = this.dicionarioConstrutos[octeto.sexto.constructor.name](octeto.sexto);
        const setimo = this.dicionarioConstrutos[octeto.setimo.constructor.name](octeto.setimo);
        const oitavo = this.dicionarioConstrutos[octeto.oitavo.constructor.name](octeto.oitavo);
        return `[${primeiro}, ${segundo}, ${terceiro}, ${quarto}, ${quinto}, ${sexto}, ${setimo}, ${oitavo}]`;
    }
    traduzirConstrutoNoneto(noneto) {
        const primeiro = this.dicionarioConstrutos[noneto.primeiro.constructor.name](noneto.primeiro);
        const segundo = this.dicionarioConstrutos[noneto.segundo.constructor.name](noneto.segundo);
        const terceiro = this.dicionarioConstrutos[noneto.terceiro.constructor.name](noneto.terceiro);
        const quarto = this.dicionarioConstrutos[noneto.quarto.constructor.name](noneto.quarto);
        const quinto = this.dicionarioConstrutos[noneto.quinto.constructor.name](noneto.quinto);
        const sexto = this.dicionarioConstrutos[noneto.sexto.constructor.name](noneto.sexto);
        const setimo = this.dicionarioConstrutos[noneto.setimo.constructor.name](noneto.setimo);
        const oitavo = this.dicionarioConstrutos[noneto.oitavo.constructor.name](noneto.oitavo);
        const nono = this.dicionarioConstrutos[noneto.nono.constructor.name](noneto.nono);
        return `[${primeiro}, ${segundo}, ${terceiro}, ${quarto}, ${quinto}, ${sexto}, ${setimo}, ${oitavo}, ${nono}]`;
    }
    traduzirConstrutoDeceto(deceto) {
        const primeiro = this.dicionarioConstrutos[deceto.primeiro.constructor.name](deceto.primeiro);
        const segundo = this.dicionarioConstrutos[deceto.segundo.constructor.name](deceto.segundo);
        const terceiro = this.dicionarioConstrutos[deceto.terceiro.constructor.name](deceto.terceiro);
        const quarto = this.dicionarioConstrutos[deceto.quarto.constructor.name](deceto.quarto);
        const quinto = this.dicionarioConstrutos[deceto.quinto.constructor.name](deceto.quinto);
        const sexto = this.dicionarioConstrutos[deceto.sexto.constructor.name](deceto.sexto);
        const setimo = this.dicionarioConstrutos[deceto.setimo.constructor.name](deceto.setimo);
        const oitavo = this.dicionarioConstrutos[deceto.oitavo.constructor.name](deceto.oitavo);
        const nono = this.dicionarioConstrutos[deceto.nono.constructor.name](deceto.nono);
        const decimo = this.dicionarioConstrutos[deceto.decimo.constructor.name](deceto.decimo);
        return `[${primeiro}, ${segundo}, ${terceiro}, ${quarto}, ${quinto}, ${sexto}, ${setimo}, ${oitavo}, ${nono}, ${decimo}]`;
    }
    traduzirConstrutoTuplaN(tuplaN) {
        const elementos = tuplaN.elementos.map((elemento) => this.dicionarioConstrutos[elemento.constructor.name](elemento));
        return `[${elementos.join(', ')}]`;
    }
    traduzirConstrutoSeTernario(seTernario) {
        const condicao = this.dicionarioConstrutos[seTernario.condicao.constructor.name](seTernario.condicao);
        const expressaoSe = this.dicionarioConstrutos[seTernario.expressaoSe.constructor.name](seTernario.expressaoSe);
        const expressaoSenao = this.dicionarioConstrutos[seTernario.expressaoSenao.constructor.name](seTernario.expressaoSenao);
        return `${condicao} ? ${expressaoSe} : ${expressaoSenao}`;
    }
    traduzirConstrutoElvis(elvis) {
        const esquerda = this.dicionarioConstrutos[elvis.esquerda.constructor.name](elvis.esquerda);
        const direita = this.dicionarioConstrutos[elvis.direita.constructor.name](elvis.direita);
        // Elvis operator (?:) is equivalent to || in JavaScript for null-coalescing
        return `${esquerda} || ${direita}`;
    }
    traduzirConstrutoAcessoPropriedade(acessoPropriedade) {
        const objeto = this.dicionarioConstrutos[acessoPropriedade.objeto.constructor.name](acessoPropriedade.objeto);
        return `${objeto}.${acessoPropriedade.nomePropriedade}`;
    }
    traduzirConstrutoExpressaoRegular(expressaoRegular) {
        // AssemblyScript doesn't have native regex support like JavaScript
        // Return the pattern as a string for now
        const valor = expressaoRegular.valor;
        if (typeof valor === 'string') {
            return `"${valor}"`;
        }
        return String(valor);
    }
    traduzirConstrutoVariavel(variavel) {
        return variavel.simbolo.lexema;
    }
    traduzirConstrutoUnario(unario) {
        var _a, _b;
        let resultado = '';
        if ([delegua_1.default.INCREMENTAR, delegua_1.default.DECREMENTAR].includes(unario.operador.tipo)) {
            resultado += (_a = unario.operando.valor) !== null && _a !== void 0 ? _a : unario.operando.simbolo.lexema;
            resultado += unario.operador.tipo === delegua_1.default.INCREMENTAR ? '++' : '--';
        }
        else {
            resultado += this.traduzirSimboloOperador(unario.operador);
            resultado += (_b = unario.operando.valor) !== null && _b !== void 0 ? _b : unario.operando.simbolo.lexema;
        }
        return resultado;
    }
    traduzirConstrutoTipoDe(tipoDe) {
        throw new Error('O operador typeof não é suportado no AssemblyScript. Use verificações de tipo em tempo de compilação como instanceof ou is<T>() em vez disso.');
    }
    traduzirConstrutoLogico(logico) {
        let esquerda = this.dicionarioConstrutos[logico.esquerda.constructor.name](logico.esquerda);
        let operador = this.traduzirSimboloOperador(logico.operador);
        let direita = this.dicionarioConstrutos[logico.direita.constructor.name](logico.direita);
        return `${esquerda} ${operador} ${direita}`;
    }
    traduzirFuncaoConstruto(funcaoConstruto) {
        let resultado = 'function(';
        for (const parametro of funcaoConstruto.parametros) {
            const tipoParametro = this.resolveTipoDeclaracaoVarEContante(parametro.tipoDado);
            resultado += `${parametro.nome.lexema}${tipoParametro}, `;
        }
        if (funcaoConstruto.parametros.length > 0) {
            resultado = resultado.slice(0, -2);
        }
        resultado += ') ';
        resultado += this.logicaComumBlocoEscopo(funcaoConstruto.corpo);
        return resultado;
    }
    traduzirConstrutoDefinirValor(definirValor) {
        let resultado = '';
        if (definirValor.objeto instanceof construtos_1.Isto) {
            resultado = 'this.' + definirValor.nome.lexema + ' = ';
        }
        resultado += definirValor.valor.simbolo.lexema;
        return resultado;
    }
    traduzirConstrutoChamada(chamada) {
        let resultado = '';
        // Check if this is a native library function call
        if (chamada.entidadeChamada instanceof construtos_1.Variavel) {
            const nomeVariavel = chamada.entidadeChamada.simbolo.lexema;
            const argumentosTexto = chamada.argumentos.map((arg) => this.dicionarioConstrutos[arg.constructor.name](arg));
            const funcaoNativa = this.traduzirFuncaoNativaGlobal(nomeVariavel, argumentosTexto);
            if (funcaoNativa) {
                return funcaoNativa;
            }
        }
        const retorno = `${this.dicionarioConstrutos[chamada.entidadeChamada.constructor.name](chamada.entidadeChamada, chamada.argumentos)}`;
        const instanciaClasse = this.declaracoesDeClasses.some((declaracao) => { var _a; return ((_a = declaracao === null || declaracao === void 0 ? void 0 : declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) === retorno; });
        if (instanciaClasse) {
            const classe = this.declaracoesDeClasses.find((declaracao) => { var _a; return ((_a = declaracao === null || declaracao === void 0 ? void 0 : declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) === retorno; });
            if (classe.simbolo.lexema === retorno)
                resultado += `new ${retorno}`;
        }
        else {
            resultado += retorno;
        }
        resultado += '(';
        for (let parametro of chamada.argumentos) {
            resultado += this.dicionarioConstrutos[parametro.constructor.name](parametro) + ', ';
        }
        if (chamada.argumentos.length > 0) {
            resultado = resultado.slice(0, -2);
        }
        resultado += ')';
        return resultado;
    }
    traduzirConstrutoComentario(comentario) {
        let resultado = '';
        if (comentario.multilinha) {
            resultado += `/*`;
            for (let linhaComentario of comentario.conteudo) {
                resultado += `${linhaComentario}\n`;
            }
            resultado += `*/`;
        }
        else {
            resultado += `// ${comentario.conteudo}`;
        }
        return resultado;
    }
    traduzirConstrutoBinario(binario) {
        // Tratamento especial para exponenciação no AssemblyScript
        if (binario.operador.tipo === delegua_1.default.EXPONENCIACAO) {
            const esquerda = this.dicionarioConstrutos[binario.esquerda.constructor.name](binario.esquerda);
            const direita = this.dicionarioConstrutos[binario.direita.constructor.name](binario.direita);
            return `Math.pow(${esquerda}, ${direita})`;
        }
        let resultado = '';
        if (binario.esquerda.constructor.name === 'Agrupamento')
            resultado +=
                '(' +
                    this.dicionarioConstrutos[binario.esquerda.constructor.name](binario.esquerda) +
                    ')';
        else
            resultado += this.dicionarioConstrutos[binario.esquerda.constructor.name](binario.esquerda);
        let operador = this.traduzirSimboloOperador(binario.operador);
        resultado += ` ${operador} `;
        if (binario.direita.constructor.name === 'Agrupamento')
            resultado +=
                '(' +
                    this.dicionarioConstrutos[binario.direita.constructor.name](binario.direita) +
                    ')';
        else
            resultado += this.dicionarioConstrutos[binario.direita.constructor.name](binario.direita);
        return resultado;
    }
    traduzirConstrutoAtribuir(atribuir) {
        let resultado = this.dicionarioConstrutos[atribuir.alvo.constructor.name](atribuir.alvo);
        resultado +=
            ' = ' + this.dicionarioConstrutos[atribuir.valor.constructor.name](atribuir.valor);
        return resultado;
    }
    traduzirConstrutoAtribuicaoPorIndice(AtribuicaoPorIndice) {
        let resultado = '';
        // Traduz o objeto (array ou coleção)
        if (AtribuicaoPorIndice.objeto instanceof construtos_1.Variavel) {
            resultado += AtribuicaoPorIndice.objeto.simbolo.lexema;
        }
        else {
            resultado += this.dicionarioConstrutos[AtribuicaoPorIndice.objeto.constructor.name](AtribuicaoPorIndice.objeto);
        }
        // Adiciona o índice
        resultado += '[';
        resultado +=
            this.dicionarioConstrutos[AtribuicaoPorIndice.indice.constructor.name](AtribuicaoPorIndice.indice) + ']';
        resultado += ' = ';
        // Traduz o valor a ser atribuído
        if (AtribuicaoPorIndice.valor instanceof construtos_1.Variavel) {
            resultado += AtribuicaoPorIndice.valor.simbolo.lexema;
        }
        else {
            resultado += this.dicionarioConstrutos[AtribuicaoPorIndice.valor.constructor.name](AtribuicaoPorIndice.valor);
        }
        return resultado;
    }
    traduzirConstrutoAcessoMetodo(acessoMetodo) {
        if (acessoMetodo.objeto instanceof construtos_1.Variavel) {
            let objetoVariavel = acessoMetodo.objeto;
            return `${objetoVariavel.simbolo.lexema}.${this.traduzirFuncoesNativas(acessoMetodo.simbolo.lexema)}`;
        }
        return `this.${acessoMetodo.simbolo.lexema}`;
    }
    traduzirConstrutoAcessoIndiceVariavel(acessoIndiceVariavel) {
        let resultado = '';
        resultado += this.dicionarioConstrutos[acessoIndiceVariavel.entidadeChamada.constructor.name](acessoIndiceVariavel.entidadeChamada);
        resultado += `[${this.dicionarioConstrutos[acessoIndiceVariavel.indice.constructor.name](acessoIndiceVariavel.indice)}]`;
        return resultado;
    }
    traduzirConstrutoAgrupamento(agrupamento) {
        return this.dicionarioConstrutos[agrupamento.constructor.name](agrupamento.expressao || agrupamento);
    }
    traduzir(declaracoes) {
        let resultado = '';
        this.declaracoesDeClasses = declaracoes.filter((declaracao) => declaracao instanceof declaracoes_1.Classe);
        for (const declaracao of declaracoes) {
            resultado += `${this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao)} \n`;
        }
        return resultado;
    }
}
exports.TradutorAssemblyScript = TradutorAssemblyScript;
//# sourceMappingURL=tradutor-assemblyscript.js.map