Repository: DesignLiquido/delegua (ts)

Issue:
`numero = leia_inteiros` deve ser resolvido como vetor

Pull request:
[potigol] - implementação leia multiplo
resolve #522

## Instruções para ler listas de valores

- `leia_inteiros(n)` para ler `n` números inteiro, um por linha
- `leia_reais(n)` para ler `n` números reais, um por linha
- `leia_textos(n)` para ler `n` linhas de texto

````potigol
números = leia_inteiros(5)      # lê um lista de 5 números inteiros, um por linha
````

- `leia_inteiros(s)` para ler vários números inteiros em uma mesma linha usando `s` como separador
- `leia_reais(s)` para ler vários números reais em uma mesma linha usando `s` como separador
- `leia_textos(s)` para ler vários textos em uma mesma linha usando `s` como separador

````potigol
números = leia_inteiros(",")    # lê uma lista de números inteiros separados por vírgula
````

Patch:
diff --git a/fontes/avaliador-sintatico/dialetos/potigol/avaliador-sintatico-potigol.ts b/fontes/avaliador-sintatico/dialetos/potigol/avaliador-sintatico-potigol.ts
index 9c3b6efa..661dae38 100644
--- a/fontes/avaliador-sintatico/dialetos/potigol/avaliador-sintatico-potigol.ts
+++ b/fontes/avaliador-sintatico/dialetos/potigol/avaliador-sintatico-potigol.ts
@@ -372,19 +372,16 @@ export class AvaliadorSintaticoPotigol extends AvaliadorSintaticoBase {
                     tiposDeSimbolos.PARENTESE_ESQUERDO,
                     `Esperado parêntese esquerdo após ${simboloLeiaDefinido.lexema}.`
                 );
-                if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.INTEIRO, tiposDeSimbolos.REAL)) {
-                    throw this.erro(
-                        this.simbolos[this.atual],
-                        `Esperado número de argumentos como inteiro ou real em ${simboloLeiaDefinido.lexema}`
-                    );
-                }
-                let numeroArgumentosLeia = this.simbolos[this.atual - 1];
+                
+                const argumento = this.expressao();
+                
                 this.consumir(
                     tiposDeSimbolos.PARENTESE_DIREITO,
                     `Esperado parêntese direito após número de parâmetros em chamada de ${simboloLeiaDefinido.lexema}.`
                 );
-                const leiaDefinido = new LeiaMultiplo(simboloLeiaDefinido, []);
-                leiaDefinido.numeroArgumentosEsperados = parseInt(numeroArgumentosLeia.literal);
+
+                const leiaDefinido = new LeiaMultiplo(simboloLeiaDefinido, argumento);
+
                 return leiaDefinido;
             default:
                 const simboloIdentificador: SimboloInterface = this.avancarEDevolverAnterior();
@@ -803,8 +800,7 @@ export class AvaliadorSintaticoPotigol extends AvaliadorSintaticoBase {
             if (inicializador instanceof Leia && identificadores.length > 1) {
                 inicializador = new LeiaMultiplo(
                     inicializador.simbolo,
-                    inicializador.argumentos,
-                    inicializador.numeroArgumentosEsperados
+                    inicializador.argumentos[0],
                 );
             }
 
@@ -821,18 +817,8 @@ export class AvaliadorSintaticoPotigol extends AvaliadorSintaticoBase {
                 );
             }
 
-            // `leia_inteiros`, `leia_reais` e `leia_textos` pedem um inteiro como argumento,
-            // que pode ser usado para verificar se a expressão faz sentido ou não aqui.
             const inicializadorLeia = <LeiaMultiplo>inicializadores[0];
