Repository: DesignLiquido/delegua
Pull request #415 (2023-05-26 21:49:57)

#385 Definindo `tipo de` equivalente ao typeof do JavaScript.
Discussão https://github.com/DesignLiquido/delegua/discussions/385

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.94%">54.98% (+0.04% 🔼)</div> |    7537/13709   |
|                                                                           🔴                                                                           | Branches   | <div title="Base coverage is: 45.26%">45.38% (+0.12% 🔼)</div> |    2299/5066    |
|                                                                           🔴                                                                           | Functions  | <div title="Base coverage is: 48.07%">48.04% (-0.04% 🔻)</div> |    1089/2267    |
|                                                                           🔴                                                                           | Lines      | <div title="Base coverage is: 54.82%">54.86% (+0.04% 🔼)</div> |    7367/13429   |

<details><summary>Show new covered files 🐣</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="construtos/tipo-de.ts">`...` / tipo-de.ts</div> | 100%       | 100%     | 100%      | 100%  |

</details>


<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="interpretador/dialetos/egua-classico/interpretador-egua-classico.ts">`...` / interpretador-egua-classico.ts</div> | <div title="Base coverage is: 55.91%">55.76% (-0.15% 🔻)</div> | 46.48%   | <div title="Base coverage is: 61.11%">60% (-1.11% 🔻)</div>    | <div title="Base coverage is: 56.86%">56.7% (-0.16% 🔻)</div>  |
|                                                                           🟡                                                                           | <div title="interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts">`...` / resolvedor.ts</div>                        | <div title="Base coverage is: 65.2%">64.91% (-0.29% 🔻)</div>  | 64.1%    | <div title="Base coverage is: 47.46%">46.67% (-0.79% 🔻)</div> | <div title="Base coverage is: 64.76%">64.45% (-0.31% 🔻)</div> |
|                                                                           🔴                                                                           | <div title="interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts">`...` / interpretador-portugol-ipt.ts</div>    | <div title="Base coverage is: 52.24%">51.98% (-0.26% 🔻)</div> | 47.62%   | <div title="Base coverage is: 38.18%">37.5% (-0.68% 🔻)</div>  | <div title="Base coverage is: 53.65%">53.37% (-0.28% 🔻)</div> |
|                                                                           🔴                                                                           | <div title="interpretador/dialetos/birl/interpretador-birl.ts">`...` / interpretador-birl.ts</div>                            | <div title="Base coverage is: 57.04%">56.83% (-0.21% 🔻)</div> | 51.9%    | <div title="Base coverage is: 37.7%">37.1% (-0.61% 🔻)</div>   | <div title="Base coverage is: 57.95%">57.74% (-0.22% 🔻)</div> |
|                                                                           🔴                                                                           | <div title="analisador-semantico/analisador-semantico.ts">`...` / analisador-semantico.ts</div>                               | <div title="Base coverage is: 34.43%">33.87% (-0.56% 🔻)</div> | 50%      | <div title="Base coverage is: 14.29%">13.95% (-0.33% 🔻)</div> | <div title="Base coverage is: 34.43%">33.87% (-0.56% 🔻)</div> |

</details>

## Test suite run success
526 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 36e4870a01e49ff256e71cdac11099d09b5f0502</p>
<!-- Sticky Pull Request Comment -->

Patch:
diff --git a/fontes/analisador-semantico/analisador-semantico.ts b/fontes/analisador-semantico/analisador-semantico.ts
index 958e5ecc..446a5f1a 100644
--- a/fontes/analisador-semantico/analisador-semantico.ts
+++ b/fontes/analisador-semantico/analisador-semantico.ts
@@ -1,4 +1,4 @@
-import { Literal, Atribuir, FimPara, FormatacaoEscrita, Super } from '../construtos';
+import { Literal, Atribuir, FimPara, FormatacaoEscrita, Super, TipoDe } from '../construtos';
 import {
     Declaracao,
     Expressao,
@@ -58,6 +58,10 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
         this.erros = [];
     }
     
