"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.aleatorio = aleatorio;
exports.aleatorioEntre = aleatorioEntre;
exports.algum = algum;
exports.clonar = clonar;
exports.encontrar = encontrar;
exports.encontrarIndice = encontrarIndice;
exports.encontrarUltimo = encontrarUltimo;
exports.encontrarUltimoIndice = encontrarUltimoIndice;
exports.filtrarPor = filtrarPor;
exports.incluido = incluido;
exports.inteiro = inteiro;
exports.intervalo = intervalo;
exports.mapear = mapear;
exports.maximo = maximo;
exports.minimo = minimo;
exports.numero = numero;
exports.ordenar = ordenar;
exports.paraCada = paraCada;
exports.primeiroEmCondicao = primeiroEmCondicao;
exports.real = real;
exports.reduzir = reduzir;
exports.somar = somar;
exports.tamanho = tamanho;
exports.texto = texto;
exports.todosEmCondicao = todosEmCondicao;
exports.tupla = tupla;
exports.vetor = vetor;
const excecoes_1 = require("../excecoes");
const objeto_delegua_classe_1 = require("../interpretador/estruturas/objeto-delegua-classe");
const funcao_padrao_1 = require("../interpretador/estruturas/funcao-padrao");
const descritor_tipo_classe_1 = require("../interpretador/estruturas/descritor-tipo-classe");
const estruturas_1 = require("../interpretador/estruturas");
const construtos_1 = require("../construtos");
const quebras_1 = require("../quebras");
const configTuplas = {
    'Dupla': { Classe: construtos_1.Dupla, props: ['primeiro', 'segundo'] },
    'Trio': { Classe: construtos_1.Trio, props: ['primeiro', 'segundo', 'terceiro'] },
    'Quarteto': { Classe: construtos_1.Quarteto, props: ['primeiro', 'segundo', 'terceiro', 'quarto'] },
    'Quinteto': { Classe: construtos_1.Quinteto, props: ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto'] },
    'Sexteto': { Classe: construtos_1.Sexteto, props: ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto'] },
    'Septeto': { Classe: construtos_1.Septeto, props: ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto', 'setimo'] },
    'Octeto': { Classe: construtos_1.Octeto, props: ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto', 'setimo', 'oitavo'] },
    'Noneto': { Classe: construtos_1.Noneto, props: ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto', 'setimo', 'oitavo', 'nono'] },
    'Deceto': { Classe: construtos_1.Deceto, props: ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto', 'setimo', 'oitavo', 'nono', 'decimo'] },
};
const mapaConstrutoresTupla = {
    2: construtos_1.Dupla,
    3: construtos_1.Trio,
    4: construtos_1.Quarteto,
    5: construtos_1.Quinteto,
    6: construtos_1.Sexteto,
    7: construtos_1.Septeto,
    8: construtos_1.Octeto,
    9: construtos_1.Noneto,
    10: construtos_1.Deceto
};
const mapaPropriedadesTuplas = {
    'Dupla': ['primeiro', 'segundo'],
    'Trio': ['primeiro', 'segundo', 'terceiro'],
    'Quarteto': ['primeiro', 'segundo', 'terceiro', 'quarto'],
    'Quinteto': ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto'],
    'Sexteto': ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto'],
    'Septeto': ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto', 'setimo'],
    'Octeto': ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto', 'setimo', 'oitavo'],
    'Noneto': ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto', 'setimo', 'oitavo', 'nono'],
    'Deceto': ['primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto', 'setimo', 'oitavo', 'nono', 'decimo'],
};
/**
 * Compara dois valores (números ou vetores).
 * Retorna:
 * > 0 se a > b
 * < 0 se a < b
 * 0 se a == b
 * Lança erro se os tipos forem incompatíveis.
 */
function compararElementosRecursivamente(a, b) {
    if (typeof a === 'number' && typeof b === 'number') {
        return a - b;
    }
    if (Array.isArray(a) && Array.isArray(b)) {
        const tamanho = Math.min(a.length, b.length);
        for (let i = 0; i < tamanho; i++) {
            const comparacao = compararElementosRecursivamente(a[i], b[i]);
            if (comparacao !== 0)
                return comparacao;
        }
        return a.length - b.length;
    }
    // Tipos incompatíveis (ex: comparar número com vetor)
    throw new Error('Tipos incompatíveis para comparação.');
}
/**
 * Retorna um número aleatório entre 0 e 1.
 * @returns {Promise<number>} Número real.
 */
async function aleatorio(interpretador) {
    return Promise.resolve(Math.random());
}
/**
 * Retorna um número aleatório de acordo com o parâmetro passado.
 * Mínimo(inclusivo) - Máximo(exclusivo).
 * @param {number} minimo O número mínimo.
 * @param {number} maximo O número máximo.
 * @returns {Promise<number>} Um número real entre os valores máximo e mínimo especificados.
 */
async function aleatorioEntre(interpretador, minimo, maximo) {
    if (arguments.length <= 0) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'A função recebe ao menos um parâmetro.'));
    }
    const valorMinimo = minimo.hasOwnProperty('valor')
        ? minimo.valor
        : minimo;
    if (arguments.length === 2) {
        if (typeof valorMinimo !== 'number') {
            return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
                hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
                linha: interpretador.linhaDeclaracaoAtual,
            }, 'O parâmetro deve ser um número.'));
        }
        return Math.floor(Math.random() * (0 - valorMinimo)) + valorMinimo;
    }
    if (arguments.length > 3) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'A quantidade de parâmetros máxima para esta função é 2.'));
    }
    const valorMaximo = maximo.hasOwnProperty('valor')
        ? maximo.valor
        : maximo;
    if (typeof valorMinimo !== 'number' || typeof valorMaximo !== 'number') {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Os dois parâmetros devem ser do tipo número.'));
    }
    return Promise.resolve(Math.floor(Math.random() * (valorMaximo - valorMinimo)) + valorMinimo);
}
/**
 * Verifica se algum dos elementos satisfaz à condição para por parâmetro.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} vetor Uma variável de Delégua ou um vetor nativo de JavaScript.
 * @param {VariavelInterface | any} funcaoPesquisa A função que ensina o método de pesquisa.
 * @returns {Promise<boolean>} Verdadeiro se há algum elemento no vetor com a condição. Falso caso contrário.
 */
