Repository: DesignLiquido/delegua
Pull request #521 (2023-09-30 16:01:19)

Analisador semântico melhorias - Parte 2


Patch:
diff --git a/fontes/analisador-semantico/analisador-semantico.ts b/fontes/analisador-semantico/analisador-semantico.ts
index d788f750..3ed04d06 100644
--- a/fontes/analisador-semantico/analisador-semantico.ts
+++ b/fontes/analisador-semantico/analisador-semantico.ts
@@ -158,6 +158,25 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
                     `Função '${expressao.entidadeChamada.simbolo.lexema}' espera ${funcao.parametros.length} parametros.`
                 );
             }
+
+            for (let [indice, arg0] of funcao.parametros.entries()) {
+                const arg1 = expressao.argumentos[indice];
+                if (arg1) {
+                    if (arg0.tipoDado?.tipo === 'texto' && typeof arg1.valor !== 'string') {
+                        this.erro(
+                            expressao.entidadeChamada.simbolo,
+                            `O valor passado para o parâmetro '${arg0.tipoDado.nome}' é diferente do esperado pela função.`
+                        );
+                    }
+                    else if (['inteiro', 'real'].includes(arg0.tipoDado?.tipo) 
+                            && typeof arg1.valor !== 'number') {
+                        this.erro(
+                            expressao.entidadeChamada.simbolo,
+                            `O valor passado para o parâmetro '${arg0.tipoDado.nome}' é diferente do esperado pela função.`
+                        );
+                    }                    
+                }
+            }
         }
 
         return Promise.resolve();
@@ -349,6 +368,13 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
 
         this.verificarTipoAtribuido(declaracao);
 
