@designliquido/delegua
Version:
Linguagem de programação simples e moderna usando português estruturado.
114 lines • 5.33 kB
JavaScript
;
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