async function algum(interpretador, vetor, funcaoPesquisa) {
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorFuncaoPesquisa = funcaoPesquisa.hasOwnProperty('valor')
        ? funcaoPesquisa.valor
        : funcaoPesquisa;
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função deve ser um vetor.'));
    }
    if (valorFuncaoPesquisa.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função deve ser uma função.'));
    }
    for (let indice = 0; indice < valorVetor.length; ++indice) {
        if (await valorFuncaoPesquisa.chamar(interpretador, [valorVetor[indice]])) {
            return true;
        }
    }
    return false;
}
/**
 * Clona profundamente uma variável ou constante em Delégua.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} valor O valor a ser clonado.
 * @returns {Promise<any>} Uma cópia profunda do valor fornecido.
 */
async function clonar(interpretador, valor) {
    // Resolver o valor caso seja uma VariavelInterface
    // Verificar se é null/undefined antes de usar hasOwnProperty
    let valorResolvido;
    if (valor === null || valor === undefined) {
        valorResolvido = valor;
    }
    else if (typeof valor === 'object' && valor.hasOwnProperty('valor')) {
        valorResolvido = valor.valor;
    }
    else {
        valorResolvido = valor;
    }
    // Map para evitar referências circulares
    const visitados = new WeakMap();
    function clonarProfundo(valorAtual) {
        var _a;
        // Valores primitivos (null, undefined, number, string, boolean)
        if (valorAtual === null || valorAtual === undefined) {
            return valorAtual;
        }
        if (typeof valorAtual !== 'object') {
            return valorAtual;
        }
        // Verificar se já visitamos este objeto (evitar referências circulares)
        if (visitados.has(valorAtual)) {
            return visitados.get(valorAtual);
        }
        // Arrays
        if (Array.isArray(valorAtual)) {
            const arrayClonado = [];
            visitados.set(valorAtual, arrayClonado);
            for (let i = 0; i < valorAtual.length; i++) {
                arrayClonado[i] = clonarProfundo(valorAtual[i]);
            }
            return arrayClonado;
        }
        // Objetos de Delégua - ObjetoDeleguaClasse
        if (valorAtual instanceof objeto_delegua_classe_1.ObjetoDeleguaClasse) {
            // Clonar propriedades do objeto
            const propriedadesClonadas = {};
            visitados.set(valorAtual, propriedadesClonadas);
            for (const chave in valorAtual.propriedades) {
                if (valorAtual.propriedades.hasOwnProperty(chave)) {
                    propriedadesClonadas[chave] = clonarProfundo(valorAtual.propriedades[chave]);
                }
            }
            // Criar novo objeto com as propriedades clonadas
            // Nota: A classe em si não é clonada, apenas suas propriedades
            const objetoClonado = new objeto_delegua_classe_1.ObjetoDeleguaClasse(valorAtual.classe);
            objetoClonado.propriedades = propriedadesClonadas;
            return objetoClonado;
        }
        // Tuplas com 11 elementos ou mais
        if (valorAtual instanceof construtos_1.TuplaN) {
            const elementosClonados = [];
            visitados.set(valorAtual, elementosClonados);
            for (let i = 0; i < valorAtual.elementos.length; i++) {
                elementosClonados.push(clonarProfundo(valorAtual.elementos[i]));
            }
            return new construtos_1.TuplaN(valorAtual.hashArquivo, valorAtual.linha, elementosClonados);
        }
        // Tuplas com até 10 elementos
        const nomeClasseTupla = (_a = valorAtual.constructor) === null || _a === void 0 ? void 0 : _a.name;
        if (nomeClasseTupla && configTuplas[nomeClasseTupla]) {
            const config = configTuplas[nomeClasseTupla];
            const argsClonados = [];
            visitados.set(valorAtual, argsClonados);
            for (const prop of config.props) {
                argsClonados.push(clonarProfundo(valorAtual[prop]));
            }
            return new config.Classe(...argsClonados);
        }
        // DeleguaFuncao e FuncaoPadrao - funções não são clonadas profundamente
        // Elas mantêm referência à mesma definição, mas isso é comportamento esperado
        if (valorAtual instanceof estruturas_1.DeleguaFuncao || valorAtual instanceof funcao_padrao_1.FuncaoPadrao) {
            return valorAtual;
        }
        // Objetos simples (plain objects)
        const objetoClonado = {};
        visitados.set(valorAtual, objetoClonado);
        for (const chave in valorAtual) {
            if (valorAtual.hasOwnProperty(chave)) {
                objetoClonado[chave] = clonarProfundo(valorAtual[chave]);
            }
        }
        return objetoClonado;
    }
    return Promise.resolve(clonarProfundo(valorResolvido));
}
/**
 * Encontra o primeiro elemento de um vetor cuja função de pesquisa retorne
 * verdadeiro na avaliação de cada elemento.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} vetor Uma variável de Delégua ou um vetor nativo de JavaScript.
 * @param {VariavelInterface | any} funcaoPesquisa A função que ensina o método de pesquisa.
 * @returns {Promise<any>} Um elemento, caso o elemento seja encontraro, ou nulo em caso contrário.
 */
