Repository: DesignLiquido/delegua
Pull request #410 (2023-05-24 20:02:33)

Tradução delégua para python melhorias

github-actions[bot]: <!-- jest coverage report action for options with hash 781087021f8e6c43aac1e668f4520603 -->

## Coverage report 



| <div title="Status of coverage:&#10; 🟢 - ok&#10; 🟡 - slightly more than threshold&#10; 🔴 - under the threshold">St.<sup>:grey_question:</sup></div> | Category   | Percentage                                                     | Covered / Total |
| :----------------------------------------------------------------------------------------------------------------------------------------------------: | :--------- | :------------------------------------------------------------- | :-------------: |
|                                                                           🔴                                                                           | Statements | <div title="Base coverage is: 54.62%">54.82% (+0.2% 🔼)</div>  |    7484/13652   |
|                                                                           🔴                                                                           | Branches   | <div title="Base coverage is: 45.03%">45.12% (+0.1% 🔼)</div>  |    2276/5044    |
|                                                                           🔴                                                                           | Functions  | <div title="Base coverage is: 47.95%">48.13% (+0.18% 🔼)</div> |    1084/2252    |
|                                                                           🔴                                                                           | Lines      | <div title="Base coverage is: 54.49%">54.7% (+0.21% 🔼)</div>  |    7315/13373   |


<details><summary>Show files with reduced coverage 🔻</summary>
<br/>

| <div title="Status of coverage:&#10; 🟢 - ok&#10; 🟡 - slightly more than threshold&#10; 🔴 - under the threshold">St.<sup>:grey_question:</sup></div> | File                                                                                                            | Statements                                                     | Branches                                                       | Functions | Lines                                                          |
| :----------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------- | :------------------------------------------------------------- | :-------- | :------------------------------------------------------------- |
|                                                                           🟡                                                                           | <div title="avaliador-sintatico/dialetos/avaliador-sintatico-birl.ts">`...` / avaliador-sintatico-birl.ts</div> | <div title="Base coverage is: 78.04%">77.45% (-0.59% 🔻)</div> | <div title="Base coverage is: 67.92%">66.04% (-1.89% 🔻)</div> | 81.08%    | <div title="Base coverage is: 78.04%">77.45% (-0.59% 🔻)</div> |

</details>

## Test suite run success
521 tests passing in 45 suites.

<p align="right">Report generated by <a href="https://github.com/ArtiomTr/jest-coverage-report-action">🧪jest coverage report action</a> from 91edccab973d6c3df1abc68548c3f8bc0c0c014c</p>
<!-- Sticky Pull Request Comment -->

Patch:
diff --git a/fontes/tradutores/tradutor-python.ts b/fontes/tradutores/tradutor-python.ts
index f5cb1ef7..8e3279e6 100644
--- a/fontes/tradutores/tradutor-python.ts
+++ b/fontes/tradutores/tradutor-python.ts
@@ -1,5 +1,5 @@
-import { Agrupamento, Atribuir, Binario, Chamada, Literal, Logico, Variavel, Vetor } from "../construtos";
-import { Bloco, Declaracao, Escreva, Expressao, FuncaoDeclaracao, Leia, ParaCada, Retorna, Se, Var } from "../declaracoes";
+import { AcessoMetodo, Agrupamento, Atribuir, Binario, Chamada, DefinirValor, Isto, Literal, Logico, Variavel, Vetor } from "../construtos";
+import { Bloco, Classe, Const, Declaracao, Escreva, Expressao, FuncaoDeclaracao, Leia, ParaCada, Retorna, Se, Tente, Var } from "../declaracoes";
 import { SimboloInterface, TradutorInterface } from "../interfaces";
 import tiposDeSimbolos from '../tipos-de-simbolos/delegua';
 
@@ -72,6 +72,42 @@ export class TradutorPython implements TradutorInterface {
         return resultado;
     }
 
