"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TradutorAssemblyARM = void 0;
const construtos_1 = require("../construtos");
const declaracoes_1 = require("../declaracoes");
class TradutorAssemblyARM {
    constructor(alvo = 'linux-arm') {
        this.alvo = alvo;
        this.indentacao = 0;
        this.contadorLabels = 0;
        this.variaveis = new Map();
        this.registradoresDisponiveis = ['r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'];
        this.pilhaRegistradores = [];
        this.bss = '.bss\n';
        this.data = '.data\n';
        this.dicionarioConstrutos = {
            AcessoIndiceVariavel: this.traduzirAcessoIndiceVariavel.bind(this),
            AcessoMetodoOuPropriedade: this.trazudirConstrutoAcessoMetodo.bind(this),
            Agrupamento: this.traduzirConstrutoAgrupamento.bind(this),
            AtribuicaoPorIndice: this.traduzirConstrutoAtribuicaoPorIndice.bind(this),
            Atribuir: this.traduzirConstrutoAtribuir.bind(this),
            Binario: this.traduzirConstrutoBinario.bind(this),
            Chamada: this.traduzirConstrutoChamada.bind(this),
            DefinirValor: this.traduzirConstrutoDefinirValor.bind(this),
            FuncaoConstruto: this.traduzirFuncaoConstruto.bind(this),
            Isto: () => 'this',
            Literal: this.traduzirConstrutoLiteral.bind(this),
            Logico: this.traduzirConstrutoLogico.bind(this),
            TipoDe: this.traduzirConstrutoTipoDe.bind(this),
            Unario: this.traduzirConstrutoUnario.bind(this),
            Variavel: this.traduzirConstrutoVariavel.bind(this),
            Vetor: this.traduzirConstrutoVetor.bind(this),
        };
        this.dicionarioDeclaracoes = {
            Bloco: this.traduzirDeclaracaoBloco.bind(this),
            Enquanto: this.traduzirDeclaracaoEnquanto.bind(this),
            Continua: () => 'b .continue_label',
            Escolha: this.traduzirDeclaracaoEscolha.bind(this),
            Escreva: this.traduzirDeclaracaoEscreva.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: () => 'b .break_label',
            Classe: this.traduzirDeclaracaoClasse.bind(this),
            Tente: this.traduzirDeclaracaoTente.bind(this),
            Const: this.traduzirDeclaracaoConst.bind(this),
            Var: this.traduzirDeclaracaoVar.bind(this),
        };
        this.indentacao = 0;
        // Seleciona o símbolo de entrada conforme a plataforma alvo.
        // Para linux-arm: programa standalone com _start.
        // Para android: ainda é um binário standalone, mas com rótulo Delegua_main
        // para deixar claro que não é o _start do CRT padrão.
        const entryLabel = this.alvo === 'android' ? 'Delegua_main' : '_start';
        this.text = `
.text
.global ${entryLabel}

${entryLabel}:`;
    }
    gerarDigitoAleatorio() {
        let result = '';
        const digits = '0123456789';
        for (let i = 0; i < 5; i++) {
            const randomIndex = Math.floor(Math.random() * digits.length);
            result += digits.charAt(randomIndex);
        }
        return result;
    }
    gerarLabel() {
        return `.L${this.contadorLabels++}`;
    }
    obterRegistrador() {
        if (this.registradoresDisponiveis.length > 0) {
            const reg = this.registradoresDisponiveis.pop();
            this.pilhaRegistradores.push(reg);
            return reg;
        }
        return 'r0'; // fallback
    }
    liberarRegistrador(reg) {
        const index = this.pilhaRegistradores.indexOf(reg);
        if (index > -1) {
            this.pilhaRegistradores.splice(index, 1);
            this.registradoresDisponiveis.push(reg);
        }
    }
    // Implementação dos Construtos
    traduzirAcessoIndiceVariavel(construto) {
        var _a;
        let nomeVar;
        if (construto.entidadeChamada instanceof construtos_1.Variavel) {
            nomeVar = (_a = construto.entidadeChamada.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
        }
        if (!nomeVar) {
            nomeVar = 'unknown';
        }
        const indice = this.dicionarioConstrutos[construto.indice.constructor.name](construto.indice);
        const reg = this.obterRegistrador();
        this.text += `
    ldr ${reg}, =${nomeVar}
    ldr r0, =${indice}
    lsl r0, r0, #2          @ multiply index by 4 (word size)
    add ${reg}, ${reg}, r0
    ldr r0, [${reg}]`;
        this.liberarRegistrador(reg);
        return 'r0';
    }
    trazudirConstrutoAcessoMetodo(construto) {
        const objeto = this.dicionarioConstrutos[construto.objeto.constructor.name](construto.objeto);
        return `${objeto}_${construto.nomeMetodo}`;
    }
    traduzirConstrutoAgrupamento(construto) {
        return this.dicionarioConstrutos[construto.expressao.constructor.name](construto.expressao);
    }
    traduzirConstrutoAtribuicaoPorIndice(construto) {
        var _a;
        let nomeVar;
        if (construto.objeto instanceof construtos_1.Variavel) {
            nomeVar = (_a = construto.objeto.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
        }
        if (!nomeVar) {
            nomeVar = 'unknown';
        }
        const indice = this.dicionarioConstrutos[construto.indice.constructor.name](construto.indice);
        const valor = this.dicionarioConstrutos[construto.valor.constructor.name](construto.valor);
        const reg = this.obterRegistrador();
        this.text += `
    ldr ${reg}, =${nomeVar}
    ldr r1, =${indice}
    lsl r1, r1, #2          @ multiply by 4
    add ${reg}, ${reg}, r1
    ldr r1, =${valor}
    str r1, [${reg}]`;
        this.liberarRegistrador(reg);
    }
    traduzirConstrutoAtribuir(construto) {
        var _a;
        let nomeVar;
        if (construto.alvo instanceof construtos_1.Variavel) {
            nomeVar = (_a = construto.alvo.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
        }
        if (!nomeVar) {
            return;
        }
        const valor = this.dicionarioConstrutos[construto.valor.constructor.name](construto.valor);
        if (!this.variaveis.has(nomeVar)) {
            const varLabel = `var_${nomeVar}`;
            this.bss += `    ${varLabel}: .space 4\n`;
            this.variaveis.set(nomeVar, varLabel);
        }
        this.text += `
    ldr r0, =${valor}
    ldr r1, =${this.variaveis.get(nomeVar)}
    str r0, [r1]`;
    }
    traduzirConstrutoBinario(construto) {
        const esquerda = this.dicionarioConstrutos[construto.esquerda.constructor.name](construto.esquerda);
        const direita = this.dicionarioConstrutos[construto.direita.constructor.name](construto.direita);
        const operador = construto.operador.lexema;
        const reg = this.obterRegistrador();
        // Load left operand into r0
        if (esquerda !== 'r0') {
            this.text += `
    ldr r0, =${esquerda}`;
        }
        // Load right operand into reg
        this.text += `
    ldr ${reg}, =${direita}`;
        switch (operador) {
            case '+':
                this.text += `
    add r0, r0, ${reg}`;
                break;
            case '-':
                this.text += `
    sub r0, r0, ${reg}`;
                break;
            case '*':
                this.text += `
    mul r0, r0, ${reg}`;
                break;
            case '/':
                this.text += `
    sdiv r0, r0, ${reg}`;
                break;
            case '%':
                this.text += `
    sdiv r1, r0, ${reg}
    mul r1, r1, ${reg}
    sub r0, r0, r1          @ r0 = r0 - (r0/reg)*reg`;
                break;
            case '<':
                this.text += `
    cmp r0, ${reg}
    movlt r0, #1
    movge r0, #0`;
                break;
            case '>':
                this.text += `
    cmp r0, ${reg}
    movgt r0, #1
    movle r0, #0`;
                break;
            case '<=':
                this.text += `
    cmp r0, ${reg}
    movle r0, #1
    movgt r0, #0`;
                break;
            case '>=':
                this.text += `
    cmp r0, ${reg}
    movge r0, #1
    movlt r0, #0`;
                break;
            case '==':
            case '===':
                this.text += `
    cmp r0, ${reg}
    moveq r0, #1
    movne r0, #0`;
                break;
            case '!=':
            case '!==':
                this.text += `
    cmp r0, ${reg}
    movne r0, #1
    moveq r0, #0`;
                break;
            default:
                this.text += `
    @ Operador ${operador} não implementado`;
        }
        this.liberarRegistrador(reg);
        return 'r0';
    }
    traduzirConstrutoChamada(construto) {
        var _a;
        let nomeFuncao = 'funcao';
        if (construto.entidadeChamada instanceof construtos_1.Variavel) {
            nomeFuncao = ((_a = construto.entidadeChamada.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) || 'funcao';
        }
        // ARM calling convention: r0-r3 for first 4 args, rest on stack
        const registrosArgs = ['r0', 'r1', 'r2', 'r3'];
        construto.argumentos.forEach((arg, index) => {
            if (index < registrosArgs.length) {
                const valorArg = this.dicionarioConstrutos[arg.constructor.name](arg);
                if (valorArg !== registrosArgs[index]) {
                    this.text += `
    ldr ${registrosArgs[index]}, =${valorArg}`;
                }
            }
            else {
                // Push extra args on stack
                const valorArg = this.dicionarioConstrutos[arg.constructor.name](arg);
                this.text += `
    ldr r0, =${valorArg}
    push {r0}`;
            }
        });
        this.text += `
    bl ${nomeFuncao}`;
    }
    traduzirConstrutoDefinirValor(construto) {
        const objeto = this.dicionarioConstrutos[construto.objeto.constructor.name](construto.objeto);
        const valor = this.dicionarioConstrutos[construto.valor.constructor.name](construto.valor);
        this.text += `
    ldr r0, =${valor}
    ldr r1, =${objeto}
    str r0, [r1]`;
    }
    traduzirFuncaoConstruto(construto) {
        const labelFuncao = `func_${this.gerarDigitoAleatorio()}`;
        this.text += `

${labelFuncao}:
    push {fp, lr}
    mov fp, sp`;
        // Traduzir corpo da função
        if (construto.corpo && Array.isArray(construto.corpo)) {
            construto.corpo.forEach((declaracao) => {
                if (this.dicionarioDeclaracoes[declaracao.constructor.name]) {
                    this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao);
                }
            });
        }
        this.text += `
    mov sp, fp
    pop {fp, pc}`;
    }
    traduzirConstrutoLiteral(construto) {
        if (typeof construto.valor === 'string') {
            return this.criaStringLiteral(construto);
        }
        return String(construto.valor);
    }
    traduzirConstrutoLogico(construto) {
        const esquerda = this.dicionarioConstrutos[construto.esquerda.constructor.name](construto.esquerda);
        const direita = this.dicionarioConstrutos[construto.direita.constructor.name](construto.direita);
        const operador = construto.operador.lexema;
        const labelVerdadeiro = this.gerarLabel();
        const labelFim = this.gerarLabel();
        this.text += `
    ldr r0, =${esquerda}
    cmp r0, #0`;
        if (operador === 'e' || operador === '&&') {
            this.text += `
    beq ${labelFim}
    ldr r0, =${direita}
    cmp r0, #0
    beq ${labelFim}
${labelVerdadeiro}:
    mov r0, #1
${labelFim}:`;
        }
        else if (operador === 'ou' || operador === '||') {
            this.text += `
    bne ${labelVerdadeiro}
    ldr r0, =${direita}
    cmp r0, #0
    bne ${labelVerdadeiro}
    mov r0, #0
    b ${labelFim}
${labelVerdadeiro}:
    mov r0, #1
${labelFim}:`;
        }
        return 'r0';
    }
    traduzirConstrutoTipoDe(construto) {
        const expressao = this.dicionarioConstrutos[construto.valor.constructor.name](construto.valor);
        return expressao;
    }
    traduzirConstrutoUnario(construto) {
        const operando = this.dicionarioConstrutos[construto.operando.constructor.name](construto.operando);
        const operador = construto.operador.lexema;
        this.text += `
    ldr r0, =${operando}`;
        if (operador === '-') {
            this.text += `
    neg r0, r0`;
        }
        else if (operador === '!' || operador === 'nao') {
            this.text += `
    cmp r0, #0
    moveq r0, #1
    movne r0, #0`;
        }
        return 'r0';
    }
    traduzirConstrutoVariavel(construto) {
        var _a;
        const nomeVar = (_a = construto.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
        if (nomeVar && this.variaveis.has(nomeVar)) {
            const varLabel = this.variaveis.get(nomeVar);
            this.text += `
    ldr r0, =${varLabel}
    ldr r0, [r0]`;
            return 'r0';
        }
        return nomeVar || 'unknown';
    }
    traduzirConstrutoVetor(construto) {
        var _a;
        const labelVetor = `vetor_${this.gerarDigitoAleatorio()}`;
        const tamanho = ((_a = construto.valores) === null || _a === void 0 ? void 0 : _a.length) || 0;
        this.bss += `    ${labelVetor}: .space ${tamanho * 4}\n`;
        if (construto.valores && Array.isArray(construto.valores)) {
            construto.valores.forEach((valor, index) => {
                if (this.dicionarioConstrutos[valor.constructor.name]) {
                    const valorTraduzido = this.dicionarioConstrutos[valor.constructor.name](valor);
                    this.text += `
    ldr r0, =${valorTraduzido}
    ldr r1, =${labelVetor}
    str r0, [r1, #${index * 4}]`;
                }
            });
        }
        return labelVetor;
    }
    // Implementação das Declarações
    traduzirDeclaracaoBloco(declaracao) {
        if (declaracao.declaracoes && Array.isArray(declaracao.declaracoes)) {
            declaracao.declaracoes.forEach((decl) => {
                if (this.dicionarioDeclaracoes[decl.constructor.name]) {
                    this.dicionarioDeclaracoes[decl.constructor.name](decl);
                }
            });
        }
    }
    traduzirDeclaracaoEnquanto(declaracao) {
        const labelInicio = this.gerarLabel();
        const labelFim = this.gerarLabel();
        this.text += `
${labelInicio}:`;
        const condicao = this.dicionarioConstrutos[declaracao.condicao.constructor.name](declaracao.condicao);
        this.text += `
    cmp ${condicao}, #0
    beq ${labelFim}`;
        if (this.dicionarioDeclaracoes[declaracao.corpo.constructor.name]) {
            this.dicionarioDeclaracoes[declaracao.corpo.constructor.name](declaracao.corpo);
        }
        this.text += `
    b ${labelInicio}
${labelFim}:`;
    }
    traduzirDeclaracaoEscolha(declaracao) {
        const labelFim = this.gerarLabel();
        const valorEscolha = this.dicionarioConstrutos[declaracao.identificadorOuLiteral.constructor.name](declaracao.identificadorOuLiteral);
        if (declaracao.caminhos && Array.isArray(declaracao.caminhos)) {
            declaracao.caminhos.forEach((caminho) => {
                const labelProximo = this.gerarLabel();
                if (caminho.condicoes && caminho.condicoes[0]) {
                    const valorCaso = this.dicionarioConstrutos[caminho.condicoes[0].constructor.name](caminho.condicoes[0]);
                    this.text += `
    ldr r0, =${valorEscolha}
    ldr r1, =${valorCaso}
    cmp r0, r1
    bne ${labelProximo}`;
                    if (caminho.declaracoes && Array.isArray(caminho.declaracoes)) {
                        caminho.declaracoes.forEach((decl) => {
                            if (this.dicionarioDeclaracoes[decl.constructor.name]) {
                                this.dicionarioDeclaracoes[decl.constructor.name](decl);
                            }
                        });
                    }
                    this.text += `
    b ${labelFim}
${labelProximo}:`;
                }
            });
        }
        this.text += `
${labelFim}:`;
    }
    traduzirDeclaracaoExpressao(declaracao) {
        if (declaracao.expressao && this.dicionarioConstrutos[declaracao.expressao.constructor.name]) {
            this.dicionarioConstrutos[declaracao.expressao.constructor.name](declaracao.expressao);
        }
    }
    traduzirDeclaracaoFazer(declaracao) {
        const labelInicio = this.gerarLabel();
        this.text += `
${labelInicio}:`;
        if (declaracao.caminhoFazer && declaracao.caminhoFazer.declaracoes) {
            declaracao.caminhoFazer.declaracoes.forEach((decl) => {
                if (this.dicionarioDeclaracoes[decl.constructor.name]) {
                    this.dicionarioDeclaracoes[decl.constructor.name](decl);
                }
            });
        }
        if (declaracao.condicaoEnquanto) {
            const condicao = this.dicionarioConstrutos[declaracao.condicaoEnquanto.constructor.name](declaracao.condicaoEnquanto);
            this.text += `
    cmp ${condicao}, #0
    bne ${labelInicio}`;
        }
    }
    traduzirDeclaracaoFalhar(declaracao) {
        let mensagem = '"Erro"';
        if (declaracao.explicacao && typeof declaracao.explicacao === 'object' && 'constructor' in declaracao.explicacao) {
            const explicacao = declaracao.explicacao;
            if (explicacao.constructor && this.dicionarioConstrutos[explicacao.constructor.name]) {
                mensagem = this.dicionarioConstrutos[explicacao.constructor.name](explicacao);
            }
        }
        this.text += `
    @ Falhar com mensagem: ${mensagem}
    mov r0, #1
    mov r7, #1              @ sys_exit
    swi 0`;
    }
    traduzirDeclaracaoFuncao(declaracao) {
        var _a;
        const nomeFuncao = ((_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) || 'funcao';
        this.text += `

${nomeFuncao}:
    push {fp, lr}
    mov fp, sp`;
        if (declaracao.funcao && declaracao.funcao.corpo && Array.isArray(declaracao.funcao.corpo)) {
            declaracao.funcao.corpo.forEach((decl) => {
                if (this.dicionarioDeclaracoes[decl.constructor.name]) {
                    this.dicionarioDeclaracoes[decl.constructor.name](decl);
                }
            });
        }
        this.text += `
    mov sp, fp
    pop {fp, pc}`;
    }
    traduzirDeclaracaoImportar(declaracao) {
        this.text += `
    @ Importar: ${declaracao.caminho || 'unknown'}`;
    }
    traduzirDeclaracaoLeia(declaracao) {
        var _a;
        let nomeVar;
        if (declaracao.argumentos && declaracao.argumentos[0] && declaracao.argumentos[0] instanceof construtos_1.Variavel) {
            nomeVar = (_a = declaracao.argumentos[0].simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
        }
        if (!nomeVar)
            return;
        if (!this.variaveis.has(nomeVar)) {
            const varLabel = `var_${nomeVar}`;
            this.bss += `    ${varLabel}: .space 256\n`;
            this.variaveis.set(nomeVar, varLabel);
        }
        this.text += `
    ldr r1, =${this.variaveis.get(nomeVar)}
    mov r2, #256
    mov r0, #0              @ stdin
    mov r7, #3              @ sys_read
    swi 0`;
    }
    traduzirDeclaracaoPara(declaracao) {
        const labelInicio = this.gerarLabel();
        const labelFim = this.gerarLabel();
        if (declaracao.inicializador) {
            const tipoInicializador = declaracao.inicializador.constructor.name;
            if (this.dicionarioDeclaracoes[tipoInicializador]) {
                this.dicionarioDeclaracoes[tipoInicializador](declaracao.inicializador);
            }
            else if (this.dicionarioConstrutos[tipoInicializador]) {
                this.dicionarioConstrutos[tipoInicializador](declaracao.inicializador);
            }
        }
        this.text += `
${labelInicio}:`;
        if (declaracao.condicao) {
            const condicao = this.dicionarioConstrutos[declaracao.condicao.constructor.name](declaracao.condicao);
            this.text += `
    cmp ${condicao}, #0
    beq ${labelFim}`;
        }
        if (this.dicionarioDeclaracoes[declaracao.corpo.constructor.name]) {
            this.dicionarioDeclaracoes[declaracao.corpo.constructor.name](declaracao.corpo);
        }
        if (declaracao.incrementar) {
            if (this.dicionarioConstrutos[declaracao.incrementar.constructor.name]) {
                this.dicionarioConstrutos[declaracao.incrementar.constructor.name](declaracao.incrementar);
            }
        }
        this.text += `
    b ${labelInicio}
${labelFim}:`;
    }
    traduzirDeclaracaoParaCada(declaracao) {
        var _a;
        const labelInicio = this.gerarLabel();
        const labelFim = this.gerarLabel();
        let nomeVar;
        if (declaracao.variavelIteracao instanceof construtos_1.Variavel) {
            nomeVar = (_a = declaracao.variavelIteracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
        }
        const vetor = declaracao.vetorOuDicionario;
        let tamanhoVetor = 0;
        if (vetor instanceof construtos_1.Vetor) {
            tamanhoVetor = vetor.tamanho || 0;
        }
        this.text += `
    mov r4, #0              @ counter
${labelInicio}:
    cmp r4, #${tamanhoVetor}
    bge ${labelFim}`;
        if (this.dicionarioDeclaracoes[declaracao.corpo.constructor.name]) {
            this.dicionarioDeclaracoes[declaracao.corpo.constructor.name](declaracao.corpo);
        }
        this.text += `
    add r4, r4, #1
    b ${labelInicio}
${labelFim}:`;
    }
    traduzirDeclaracaoRetorna(declaracao) {
        if (declaracao.valor) {
            const valor = this.dicionarioConstrutos[declaracao.valor.constructor.name](declaracao.valor);
            this.text += `
    ldr r0, =${valor}`;
        }
        this.text += `
    mov sp, fp
    pop {fp, pc}`;
    }
    traduzirDeclaracaoSe(declaracao) {
        const labelSenao = this.gerarLabel();
        const labelFim = this.gerarLabel();
        const condicao = this.dicionarioConstrutos[declaracao.condicao.constructor.name](declaracao.condicao);
        this.text += `
    cmp ${condicao}, #0
    beq ${labelSenao}`;
        if (this.dicionarioDeclaracoes[declaracao.caminhoEntao.constructor.name]) {
            this.dicionarioDeclaracoes[declaracao.caminhoEntao.constructor.name](declaracao.caminhoEntao);
        }
        this.text += `
    b ${labelFim}
${labelSenao}:`;
        if (declaracao.caminhoSenao && this.dicionarioDeclaracoes[declaracao.caminhoSenao.constructor.name]) {
            this.dicionarioDeclaracoes[declaracao.caminhoSenao.constructor.name](declaracao.caminhoSenao);
        }
        this.text += `
${labelFim}:`;
    }
    traduzirDeclaracaoClasse(declaracao) {
        var _a;
        this.text += `
    @ Classe: ${((_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema) || 'unknown'}`;
    }
    traduzirDeclaracaoTente(declaracao) {
        this.text += `
    @ Tente-pegue`;
        if (declaracao.caminhoTente && Array.isArray(declaracao.caminhoTente)) {
            declaracao.caminhoTente.forEach((decl) => {
                if (this.dicionarioDeclaracoes[decl.constructor.name]) {
                    this.dicionarioDeclaracoes[decl.constructor.name](decl);
                }
            });
        }
    }
    traduzirDeclaracaoConst(declaracao) {
        var _a;
        const nomeVar = (_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
        if (!nomeVar)
            return;
        const valor = this.dicionarioConstrutos[declaracao.inicializador.constructor.name](declaracao.inicializador);
        const varLabel = `const_${nomeVar}`;
        this.data += `    ${varLabel}: .word ${valor}\n`;
        this.variaveis.set(nomeVar, varLabel);
    }
    traduzirDeclaracaoVar(declaracao) {
        var _a;
        const nomeVar = (_a = declaracao.simbolo) === null || _a === void 0 ? void 0 : _a.lexema;
        if (!nomeVar)
            return;
        const varLabel = `var_${nomeVar}`;
        this.bss += `    ${varLabel}: .space 4\n`;
        this.variaveis.set(nomeVar, varLabel);
        if (declaracao.inicializador && declaracao.inicializador.valor !== null) {
            const tipoInicializador = declaracao.inicializador.constructor.name;
            // Verificar se é um vetor
            if (declaracao.inicializador instanceof construtos_1.Vetor) {
                // Vetor precisa de tratamento especial
                const labelVetor = this.traduzirConstrutoVetor(declaracao.inicializador);
                // Associar o nome da variável com o label do vetor
                this.variaveis.set(nomeVar, labelVetor);
            }
            else if (this.dicionarioConstrutos[tipoInicializador]) {
                const valor = this.dicionarioConstrutos[tipoInicializador](declaracao.inicializador);
                this.text += `
    ldr r0, =${valor}
    ldr r1, =${varLabel}
    str r0, [r1]`;
            }
        }
    }
    criaStringLiteral(literal) {
        const varLiteral = `Delegua_${this.gerarDigitoAleatorio()}`;
        this.data += `    ${varLiteral}: .asciz "${literal.valor}"\n`;
        return varLiteral;
    }
    criaTamanhoNaMemoriaReferenteAVar(nomeStringLiteral) {
        const varTamanho = `tam_${nomeStringLiteral}`;
        // Em ARM, calculamos o tamanho de forma diferente
        // Podemos usar uma diretiva ou calcular em tempo de execução
        return varTamanho;
    }
    traduzirDeclaracaoEscreva(declaracaoEscreva) {
        let tam_string_literal = '';
        let nome_string_literal = '';
        if (declaracaoEscreva.argumentos[0] instanceof construtos_1.Literal) {
            nome_string_literal = this.criaStringLiteral(declaracaoEscreva.argumentos[0]);
            const stringValue = declaracaoEscreva.argumentos[0].valor;
            tam_string_literal = String(stringValue.length);
        }
        // Para ambos linux-arm e android, continuamos usando a convenção
        // de syscall Linux ARM (write). Em Android típico, esse binário
        // seria executado via adb/Termux, onde essa convenção ainda é válida.
        this.text += `
    ldr r1, =${nome_string_literal}
    mov r2, #${tam_string_literal}
    mov r0, #1              @ fd stdout
    mov r7, #4              @ sys_write
    swi 0`;
    }
    saidaSistema() {
        // Mesmo comentário da função Escreva: usamos sys_exit Linux.
        // Em um futuro modo Android "NDK/JNI", esta função deveria
        // apenas retornar ao chamador em vez de fazer syscall direta.
        this.text += `
    mov r0, #1              @ exit status
    mov r7, #1              @ sys_exit
    swi 0`;
    }
    traduzir(declaracoes) {
        let resultado = '';
        this.declaracoesDeClasses = declaracoes.filter((declaracao) => declaracao instanceof declaracoes_1.Classe);
        for (const declaracao of declaracoes) {
            if (this.dicionarioDeclaracoes[declaracao.constructor.name]) {
                this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao);
            }
        }
        this.saidaSistema();
        resultado += this.bss + '\n' + this.data + '\n' + this.text;
        return resultado;
    }
}
exports.TradutorAssemblyARM = TradutorAssemblyARM;
//# sourceMappingURL=tradutor-assembly-arm.js.map