async function encontrar(interpretador, vetor, funcaoPesquisa) {
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorFuncaoPesquisa = funcaoPesquisa.hasOwnProperty('valor')
        ? funcaoPesquisa.valor
        : funcaoPesquisa;
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função deve ser um vetor.'));
    }
    if (valorFuncaoPesquisa.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função deve ser uma função.'));
    }
    for (let indice = 0; indice < valorVetor.length; ++indice) {
        if (await valorFuncaoPesquisa.chamar(interpretador, [valorVetor[indice]])) {
            return valorVetor[indice];
        }
    }
    return null;
}
/**
 * Encontra o índice do primeiro elemento de um vetor cuja função de pesquisa retorne
 * verdadeiro na avaliação de cada elemento.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} vetor Uma variável de Delégua ou um vetor nativo de JavaScript.
 * @param {VariavelInterface | any} funcaoPesquisa A função que ensina o método de pesquisa.
 * @returns {Promise<number>} O número correspondente ao índice se o elemento for encontrado, ou nulo em caso contrário.
 */
async function encontrarIndice(interpretador, vetor, funcaoPesquisa) {
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorFuncaoPesquisa = funcaoPesquisa.hasOwnProperty('valor')
        ? funcaoPesquisa.valor
        : funcaoPesquisa;
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função deve ser um vetor.'));
    }
    if (valorFuncaoPesquisa.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função deve ser uma função.'));
    }
    for (let indice = 0; indice < valorVetor.length; ++indice) {
        if (await valorFuncaoPesquisa.chamar(interpretador, [valorVetor[indice]])) {
            return indice;
        }
    }
    return -1;
}
/**
 * Encontrar o último elemento de um vetor cuja função de pesquisa retorne
 * verdadeiro na avaliação de cada elemento.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} vetor Uma variável de Delégua ou um vetor nativo de JavaScript.
 * @param {VariavelInterface | any} funcaoPesquisa A função que ensina o método de pesquisa.
 * @returns {Promise<any>} O número correspondente ao índice se o elemento for encontrado, ou nulo em caso contrário.
 */