+    traduzirDeclaracaoTente(declaracaoTente: Tente): string {
+        let resultado = 'try:\n';
+        this.indentacao += 4;
+        resultado += ' '.repeat(this.indentacao);
+
+        for (let condicao of declaracaoTente.caminhoTente) {
+            resultado += this.dicionarioDeclaracoes[condicao.constructor.name](condicao) + '\n';
+            resultado += ' '.repeat(this.indentacao);
+        }
+
+        if (declaracaoTente.caminhoPegue !== null) {
+            resultado += '\nexcept:\n';
+            resultado += ' '.repeat(this.indentacao);
+            if (Array.isArray(declaracaoTente.caminhoPegue)) {
+                for (let declaracao of declaracaoTente.caminhoPegue) {
+                    resultado += this.dicionarioDeclaracoes[declaracao.constructor.name](declaracao) + '\n';
+                }
+            } else {
+                for (let corpo of declaracaoTente.caminhoPegue.corpo) {
+                    resultado += this.dicionarioDeclaracoes[corpo.constructor.name](corpo) + '\n';
+                }
+            }
+
+            resultado += ' '.repeat(this.indentacao);
+        }
+        if (declaracaoTente.caminhoFinalmente !== null) {
+            resultado += '\nfinally:\n';
+            resultado += ' '.repeat(this.indentacao);
+            for (let finalmente of declaracaoTente.caminhoFinalmente) {
+                resultado += this.dicionarioDeclaracoes[finalmente.constructor.name](finalmente) + '\n';
+            }
+        }
+
+        return resultado;
+    }
+
     traduzirConstrutoLogico(logico: Logico): string {
         let direita = this.dicionarioConstrutos[logico.direita.constructor.name](logico.direita);
         let operador = this.traduzirSimboloOperador(logico.operador);
@@ -88,6 +124,14 @@ export class TradutorPython implements TradutorInterface {
         if (!literal.valor) return 'None';
         return literal.valor;
     }
+
+    trazudirConstrutoAcessoMetodo(acessoMetodo: AcessoMetodo): string {
+        if (acessoMetodo.objeto instanceof Variavel) {
+            let objetoVariavel = acessoMetodo.objeto as Variavel;
+            return `${objetoVariavel.simbolo.lexema}.${acessoMetodo.simbolo.lexema}`;
+        }
+        return `self.${acessoMetodo.simbolo.lexema}`;
+    }
     
     traduzirDeclaracaoEscreva(declaracaoEscreva: Escreva): string {
         let resultado = 'print(';
@@ -160,7 +204,6 @@ export class TradutorPython implements TradutorInterface {
 
         if (declaracaoSe.caminhoSenao !== null) {
             resultado += ' '.repeat(this.indentacao);
-            // resultado += 'else ';
             const se = declaracaoSe?.caminhoSenao as Se;
             if (se?.caminhoEntao) {
                 resultado += 'elif ';
@@ -185,28 +228,59 @@ export class TradutorPython implements TradutorInterface {
         return resultado;
     }
 
+    logicaTraducaoMetodoClasse(metodoClasse: FuncaoDeclaracao): string {
+        this.indentacao += 4;
+        let resultado = ' '.repeat(this.indentacao);
+        let temContrutor = metodoClasse.simbolo.lexema === 'construtor';
+        resultado += temContrutor ? 'def __init__(' : 'def ' + metodoClasse.simbolo.lexema + '(';
+        
+        let temParametros = metodoClasse.funcao.parametros.length;
+        resultado += temParametros ? 'self, ' : 'self'
+
+        for (let parametro of metodoClasse.funcao.parametros) {
+            resultado += parametro.nome.lexema + ', ';
+        }
+        if (metodoClasse.funcao.parametros.length > 0) {
+            resultado = resultado.slice(0, -2);
+        }
+
+        resultado += '):\n';
+        resultado += this.logicaComumBlocoEscopo(metodoClasse.funcao.corpo);
+        resultado += ' '.repeat(this.indentacao) + '\n';
+
+        this.indentacao -= 4;
+        return resultado;
+    }
+
+    traduzirDeclaracaoClasse(declaracaoClasse: Classe): string {
+        let resultado = 'class ';
+
+        if (declaracaoClasse.superClasse)
+            resultado += `${declaracaoClasse.simbolo.lexema} extends ${declaracaoClasse.superClasse.simbolo.lexema} {\n`;
+        else resultado += declaracaoClasse.simbolo.lexema + ':\n';
+
+        for (let metodo of declaracaoClasse.metodos) {
+            resultado += this.logicaTraducaoMetodoClasse(metodo);
+        }
+
+        return resultado;
+    }
+
     traduzirConstrutoChamada(chamada: Chamada): string {
         let resultado = '';
 
-        // const retorno = `${this.dicionarioConstrutos[chamada.entidadeChamada.constructor.name](
-        //     chamada.entidadeChamada
-        // )}`;
-
-        // const instanciaClasse = this.declaracoesDeClasses.some((declaracao) => declaracao?.simbolo?.lexema === retorno);
-        // if (instanciaClasse) {
-        //     const classe = this.declaracoesDeClasses.find((declaracao) => declaracao?.simbolo?.lexema === retorno);
-        //     if (classe.simbolo.lexema === retorno) resultado += `new ${retorno}`;
-        // } else {
-        //     resultado += retorno;
-        // }
-        // resultado += '(';
-        // for (let parametro of chamada.argumentos) {
-        //     resultado += this.dicionarioConstrutos[parametro.constructor.name](parametro) + ', ';
-        // }
-        // if (chamada.argumentos.length > 0) {
-        //     resultado = resultado.slice(0, -2);
-        // }
-        // resultado += ')';
+        const retorno = `${this.dicionarioConstrutos[chamada.entidadeChamada.constructor.name](
+            chamada.entidadeChamada
+        )}`;
+        resultado += retorno;
+        resultado += '(';
+        for (let parametro of chamada.argumentos) {
+            resultado += this.dicionarioConstrutos[parametro.constructor.name](parametro) + ', ';
+        }
+        if (chamada.argumentos.length > 0) {
+            resultado = resultado.slice(0, -2);
+        }
+        resultado += ')';
         return resultado;
     }
 
@@ -235,11 +309,19 @@ export class TradutorPython implements TradutorInterface {
         return resultado;
     }
 
+    traduzirConstrutoDefinirValor(definirValor: DefinirValor): string {
+        let resultado = '';
+        if (definirValor.objeto instanceof Isto) {
+            resultado = 'self.' + definirValor.nome.lexema + ' = ';
+        }
+
+        resultado += definirValor.valor.simbolo.lexema;
+        return resultado;
+    }
+
     traduzirDeclaracaoVar(declaracaoVar: Var): string {
         let resultado = '';
         resultado += declaracaoVar.simbolo.lexema;
-        // if (!declaracaoVar?.inicializador) resultado += ';';
-        // else {
         resultado += ' = ';
         if (this.dicionarioConstrutos[declaracaoVar.inicializador.constructor.name]) {
             resultado += this.dicionarioConstrutos[declaracaoVar.inicializador.constructor.name](
@@ -250,7 +332,23 @@ export class TradutorPython implements TradutorInterface {
                 declaracaoVar.inicializador
             );
         }
-        // }
+        return resultado;
+    }
+
+    traduzirDeclaracaoConst(declaracaoConst: Const): string {
+        let resultado = '';
+        resultado += declaracaoConst.simbolo.lexema;
+        resultado += ' = ';
+        if (this.dicionarioConstrutos[declaracaoConst.inicializador.constructor.name]) {
+            resultado += this.dicionarioConstrutos[declaracaoConst.inicializador.constructor.name](
+                declaracaoConst.inicializador
+            );
+        } else {
+            resultado += this.dicionarioDeclaracoes[declaracaoConst.inicializador.constructor.name](
+                declaracaoConst.inicializador
+            );
+        }
+        
         return resultado;
     }
 
@@ -286,10 +384,12 @@ export class TradutorPython implements TradutorInterface {
     }
     
     dicionarioConstrutos = {
+        AcessoMetodo: this.trazudirConstrutoAcessoMetodo.bind(this),
         Agrupamento: this.traduzirConstrutoAgrupamento.bind(this),
         Atribuir: this.traduzirConstrutoAtribuir.bind(this),
         Binario: this.traduzirConstrutoBinario.bind(this),
         Chamada: this.traduzirConstrutoChamada.bind(this),
+        DefinirValor: this.traduzirConstrutoDefinirValor.bind(this),
         Literal: this.traduzirConstrutoLiteral.bind(this),
         Logico: this.traduzirConstrutoLogico.bind(this),
         Variavel: this.traduzirConstrutoVariavel.bind(this),
@@ -298,6 +398,8 @@ export class TradutorPython implements TradutorInterface {
 
     dicionarioDeclaracoes = {
         Bloco: this.traduzirDeclaracaoBloco.bind(this),
+        Classe: this.traduzirDeclaracaoClasse.bind(this),
+        Const : this.traduzirDeclaracaoConst.bind(this),
         Continua: () => 'continue',
         Escreva: this.traduzirDeclaracaoEscreva.bind(this),
         Expressao: this.traduzirDeclaracaoExpressao.bind(this),
@@ -307,6 +409,7 @@ export class TradutorPython implements TradutorInterface {
         Retorna: this.traduzirDeclaracaoRetorna.bind(this),
         Se: this.traduzirDeclaracaoSe.bind(this),
         Sustar: () => 'break',
+        Tente: this.traduzirDeclaracaoTente.bind(this),
         Var: this.traduzirDeclaracaoVar.bind(this),
     }
 


Test patch:
diff --git a/testes/tradutores/tradutor-python.test.ts b/testes/tradutores/tradutor-python.test.ts
index aee6b863..5ee8cdbe 100644
--- a/testes/tradutores/tradutor-python.test.ts
+++ b/testes/tradutores/tradutor-python.test.ts
@@ -50,6 +50,7 @@ describe('Tradutor Delégua -> Python', () => {
                     'var c = verdadeiro',
                     'var d = falso',
                     'var f = nulo',
+                    'const g = \'olá\'',
                     '2 * 2'
                 ], 
                 -1
@@ -65,6 +66,7 @@ describe('Tradutor Delégua -> Python', () => {
             expect(resultado).toMatch(/c = True/i);
             expect(resultado).toMatch(/d = False/i);
             expect(resultado).toMatch(/f = None/i);
+            expect(resultado).toMatch(/g = \'olá\'/i);
             expect(resultado).toMatch(/2 \* 2/i);
         });
 
@@ -151,7 +153,7 @@ describe('Tradutor Delégua -> Python', () => {
             expect(resultado).toMatch(/print\(\'Valor: \', elemento\)/i);
         });
 
-        it('função com retorno nulo -> function', () => {
+        it('função com retorno nulo -> def', () => {
             const codigo = ['funcao minhaFuncao() { retorna nulo }'];
             const retornoLexador = lexador.mapear(codigo, -1);
             const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
@@ -162,7 +164,7 @@ describe('Tradutor Delégua -> Python', () => {
             expect(resultado).toMatch(/return None/i);
         });
 
-        it('função com retorno lógico de texto e número -> function', () => {
+        it('função com retorno lógico de texto e número -> def', () => {
             const codigo = ["funcao minhaFuncao() { retorna '1' == 1 }"];
             const retornoLexador = lexador.mapear(codigo, -1);
             const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
@@ -173,7 +175,7 @@ describe('Tradutor Delégua -> Python', () => {
             expect(resultado).toMatch(/return '1' == 1/i);
         });
 
-        it('função com retorno lógico de número -> function', () => {
+        it('função com retorno lógico de número -> def', () => {
             const codigo = ['funcao minhaFuncao() { retorna 1 == 1 }'];
             const retornoLexador = lexador.mapear(codigo, -1);
             const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
@@ -184,7 +186,7 @@ describe('Tradutor Delégua -> Python', () => {
             expect(resultado).toMatch(/return 1 == 1/i);
         });
 
-        it('função com retorno lógico de texto -> function', () => {
+        it('função com retorno lógico de texto -> def', () => {
             const codigo = ["funcao minhaFuncao() { retorna '1' == '1' }"];
             const retornoLexador = lexador.mapear(codigo, -1);
             const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
@@ -195,7 +197,7 @@ describe('Tradutor Delégua -> Python', () => {
             expect(resultado).toMatch(/return '1' == '1'/i);
         });
 
-        it('função com retorno número -> function', () => {
+        it('função com retorno número -> def', () => {
             const codigo = ['funcao minhaFuncao() { retorna 10 }'];
             const retornoLexador = lexador.mapear(codigo, -1);
             const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
@@ -206,7 +208,7 @@ describe('Tradutor Delégua -> Python', () => {
             expect(resultado).toMatch(/return 10/i);
         });
 
-        it('função com retorno texto -> function', () => {
+        it('função com retorno texto -> def', () => {
             const codigo = ["funcao minhaFuncao() { retorna 'Ola Mundo!!!' }"];
             const retornoLexador = lexador.mapear(codigo, -1);
             const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
@@ -217,7 +219,7 @@ describe('Tradutor Delégua -> Python', () => {
             expect(resultado).toMatch(/return 'Ola Mundo!!!'/i);
         });
 
-        it('função com retorno -> function', () => {
+        it('função com retorno -> def', () => {
             const codigo = ["funcao minhaFuncao() { retorna 'Ola Mundo!!!' }"];
             const retornoLexador = lexador.mapear(codigo, -1);
             const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
@@ -228,6 +230,47 @@ describe('Tradutor Delégua -> Python', () => {
             expect(resultado).toMatch(/return 'Ola Mundo!!!'/i);
         });
 
+        it('função com retorno -> def', () => {
+            const codigo = ["funcao minhaFuncao() { retorna 'Ola Mundo!!!' }"];
+            const retornoLexador = lexador.mapear(codigo, -1);
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/def minhaFuncao\(\):/i);
+            expect(resultado).toMatch(/return 'Ola Mundo!!!'/i);
+        });
+
+        it('chamada de função -> def', () => {
+            const codigo = [
+                "funcao minhaFuncao() { retorna 'Ola Mundo!!!' }",
+                "minhaFuncao()",
+            ];
+            const retornoLexador = lexador.mapear(codigo, -1);
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/def minhaFuncao\(\):/i);
+            expect(resultado).toMatch(/return 'Ola Mundo!!!'/i);
+            expect(resultado).toMatch(/minhaFuncao\(\)/i);
+        });
+
+        it('chamada de função com parametros-> def', () => {
+            const codigo = [
+                "funcao minhaFuncao(textoQualquer) { retorna textoQualquer }",
+                "minhaFuncao('Olá Mundo!!!')",
+            ];
+            const retornoLexador = lexador.mapear(codigo, -1);
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/def minhaFuncao\(textoQualquer\):/i);
+            expect(resultado).toMatch(/return textoQualquer/i);
+            expect(resultado).toMatch(/minhaFuncao\(\'Olá Mundo!!!\'\)/i);
+        });
+
         it('se -> if, código', () => {
             const retornoLexador = lexador.mapear(['se (a == 1) {', '    escreva(10)', '}'], -1);
             const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
@@ -308,5 +351,63 @@ describe('Tradutor Delégua -> Python', () => {
             expect(resultado).toMatch(/else:/i);
             expect(resultado).toMatch(/print\('Não é nenhum desses valores: 10, 20, 30'\)/i);
         });
+
+        it('isto -> this', () => {
+            const retornoLexador = lexador.mapear(
+                [
+                    'classe Teste {',
+                    'construtor(abc){',
+                    'isto.valor = abc',
+                    '}',
+                    'mostrarValor() {',
+                    'escreva(isto.valor)',
+                    '}',
+                    '}',
+                    'var teste = Teste(100);',
+                    'teste.mostrarValor()',
+                ],
+                -1
+            );
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/class Teste:/i);
+            expect(resultado).toMatch(/def __init__\(self, abc\):/i);
+            expect(resultado).toMatch(/self.valor = abc/i);
+            expect(resultado).toMatch(/def mostrarValor\(self\):/i);
+            expect(resultado).toMatch(/print\(self.valor\)/i);
+            expect(resultado).toMatch(/teste = Teste\(100\)/i);
+            expect(resultado).toMatch(/teste.mostrarValor\(\)/i);
+        });
+
+        it('tente - pegue - finalmente -> try - except - finally', () => {
+            const retornoLexador = lexador.mapear(
+                [
+                    'tente { ',
+                    '   1 > "2";',
+                    '   escreva("sucesso");',
+                    '}',
+                    'pegue {',
+                    '   escreva("Ocorreu uma exceção.");',
+                    '} finalmente {',
+                    '   escreva("Ocorrendo exceção ou não, eu sempre executo");',
+                    '}',
+                ],
+                -1
+            );
+            
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/try:/i);
+            expect(resultado).toMatch(/1 > \'2\'/i);
+            expect(resultado).toMatch(/print\('sucesso'\)/i);
+            expect(resultado).toMatch(/except:/i);
+            expect(resultado).toMatch(/print\('Ocorreu uma exceção.'\)/i);
+            expect(resultado).toMatch(/finally:/i);
+            expect(resultado).toMatch(/print\('Ocorrendo exceção ou não, eu sempre executo'\)/i);
+        });
     });
 });
\ No newline at end of file