"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RegraFortalecerTipos = void 0;
const declaracoes_1 = require("../../declaracoes");
const construtos_1 = require("../../construtos");
const inferenciador_1 = require("../../inferenciador");
/**
 * Regra que fortalece tipos, convertendo `qualquer` para tipos inferidos.
 *
 * Exemplos:
 * - `var x = 5` com tipo `qualquer` → `var x: número = 5`
 * - `var nomes = []` com tipo `qualquer` → `var nomes: vetor = []`
 * - `constante PI = 3.14` com tipo `qualquer` → `constante PI: número = 3.14`
 */
class RegraFortalecerTipos {
    constructor() {
        this.nome = 'fortalecer-tipos';
        this.descricao = 'Converte tipos `qualquer` para tipos inferidos quando possível';
    }
    aplicarEmDeclaracao(declaracao) {
        // Fortalece tipos em declarações Var
        if (declaracao instanceof declaracoes_1.Var) {
            return this.fortalecerTipoVar(declaracao);
        }
        // Fortalece tipos em declarações Const
        if (declaracao instanceof declaracoes_1.Const) {
            return this.fortalecerTipoConst(declaracao);
        }
        return declaracao;
    }
    /**
     * Fortalece o tipo de uma declaração Var.
     */
    fortalecerTipoVar(declaracao) {
        // Se o tipo já foi explicitamente definido, não modifica
        if (declaracao.tipoExplicito && declaracao.tipo !== 'qualquer') {
            return declaracao;
        }
        // Se há um inicializador, tenta inferir o tipo
        if (declaracao.inicializador) {
            const tipoInferido = this.inferirTipoDeConstruto(declaracao.inicializador);
            if (tipoInferido && tipoInferido !== 'qualquer') {
                declaracao.tipo = tipoInferido;
                declaracao.tipoExplicito = true;
            }
        }
        return declaracao;
    }
    /**
     * Fortalece o tipo de uma declaração Const.
     */
    fortalecerTipoConst(declaracao) {
        // Se o tipo já foi explicitamente definido, não modifica
        if (declaracao.tipoExplicito && declaracao.tipo !== 'qualquer') {
            return declaracao;
        }
        // Se há um inicializador, tenta inferir o tipo
        if (declaracao.inicializador) {
            const tipoInferido = this.inferirTipoDeConstruto(declaracao.inicializador);
            if (tipoInferido && tipoInferido !== 'qualquer') {
                declaracao.tipo = tipoInferido;
                declaracao.tipoExplicito = true;
            }
        }
        return declaracao;
    }
    /**
     * Infere o tipo de um construto.
     */
    inferirTipoDeConstruto(construto) {
        // Se é um literal, usa o tipo do literal
        if (construto instanceof construtos_1.Literal) {
            const tipoInferido = (0, inferenciador_1.inferirTipoVariavel)(construto.valor);
            return typeof tipoInferido === 'string' ? tipoInferido : 'qualquer';
        }
        // Se o construto tem tipo definido, usa esse tipo
        if ('tipo' in construto && construto.tipo) {
            return construto.tipo;
        }
        return 'qualquer';
    }
}
exports.RegraFortalecerTipos = RegraFortalecerTipos;
//# sourceMappingURL=fortalecer-tipos.js.map