async function encontrarUltimo(interpretador, vetor, funcaoPesquisa) {
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorFuncaoPesquisa = funcaoPesquisa.hasOwnProperty('valor')
        ? funcaoPesquisa.valor
        : funcaoPesquisa;
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função deve ser um vetor.'));
    }
    if (valorFuncaoPesquisa.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função deve ser uma função.'));
    }
    for (let indice = valorVetor.length - 1; indice >= 0; --indice) {
        if (await valorFuncaoPesquisa.chamar(interpretador, [valorVetor[indice]])) {
            return valorVetor[indice];
        }
    }
    return null;
}
/**
 *
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} vetor Uma variável de Delégua ou um vetor nativo de JavaScript.
 * @param {VariavelInterface | any} funcaoPesquisa A função que ensina o método de pesquisa.
 * @returns {Promise<number>} O número correspondente ao índice se o elemento for encontrado, ou nulo em caso contrário.
 */
async function encontrarUltimoIndice(interpretador, vetor, funcaoPesquisa) {
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorFuncaoPesquisa = funcaoPesquisa.hasOwnProperty('valor')
        ? funcaoPesquisa.valor
        : funcaoPesquisa;
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função deve ser um vetor.'));
    }
    if (valorFuncaoPesquisa.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função deve ser uma função.'));
    }
    for (let indice = valorVetor.length - 1; indice >= 0; --indice) {
        if (await valorFuncaoPesquisa.chamar(interpretador, [valorVetor[indice]])) {
            return indice;
        }
    }
    return null;
}
/**
 *
 * @param interpretador
 * @param vetor
 * @param funcaoFiltragem
 * @returns
 */
async function filtrarPor(interpretador, vetor, funcaoFiltragem) {
    if (vetor === null || vetor === undefined)
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função filtrarPor() não pode ser nulo.'));
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorFuncaoFiltragem = funcaoFiltragem.hasOwnProperty('valor')
        ? funcaoFiltragem.valor
        : funcaoFiltragem;
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função filtrarPor() deve ser um vetor.'));
    }
    if (valorFuncaoFiltragem.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função filtrarPor() deve ser uma função.'));
    }
    const resultados = [];
    for (let indice = 0; indice < valorVetor.length; ++indice) {
        const informacoesValor = await valorFuncaoFiltragem.chamar(interpretador, [
            valorVetor[indice],
        ]);
        if (informacoesValor === null || informacoesValor === undefined) {
            continue;
        }
        const deveRetornarValor = informacoesValor.valorRetornado.valor;
        if (deveRetornarValor === false)
            continue;
        resultados.push(valorVetor[indice]);
    }
    return resultados;
}
/**
 *
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} vetor Uma variável de Delégua ou um vetor nativo de JavaScript.
 * @param valor
 * @returns
 */
async function incluido(interpretador, vetor, valor) {
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorValor = valor.hasOwnProperty('valor') ? valor.valor : valor;
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função deve ser um vetor.'));
    }
    for (let indice = 0; indice < valorVetor.length; ++indice) {
        if (valorVetor[indice] == valorValor) {
            return true;
        }
    }
    return false;
}
function validacaoComumNumeros(interpretador, valorParaConverter) {
    if (isNaN(valorParaConverter)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Valor não parece ser um número. Somente números ou textos com números podem ser convertidos para inteiro.'));
    }
    if (!/^(-)?\d+(\.\d+)?$/.test(valorParaConverter)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Valor não parece estar estruturado como um número (texto vazio, falso ou não definido). Somente números ou textos com números podem ser convertidos para inteiro.'));
    }
    return null;
}
/**
 * Converte um valor em um número inteiro.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} valorParaConverter O valor a ser convertido.
 * @returns {Promise<any>} Uma Promise com o resultado da conversão.
 */
