From 3cc86e7eb203af26b07fd5066faa2f290cd5fe66 Mon Sep 17 00:00:00 2001 From: Leonel Sanches da Silva Date: Tue, 27 Feb 2024 11:33:24 -0800 Subject: [PATCH] =?UTF-8?q?Corrigindo=20o=20comportamento=20de=20`leia=5Fi?= =?UTF-8?q?nteiro`=20para=20vari=C3=A1veis=20e=20constantes=20=C3=A0=20esq?= =?UTF-8?q?uerda=20da=20atribui=C3=A7=C3=A3o.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fontes/interpretador/comum.ts | 72 ++++++++++++++++++- .../interpretador-potigol-com-depuracao.ts | 15 +++- fontes/interpretador/interpretador-potigol.ts | 41 ++--------- testes/interpretador.test.ts | 33 ++++++++- 4 files changed, 123 insertions(+), 38 deletions(-) diff --git a/fontes/interpretador/comum.ts b/fontes/interpretador/comum.ts index 001c952..d73555c 100644 --- a/fontes/interpretador/comum.ts +++ b/fontes/interpretador/comum.ts @@ -1,4 +1,4 @@ -import { AcessoMetodoOuPropriedade } from '@designliquido/delegua/construtos'; +import { AcessoMetodoOuPropriedade, Binario, ConstanteOuVariavel, Construto, Literal, QualTipo, Unario, Variavel } from '@designliquido/delegua/construtos'; import { DeleguaModulo, MetodoPrimitiva, ObjetoDeleguaClasse } from '@designliquido/delegua/estruturas'; import { VariavelInterface } from '@designliquido/delegua/interfaces'; import { ErroEmTempoDeExecucao } from '@designliquido/delegua/excecoes'; @@ -8,6 +8,7 @@ import { inferirTipoVariavel } from './inferenciador'; import primitivasNumero from '../bibliotecas/primitivas-numero'; import primitivasTexto from '../bibliotecas/primitivas-texto'; import primitivasVetor from '../bibliotecas/primitivas-vetor'; +import { LeiaMultiplo } from '@designliquido/delegua'; /** * Executa um acesso a método, normalmente de um objeto de classe. @@ -83,6 +84,75 @@ export async function visitarExpressaoAcessoMetodo( ); } +export async function visitarExpressaoLeiaMultiplo( + interpretador: InterpretadorBase, + expressao: LeiaMultiplo +): Promise { + let respostas = []; + // O argumento sempre vem preenchido aqui. + // Se for um literal, o literal contém o número de valores a serem lidos + // da entrada. + let valores = 0; + const argumento = expressao.argumento; + if (argumento instanceof Literal) { + valores = argumento.valor; + } + + for (let i = 0; i < valores; i++) { + await interpretador.interfaceEntradaSaida.question('> ', (resposta: any) => { + respostas.push(resposta); + }); + } + + return Promise.resolve(respostas); +} + +export async function visitarExpressaoQualTipo( + interpretador: InterpretadorBase, + expressao: QualTipo +): Promise { + let qualTipo = expressao.valor; + + if (expressao?.valor instanceof ConstanteOuVariavel) { + const nome = expressao?.valor.simbolo.lexema; + qualTipo = interpretador.pilhaEscoposExecucao.topoDaPilha().ambiente.valores[nome].valor; + } + + if ( + qualTipo instanceof Binario || + qualTipo instanceof Literal || + qualTipo instanceof QualTipo || + qualTipo instanceof Unario || + qualTipo instanceof Variavel + ) { + qualTipo = await interpretador.avaliar(qualTipo); + return qualTipo.tipo || inferirTipoVariavel(qualTipo); + } + + return inferirTipoVariavel(qualTipo?.valores || qualTipo); +} + +export async function avaliarArgumentosEscreva( + interpretador: InterpretadorBase, + argumentos: Construto[] +): Promise { + let formatoTexto: string = ''; + + for (const argumento of argumentos) { + const resultadoAvaliacao = await interpretador.avaliar(argumento); + let valor = resultadoAvaliacao?.hasOwnProperty('valor') ? resultadoAvaliacao.valor : resultadoAvaliacao; + formatoTexto += `${interpretador.paraTexto(valor)},`; + } + + formatoTexto = formatoTexto.slice(0, -1); + + if (argumentos.length > 1) { + formatoTexto = `(${formatoTexto})`; + } + + return formatoTexto; +} + /** * Resolve todas as interpolações em um texto. * @param {texto} textoOriginal O texto original com as variáveis interpoladas. diff --git a/fontes/interpretador/interpretador-potigol-com-depuracao.ts b/fontes/interpretador/interpretador-potigol-com-depuracao.ts index 23fab8e..beccba7 100644 --- a/fontes/interpretador/interpretador-potigol-com-depuracao.ts +++ b/fontes/interpretador/interpretador-potigol-com-depuracao.ts @@ -1,8 +1,9 @@ import { registrarBibliotecaGlobalPotigol } from '@designliquido/delegua/bibliotecas/dialetos/potigol/biblioteca-global'; -import { AcessoMetodoOuPropriedade } from '@designliquido/delegua/construtos'; +import { AcessoMetodoOuPropriedade, Construto, QualTipo } from '@designliquido/delegua/construtos'; import { InterpretadorComDepuracao } from '@designliquido/delegua/interpretador/interpretador-com-depuracao'; import * as comum from './comum'; +import { LeiaMultiplo } from '@designliquido/delegua'; export class InterpretadorPotigolComDepuracao extends InterpretadorComDepuracao { constructor(diretorioBase: string, funcaoDeRetorno: Function = null, funcaoDeRetornoMesmaLinha: Function = null) { @@ -24,4 +25,16 @@ export class InterpretadorPotigolComDepuracao extends InterpretadorComDepuracao async visitarExpressaoAcessoMetodo(expressao: AcessoMetodoOuPropriedade): Promise { return comum.visitarExpressaoAcessoMetodo(this, expressao); } + + async visitarExpressaoLeiaMultiplo(expressao: LeiaMultiplo): Promise { + return comum.visitarExpressaoLeiaMultiplo(this, expressao); + } + + async visitarExpressaoQualTipo(expressao: QualTipo): Promise { + return comum.visitarExpressaoQualTipo(this, expressao); + } + + async avaliarArgumentosEscreva(argumentos: Construto[]): Promise { + return comum.avaliarArgumentosEscreva(this, argumentos); + } } diff --git a/fontes/interpretador/interpretador-potigol.ts b/fontes/interpretador/interpretador-potigol.ts index af1ed49..8e0b79d 100644 --- a/fontes/interpretador/interpretador-potigol.ts +++ b/fontes/interpretador/interpretador-potigol.ts @@ -16,6 +16,7 @@ import { InterpretadorInterfacePotigol } from '../interfaces/interpretador-inter import { registrarBibliotecaGlobalPotigol } from '../bibliotecas/biblioteca-global'; import { inferirTipoVariavel } from './inferenciador'; import * as comum from './comum'; +import { LeiaMultiplo } from '@designliquido/delegua'; /** * Uma implementação do interpretador de Potigol. @@ -67,43 +68,15 @@ export class InterpretadorPotigol extends InterpretadorBase implements Interpret return comum.visitarExpressaoAcessoMetodo(this, expressao); } - async visitarExpressaoQualTipo(expressao: QualTipo): Promise { - let qualTipo = expressao.valor; - - if (expressao?.valor instanceof ConstanteOuVariavel) { - const nome = expressao?.valor.simbolo.lexema; - qualTipo = this.pilhaEscoposExecucao.topoDaPilha().ambiente.valores[nome].valor; - } - - if ( - qualTipo instanceof Binario || - qualTipo instanceof Literal || - qualTipo instanceof QualTipo || - qualTipo instanceof Unario || - qualTipo instanceof Variavel - ) { - qualTipo = await this.avaliar(qualTipo); - return qualTipo.tipo || inferirTipoVariavel(qualTipo); - } + async visitarExpressaoLeiaMultiplo(expressao: LeiaMultiplo): Promise { + return comum.visitarExpressaoLeiaMultiplo(this, expressao); + } - return inferirTipoVariavel(qualTipo?.valores || qualTipo); + async visitarExpressaoQualTipo(expressao: QualTipo): Promise { + return comum.visitarExpressaoQualTipo(this, expressao); } protected async avaliarArgumentosEscreva(argumentos: Construto[]): Promise { - let formatoTexto: string = ''; - - for (const argumento of argumentos) { - const resultadoAvaliacao = await this.avaliar(argumento); - let valor = resultadoAvaliacao?.hasOwnProperty('valor') ? resultadoAvaliacao.valor : resultadoAvaliacao; - formatoTexto += `${this.paraTexto(valor)},`; - } - - formatoTexto = formatoTexto.slice(0, -1); - - if (argumentos.length > 1) { - formatoTexto = `(${formatoTexto})`; - } - - return formatoTexto; + return comum.avaliarArgumentosEscreva(this, argumentos); } } diff --git a/testes/interpretador.test.ts b/testes/interpretador.test.ts index 116d211..d3c836d 100644 --- a/testes/interpretador.test.ts +++ b/testes/interpretador.test.ts @@ -272,7 +272,7 @@ describe('Interpretador', () => { }); }); - describe('Leia vetores', () => { + describe('Leia inteiros', () => { it('Dado um leia_inteiros separador por virgula, escreva deve imprimir o valor lido', async () => { const retornoLexador = lexador.mapear([ 'escreva(leia_inteiros(","))' @@ -299,7 +299,7 @@ describe('Interpretador', () => { 'escreva(leia_inteiros(3))' ], -1); - const respostas = [1, 2, 3]; + const respostas = ["1", "2", "3"]; interpretador.interfaceEntradaSaida = { question: (mensagem: string, callback: Function) => { callback(respostas.shift()); @@ -315,6 +315,33 @@ describe('Interpretador', () => { expect(retornoInterpretador.erros).toHaveLength(0); }); + it('leia_inteiros, lado esquerdo com constantes', async () => { + const saidas: string[] = []; + const retornoLexador = lexador.mapear([ + 'a, b = leia_inteiro', + 'escreva "X = {a + b}"' + ], -1); + + const respostas = ["1", "2"]; + interpretador.interfaceEntradaSaida = { + question: (mensagem: string, callback: Function) => { + callback(respostas.shift()); + } + }; + + interpretador.funcaoDeRetorno = (saida: any) => { + saidas.push(saida); + }; + + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); + expect(retornoInterpretador.erros).toHaveLength(0); + expect(saidas).toHaveLength(1); + expect(saidas[0]).toBe('X = 3'); + }); + }); + + describe('Leia reais', () => { it('Dado um leia_reais separador por virgula, escreva deve imprimir o valor lido', async () => { const retornoLexador = lexador.mapear([ 'escreva(leia_reais(","))' @@ -356,7 +383,9 @@ describe('Interpretador', () => { const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes); expect(retornoInterpretador.erros).toHaveLength(0); }); + }); + describe('Leia textos', () => { it('Dado um leia_textos separador por virgula, escreva deve imprimir o valor lido', async () => { const retornoLexador = lexador.mapear([ 'escreva(leia_textos(","))'