+        if (declaracao.inicializador instanceof FuncaoConstruto) {
+            const funcao = declaracao.inicializador;
+            if (funcao.parametros.length >= 255) {
+                this.erro(declaracao.simbolo, 'Não pode haver mais de 255 parâmetros');
+            }
+        }
+
         this.variaveis[declaracao.simbolo.lexema] = {
             imutavel: false,
             tipo: declaracao.tipo,
@@ -393,7 +419,7 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
     visitarDeclaracaoDefinicaoFuncao(declaracao: FuncaoDeclaracao) {
         for (let parametro of declaracao.funcao.parametros) {
             if(parametro.hasOwnProperty('tipoDado') && !parametro.tipoDado.tipo) {
-                this.erro(declaracao.simbolo, `O tipo '${parametro.tipoDado.nome}' não é válido.`);
+                this.erro(declaracao.simbolo, `O tipo '${parametro.tipoDado.tipoInvalido}' não é válido.`);
             }
         }
 
@@ -401,6 +427,10 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
             this.erro(declaracao.simbolo, `Declaração de retorno da função é inválido.`);
         }
 
+        if (declaracao.funcao.parametros.length >= 255) {
+            this.erro(declaracao.simbolo, 'Não pode haver mais de 255 parâmetros');
+        }
+
         let tipoRetornoFuncao = declaracao.funcao.tipoRetorno;
         if (tipoRetornoFuncao) {
             let funcaoContemRetorno = declaracao.funcao.corpo.find((c) => c instanceof Retorna) as Retorna;
diff --git a/fontes/avaliador-sintatico/avaliador-sintatico.ts b/fontes/avaliador-sintatico/avaliador-sintatico.ts
index f3397c3b..6dd76936 100644
--- a/fontes/avaliador-sintatico/avaliador-sintatico.ts
+++ b/fontes/avaliador-sintatico/avaliador-sintatico.ts
@@ -1089,10 +1089,6 @@ export class AvaliadorSintatico implements AvaliadorSintaticoInterface<SimboloIn
         const parametros: ParametroInterface[] = [];
 
         do {
-            if (parametros.length >= 255) {
-                this.erro(this.simbolos[this.atual], 'Não pode haver mais de 255 parâmetros');
-            }
-
             const parametro: Partial<ParametroInterface> = {};
 
             if (this.simbolos[this.atual].tipo === tiposDeSimbolos.MULTIPLICACAO) {
@@ -1113,8 +1109,9 @@ export class AvaliadorSintatico implements AvaliadorSintaticoInterface<SimboloIn
             if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DOIS_PONTOS)) {
                 let tipoDadoParametro = this.verificarDefinicaoTipoAtual();
                 parametro.tipoDado = {
-                    nome: this.simboloAtual().lexema,
-                    tipo: tipoDadoParametro
+                    nome: this.simbolos[this.atual - 2].lexema,
+                    tipo: tipoDadoParametro,
+                    tipoInvalido: !tipoDadoParametro ? this.simboloAtual().lexema : null
                 }
                 this.avancarEDevolverAnterior();
             }
diff --git a/fontes/interfaces/parametro-interface.ts b/fontes/interfaces/parametro-interface.ts
index 1754864e..b314fd47 100644
--- a/fontes/interfaces/parametro-interface.ts
+++ b/fontes/interfaces/parametro-interface.ts
@@ -4,6 +4,7 @@ import { TiposDadosInterface } from './tipos-dados-interface';
 interface TipoDadoParametroInterface {
     nome: string;
     tipo: TiposDadosInterface;
+    tipoInvalido?: string;
 }
 export interface ParametroInterface {
     abrangencia: 'padrao' | 'multiplo';


Test patch:
diff --git a/testes/analisador-semantico.test.ts b/testes/analisador-semantico.test.ts
index 8ed124fe..72f7040f 100644
--- a/testes/analisador-semantico.test.ts
+++ b/testes/analisador-semantico.test.ts
@@ -346,6 +346,44 @@ describe('Analisador semântico', () => {
                 expect(retornoAnalisadorSemantico).toBeTruthy();
                 expect(retornoAnalisadorSemantico.erros[0].mensagem).toBe('Chamada da função \'x\' não existe.');
             });
+
+            it('Chamada de função com tipos inválidos na passagem dos parametros', () => {
+                const retornoLexador = lexador.mapear([
+                    'função f(a:texto, b:inteiro, c: texto, d) {',
+                    '   escreva(a + b)',
+                    '}',
+                    'f(1, \'teste0\', \'teste1\', 2)',
+                ], -1);
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+
+                expect(retornoAnalisadorSemantico).toBeTruthy();
+                expect(retornoAnalisadorSemantico.erros[0].mensagem).toBe('O valor passado para o parâmetro \'a\' é diferente do esperado pela função.');
+                expect(retornoAnalisadorSemantico.erros[1].mensagem).toBe('O valor passado para o parâmetro \'b\' é diferente do esperado pela função.');
+            });
+
+            it('Função anônima com mais de 255 parâmetros', () => {
+                let acumulador = '';
+                for (let i = 1; i <= 256; i++) {
+                    acumulador += 'a' + i + ', ';
+                }
+
+                acumulador = acumulador.substring(0, acumulador.length - 2);
+
+                const funcaoCom256Argumentos1 = 'var f1 = funcao(' + acumulador + ') {}';
+                const funcaoCom256Argumentos2 = 'funcao f2(' + acumulador + ') {}';
+
+                const retornoLexador = lexador.mapear([
+                    funcaoCom256Argumentos1,
+                    funcaoCom256Argumentos2
+                ], -1);
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+
+                expect(retornoAnalisadorSemantico).toBeTruthy();
+                expect(retornoAnalisadorSemantico.erros[0].mensagem).toBe('Não pode haver mais de 255 parâmetros');
+                expect(retornoAnalisadorSemantico.erros[1].mensagem).toBe('Não pode haver mais de 255 parâmetros');
+            });
         });
     });
 });
diff --git a/testes/avaliador-sintatico.test.ts b/testes/avaliador-sintatico.test.ts
index f051e24e..b710b947 100644
--- a/testes/avaliador-sintatico.test.ts
+++ b/testes/avaliador-sintatico.test.ts
@@ -195,23 +195,6 @@ describe('Avaliador sintático', () => {
                     expect(retornoAvaliadorSintatico.erros.length).toBeGreaterThanOrEqual(0);
                 });
 
-                it('Função anônima com mais de 255 parâmetros', () => {
-                    let acumulador = '';
-                    for (let i = 1; i <= 256; i++) {
-                        acumulador += 'a' + i + ', ';
-                    }
-    
-                    acumulador = acumulador.substring(0, acumulador.length - 2);
-    
-                    const funcaoCom256Argumentos = 'var f = funcao(' + acumulador + ') {}';
-                    const retornoLexador = lexador.mapear([funcaoCom256Argumentos], -1);
-                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
-    
-                    expect(retornoAvaliadorSintatico).toBeTruthy();
-                    expect(retornoAvaliadorSintatico.erros).toHaveLength(1);
-                    expect(retornoAvaliadorSintatico.erros[0].message).toBe('Não pode haver mais de 255 parâmetros');
-                });
-
                 it('Função com retorno de vetor', () => {
                     const retornoLexador = lexador.mapear([
                         "funcao executar(): texto[] {",