UNPKG

@designliquido/delegua

Version:

Linguagem de programação simples e moderna usando português estruturado.

114 lines 5.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buscarRetornos = buscarRetornos; exports.logicaDescobertaRetornoFuncao = logicaDescobertaRetornoFuncao; exports.registrarPrimitiva = registrarPrimitiva; const declaracoes_1 = require("../declaracoes"); const informacao_elemento_sintatico_1 = require("../informacao-elemento-sintatico"); function* buscarRetornosEmBloco(construtoBloco) { if (!construtoBloco?.declaracoes) return; for (const declaracao of construtoBloco.declaracoes) { if (declaracao?.constructor === declaracoes_1.Retorna) { yield declaracao; } } } function* buscarRetornosEmSe(construtoSe) { if (construtoSe.caminhoEntao?.constructor === declaracoes_1.Retorna) { yield construtoSe.caminhoEntao; } else { const blocoEntao = construtoSe.caminhoEntao; for (const declaracao of buscarRetornosEmBloco(blocoEntao)) { if (declaracao.constructor === declaracoes_1.Retorna) { yield declaracao; } } } if (!construtoSe.caminhoSenao) return; switch (construtoSe.caminhoSenao.constructor) { case declaracoes_1.Retorna: yield construtoSe.caminhoSenao; break; case declaracoes_1.Bloco: const blocoSenao = construtoSe.caminhoSenao; for (const declaracao of buscarRetornosEmBloco(blocoSenao)) { if (declaracao.constructor === declaracoes_1.Retorna) { yield declaracao; } } break; case declaracoes_1.Se: const senaoSe = construtoSe.caminhoSenao; for (const declaracao of buscarRetornosEmSe(senaoSe)) { if (declaracao.constructor === declaracoes_1.Retorna) { yield declaracao; } } break; } } function buscarRetornos(declaracao) { let retornasEncontrados = []; switch (declaracao.constructor) { case declaracoes_1.Retorna: retornasEncontrados.push(declaracao); break; case declaracoes_1.Se: for (const retorna of buscarRetornosEmSe(declaracao)) { retornasEncontrados.push(retorna); } break; default: break; } return retornasEncontrados; } function logicaDescobertaRetornoFuncao(avaliadorSintatico, declaracoesDaFuncao, tipoRetorno, definicaoExplicitaDeTipo, simboloParaErros) { let expressoesRetorna = []; for (const declaracao of declaracoesDaFuncao) { expressoesRetorna = expressoesRetorna.concat(buscarRetornos(declaracao)); } if (tipoRetorno === 'vazio' && expressoesRetorna.length > 0) { // Filtra retornos que têm tipo conhecido e diferente de 'vazio'. // 'qualquer' é excluído pois o tipo não pode ser determinado em tempo de análise sintática. const retornosNaoVazios = expressoesRetorna.filter((e) => e.tipo !== 'vazio' && e.tipo !== 'qualquer'); if (retornosNaoVazios.length > 0) { throw avaliadorSintatico.erro(retornosNaoVazios[0].simboloChave, `Função declara explicitamente 'vazio', mas usa expressão 'retorna' com tipo de retorno diferente de vazio.`); } } const tiposRetornos = new Set(expressoesRetorna.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo)); let retornaChamadoExplicitamente = tiposRetornos.size > 0; // Verifica se há retornos com valores (incluindo retornos 'qualquer') let temRetornosComValor = expressoesRetorna.some((e) => e.valor !== null && e.valor !== undefined); if (tiposRetornos.size > 1 && tipoRetorno !== 'qualquer') { let tiposEncontrados = Array.from(tiposRetornos).reduce((acumulador, valor) => (acumulador += valor + ', '), ''); tiposEncontrados = tiposEncontrados.slice(0, -2); throw avaliadorSintatico.erro(simboloParaErros, `Função retorna valores com mais de um tipo. Tipo esperado: ${tipoRetorno}. Tipos encontrados: ${tiposEncontrados}.`); } tiposRetornos.delete('qualquer'); if (tipoRetorno === 'qualquer') { if (tiposRetornos.size > 0) { // Se o tipo de retorno é 'qualquer', seja implícito ou explícito, // o avaliador sintático pode restringir o tipo baseado nos construtos // de retornos encontrados nos blocos internos da função. const tipoRetornoDeduzido = tiposRetornos.values().next().value; tipoRetorno = tipoRetornoDeduzido; } else if (!temRetornosComValor && !definicaoExplicitaDeTipo) { // Ou, se não há retornos com valores, e não foi definido um tipo // explícito com 'qualquer', o tipo inferido é 'vazio'. tipoRetorno = 'vazio'; } } return tipoRetorno; } function registrarPrimitiva(primitivasConhecidas, tipo, catalogoPrimitivas) { primitivasConhecidas[tipo] = {}; for (const [nomePrimitiva, dadosPrimitiva] of Object.entries(catalogoPrimitivas)) { primitivasConhecidas[tipo][nomePrimitiva] = new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomePrimitiva, dadosPrimitiva.tipoRetorno, true, dadosPrimitiva.argumentos); } } //# sourceMappingURL=comum.js.map