From 8aa27252fe5b469aa3ca1a376180d20185590987 Mon Sep 17 00:00:00 2001 From: VictorFrancelino Date: Fri, 6 Feb 2026 18:57:43 -0400 Subject: [PATCH 1/2] =?UTF-8?q?fix(bibliotecas):=20adicionar=20o=20uso=20o?= =?UTF-8?q?pcional=20do=20par=C3=A2metro=20'in=C3=ADcio'=20e=20adicionar?= =?UTF-8?q?=20o=20novo=20par=C3=A2metro=20'passo'=20na=20fun=C3=A7=C3=A3o?= =?UTF-8?q?=20intervalo()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fontes/bibliotecas/biblioteca-global.ts | 109 +++++++++++++----- .../dialetos/pitugues/biblioteca-global.ts | 109 +++++++++++++----- fontes/interpretador/comum.ts | 2 +- testes/interpretador/interpretador.test.ts | 42 +++++++ 4 files changed, 203 insertions(+), 59 deletions(-) diff --git a/fontes/bibliotecas/biblioteca-global.ts b/fontes/bibliotecas/biblioteca-global.ts index 1acbcb94..8715d9aa 100644 --- a/fontes/bibliotecas/biblioteca-global.ts +++ b/fontes/bibliotecas/biblioteca-global.ts @@ -810,47 +810,98 @@ export async function longo( * @param {InterpretadorInterface} interpretador A instância do interpretador. * @param {VariavelInterface | number} valorInicial O valor inicial (inclusivo). * @param {VariavelInterface | number} valorFinal O valor final (exclusivo). + * @param {VariavelInterface | number} valorPasso O valor do passo. * @returns {Promise} Um vetor com os números no intervalo. */ export async function intervalo( interpretador: InterpretadorInterface, valorInicial: VariavelInterface | number, - valorFinal: VariavelInterface | number + valorFinal?: VariavelInterface | number, + valorPasso?: VariavelInterface | number, ): Promise { - const inicio = interpretador.resolverValor(valorInicial); - const fim = interpretador.resolverValor(valorFinal); + const primeiroParam = interpretador.resolverValor(valorInicial); + const segundoParam = interpretador.resolverValor(valorFinal); + const terceiroParam = interpretador.resolverValor(valorPasso); - if (typeof inicio !== 'number' || typeof fim !== 'number') { - return Promise.reject( - new ErroEmTempoDeExecucao( - { - hashArquivo: interpretador.hashArquivoDeclaracaoAtual, - linha: interpretador.linhaDeclaracaoAtual, - } as SimboloInterface, - 'Os dois parâmetros devem ser do tipo número ou inteiro.' - ) - ); - } + let inicioInteiro: number; + let fimInteiro: number; + let passoInteiro: number = 1; - if (isNaN(inicio) || isNaN(fim)) { - return Promise.reject( - new ErroEmTempoDeExecucao( - { - hashArquivo: interpretador.hashArquivoDeclaracaoAtual, - linha: interpretador.linhaDeclaracaoAtual, - } as SimboloInterface, - 'Os dois parâmetros devem ser do tipo número ou inteiro.' - ) - ); + // intervalo(parada) - apenas um parâmetro + if (segundoParam === undefined || segundoParam === null) { + if (typeof primeiroParam !== 'number' || isNaN(primeiroParam)) { + return Promise.reject( + new ErroEmTempoDeExecucao( + { + hashArquivo: interpretador.hashArquivoDeclaracaoAtual, + linha: interpretador.linhaDeclaracaoAtual, + } as SimboloInterface, + 'O parâmetro deve ser do tipo número ou inteiro.' + ) + ); + } + + inicioInteiro = 0; + fimInteiro = Math.floor(primeiroParam); } + // intervalo(inicio, parada) ou intervalo(inicio, parada, passo) + else { + if (typeof primeiroParam !== 'number' || isNaN(primeiroParam) || + typeof segundoParam !== 'number' || isNaN(segundoParam)) { + return Promise.reject( + new ErroEmTempoDeExecucao( + { + hashArquivo: interpretador.hashArquivoDeclaracaoAtual, + linha: interpretador.linhaDeclaracaoAtual, + } as SimboloInterface, + 'Os parâmetros de início e fim devem ser do tipo número ou inteiro.' + ) + ); + } - // Remove a parte decimal se houver - const inicioInteiro = Math.floor(inicio); - const fimInteiro = Math.floor(fim); + inicioInteiro = Math.floor(primeiroParam); + fimInteiro = Math.floor(segundoParam); + + // Se há um terceiro parâmetro (passo) + if (terceiroParam !== undefined && terceiroParam !== null) { + if (typeof terceiroParam !== 'number' || isNaN(terceiroParam)) { + return Promise.reject( + new ErroEmTempoDeExecucao( + { + hashArquivo: interpretador.hashArquivoDeclaracaoAtual, + linha: interpretador.linhaDeclaracaoAtual, + } as SimboloInterface, + 'O parâmetro de passo deve ser do tipo número ou inteiro.' + ) + ); + } + + passoInteiro = Math.floor(terceiroParam); + if (passoInteiro === 0) { + return Promise.reject( + new ErroEmTempoDeExecucao( + { + hashArquivo: interpretador.hashArquivoDeclaracaoAtual, + linha: interpretador.linhaDeclaracaoAtual, + } as SimboloInterface, + 'O passo não pode ser zero.' + ) + ); + } + } + } const resultado = []; - for (let i = inicioInteiro; i < fimInteiro; i++) { - resultado.push(i); + + if (passoInteiro > 0) { + for (let i = inicioInteiro; i < fimInteiro; i += passoInteiro) { + resultado.push(i); + } + } else { + // Parâmetro passo sendo um número negativo + for (let i = inicioInteiro; i > fimInteiro; i += passoInteiro) { + resultado.push(i); + } } return Promise.resolve(resultado); diff --git a/fontes/bibliotecas/dialetos/pitugues/biblioteca-global.ts b/fontes/bibliotecas/dialetos/pitugues/biblioteca-global.ts index 5e85b07a..37a2f985 100644 --- a/fontes/bibliotecas/dialetos/pitugues/biblioteca-global.ts +++ b/fontes/bibliotecas/dialetos/pitugues/biblioteca-global.ts @@ -587,47 +587,98 @@ export async function inteiro( * @param {InterpretadorInterface} interpretador A instância do interpretador. * @param {VariavelInterface | number} valorInicial O valor inicial (inclusivo). * @param {VariavelInterface | number} valorFinal O valor final (exclusivo). + * @param {VariavelInterface | number} valorPasso O valor do passo. * @returns {Promise} Um vetor com os números no intervalo. */ export async function intervalo( interpretador: InterpretadorInterface, valorInicial: VariavelInterface | number, - valorFinal: VariavelInterface | number + valorFinal?: VariavelInterface | number, + valorPasso?: VariavelInterface | number, ): Promise { - const inicio = interpretador.resolverValor(valorInicial); - const fim = interpretador.resolverValor(valorFinal); + const primeiroParam = interpretador.resolverValor(valorInicial); + const segundoParam = interpretador.resolverValor(valorFinal); + const terceiroParam = interpretador.resolverValor(valorPasso); - if (typeof inicio !== 'number' || typeof fim !== 'number') { - return Promise.reject( - new ErroEmTempoDeExecucao( - { - hashArquivo: interpretador.hashArquivoDeclaracaoAtual, - linha: interpretador.linhaDeclaracaoAtual, - } as SimboloInterface, - 'Os dois parâmetros devem ser do tipo número ou inteiro.' - ) - ); - } + let inicioInteiro: number; + let fimInteiro: number; + let passoInteiro: number = 1; - if (isNaN(inicio) || isNaN(fim)) { - return Promise.reject( - new ErroEmTempoDeExecucao( - { - hashArquivo: interpretador.hashArquivoDeclaracaoAtual, - linha: interpretador.linhaDeclaracaoAtual, - } as SimboloInterface, - 'Os dois parâmetros devem ser do tipo número ou inteiro.' - ) - ); + // intervalo(parada) - apenas um parâmetro + if (segundoParam === undefined || segundoParam === null) { + if (typeof primeiroParam !== 'number' || isNaN(primeiroParam)) { + return Promise.reject( + new ErroEmTempoDeExecucao( + { + hashArquivo: interpretador.hashArquivoDeclaracaoAtual, + linha: interpretador.linhaDeclaracaoAtual, + } as SimboloInterface, + 'O parâmetro deve ser do tipo número ou inteiro.' + ) + ); + } + + inicioInteiro = 0; + fimInteiro = Math.floor(primeiroParam); } + // intervalo(inicio, parada) ou intervalo(inicio, parada, passo) + else { + if (typeof primeiroParam !== 'number' || isNaN(primeiroParam) || + typeof segundoParam !== 'number' || isNaN(segundoParam)) { + return Promise.reject( + new ErroEmTempoDeExecucao( + { + hashArquivo: interpretador.hashArquivoDeclaracaoAtual, + linha: interpretador.linhaDeclaracaoAtual, + } as SimboloInterface, + 'Os parâmetros de início e fim devem ser do tipo número ou inteiro.' + ) + ); + } - // Remove a parte decimal se houver - const inicioInteiro = Math.floor(inicio); - const fimInteiro = Math.floor(fim); + inicioInteiro = Math.floor(primeiroParam); + fimInteiro = Math.floor(segundoParam); + + // Se há um terceiro parâmetro (passo) + if (terceiroParam !== undefined && terceiroParam !== null) { + if (typeof terceiroParam !== 'number' || isNaN(terceiroParam)) { + return Promise.reject( + new ErroEmTempoDeExecucao( + { + hashArquivo: interpretador.hashArquivoDeclaracaoAtual, + linha: interpretador.linhaDeclaracaoAtual, + } as SimboloInterface, + 'O parâmetro de passo deve ser do tipo número ou inteiro.' + ) + ); + } + + passoInteiro = Math.floor(terceiroParam); + if (passoInteiro === 0) { + return Promise.reject( + new ErroEmTempoDeExecucao( + { + hashArquivo: interpretador.hashArquivoDeclaracaoAtual, + linha: interpretador.linhaDeclaracaoAtual, + } as SimboloInterface, + 'O passo não pode ser zero.' + ) + ); + } + } + } const resultado = []; - for (let i = inicioInteiro; i < fimInteiro; i++) { - resultado.push(i); + + if (passoInteiro > 0) { + for (let i = inicioInteiro; i < fimInteiro; i += passoInteiro) { + resultado.push(i); + } + } else { + // Parâmetro passo sendo um número negativo + for (let i = inicioInteiro; i > fimInteiro; i += passoInteiro) { + resultado.push(i); + } } return Promise.resolve(resultado); diff --git a/fontes/interpretador/comum.ts b/fontes/interpretador/comum.ts index 972de578..7a847969 100644 --- a/fontes/interpretador/comum.ts +++ b/fontes/interpretador/comum.ts @@ -56,7 +56,7 @@ export function carregarBibliotecasGlobais(pilhaEscoposExecucao: PilhaEscoposExe pilhaEscoposExecucao.definirVariavel('longo', new FuncaoPadrao(1, bibliotecaGlobal.longo)); - pilhaEscoposExecucao.definirVariavel('intervalo', new FuncaoPadrao(2, bibliotecaGlobal.intervalo)); + pilhaEscoposExecucao.definirVariavel('intervalo', new FuncaoPadrao(1, bibliotecaGlobal.intervalo)); pilhaEscoposExecucao.definirVariavel('mapear', new FuncaoPadrao(2, bibliotecaGlobal.mapear)); diff --git a/testes/interpretador/interpretador.test.ts b/testes/interpretador/interpretador.test.ts index ae40ad2d..2fec711d 100644 --- a/testes/interpretador/interpretador.test.ts +++ b/testes/interpretador/interpretador.test.ts @@ -1005,6 +1005,48 @@ describe('Interpretador', () => { expect(_saida).toBeTruthy(); expect(_saida).toBe('[0, 1, 2]'); }); + + it('Chamada a função nativa intervalo sem início definido', async () => { + let _saida: string = ''; + + const retornoLexador = lexador.mapear( + [ + 'escreva(intervalo(10))' + ], + -1 + ); + const retornoAvaliadorSintatico = await avaliadorSintatico.analisar(retornoLexador, -1); + + interpretador.funcaoDeRetorno = (saida: any) => { + _saida = saida; + }; + + await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + + expect(_saida).toBeTruthy(); + expect(_saida).toBe('[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'); + }); + + it('Chamada a função nativa intervalo com passo definido', async () => { + let _saida: string = ''; + + const retornoLexador = lexador.mapear( + [ + 'escreva(intervalo(0, 10, 2))' + ], + -1 + ); + const retornoAvaliadorSintatico = await avaliadorSintatico.analisar(retornoLexador, -1); + + interpretador.funcaoDeRetorno = (saida: any) => { + _saida = saida; + }; + + await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + + expect(_saida).toBeTruthy(); + expect(_saida).toBe('[0, 2, 4, 6, 8]'); + }); }); describe('Conversões entre tipos', () => { From 720356a1bde96f8cd3ae1ec3c3987ec78a3fa17d Mon Sep 17 00:00:00 2001 From: VictorFrancelino Date: Sat, 7 Feb 2026 16:02:13 -0400 Subject: [PATCH 2/2] =?UTF-8?q?feat(avaliador-sintatico)=20marcar=20como?= =?UTF-8?q?=20opcionais=20os=20par=C3=A2metros=20"valorParada"=20e=20"valo?= =?UTF-8?q?rPasso"=20da=20fun=C3=A7=C3=A3o=20"intervalo()".?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fontes/avaliador-sintatico/avaliador-sintatico.ts | 3 ++- .../dialetos/avaliador-sintatico-pitugues.ts | 3 ++- fontes/interpretador/comum.ts | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fontes/avaliador-sintatico/avaliador-sintatico.ts b/fontes/avaliador-sintatico/avaliador-sintatico.ts index 84ee1870..f9408925 100644 --- a/fontes/avaliador-sintatico/avaliador-sintatico.ts +++ b/fontes/avaliador-sintatico/avaliador-sintatico.ts @@ -3601,7 +3601,8 @@ export class AvaliadorSintatico 'intervalo', new InformacaoElementoSintatico('intervalo', 'inteiro[]', true, [ new InformacaoElementoSintatico('valorInicial', 'qualquer'), - new InformacaoElementoSintatico('valorFinal', 'qualquer'), + new InformacaoElementoSintatico('valorFinal', 'qualquer', false), + new InformacaoElementoSintatico('valorPasso', 'qualquer', false), ]) ); this.pilhaEscopos.definirInformacoesVariavel( diff --git a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.ts b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.ts index e11e26bc..10c609a0 100644 --- a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.ts +++ b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.ts @@ -2301,7 +2301,8 @@ export class AvaliadorSintaticoPitugues 'intervalo', new InformacaoElementoSintatico('intervalo', 'inteiro[]', true, [ new InformacaoElementoSintatico('valorInicial', 'qualquer'), - new InformacaoElementoSintatico('valorFinal', 'qualquer'), + new InformacaoElementoSintatico('valorFinal', 'qualquer', false), + new InformacaoElementoSintatico('valorPasso', 'qualquer', false), ]) ); this.pilhaEscopos.definirInformacoesVariavel( diff --git a/fontes/interpretador/comum.ts b/fontes/interpretador/comum.ts index 7a847969..4f348e08 100644 --- a/fontes/interpretador/comum.ts +++ b/fontes/interpretador/comum.ts @@ -56,7 +56,7 @@ export function carregarBibliotecasGlobais(pilhaEscoposExecucao: PilhaEscoposExe pilhaEscoposExecucao.definirVariavel('longo', new FuncaoPadrao(1, bibliotecaGlobal.longo)); - pilhaEscoposExecucao.definirVariavel('intervalo', new FuncaoPadrao(1, bibliotecaGlobal.intervalo)); + pilhaEscoposExecucao.definirVariavel('intervalo', new FuncaoPadrao(3, bibliotecaGlobal.intervalo)); pilhaEscoposExecucao.definirVariavel('mapear', new FuncaoPadrao(2, bibliotecaGlobal.mapear));