async function inteiro(interpretador, valorParaConverter) {
    if (valorParaConverter === null || valorParaConverter === undefined)
        return Promise.resolve(0);
    const valor = valorParaConverter.hasOwnProperty('valor')
        ? valorParaConverter.valor
        : valorParaConverter;
    const resultadoValidacao = validacaoComumNumeros(interpretador, valor);
    return resultadoValidacao || Promise.resolve(parseInt(valor));
}
/**
 * Cria um vetor com números inteiros no intervalo especificado.
 * O valor inicial é inclusivo e o valor final é exclusivo.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | number} valorInicial O valor inicial (inclusivo).
 * @param {VariavelInterface | number} valorFinal O valor final (exclusivo).
 * @returns {Promise<number[]>} Um vetor com os números no intervalo.
 */
async function intervalo(interpretador, valorInicial, valorFinal) {
    const inicio = interpretador.resolverValor(valorInicial);
    const fim = interpretador.resolverValor(valorFinal);
    if (typeof inicio !== 'number' || typeof fim !== 'number') {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Os dois parâmetros devem ser do tipo número ou inteiro.'));
    }
    if (isNaN(inicio) || isNaN(fim)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Os dois parâmetros devem ser do tipo número ou inteiro.'));
    }
    // Remove a parte decimal se houver
    const inicioInteiro = Math.floor(inicio);
    const fimInteiro = Math.floor(fim);
    const resultado = [];
    for (let i = inicioInteiro; i < fimInteiro; i++) {
        resultado.push(i);
    }
    return Promise.resolve(resultado);
}
/**
 * Dado um vetor e uma função de mapeamento, executa a função de mapeamento
 * passando como argumento cada elemento do vetor.
 * @param interpretador A instância do interpretador.
 * @param vetor O vetor
 * @param funcaoMapeamento A função de mapeamento.
 * @returns O resultado acumulado da execução da função de mapeamento.
 */
async function mapear(interpretador, vetor, funcaoMapeamento) {
    if (vetor === null || vetor === undefined)
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função mapear() não pode ser nulo.'));
    const valorVetor = interpretador.resolverValor(vetor);
    const valorFuncaoMapeamento = interpretador.resolverValor(funcaoMapeamento);
    // TODO: As lógicas de validação abaixo deixam de fazer sentido com a validação de argumentos feita
    // na avaliação sintática. Estudar remoção.
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função mapear() deve ser um vetor.'));
    }
    if (valorFuncaoMapeamento.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função mapear() deve ser uma função.'));
    }
    const resultados = [];
    for (let indice = 0; indice < valorVetor.length; ++indice) {
        const informacoesRetorno = await valorFuncaoMapeamento.chamar(interpretador, [
            valorVetor[indice],
        ]);
        if (!informacoesRetorno.hasOwnProperty('valorRetornado')) {
            console.warn(`Retorno inconsistente em mapear(): ${JSON.stringify(informacoesRetorno)}.`);
            continue;
        }
        if (!(informacoesRetorno.valorRetornado instanceof quebras_1.RetornoQuebra)) {
            console.warn(`mapear() finalizado com valor retornado diferente do esperado: ${JSON.stringify(informacoesRetorno)}.`);
            continue;
        }
        resultados.push(informacoesRetorno.valorRetornado.valor);
    }
    return resultados;
}
/**
 * Encontra o maior número dentro de um vetor.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} vetor Uma variável de Delégua ou um vetor nativo de JavaScript contendo números.
 * @returns {Promise<number>} O maior número encontrado no vetor.
 */
