Repository: DesignLiquido/delegua
Pull request #351 (2023-05-05 02:43:42)

Tradução 'para cada em/de' - Delégua  para JavaScript e JavaScript para Delégua

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: 73.7%">73.74% (+0.04% 🔼)</div>  |    5659/7674    |
|                                                                           🟡                                                                           | Branches   | <div title="Base coverage is: 62.33%">62.39% (+0.07% 🔼)</div> |    1800/2885    |
|                                                                           🟡                                                                           | Functions  | <div title="Base coverage is: 73.54%">73.59% (+0.05% 🔼)</div> |     836/1136    |
|                                                                           🟡                                                                           | Lines      | <div title="Base coverage is: 74.18%">74.22% (+0.05% 🔼)</div> |    5511/7425    |


## Test suite run success
406 tests passing in 35 suites.

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

Patch:
diff --git a/.vscode/launch.json b/.vscode/launch.json
index c8938edc..a4ba5a3c 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -757,30 +757,6 @@
             "console": "integratedTerminal",
             "internalConsoleOptions": "neverOpen"
         },
-        {
-            "type": "node",
-            "request": "launch",
-            "name": "Tradutores > Delégua > JavaScript > Teste",
-            "skipFiles": [
-                "<node_internals>/**",
-                "node_modules/**"
-            ],
-            "cwd": "${workspaceRoot}",
-            "console": "integratedTerminal",
-            "args": [
-                "${workspaceFolder}${pathSeparator}execucao.ts",
-                "-t",
-                "js",
-                "-s",
-                "./exemplos/condicionais/se.delegua"
-            ],
-            "runtimeExecutable": "node",
-            "runtimeArgs": [
-                "--nolazy",
-                "-r",
-                "ts-node/register/transpile-only"
-            ]
-        },
         {
             "type": "node",
             "request": "launch",
diff --git a/fontes/tradutores/tradutor-javascript.ts b/fontes/tradutores/tradutor-javascript.ts
index c793c0ce..459e6c1d 100644
--- a/fontes/tradutores/tradutor-javascript.ts
+++ b/fontes/tradutores/tradutor-javascript.ts
@@ -28,6 +28,7 @@ import {
     FuncaoDeclaracao,
     Importar,
     Para,
+    ParaCada,
     Retorna,
     Se,
     Tente,
@@ -334,6 +335,15 @@ export class TradutorJavaScript implements TradutorInterface {
         return `'leia() não é suportado por este padrão de JavaScript.'`;
     }
 
+    traduzirDeclaracaoParaCada(declaracaoParaCada: ParaCada): string {
+        let resultado = `for (let ${declaracaoParaCada.nomeVariavelIteracao} of `; 
+        resultado +=
+            this.dicionarioConstrutos[declaracaoParaCada.vetor.constructor.name](declaracaoParaCada.vetor) + ") ";
+
+        resultado += this.dicionarioDeclaracoes[declaracaoParaCada.corpo.constructor.name](declaracaoParaCada.corpo);
+        return resultado;
+    }
+
     traduzirDeclaracaoPara(declaracaoPara: Para): string {
         let resultado = 'for (';
         resultado +=
@@ -594,6 +604,7 @@ export class TradutorJavaScript implements TradutorInterface {
         Importar: this.traduzirDeclaracaoImportar.bind(this),
         Leia: this.traduzirDeclaracaoLeia.bind(this),
         Para: this.traduzirDeclaracaoPara.bind(this),
+        ParaCada: this.traduzirDeclaracaoParaCada.bind(this),
         Sustar: () => 'break',
         Retorna: this.traduzirDeclaracaoRetorna.bind(this),
         Se: this.traduzirDeclaracaoSe.bind(this),
diff --git a/fontes/tradutores/tradutor-reverso-javascript.ts b/fontes/tradutores/tradutor-reverso-javascript.ts
index 3e6b4340..67fe0e4a 100644
--- a/fontes/tradutores/tradutor-reverso-javascript.ts
+++ b/fontes/tradutores/tradutor-reverso-javascript.ts
@@ -5,6 +5,8 @@ import {
     BlockStatement,
     ClassDeclaration,
     DoWhileStatement,
+    ForInStatement,
+    ForOfStatement,
     ForStatement,
     Identifier,
     IfStatement,
@@ -163,9 +165,12 @@ export class TradutorReversoJavaScript {
         let informacoesDaVariavel = declaracao.declarations[0];
         const identificador = informacoesDaVariavel.id as Identifier;
         if (identificador) {
-            resultado += `${declaracao.kind === 'const' ? 'const' : 'var'} ${identificador.name} = ${this.dicionarioConstrutos[informacoesDaVariavel.init.type](
-                informacoesDaVariavel.init
-            )}`;
+            resultado += `${declaracao.kind === 'const' ? 'const' : 'var'} ${identificador.name}`;
+            if (informacoesDaVariavel.init) {
+                resultado += ` = ${this.dicionarioConstrutos[informacoesDaVariavel.init.type](
+                    informacoesDaVariavel.init
+                )}`;
+            }
         }
 
         return resultado;
@@ -204,6 +209,16 @@ export class TradutorReversoJavaScript {
         return resultado;
     }
 
+    traduzirDeclaracaoParaDe(declaracao: ForInStatement | ForOfStatement): string {
+        let resultado = '';
+        let emOuDe = declaracao.type === 'ForInStatement' ? 'em' : 'de';
+        resultado += `para (${this.traduzirDeclaracao(declaracao.left)} ${emOuDe} `;
+        resultado += this.dicionarioConstrutos[declaracao.right.constructor.name](declaracao.right) + ') ';
+        resultado += this.logicaComumBlocoEscopo(declaracao.body);
+
+        return resultado;
+    }
+
     traduzirDeclaracaoFuncao(declaracao: any): string {
         let resultado = '';
         const eFuncaoSeta = !declaracao.id;
@@ -375,6 +390,9 @@ export class TradutorReversoJavaScript {
                 return this.traduzirExpressaoDeclaracao(declaracao);
             case 'ForStatement':
                 return this.traduzirDeclaracaoPara(declaracao);
+            case 'ForInStatement':
+            case 'ForOfStatement':
+                return this.traduzirDeclaracaoParaDe(declaracao);
             case 'FunctionDeclaration':
                 return this.traduzirDeclaracaoFuncao(declaracao);
             case 'IfStatement':


Test patch:
diff --git a/testes/tradutores/tradutor-javascript.test.ts b/testes/tradutores/tradutor-javascript.test.ts
index 2ca483cc..441f7325 100644
--- a/testes/tradutores/tradutor-javascript.test.ts
+++ b/testes/tradutores/tradutor-javascript.test.ts
@@ -270,6 +270,84 @@ describe('Tradutor Delégua -> JavaScript', () => {
             expect(resultado).toMatch(/}/i);
         });
 
+        it('\'para\' sem parenteses -> for', () => {
+            const retornoLexador = lexador.mapear(
+                ['para var i = 0; i < 5; i = i + 1 {', 'escreva(i);', '}'],
+                -1
+            );
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/for \(let i = 0; i < 5; i = i \+ 1\) {/i);
+            expect(resultado).toMatch(/console\.log\(i\)/i);
+            expect(resultado).toMatch(/}/i);
+        });
+
+        it('para cada \'em\' - vetor variável', async () => {
+            const retornoLexador = lexador.mapear([
+                "var v = [1, 2, 3]",
+                "para cada elemento em v {",
+                "   escreva('Valor: ', elemento)",
+                "}",
+            ], -1);
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/let v = \[1, 2, 3\]/i);
+            expect(resultado).toMatch(/for \(let elemento of v\) {/i);
+            expect(resultado).toMatch(/console\.log\(\'Valor: \', elemento\)/i);
+            expect(resultado).toMatch(/}/i);
+        });
+
+        it('para cada \'em\' - vetor variável', async () => {
+            const retornoLexador = lexador.mapear([
+                "para cada elemento em [1, 2, 3] {",
+                "   escreva('Valor: ', elemento)",
+                "}",
+            ], -1);
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/for \(let elemento of \[1, 2, 3\]\) {/i);
+            expect(resultado).toMatch(/console\.log\(\'Valor: \', elemento\)/i);
+            expect(resultado).toMatch(/}/i);
+        });
+
+        it('para cada elemento \'de\' - vetor variável', async () => {
+            const retornoLexador = lexador.mapear([
+                "var v = [1, 2, 3]",
+                "para cada elemento de v {",
+                "   escreva('Valor: ', elemento)",
+                "}",
+            ], -1);
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/let v = \[1, 2, 3\]/i);
+            expect(resultado).toMatch(/for \(let elemento of v\) {/i);
+            expect(resultado).toMatch(/console\.log\(\'Valor: \', elemento\)/i);
+            expect(resultado).toMatch(/}/i);
+        });
+
+        it('para cada elemento \'de\' - vetor variável', async () => {
+            const retornoLexador = lexador.mapear([
+                "para cada elemento de [1, 2, 3] {",
+                "   escreva('Valor: ', elemento)",
+                "}",
+            ], -1);
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/for \(let elemento of \[1, 2, 3\]\) {/i);
+            expect(resultado).toMatch(/console\.log\(\'Valor: \', elemento\)/i);
+            expect(resultado).toMatch(/}/i);
+        });
+
         it('enquanto -> while', () => {
             const retornoLexador = lexador.mapear(
                 ['var i = 0;', 'fazer {', 'escreva(i);', 'i = i + 1;', '} enquanto (i < 5)'],
@@ -706,7 +784,7 @@ describe('Tradutor Delégua -> JavaScript', () => {
             expect(resultado).toMatch(/console\.log\(10\)/i);
         });
 
-        it('se -> if com operadores lógicos, código', () => {
+        it('condicional \'se\' com parenteses -> if com operadores lógicos, código', () => {
             const retornoLexador = lexador.mapear(
                 [
                     'se (a == 1 ou a == 2) {',
@@ -723,7 +801,28 @@ describe('Tradutor Delégua -> JavaScript', () => {
             expect(resultado).toMatch(/if/i);
             expect(resultado).toMatch(/a === 1 || a === 2/i);
             expect(resultado).toMatch(/console\.log\(10\)/i);
-            // expect(resultado).toMatch(/a > 0 && a === 3/i);
+            expect(resultado).toMatch(/a === 3 && a > 0/i);
+            expect(resultado).toMatch(/console\.log\(5\)/i);
+        });
+
+        it('condicional \'se\' sem parenteses -> if com operadores lógicos, código', () => {
+            const retornoLexador = lexador.mapear(
+                [
+                    'se a == 1 ou a == 2 {',
+                    'escreva(10)', 
+                    '}',
+                    'se a > 0 e a == 3 {',
+                    'escreva(5)', 
+                    '}'
+                ], -1);
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+            const resultado = tradutor.traduzir(retornoAvaliadorSintatico.declaracoes);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/if/i);
+            expect(resultado).toMatch(/a === 1 || a === 2/i);
+            expect(resultado).toMatch(/console\.log\(10\)/i);
+            expect(resultado).toMatch(/a === 3 && a > 0/i);
             expect(resultado).toMatch(/console\.log\(5\)/i);
         });
 
diff --git a/testes/tradutores/tradutor-reverso-javascript.test.ts b/testes/tradutores/tradutor-reverso-javascript.test.ts
index 3e711db5..eae1766a 100644
--- a/testes/tradutores/tradutor-reverso-javascript.test.ts
+++ b/testes/tradutores/tradutor-reverso-javascript.test.ts
@@ -31,6 +31,24 @@ describe('Tradutor Reverso JavaScript -> Delégua', () => {
             expect(resultado).toMatch(/escreva\(i\)/i);
         });
 
+        it('for in -> para cada em', () => {
+            const codigo = 'for (let elemento in [1, 2, 3]) { console.log(elemento) }'
+
+            const resultado = tradutor.traduzir(codigo);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/para \(var elemento em \[1, 2, 3\]\)/i);
+            expect(resultado).toMatch(/escreva\(elemento\)/i);
+        });
+
+        it('for of -> para cada de', () => {
+            const codigo = 'for (let elemento of [1, 2, 3]) { console.log(elemento) }'
+
+            const resultado = tradutor.traduzir(codigo);
+            expect(resultado).toBeTruthy();
+            expect(resultado).toMatch(/para \(var elemento de \[1, 2, 3\]\)/i);
+            expect(resultado).toMatch(/escreva\(elemento\)/i);
+        });
+
         it('array - vetor - com valores', () => {
             const codigo = 'let vetor = [1, \'2\']'
             const resultado = tradutor.traduzir(codigo);