Repository: DesignLiquido/delegua
Pull request #551 (2023-11-09 13:00:28)

[delegua] analisador semântico - aviso conversão implícita


Patch:
diff --git a/fontes/analisador-semantico/analisador-semantico.ts b/fontes/analisador-semantico/analisador-semantico.ts
index f821fbf1..1a0bfe8a 100644
--- a/fontes/analisador-semantico/analisador-semantico.ts
+++ b/fontes/analisador-semantico/analisador-semantico.ts
@@ -63,16 +63,26 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
         return Promise.resolve();
     }
 
-    erro(simbolo: SimboloInterface, mensagemDeErro: string): void {
+    erro(simbolo: SimboloInterface, mensagem: string): void {
         this.diagnosticos.push({
             simbolo: simbolo,
-            mensagem: mensagemDeErro,
+            mensagem: mensagem,
             hashArquivo: simbolo.hashArquivo,
             linha: simbolo.linha,
             severidade: DiagnosticoSeveridade.ERRO
         });
     }
 
+    aviso(simbolo: SimboloInterface, mensagem: string): void {
+        this.diagnosticos.push({
+            simbolo: simbolo,
+            mensagem: mensagem,
+            hashArquivo: simbolo.hashArquivo,
+            linha: simbolo.linha,
+            severidade: DiagnosticoSeveridade.AVISO
+        });
+    }
+
     verificarTipoAtribuido(declaracao: Var | Const) {
         if (declaracao.tipo) {
             if (['vetor', 'qualquer[]', 'inteiro[]', 'texto[]'].includes(declaracao.tipo)) {
@@ -483,13 +493,7 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
         this.verificarTipoAtribuido(declaracao);
 
         if (this.variaveis.hasOwnProperty(declaracao.simbolo.lexema)) {
-            this.diagnosticos.push({
-                simbolo: declaracao.simbolo,
-                mensagem: 'Declaração de constante já feita.',
-                hashArquivo: declaracao.hashArquivo,
-                linha: declaracao.linha,
-                severidade: DiagnosticoSeveridade.ERRO,
-            });
+            this.erro(declaracao.simbolo, 'Declaração de constante já feita.');
         } else {
             this.variaveis[declaracao.simbolo.lexema] = {
                 imutavel: true,
@@ -498,6 +502,28 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
             };
         }
 
+        this.virificarTipoDeclaracaoConst(declaracao);
+
+
+        return Promise.resolve();
+    }
+
+    virificarTipoDeclaracaoConst(declaracao: Const): Promise<any> {
+        
+        if (declaracao.inicializador instanceof Binario) {
+            // verificar tipos iguais no lado esquerdo e direito
+            const binario = declaracao.inicializador as Binario;
+            this.verificarLadoBinario(binario.direita);
+            this.verificarLadoBinario(binario.esquerda);
+
+            const tipoDireita = typeof binario.direita.valor;
+            const tipoEsquerda = typeof binario.esquerda.valor;
+
+            if (tipoDireita !== tipoEsquerda) {
+                this.aviso(declaracao.simbolo, 'Declaração de constante com tipos diferentes.');
+            }
+        }
+
         return Promise.resolve();
     }
 


Test patch:
diff --git a/testes/analisador-semantico.test.ts b/testes/analisador-semantico.test.ts
index 97f52f9e..3dcf4ba6 100644
--- a/testes/analisador-semantico.test.ts
+++ b/testes/analisador-semantico.test.ts
@@ -1,6 +1,7 @@
 import { Lexador } from '../fontes/lexador';
 import { AvaliadorSintatico } from '../fontes/avaliador-sintatico';
 import { AnalisadorSemantico } from '../fontes/analisador-semantico';
+import { DiagnosticoSeveridade } from '../fontes/interfaces/erros';
 
 describe('Analisador semântico', () => {
     let lexador: Lexador;
@@ -505,13 +506,13 @@ describe('Analisador semântico', () => {
 
                 it('sucesso - verificar função declarada', () => {
                     const retornoLexador = lexador.mapear([
-                          "funcao funcaoExistente() {       ",
-                          "  retorna verdadeiro;            ",
-                          "}                                ",
-                          "enquanto (funcaoExistente()) {   ",
-                          "    escreva('teste');            ",
-                          "    sustar;                      ",
-                          "}                                ",
+                        "funcao funcaoExistente() {       ",
+                        "  retorna verdadeiro;            ",
+                        "}                                ",
+                        "enquanto (funcaoExistente()) {   ",
+                        "    escreva('teste');            ",
+                        "    sustar;                      ",
+                        "}                                ",
                     ], -1);
                     const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
                     const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
@@ -651,7 +652,7 @@ describe('Analisador semântico', () => {
                     const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
                     expect(retornoAnalisadorSemantico).toBeTruthy();
                     expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(2);
-                });                
+                });
             });
         });
 
@@ -763,8 +764,33 @@ describe('Analisador semântico', () => {
                     expect(retornoAnalisadorSemantico).toBeTruthy();
                     expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1);
                 });
-             });
+            });
+        });
 
+        describe('Cenários conversão implicita', () => {
+            describe('Cenários de sucesso', () => {
+                it('Sucesso - conversão implicita com variável definida com valor válido', () => {
+                    const retornoLexador = lexador.mapear([
+                        "const valor = 2 + 2",
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                    const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+                    expect(retornoAnalisadorSemantico).toBeTruthy();
+                    expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(0);
+                });
+            });
+            describe('Cenários de aviso', () => {
+                it('Aviso - conversão implicita com variável definida com valor válido', () => {
+                    const retornoLexador = lexador.mapear([
+                        "const valor = 2 + '2'",
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                    const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+                    expect(retornoAnalisadorSemantico).toBeTruthy();
+                    expect(retornoAnalisadorSemantico.diagnosticos.filter(item=> item.severidade === DiagnosticoSeveridade.AVISO)).toHaveLength(1);
+                    expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1);
+                });
+             });
         });
     });
 });