-            if (inicializadorLeia.numeroArgumentosEsperados > 0) {
-                if (identificadores.length !== inicializadorLeia.numeroArgumentosEsperados) {
-                    throw this.erro(
-                        this.simbolos[this.atual],
-                        `Quantidade de identificadores à esquerda do igual é diferente da quantidade de valores passada por parâmetro à direita em ${inicializadorLeia.simbolo.lexema}.`
-                    );
-                }
-            }
-
+            
             let tipoConversao: TiposDadosInterface;
             switch (inicializadorLeia.simbolo.tipo) {
                 case tiposDeSimbolos.LEIA_INTEIROS:
diff --git a/fontes/declaracoes/leia-multiplo.ts b/fontes/declaracoes/leia-multiplo.ts
index 7103787b..263a9426 100644
--- a/fontes/declaracoes/leia-multiplo.ts
+++ b/fontes/declaracoes/leia-multiplo.ts
@@ -10,16 +10,14 @@ import { Declaracao } from './declaracao';
 export class LeiaMultiplo extends Declaracao {
     simbolo: SimboloInterface;
     id: string;
-    argumentos: Construto[];
-    tipo?: string;
-    numeroArgumentosEsperados?: number;
 
-    constructor(simbolo: SimboloInterface, argumentos: Construto[], numeroArgumentosEsperados?: number) {
+    argumento: Construto;
+
+    constructor(simbolo: SimboloInterface, argumento: Construto) {
         super(simbolo.linha, simbolo.hashArquivo);
         this.simbolo = simbolo;
         this.id = uuidv4();
-        this.argumentos = argumentos;
-        this.numeroArgumentosEsperados = numeroArgumentosEsperados;
+        this.argumento = argumento;
     }
 
     async aceitar(visitante: VisitanteComumInterface): Promise<any> {
diff --git a/fontes/interpretador/interpretador-base.ts b/fontes/interpretador/interpretador-base.ts
index 8430d547..62a9a80d 100644
--- a/fontes/interpretador/interpretador-base.ts
+++ b/fontes/interpretador/interpretador-base.ts
@@ -219,16 +219,30 @@ export class InterpretadorBase implements InterpretadorInterface {
      * @returns Promise com o resultado da leitura.
      */
     async visitarExpressaoLeiaMultiplo(expressao: LeiaMultiplo): Promise<any> {
-        const mensagem = expressao.argumentos && expressao.argumentos[0] ? expressao.argumentos[0].valor : '> ';
-        return new Promise((resolucao) =>
-            this.interfaceEntradaSaida.question(mensagem, (resposta: any) => {
-                resolucao(
-                    String(resposta)
-                        .split(/(\s+)/)
-                        .filter((r) => !/(\s+)/.test(r))
+        const mensagem = '> ';
+        if (expressao.argumento instanceof Literal) {
+            let valor = expressao.argumento.valor;
+            if (typeof valor === 'string') {
+                return new Promise((resolucao) =>
+                    this.interfaceEntradaSaida.question(mensagem, (resposta: any) => {
+                        resolucao(
+                            String(resposta)
+                                .split(valor)
+                                .filter((r) => !/(\s+)/.test(r))
+                        );
+                    })
                 );
-            })
-        );
+            }
+
+            let respostas = [];
+            for (let i = 0; i < valor; i++) {
+                this.interfaceEntradaSaida.question(mensagem, (resposta: any) => {
+                    respostas.push(resposta);
+                })
+            }
+            return Promise.resolve(respostas);
+        }
+        return Promise.resolve();
     }
 
     /**


Test patch:
diff --git a/testes/potigol/avaliador-sintatico.test.ts b/testes/potigol/avaliador-sintatico.test.ts
index f4819c00..68c24833 100644
--- a/testes/potigol/avaliador-sintatico.test.ts
+++ b/testes/potigol/avaliador-sintatico.test.ts
@@ -428,16 +428,6 @@ describe('Avaliador sintático', () => {
                     })
                 );
             });
-
-            it('Sucesso - Declaração de múltiplas constantes, lado direito usando `leia_inteiros` com número errado de parâmetros', () => {
-                const retornoLexador = lexador.mapear(['a, b, c = leia_inteiros(1)'], -1);
-                expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrow(ErroAvaliadorSintatico);
-                expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrow(
-                    expect.objectContaining({
-                        message: "Quantidade de identificadores à esquerda do igual é diferente da quantidade de valores passada por parâmetro à direita em leia_inteiros.",
-                    })
-                );
-            });
         });
     });
 });
diff --git a/testes/potigol/interpretador.test.ts b/testes/potigol/interpretador.test.ts
index afebfde3..caee27a4 100644
--- a/testes/potigol/interpretador.test.ts
+++ b/testes/potigol/interpretador.test.ts
@@ -154,8 +154,134 @@ describe('Interpretador', () => {
                 const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
                 expect(retornoInterpretador.erros).toHaveLength(0);
             });
+        })
 
+        describe('Leia Multiplo', () => {
+            it('Dado um leia_inteiros separador por virgula, escreva deve imprimir o valor lido', async () => {
+                const retornoLexador = lexador.mapear([
+                    'escreva(leia_inteiros(","))'
+                ], -1);
 
-        })
+                const resposta = '1,2,3';
+                interpretador.interfaceEntradaSaida = {
+                    question: (mensagem: string, callback: Function) => {
+                        callback(resposta);
+                    }
+                };
+
+                interpretador.funcaoDeRetorno = (saida: any) => {
+                    expect(saida).toEqual('[1, 2, 3]');
+                };
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoInterpretador.erros).toHaveLength(0);
+            });
+
+            it('Dado um leia_inteiros, escreva deve imprimir o valor lido', async () => {
+                const retornoLexador = lexador.mapear([
+                    'escreva(leia_inteiros(3))'
+                ], -1);
+
+                const respostas = [1, 2, 3];
+                interpretador.interfaceEntradaSaida = {
+                    question: (mensagem: string, callback: Function) => {
+                        callback(respostas.shift());
+                    }
+                };
+
+                interpretador.funcaoDeRetorno = (saida: any) => {
+                    expect(saida).toEqual('[1, 2, 3]');
+                };
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoInterpretador.erros).toHaveLength(0);
+            });
+
+            it('Dado um leia_reais separador por virgula, escreva deve imprimir o valor lido', async () => {
+                const retornoLexador = lexador.mapear([
+                    'escreva(leia_reais(","))'
+                ], -1);
+
+                const resposta = '1,2,3';
+                interpretador.interfaceEntradaSaida = {
+                    question: (mensagem: string, callback: Function) => {
+                        callback(resposta);
+                    }
+                };
+
+                interpretador.funcaoDeRetorno = (saida: any) => {
+                    expect(saida).toEqual('[1, 2, 3]');
+                };
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoInterpretador.erros).toHaveLength(0);
+            });
+
+            it('Dado um leia_reais, escreva deve imprimir o valor lido', async () => {
+                const retornoLexador = lexador.mapear([
+                    'escreva(leia_reais(3))'
+                ], -1);
+
+                const respostas = [1, 2, 3];
+                interpretador.interfaceEntradaSaida = {
+                    question: (mensagem: string, callback: Function) => {
+                        callback(respostas.shift());
+                    }
+                };
+
+                interpretador.funcaoDeRetorno = (saida: any) => {
+                    expect(saida).toEqual('[1, 2, 3]');
+                };
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoInterpretador.erros).toHaveLength(0);
+            });
+
+            it('Dado um leia_textos separador por virgula, escreva deve imprimir o valor lido', async () => {
+                const retornoLexador = lexador.mapear([
+                    'escreva(leia_textos(","))'
+                ], -1);
+
+                const resposta = 'a,b,c';
+                interpretador.interfaceEntradaSaida = {
+                    question: (mensagem: string, callback: Function) => {
+                        callback(resposta);
+                    }
+                };
+
+                interpretador.funcaoDeRetorno = (saida: any) => {
+                    expect(saida).toEqual('[a, b, c]');
+                };
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoInterpretador.erros).toHaveLength(0);
+            });
+
+            it('Dado um leia_textos, escreva deve imprimir o valor lido', async () => {
+                const retornoLexador = lexador.mapear([
+                    'escreva(leia_textos(3))'
+                ], -1);
+
+                const respostas = ['a', 'b', 'c'];
+                interpretador.interfaceEntradaSaida = {
+                    question: (mensagem: string, callback: Function) => {
+                        callback(respostas.shift());
+                    }
+                };
+
+                interpretador.funcaoDeRetorno = (saida: any) => {
+                    expect(saida).toEqual('[a, b, c]');
+                };
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoInterpretador.erros).toHaveLength(0);
+            });
+        });
     });
 });