Repository: DesignLiquido/delegua
Pull request #549 (2023-11-08 07:59:16)

Permitindo chamada a `super()` para construtor de classe herdada.


Patch:
diff --git a/fontes/avaliador-sintatico/avaliador-sintatico.ts b/fontes/avaliador-sintatico/avaliador-sintatico.ts
index 4a321233..8798c3b4 100644
--- a/fontes/avaliador-sintatico/avaliador-sintatico.ts
+++ b/fontes/avaliador-sintatico/avaliador-sintatico.ts
@@ -1,11 +1,7 @@
 import tiposDeSimbolos from '../tipos-de-simbolos/delegua';
 import hrtime from 'browser-process-hrtime';
 
-import { 
-    AvaliadorSintaticoInterface, 
-    ParametroInterface, 
-    SimboloInterface,
-} from '../interfaces';
+import { AvaliadorSintaticoInterface, ParametroInterface, SimboloInterface } from '../interfaces';
 import {
     AcessoMetodo as AcessoMetodo,
     Agrupamento,
@@ -58,6 +54,7 @@ import { RetornoAvaliadorSintatico } from '../interfaces/retornos/retorno-avalia
 import { RetornoLexador } from '../interfaces/retornos/retorno-lexador';
 import { RetornoDeclaracao } from './retornos';
 import { TiposDadosInterface } from '../interfaces/tipos-dados-interface';
+import { Simbolo } from '../lexador';
 
 /**
  * O avaliador sintático (_Parser_) é responsável por transformar os símbolos do Lexador em estruturas de alto nível.
@@ -254,10 +251,22 @@ export class AvaliadorSintatico implements AvaliadorSintaticoInterface<SimboloIn
                 return new Agrupamento(this.hashArquivo, Number(simboloAtual.linha), expressao);
 
             case tiposDeSimbolos.SUPER:
-                const simboloChave = this.avancarEDevolverAnterior();
-                this.consumir(tiposDeSimbolos.PONTO, "Esperado '.' após 'super'.");
-                const metodo = this.consumir(tiposDeSimbolos.IDENTIFICADOR, 'Esperado nome do método da Superclasse.');
-                return new Super(this.hashArquivo, simboloChave, metodo);
+                const simboloSuper = this.avancarEDevolverAnterior();
+                // Se o próximo símbolo for uma abertura de parênteses, significa que
+                // é uma chamada ao construtor da classe ancestral (superclasse).
+                // Se o próximo símbolo for um ponto, significa que é uma chamada
+                // a um método da superclasse.
+                switch (this.simbolos[this.atual].tipo) {
+                    case tiposDeSimbolos.PARENTESE_ESQUERDO:
+                        return new Super(
+                            this.hashArquivo, 
+                            simboloSuper, 
+                            new Simbolo(tiposDeSimbolos.IDENTIFICADOR, 'construtor', null, simboloSuper.linha, this.hashArquivo));
+                    default:
+                        this.consumir(tiposDeSimbolos.PONTO, "Esperado '.' após 'super'.");
+                        const metodoSuperclasse = this.consumir(tiposDeSimbolos.IDENTIFICADOR, 'Esperado nome do método da Superclasse.');
+                        return new Super(this.hashArquivo, simboloSuper, metodoSuperclasse);
+                }
 
             case tiposDeSimbolos.VERDADEIRO:
                 this.avancarEDevolverAnterior();
@@ -276,21 +285,19 @@ export class AvaliadorSintatico implements AvaliadorSintaticoInterface<SimboloIn
             case tiposDeSimbolos.EXPRESSAO_REGULAR:
                 let valor: string = '';
                 let linhaAtual = this.simbolos[this.atual].linha;
-                let eParExpressaoRegular = this.simbolos
-                            .filter(l => l.linha === linhaAtual && l.tipo === tiposDeSimbolos.EXPRESSAO_REGULAR)
-                            .length % 2 === 0;
-                if(eParExpressaoRegular) {
+                let eParExpressaoRegular =
+                    this.simbolos.filter((l) => l.linha === linhaAtual && l.tipo === tiposDeSimbolos.EXPRESSAO_REGULAR)
+                        .length %
+                        2 ===
+                    0;
+                if (eParExpressaoRegular) {
                     this.avancarEDevolverAnterior();
                     while (!this.verificarTipoSimboloAtual(tiposDeSimbolos.EXPRESSAO_REGULAR)) {
                         valor += this.simboloAtual().lexema || '';
                         this.avancarEDevolverAnterior();
                     }
                     this.avancarEDevolverAnterior();
-                    return new ExpressaoRegular(
-                        this.hashArquivo,
-                        simboloAtual,
-                        valor
-                    );
+                    return new ExpressaoRegular(this.hashArquivo, simboloAtual, valor);
                 }
         }
 
@@ -704,7 +711,7 @@ export class AvaliadorSintatico implements AvaliadorSintaticoInterface<SimboloIn
         let incrementar = null;
         if (!this.verificarTipoSimboloAtual(tiposDeSimbolos.PARENTESE_DIREITO)) {
             incrementar = this.expressao();
-            this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.INCREMENTAR, tiposDeSimbolos.DECREMENTAR)
+            this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.INCREMENTAR, tiposDeSimbolos.DECREMENTAR);
         }
 
         if (comParenteses) {
@@ -1132,8 +1139,8 @@ export class AvaliadorSintatico implements AvaliadorSintaticoInterface<SimboloIn
                 parametro.tipoDado = {
                     nome: this.simbolos[this.atual - 2].lexema,
                     tipo: tipoDadoParametro,
-                    tipoInvalido: !tipoDadoParametro ? this.simboloAtual().lexema : null
-                }
+                    tipoInvalido: !tipoDadoParametro ? this.simboloAtual().lexema : null,
+                };
                 this.avancarEDevolverAnterior();
             }
 
diff --git a/fontes/interpretador/interpretador-base.ts b/fontes/interpretador/interpretador-base.ts
index 751e8158..be99d1ef 100644
--- a/fontes/interpretador/interpretador-base.ts
+++ b/fontes/interpretador/interpretador-base.ts
@@ -1488,6 +1488,8 @@ export class InterpretadorBase implements InterpretadorInterface {
 
         if (Array.isArray(objeto)) return objeto;
         if (objeto.valor instanceof ObjetoPadrao) return objeto.valor.paraTexto();
+        // TODO: Idealmente isso deveria devolver um texto estruturado representando o objeto.
+        if (objeto instanceof ObjetoDeleguaClasse) return objeto.toString();
         if (typeof objeto === 'object') return JSON.stringify(objeto);
 
         return objeto.toString();


Test patch:
diff --git a/testes/interpretador.test.ts b/testes/interpretador.test.ts
index 6db32449..57530ce3 100644
--- a/testes/interpretador.test.ts
+++ b/testes/interpretador.test.ts
@@ -902,7 +902,7 @@ describe('Interpretador', () => {
                     expect(retornoInterpretador.erros).toHaveLength(0);
                 });
 
-                it.skip('Chamada de método com `super` e definição de propriedade com `isto`', async () => {
+                it('Chamada de método com `super` e definição de propriedade com `isto`', async () => {
                     const codigo = [
                         "classe A {",
                             "construtor() {",
@@ -914,7 +914,7 @@ describe('Interpretador', () => {
                         "}",
                         "classe B herda A {",
                             "construtor(data) {",
-                              // "super();",
+                              "super();",
                               "super.data(data);",
                             "}",
                         "}",