async function maximo(interpretador, vetor) {
    if (vetor === null || vetor === undefined) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O parâmetro da função maximo() não pode ser nulo.'));
    }
    const valorVetor = interpretador.resolverValor(vetor);
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O parâmetro da função maximo() deve ser um vetor.'));
    }
    if (vetor.length == 0) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O vetor não pode estar vazio.'));
    }
    let maiorValor = valorVetor[0];
    try {
        for (let i = 1; i < valorVetor.length; i++) {
            const elementoAtual = valorVetor[i];
            if (compararElementosRecursivamente(elementoAtual, maiorValor) > 0) {
                maiorValor = elementoAtual;
            }
        }
    }
    catch (erro) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Não é possível comparar elementos de tipos diferentes dentro do vetor (ex: números com vetores).'));
    }
    return Promise.resolve(maiorValor);
}
/**
 * Encontra o menor número dentro de um vetor.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} vetor Uma variável de Delégua ou um vetor nativo de JavaScript contendo números.
 * @returns {Promise<number>} O menor número encontrado no vetor.
 */
async function minimo(interpretador, vetor) {
    if (vetor === null || vetor === undefined) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O parâmetro da função minimo() não pode ser nulo.'));
    }
    const valorVetor = interpretador.resolverValor(vetor);
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O parâmetro da função minimo() deve ser um vetor.'));
    }
    if (valorVetor.length == 0) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O vetor não pode estar vazio.'));
    }
    let menorValor = valorVetor[0];
    try {
        for (let i = 1; i < valorVetor.length; i++) {
            const elementoAtual = valorVetor[i];
            if (compararElementosRecursivamente(elementoAtual, menorValor) < 0) {
                menorValor = elementoAtual;
            }
        }
    }
    catch (erro) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Não é possível comparar elementos de tipos diferentes dentro do vetor (ex: números com vetores).'));
    }
    return Promise.resolve(menorValor);
}
/**
 * Converte um valor em um número, com parte decimal ou não.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} valorParaConverter O valor a ser convertido.
 * @returns {Promise<any>} Uma Promise com o resultado da conversão.
 */
async function numero(interpretador, valorParaConverter) {
    if (valorParaConverter === null || valorParaConverter === undefined)
        return Promise.resolve(0);
    const valor = valorParaConverter.hasOwnProperty('valor')
        ? valorParaConverter.valor
        : valorParaConverter;
    const resultadoValidacao = validacaoComumNumeros(interpretador, valor);
    return resultadoValidacao || Promise.resolve(Number(valor));
}
/**
 *
 * @param vetor
 * @returns
 */
async function ordenar(interpretador, vetor) {
    if (vetor === null || vetor === undefined)
        throw new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função ordenar() não pode ser nulo.');
    const objeto = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    if (!Array.isArray(objeto)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Valor inválido. Objeto inserido não é um vetor.'));
    }
    let trocado;
    const tamanho = objeto.length;
    do {
        trocado = false;
        for (let i = 0; i < tamanho - 1; i++) {
            if (objeto[i] > objeto[i + 1]) {
                [objeto[i], objeto[i + 1]] = [objeto[i + 1], objeto[i]];
                trocado = true;
            }
        }
    } while (trocado);
    return Promise.resolve(objeto);
}
/**
 *
 * @param interpretador
 * @param vetor
 * @param funcaoFiltragem
 * @returns
 */
async function paraCada(interpretador, vetor, funcaoFiltragem) {
    if (vetor === null || vetor === undefined)
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função paraCada() não pode ser nulo.'));
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorFuncaoFiltragem = funcaoFiltragem.hasOwnProperty('valor')
        ? funcaoFiltragem.valor
        : funcaoFiltragem;
    // TODO: As lógicas de validação abaixo deixam de fazer sentido com a validação de argumentos feita
    // na avaliação sintática. Estudar remoção.
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função paraCada() deve ser um vetor.'));
    }
    if (valorFuncaoFiltragem.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função paraCada() deve ser uma função.'));
    }
    for (let indice = 0; indice < valorVetor.length; ++indice) {
        await valorFuncaoFiltragem.chamar(interpretador, [valorVetor[indice]]);
    }
}
/**
 *
 * @param interpretador
 * @param vetor
 * @param funcaoFiltragem
 * @returns
 */
