Repository: DesignLiquido/delegua
Pull request #630 (2024-02-07 04:05:33)

#624 Descrever função com escreva
Resolve: https://github.com/DesignLiquido/delegua/issues/624


Patch:
diff --git a/fontes/estruturas/delegua-funcao.ts b/fontes/estruturas/delegua-funcao.ts
index dc23cb67..79b253d7 100644
--- a/fontes/estruturas/delegua-funcao.ts
+++ b/fontes/estruturas/delegua-funcao.ts
@@ -8,6 +8,7 @@ import { FuncaoConstruto } from '../construtos';
 import { ArgumentoInterface } from '../interpretador/argumento-interface';
 import { PilhaEscoposExecucaoInterface } from '../interfaces/pilha-escopos-execucao-interface';
 import { inferirTipoVariavel } from '../interpretador/inferenciador';
+import { Retorna } from '../declaracoes';
 
 /**
  * Qualquer função declarada em código é uma DeleguaFuncao.
@@ -37,7 +38,33 @@ export class DeleguaFuncao extends Chamavel {
 
     paraTexto(): string {
         if (this.nome === null) return '<função>';
-        return `<função ${this.nome}>`;
+        let resultado = `<função ${this.nome}`;
+        let parametros = '';
+        let retorno = '';
+
+        for (let parametro of this.declaracao.parametros) {
+            parametros += `${parametro.nome.lexema}${
+                parametro.tipoDado && parametro.tipoDado.tipo ? `: ${parametro.tipoDado.tipo}, ` : ', '
+            }`
+        }
+        if (this.declaracao.parametros.length > 0) {
+            parametros = `argumentos=<${parametros.slice(0, -2)}>`;
+        }
+
+        const retorna = this.declaracao.corpo.filter(c => c instanceof Retorna)[0];
+        if (retorna instanceof Retorna) {
+            const valor = retorna?.valor?.valor;
+            retorno = `retorna=<${typeof valor === 'number' ? valor : `'${valor}'`}>`
+        }
+
+        if (parametros) {
+            resultado += ` ${parametros}`
+        }
+        if (retorno) {
+            resultado += ` ${retorno}`
+        }
+        resultado += '>'
+        return resultado;
     }
 
     async chamar(visitante: VisitanteComumInterface, argumentos: Array<ArgumentoInterface>): Promise<any> {
diff --git a/fontes/estruturas/objeto-delegua-classe.ts b/fontes/estruturas/objeto-delegua-classe.ts
index 306ea3ba..42cdb2c4 100644
--- a/fontes/estruturas/objeto-delegua-classe.ts
+++ b/fontes/estruturas/objeto-delegua-classe.ts
@@ -44,7 +44,7 @@ export class ObjetoDeleguaClasse {
         this.propriedades[simbolo.lexema] = valor;
     }
 
-    toString(): string {
+    paraTexto(): string {
         return '<Objeto ' + this.classe.simboloOriginal.lexema + '>';
     }
 }
diff --git a/fontes/interpretador/interpretador-base.ts b/fontes/interpretador/interpretador-base.ts
index 416ec7e3..e88528e7 100644
--- a/fontes/interpretador/interpretador-base.ts
+++ b/fontes/interpretador/interpretador-base.ts
@@ -1591,8 +1591,9 @@ export class InterpretadorBase implements InterpretadorInterface {
 
         if (Array.isArray(objeto)) return objeto;
         if (objeto.valor instanceof ObjetoPadrao) return objeto.valor.paraTexto();
-        // TODO: Idealmente isso deveria devolver um texto estruturado representando o objeto.
-        if (objeto instanceof ObjetoDeleguaClasse) return objeto.toString();
+        if (objeto instanceof ObjetoDeleguaClasse 
+            || objeto instanceof DeleguaFuncao) 
+            return objeto.paraTexto();
         if (typeof objeto === tipoDeDadosPrimitivos.OBJETO) return JSON.stringify(objeto);
 
         return objeto.toString();


Test patch:
diff --git a/testes/interpretador.test.ts b/testes/interpretador.test.ts
index 35d46f30..9321efbb 100644
--- a/testes/interpretador.test.ts
+++ b/testes/interpretador.test.ts
@@ -15,6 +15,82 @@ describe('Interpretador', () => {
         });
 
         describe('Cenários de sucesso', () => {
+
+            describe('Descrever objetos - paraTexto()', () => {
+                it('Descrever função com parametros e tipos - DeleguaFuncao', async () => {
+                    let _saida: string = ""
+                    const retornoLexador = lexador.mapear([
+                        "funcao retorneAlgo(a: inteiro, b: texto) {",
+                        "}",
+                        "escreva(retorneAlgo)"
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+    
+                    interpretador.funcaoDeRetorno = (saida: any) => {
+                        _saida = saida;
+                    }
+    
+                    await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+    
+                    expect(_saida).toBe("<função retorneAlgo argumentos=<a: inteiro, b: texto>>");
+                });
+
+                it('Descrever função com parametros sem tipos - DeleguaFuncao', async () => {
+                    let _saida: string = ""
+                    const retornoLexador = lexador.mapear([
+                        "funcao retorneAlgo(a, b) {",
+                        "}",
+                        "escreva(retorneAlgo)"
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+    
+                    interpretador.funcaoDeRetorno = (saida: any) => {
+                        _saida = saida;
+                    }
+    
+                    await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+    
+                    expect(_saida).toBe("<função retorneAlgo argumentos=<a, b>>");
+                });
+
+                it('Descrever função com retorno - DeleguaFuncao', async () => {
+                    let _saida: string = ""
+                    const retornoLexador = lexador.mapear([
+                        "funcao retorneAlgo() {",
+                        "   retorna \"Algo\"",
+                        "}",
+                        "escreva(retorneAlgo)"
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+    
+                    interpretador.funcaoDeRetorno = (saida: any) => {
+                        _saida = saida;
+                    }
+    
+                    await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+    
+                    expect(_saida).toBe("<função retorneAlgo retorna=<'Algo'>>");
+                });
+
+                it('Descrever nome função - DeleguaFuncao', async () => {
+                    let _saida: string = ""
+                    const retornoLexador = lexador.mapear([
+                        "funcao retorneAlgo() {",
+                        "}",
+                        "escreva(retorneAlgo)"
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+    
+                    interpretador.funcaoDeRetorno = (saida: any) => {
+                        _saida = saida;
+                    }
+    
+                    await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+    
+                    expect(_saida).toBe("<função retorneAlgo>");
+                });
+            })
+
             describe('Atribuições', () => {
                 it('Trivial var/variavel', async () => {
                     const retornoLexador = lexador.mapear([