+    visitarExpressaoTipoDe(expressao: TipoDe): Promise<any> {
+        return Promise.resolve();
+    }
+    
     visitarExpressaoFalhar(expressao: any): Promise<any> {
         return Promise.resolve();
     }
diff --git a/fontes/avaliador-sintatico/avaliador-sintatico.ts b/fontes/avaliador-sintatico/avaliador-sintatico.ts
index 6fd1923f..980a5e6e 100644
--- a/fontes/avaliador-sintatico/avaliador-sintatico.ts
+++ b/fontes/avaliador-sintatico/avaliador-sintatico.ts
@@ -3,24 +3,25 @@ import hrtime from 'browser-process-hrtime';
 
 import { AvaliadorSintaticoInterface, ParametroInterface, SimboloInterface } from '../interfaces';
 import {
+    AcessoMetodo as AcessoMetodo,
+    Agrupamento,
     AtribuicaoPorIndice,
     Atribuir,
     Binario,
     Chamada,
+    Construto,
     Dicionario,
     DefinirValor,
     FuncaoConstruto,
-    AcessoMetodo as AcessoMetodo,
-    Agrupamento,
     Literal,
     Logico,
     AcessoIndiceVariavel,
     Super,
+    TipoDe,
     Unario,
     Variavel,
     Vetor,
     Isto,
-    Construto,
 } from '../construtos';
 
 import { ErroAvaliadorSintatico } from './erro-avaliador-sintatico';
@@ -235,6 +236,12 @@ export class AvaliadorSintatico implements AvaliadorSintaticoInterface {
             case tiposDeSimbolos.VERDADEIRO:
                 this.avancarEDevolverAnterior();
                 return new Literal(this.hashArquivo, Number(simboloAtual.linha), true);
+
+            case tiposDeSimbolos.TIPO:
+                this.avancarEDevolverAnterior();
+                this.consumir(tiposDeSimbolos.DE, "Esperado 'de' após 'tipo'.");
+                const _expressao = this.expressao() as any;
+                return new TipoDe(this.hashArquivo, simboloAtual, _expressao instanceof Literal ? _expressao.valor : _expressao);
         }
 
         throw this.erro(this.simbolos[this.atual], 'Esperado expressão.');
diff --git a/fontes/construtos/index.ts b/fontes/construtos/index.ts
index 5cfaf16d..640ff89e 100644
--- a/fontes/construtos/index.ts
+++ b/fontes/construtos/index.ts
@@ -16,6 +16,7 @@ export * from './literal';
 export * from './logico';
 export * from './acesso-indice-variavel';
 export * from './super';
+export * from './tipo-de';
 export * from './unario';
 export * from './variavel';
 export * from './vetor';
