Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion fontes/avaliador-sintatico/avaliador-sintatico.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
109 changes: 80 additions & 29 deletions fontes/bibliotecas/biblioteca-global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<number[]>} 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<number[]> {
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);
Expand Down
109 changes: 80 additions & 29 deletions fontes/bibliotecas/dialetos/pitugues/biblioteca-global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<number[]>} 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<number[]> {
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);
Expand Down
2 changes: 1 addition & 1 deletion fontes/interpretador/comum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(3, bibliotecaGlobal.intervalo));

pilhaEscoposExecucao.definirVariavel('mapear', new FuncaoPadrao(2, bibliotecaGlobal.mapear));

Expand Down
42 changes: 42 additions & 0 deletions testes/interpretador/interpretador.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
Loading