async function primeiroEmCondicao(interpretador, vetor, funcaoFiltragem) {
    if (vetor === null || vetor === undefined)
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função primeiroEmCondicao() não pode ser nulo.'));
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorFuncaoFiltragem = funcaoFiltragem.hasOwnProperty('valor')
        ? funcaoFiltragem.valor
        : funcaoFiltragem;
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função primeiroEmCondicao() deve ser um vetor.'));
    }
    if (valorFuncaoFiltragem.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função primeiroEmCondicao() deve ser uma função.'));
    }
    for (let indice = 0; indice < valorVetor.length; ++indice) {
        const valorResolvido = await valorFuncaoFiltragem.chamar(interpretador, [
            valorVetor[indice],
        ]);
        if (valorResolvido !== null) {
            return valorResolvido;
        }
    }
    return undefined;
}
/**
 *
 * @param interpretador
 * @param numero
 * @returns
 */
async function real(interpretador, numero) {
    if (numero === null || numero === undefined)
        return Promise.resolve(parseFloat('0'));
    const valor = numero.hasOwnProperty('valor') ? numero.valor : numero;
    if (!/^(-)?\d+(\.\d+)?$/.test(valor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Valor não parece estar estruturado como um número (texto/valor vazio, falso ou não definido). Somente números ou textos com números podem ser convertidos para real.'));
    }
    return Promise.resolve(parseFloat(valor));
}
/**
 *
 * @param interpretador
 * @param vetor
 * @param funcaoReducao
 * @param valorInicial
 * @returns
 */
async function reduzir(interpretador, vetor, funcaoReducao, valorInicial = null) {
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorFuncaoReducao = funcaoReducao.hasOwnProperty('valor')
        ? funcaoReducao.valor
        : funcaoReducao;
    const valorPadrao = valorInicial.hasOwnProperty('valor') ? valorInicial.valor : valorInicial;
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função deve ser um vetor.'));
    }
    if (valorFuncaoReducao.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função deve ser uma função.'));
    }
    let resultado = valorPadrao;
    let inicio = 0;
    if (!resultado) {
        resultado = vetor[0];
        inicio = 1;
    }
    for (let index = inicio; index < vetor.length; ++index) {
        resultado = await valorFuncaoReducao.chamar(interpretador, [resultado, vetor[index]]);
    }
    return resultado;
}
/**
 * Realiza a soma de todos os números dentro de um vetor.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} vetor Uma variável de Pituguês ou um vetor nativo de JavaScript contendo números.
 * @returns {Promise<number>} A soma de todos os elementos do vetor.
 */
async function somar(interpretador, vetor) {
    if (vetor === null || vetor === undefined) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O parâmetro da função somar() não pode ser nulo.'));
    }
    const valorVetor = interpretador.resolverValor(vetor);
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O parâmetro da função somar() deve ser um vetor.'));
    }
    if (valorVetor.length === 0)
        return Promise.resolve(0);
    let somaDosElementos = 0;
    for (let elemento of valorVetor) {
        if (typeof elemento !== 'number' || isNaN(elemento)) {
            return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
                hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
                linha: interpretador.linhaDeclaracaoAtual,
            }, 'A função somar() aceita apenas vetores contendo números.'));
        }
        somaDosElementos += elemento;
    }
    return Promise.resolve(somaDosElementos);
}
/**
 *
 * @param objeto
 * @returns
 */
async function tamanho(interpretador, objeto) {
    const valorObjeto = objeto.hasOwnProperty('valor') ? objeto.valor : objeto;
    if (typeof valorObjeto === 'number') {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Função global tamanho() não funciona com números.'));
    }
    if (valorObjeto instanceof objeto_delegua_classe_1.ObjetoDeleguaClasse) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Função global tamanho não funciona com objetos complexos.'));
    }
    if (valorObjeto instanceof estruturas_1.DeleguaFuncao) {
        return Promise.resolve(valorObjeto.declaracao.parametros.length);
    }
    if (valorObjeto instanceof funcao_padrao_1.FuncaoPadrao) {
        return Promise.resolve(valorObjeto.valorAridade);
    }
    if (valorObjeto instanceof descritor_tipo_classe_1.DescritorTipoClasse) {
        const metodos = valorObjeto.metodos;
        let tamanho = 0;
        if (metodos.inicializacao && metodos.inicializacao.eInicializador) {
            tamanho = metodos.inicializacao.declaracao.parametros.length;
        }
        return Promise.resolve(tamanho);
    }
    return Promise.resolve(valorObjeto.length);
}
/**
 * Transforma o valor ou variável em texto.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} valorParaConverter O valor ou variável.
 * @returns {Promise<string>} O valor resolvido em texto.
 */
