Repository: DesignLiquido/delegua (ts)

Issue:
Expandir avaliação semântica de condição de `enquanto` para `Agrupamento` e `Binario`
Em: 

```js
enquanto a != 5 {
    escreva(a)
    a++
}
```

A condição é:

![image](https://github.com/DesignLiquido/delegua/assets/53848829/5a7125b9-d6ae-44bd-be42-f0b7934ac3c2)

Em:

```js
enquanto (a != 5) {
    escreva(a)
    a++
}
```

A condição é:

![image](https://github.com/DesignLiquido/delegua/assets/53848829/e365206f-ee27-4d72-87a2-22d8b9ccd11d)

A avaliação semântica de Delégua até então só aceita algo como:

```js
enquanto (a) {
    escreva(a)
    a++
}
```

Pull request description:
[delegua] avaliador sintático enquanto expressao binária
resolve #539 

Patch:
diff --git a/fontes/analisador-semantico/analisador-semantico.ts b/fontes/analisador-semantico/analisador-semantico.ts
index ced15394..c58d05c0 100644
--- a/fontes/analisador-semantico/analisador-semantico.ts
+++ b/fontes/analisador-semantico/analisador-semantico.ts
@@ -1,4 +1,4 @@
-import { Atribuir, Chamada, ExpressaoRegular, FimPara, FormatacaoEscrita, FuncaoConstruto, Literal, Super, TipoDe, Variavel, Vetor } from '../construtos';
+import { Agrupamento, Atribuir, Binario, Chamada, Construto, ExpressaoRegular, FimPara, FormatacaoEscrita, FuncaoConstruto, Literal, Logico, Super, TipoDe, Variavel, Vetor } from '../construtos';
 import {
     Bloco,
     Classe,
@@ -314,24 +314,72 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
     }
 
     visitarDeclaracaoEnquanto(declaracao: Enquanto) {
-        if (declaracao.condicao instanceof Variavel) {
-            const variavel = declaracao.condicao as Variavel;
-            const valor = this.variaveis[variavel.simbolo.lexema];
-            if (!valor) {
-                this.erro(
-                    declaracao.condicao.simbolo,
-                    `Variável ${declaracao.condicao.simbolo.lexema} ainda não foi declarada até este ponto.`
-                );
-            } else if (typeof(valor.valor) !== 'boolean') {
-                this.erro(
-                    declaracao.condicao.simbolo,
-                    `Esperado tipo 'lógico' na condição do 'enquanto'.`
-                );
-            }
+        return this.verificarCondicao(declaracao.condicao);
+    }
+
+    private verificarCondicao(condicao: Construto): Promise<void> {
+        if (condicao instanceof Variavel) {
+            return this.verificarVariavel(condicao);
+        }
+        if (condicao instanceof Binario) {
+            return this.verificarBinario(condicao);
+        }
+        if (condicao instanceof Agrupamento) {
+            return this.verificarAgrupamento(condicao);
+        }
+        return Promise.resolve();
+    }
+
+    private verificarVariavel(variavel: Variavel): Promise<void> {
+        const variavelHipotetica = this.variaveis[variavel.simbolo.lexema];
+        if (!variavelHipotetica) {
+            this.erro(
+                variavel.simbolo,
+                `Variável ${variavel.simbolo.lexema} ainda não foi declarada até este ponto.`
+            );
+        } else if (!(variavelHipotetica.valor instanceof Binario) && (typeof variavelHipotetica.valor !== 'boolean')) {
+            this.erro(
+                variavel.simbolo,
+                `Esperado tipo 'lógico' na condição do 'enquanto'.`
+            );
         }
         return Promise.resolve();
     }
 
+    private verificarBinario(binario: Binario): Promise<void> {
+        this.verificarLadoBinario(binario.direita);
+        this.verificarLadoBinario(binario.esquerda);
+        return Promise.resolve();
+    }
+
+    private verificarLadoBinario(lado: any): void {
+        if (lado instanceof Variavel && !this.variaveis[lado.simbolo.lexema]) {
+            this.erro(
+                lado.simbolo,
+                `Variável ${lado.simbolo.lexema} ainda não foi declarada até este ponto.`
+            );
+        }
+    }
+
+    private verificarAgrupamento(agrupamento: Agrupamento): Promise<void> {
+        if (agrupamento.expressao instanceof Binario) {
+            return this.verificarBinario(agrupamento.expressao);
+        }
+        if (agrupamento.expressao instanceof Logico) {
+            this.verificarLadoLogico(agrupamento.expressao.direita);
+            this.verificarLadoLogico(agrupamento.expressao.esquerda);
+        }
+        return Promise.resolve();
+    }
+
+    private verificarLadoLogico(lado: any): void {
+        if (lado instanceof Variavel) {
+            let variavel = lado as Variavel;
+            this.verificarVariavel(variavel)
+        }
+    }
+
+
     visitarDeclaracaoImportar(declaracao: Importar) {
         return Promise.resolve();
     }


Test patch:
diff --git a/testes/analisador-semantico.test.ts b/testes/analisador-semantico.test.ts
index 1f2ed855..d75e58ac 100644
--- a/testes/analisador-semantico.test.ts
+++ b/testes/analisador-semantico.test.ts
@@ -428,7 +428,7 @@ describe('Analisador semântico', () => {
                     expect(retornoAnalisadorSemantico.erros).toHaveLength(0);
                 });
 
-                it('com variavel definida com valor inválido', () => {
+                it('com variavel definida com valor válido', () => {
                     const retornoLexador = lexador.mapear([
                         "const condicional = verdadeiro     ",
                         "enquanto condicional {             ",
@@ -441,7 +441,53 @@ describe('Analisador semântico', () => {
 
                     expect(retornoAnalisadorSemantico).toBeTruthy();
                     expect(retornoAnalisadorSemantico.erros).toHaveLength(0);
-                });      
+                });
+
+                it('com variável e expressão binária', () => {
+                    const retornoLexador = lexador.mapear([
+                        "const valor = 1                    ",
+                        "enquanto valor != 5 {              ",
+                        "    escreva(\"sim\");              ",
+                        "    valor++;                       ",
+                        "}                                  ",
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                    const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoAnalisadorSemantico).toBeTruthy();
+                    expect(retornoAnalisadorSemantico.erros).toHaveLength(0);
+                });
+
+                it('com variável e agrupamento', () => {
+                    const retornoLexador = lexador.mapear([
+                        "const valor = 1                    ",
+                        "enquanto (valor != 5) {            ",
+                        "    escreva(\"sim\");              ",
+                        "    valor++;                       ",
+                        "}                                  ",
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                    const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoAnalisadorSemantico).toBeTruthy();
+                    expect(retornoAnalisadorSemantico.erros).toHaveLength(0);
+                });
+
+                it('sucesso - verificar valores lógicos nas operações binárias', () => {
+                    const retornoLexador = lexador.mapear([
+                        "var x = 5 > 2;                     ",
+                        "var y = 10 < 11;                   ",
+                        "enquanto (x e y) {                 ",
+                        "    escreva(\"sim\");              ",
+                        "    sustar;                        ",
+                        "}                                  ",
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                    const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+                    expect(retornoAnalisadorSemantico).toBeTruthy();
+                    expect(retornoAnalisadorSemantico.erros).toHaveLength(0);
+                });
+
             });
             describe('Cenários de falha', () => {
                 it('com condicional não declarada', () => {
@@ -471,8 +517,52 @@ describe('Analisador semântico', () => {
 
                     expect(retornoAnalisadorSemantico).toBeTruthy();
                     expect(retornoAnalisadorSemantico.erros).toHaveLength(1);
-                });                
-             });
+                });
+
+                it('com variável não declarada e expressão binária', () => {
+                    const retornoLexador = lexador.mapear([
+                        "enquanto valor != 5 {              ",
+                        "    escreva(\"sim\");              ",
+                        "    valor++;                       ",
+                        "}                                  ",
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                    const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoAnalisadorSemantico).toBeTruthy();
+                    expect(retornoAnalisadorSemantico.erros).toHaveLength(1);
+                });
+
+                it('com variável não declarada e agrupamento', () => {
+                    const retornoLexador = lexador.mapear([
+                        "enquanto (valor != 5) {            ",
+                        "    escreva(\"sim\");              ",
+                        "    valor++;                       ",
+                        "}                                  ",
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                    const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoAnalisadorSemantico).toBeTruthy();
+                    expect(retornoAnalisadorSemantico.erros).toHaveLength(1);
+                });
+
+                it('falha - verificar valores lógicos nas operações binárias', () => {
+                    const retornoLexador = lexador.mapear([
+                        "var x = 5;                         ",
+                        "var y = 10;                        ",
+                        "enquanto (x e y) {                 ",
+                        "    escreva(\"sim\");              ",
+                        "    sustar;                        ",
+                        "}                                  ",
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                    const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoAnalisadorSemantico).toBeTruthy();
+                    expect(retornoAnalisadorSemantico.erros).toHaveLength(2);
+                });
+            });
         });
     });
 });