diff --git a/fontes/construtos/tipo-de.ts b/fontes/construtos/tipo-de.ts
new file mode 100644
index 00000000..09ed689e
--- /dev/null
+++ b/fontes/construtos/tipo-de.ts
@@ -0,0 +1,22 @@
+import { VisitanteComumInterface, SimboloInterface, VariavelInterface } from '../interfaces';
+import { Construto } from './construto';
+
+export class TipoDe implements Construto {
+    linha: number;
+    hashArquivo: number;
+    valor: any;
+
+    simbolo: SimboloInterface;
+
+    constructor(hashArquivo: number, simbolo: SimboloInterface, valor: any) {
+        this.linha = Number(simbolo.linha);
+        this.hashArquivo = hashArquivo;
+        this.valor = valor;
+        this.simbolo = simbolo;
+    }
+
+    async aceitar(visitante: VisitanteComumInterface): Promise<VariavelInterface> {
+        return Promise.resolve(visitante.visitarExpressaoTipoDe(this));
+    }
+}
+
diff --git a/fontes/interfaces/visitante-comum-interface.ts b/fontes/interfaces/visitante-comum-interface.ts
index cec4f609..7d924389 100644
--- a/fontes/interfaces/visitante-comum-interface.ts
+++ b/fontes/interfaces/visitante-comum-interface.ts
@@ -1,10 +1,9 @@
-import { Atribuir, FimPara, Literal, Super } from '../construtos';
+import { Atribuir, FimPara, Literal, Super, TipoDe } from '../construtos';
 import {
     Bloco,
     Classe,
     Const,
     Continua,
-    Declaracao,
     Enquanto,
     Escolha,
     Escreva,
@@ -65,6 +64,7 @@ export interface VisitanteComumInterface {
     visitarExpressaoRetornar(declaracao: Retorna): Promise<RetornoQuebra>;
     visitarExpressaoSuper(expressao: Super): any;
     visitarExpressaoSustar(declaracao?: Sustar): SustarQuebra;
+    visitarExpressaoTipoDe(expressao: TipoDe): Promise<any>;
     visitarExpressaoUnaria(expressao: any): any;
     visitarExpressaoVetor(expressao: any): any;
 }
diff --git a/fontes/interpretador/dialetos/birl/interpretador-birl.ts b/fontes/interpretador/dialetos/birl/interpretador-birl.ts
index 9dbb7e3b..299939fb 100644
--- a/fontes/interpretador/dialetos/birl/interpretador-birl.ts
+++ b/fontes/interpretador/dialetos/birl/interpretador-birl.ts
@@ -1,4 +1,4 @@
-import { Construto, Atribuir, Literal, FimPara, FormatacaoEscrita, Super, Variavel, Unario } from '../../../construtos';
+import { Construto, Atribuir, Literal, FimPara, FormatacaoEscrita, Super, Variavel, Unario, TipoDe } from '../../../construtos';
 import {
     Declaracao,
     Expressao,
@@ -72,6 +72,10 @@ export class InterpretadorBirl implements InterpretadorInterface {
         this.pilhaEscoposExecucao.empilhar(escopoExecucao);
     }
 
+    visitarExpressaoTipoDe(expressao: TipoDe): Promise<any> {
+        throw new Error('Método não implementado.');
+    }
+
     visitarExpressaoFalhar(expressao: any): Promise<any> {
         throw new Error('Método não implementado.');
     }
diff --git a/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts b/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts
index c4fd49b7..91ccf23e 100644
--- a/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts
+++ b/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts
@@ -37,6 +37,7 @@ import {
     FormatacaoEscrita,
     Literal,
     Super,
+    TipoDe,
     Variavel,
 } from '../../../construtos';
 import { RetornoInterpretador } from '../../../interfaces/retornos/retorno-interpretador';
@@ -87,6 +88,10 @@ export class InterpretadorEguaClassico implements InterpretadorInterface {
         carregarBibliotecaGlobal(this, this.pilhaEscoposExecucao);
     }
 
+    visitarExpressaoTipoDe(expressao: TipoDe): Promise<any> {
+        throw new Error('Método não implementado.');
+    }
+
     visitarExpressaoFalhar(expressao: any): Promise<any> {
         throw new Error('Método não implementado.');
     }
diff --git a/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts b/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts
index 313fee33..137bf434 100644
--- a/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts
+++ b/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts
@@ -3,7 +3,7 @@ import { PilhaEscopos } from './pilha-escopos';
 import { ErroResolvedor } from './erro-resolvedor';
 import { InterpretadorInterface, SimboloInterface } from '../../../../interfaces';
 import { Bloco, Const, Declaracao, EscrevaMesmaLinha, Expressao, Leia, ParaCada, Se } from '../../../../declaracoes';
-import { AcessoMetodo, Construto, FimPara, FormatacaoEscrita, Super, Variavel } from '../../../../construtos';
+import { AcessoMetodo, Construto, FimPara, FormatacaoEscrita, Super, TipoDe, Variavel } from '../../../../construtos';
 import { RetornoResolvedor } from './retorno-resolvedor';
 import { EspacoVariaveis } from '../../../../espaco-variaveis';
 import { PilhaEscoposExecucaoInterface } from '../../../../interfaces/pilha-escopos-execucao-interface';
@@ -62,6 +62,10 @@ export class ResolvedorEguaClassico implements ResolvedorInterface, Interpretado
         this.classeAtual = TipoClasse.NENHUM;
         this.cicloAtual = TipoClasse.NENHUM;
     }
+    
+    visitarExpressaoTipoDe(expressao: TipoDe): Promise<any> {
+        throw new Error('Método não implementado.');
+    }
 
     visitarExpressaoFalhar(expressao: any): Promise<any> {
         throw new Error('Método não implementado.');
diff --git a/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts b/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts
index 478fbbbe..126eb15f 100644
--- a/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts
+++ b/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts
@@ -1,4 +1,4 @@
-import { Literal, Construto, Atribuir, FimPara, FormatacaoEscrita, Super, Variavel } from "../../../construtos";
+import { Literal, Construto, Atribuir, FimPara, FormatacaoEscrita, Super, Variavel, TipoDe } from "../../../construtos";
 import { Declaracao, Expressao, Leia, Se, Para, Fazer, Escolha, Tente, Enquanto, Importar, Escreva, EscrevaMesmaLinha, Bloco, Var, Const, Continua, Sustar, Retorna, FuncaoDeclaracao, Classe, ParaCada } from "../../../declaracoes";
 import { EspacoVariaveis } from "../../../espaco-variaveis";
 import { ObjetoPadrao } from "../../../estruturas";
@@ -55,6 +55,10 @@ export class InterpretadorPortugolIpt
         this.pilhaEscoposExecucao.empilhar(escopoExecucao);
     }
 
+    visitarExpressaoTipoDe(expressao: TipoDe): Promise<any> {
+        throw new Error('Método não implementado.');
+    }
+
     visitarExpressaoFalhar(expressao: any): Promise<any> {
         throw new Error('Método não implementado.');
     }
diff --git a/fontes/interpretador/inferenciador.ts b/fontes/interpretador/inferenciador.ts
index 51a8ef38..5aa4c5b8 100644
--- a/fontes/interpretador/inferenciador.ts
+++ b/fontes/interpretador/inferenciador.ts
@@ -15,7 +15,9 @@ export function inferirTipoVariavel(variavel: string | number | Array<any> | boo
         case 'object':
             if (Array.isArray(variavel)) return 'vetor';
             if (variavel === null) return 'nulo';
+            if (variavel.constructor.name === 'DeleguaFuncao') return 'função';
             if (variavel.constructor.name === 'DeleguaModulo') return 'módulo';
+            if (variavel.constructor.name === 'Classe') return 'objeto';
             return 'dicionário';
         case 'function':
             return 'função';
diff --git a/fontes/interpretador/interpretador-base.ts b/fontes/interpretador/interpretador-base.ts
index df7f11bf..63f3bbc0 100644
--- a/fontes/interpretador/interpretador-base.ts
+++ b/fontes/interpretador/interpretador-base.ts
@@ -44,6 +44,7 @@ import {
     AcessoIndiceVariavel,
     Agrupamento,
     Atribuir,
+    Binario,
     Chamada,
     Construto,
     FimPara,
@@ -51,6 +52,7 @@ import {
     Literal,
     Logico,
     Super,
+    TipoDe,
     Unario,
     Variavel,
 } from '../construtos';
@@ -117,6 +119,19 @@ export class InterpretadorBase implements InterpretadorInterface {
         this.pilhaEscoposExecucao.empilhar(escopoExecucao);
 
         carregarBibliotecasGlobais(this, this.pilhaEscoposExecucao);
+    
+    }
+
+    async visitarExpressaoTipoDe(expressao: TipoDe): Promise<string> {
+        let tipoDe = expressao.valor;
+        
+        if(expressao.valor instanceof Variavel 
+            || expressao.valor instanceof Binario) {
+            tipoDe = await this.avaliar(expressao.valor);
+            return tipoDe.tipo || inferirTipoVariavel(tipoDe);
+        }
+
+        return inferirTipoVariavel(tipoDe?.valores || tipoDe)
     }
 
     visitarExpressaoFalhar(expressao: Falhar): Promise<any> {
@@ -1193,7 +1208,7 @@ export class InterpretadorBase implements InterpretadorInterface {
             }
         }
 
-        this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, null);
+        this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, declaracao);
 
         if (declaracao.superClasse !== null) {
             this.pilhaEscoposExecucao.definirVariavel('super', superClasse);
diff --git a/fontes/lexador/palavras-reservadas.ts b/fontes/lexador/palavras-reservadas.ts
index 4d19b691..bbe20b3e 100644
--- a/fontes/lexador/palavras-reservadas.ts
+++ b/fontes/lexador/palavras-reservadas.ts
@@ -38,6 +38,7 @@ export const palavrasReservadas = {
     super: tiposDeSimbolos.SUPER,
     sustar: tiposDeSimbolos.SUSTAR,
     tente: tiposDeSimbolos.TENTE,
+    tipo: tiposDeSimbolos.TIPO,
     var: tiposDeSimbolos.VARIAVEL,
     variavel: tiposDeSimbolos.VARIAVEL,
     variável: tiposDeSimbolos.VARIAVEL,
diff --git a/fontes/tipos-de-simbolos/delegua.ts b/fontes/tipos-de-simbolos/delegua.ts
index be42dbca..d8c3fc91 100644
--- a/fontes/tipos-de-simbolos/delegua.ts
+++ b/fontes/tipos-de-simbolos/delegua.ts
@@ -77,6 +77,7 @@ export default {
     SUSTAR: 'SUSTAR',
     TENTE: 'TENTE',
     TEXTO: 'TEXTO',
+    TIPO: 'TIPO',
     VARIAVEL: 'VARIAVEL',
     VERDADEIRO: 'VERDADEIRO',
     VIRGULA: 'VIRGULA',
diff --git a/package.json b/package.json
index 36897e23..3c01f271 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
         "egua",
         "eguap",
         "delegua",
+        "mapler",
         "visualg",
         "birl"
     ],


Test patch:
diff --git a/testes/interpretador.test.ts b/testes/interpretador.test.ts
index 98ff22d1..85be00b0 100644
--- a/testes/interpretador.test.ts
+++ b/testes/interpretador.test.ts
@@ -189,6 +189,38 @@ describe('Interpretador', () => {
 
                     expect(retornoInterpretador.erros).toHaveLength(0);
                 });
+
+                it('Tipo de', async () => {
+                    const retornoLexador = lexador.mapear([
+                        "escreva(tipo de verdadeiro)",
+                        "escreva(tipo de falso)",
+                        "escreva(tipo de 123)",
+                        "escreva(tipo de \"123\")",
+                        "escreva(tipo de [1,2,3])",
+                        "escreva(tipo de [])",
+                        "escreva(tipo de [1, '2'])",
+                        "var f = funcao(algumTexto) { }",
+                        "var a;",
+                        "var c = 1",
+                        "var d = \'2\'",
+                        "escreva(tipo de f)",
+                        "escreva(tipo de a)",
+                        "escreva(tipo de c)",
+                        "escreva(tipo de d)",
+                        "escreva(tipo de 4 + 2)",
+                        "escreva(tipo de 4 * 2 + (3 ^ 2))",
+                        "classe Teste {}",
+                        "escreva(tipo de Teste)",
+                        "classe OutroTeste {}",
+                        "escreva(tipo de OutroTeste)",
+                        "escreva(tipo de nulo)",
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                });
             });
 
             describe('Operações matemáticas', () => {