async function texto(interpretador, valorParaConverter) {
    return Promise.resolve(`${valorParaConverter.hasOwnProperty('valor') ? valorParaConverter.valor : valorParaConverter}`);
}
/**
 * Retorna verdadeiro se todos os elementos do primeiro parâmetro retornam verdadeiro ao
 * serem aplicados como argumentos da função passada como segundo parâmetro.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any} vetor O primeiro parâmetro, um vetor.
 * @param {VariavelInterface | any} funcaoCondicional A função que será executada com cada
 *                                  valor do vetor passado como primeiro parâmetro.
 * @returns {Promise<boolean>} Verdadeiro, se todos os valores do vetor fazem a função passada
 *                             por parâmetro devolver verdadeiro, ou falso em caso contrário.
 */
async function todosEmCondicao(interpretador, vetor, funcaoCondicional) {
    if (vetor === null || vetor === undefined)
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função todosEmCondicao() não pode ser nulo.'));
    const valorVetor = vetor.hasOwnProperty('valor') ? vetor.valor : vetor;
    const valorFuncaoCondicional = funcaoCondicional.hasOwnProperty('valor')
        ? funcaoCondicional.valor
        : funcaoCondicional;
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O primeiro parâmetro da função todosEmCondicao() deve ser um vetor.'));
    }
    if (valorFuncaoCondicional.constructor !== estruturas_1.DeleguaFuncao) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Parâmetro inválido. O segundo parâmetro da função todosEmCondicao() deve ser uma função.'));
    }
    for (let indice = 0; indice < valorVetor.length; ++indice) {
        if (!(await valorFuncaoCondicional.chamar(interpretador, [valorVetor[indice]])))
            return false;
    }
    return true;
}
/**
 * Transforma um vetor de elementos em uma tupla de N elementos, sendo N a
 * largura do vetor.
 * @param {InterpretadorInterface} interpretador A instância do interpretador.
 * @param {VariavelInterface | any[]} vetor O vetor.
 * @returns A tupla resolvida.
 */
async function tupla(interpretador, vetor) {
    const valorVetor = interpretador.resolverValor(vetor);
    // TODO: As lógicas de validação abaixo deixam de fazer sentido com a validação de argumentos feita
    // na avaliação sintática. Estudar remoção.
    if (!Array.isArray(valorVetor)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Argumento de função nativa `tupla` não parece ser um vetor.'));
    }
    const elementos = valorVetor.map(item => new construtos_1.Literal(interpretador.hashArquivoDeclaracaoAtual, interpretador.linhaDeclaracaoAtual, interpretador.resolverValor(item)));
    return new construtos_1.TuplaN(interpretador.hashArquivoDeclaracaoAtual, interpretador.linhaDeclaracaoAtual, elementos);
}
async function vetor(interpretador, tupla) {
    const objetoTupla = interpretador.resolverValor(tupla);
    // TODO: As lógicas de validação abaixo deixam de fazer sentido com a validação de argumentos feita
    // na avaliação sintática. Estudar remoção.
    if (!(objetoTupla instanceof construtos_1.Tupla || objetoTupla instanceof construtos_1.TuplaN)) {
        return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({
            hashArquivo: interpretador.hashArquivoDeclaracaoAtual,
            linha: interpretador.linhaDeclaracaoAtual,
        }, 'Argumento de função nativa `vetor` não parece ser uma tupla.'));
    }
    let resultado = [];
    if (objetoTupla instanceof construtos_1.TuplaN) {
        resultado = objetoTupla.elementos;
    }
    else {
        const nomeClasse = objetoTupla.constructor.name;
        if (mapaPropriedadesTuplas.hasOwnProperty(nomeClasse)) {
            const props = mapaPropriedadesTuplas[nomeClasse];
            resultado = props.map(prop => objetoTupla[prop]);
        }
        else if (objetoTupla.elementos && Array.isArray(objetoTupla.elementos)) {
            resultado = objetoTupla.elementos;
        }
    }
    const resultadoFinal = resultado.map(item => (item && item.hasOwnProperty('valor')) ? item.valor : item);
    return Promise.resolve(resultadoFinal);
}
//# sourceMappingURL=biblioteca-global.js.map