Repository: DesignLiquido/delegua
Pull request #297 (2023-03-23 23:05:56)

Implementando biblioteca de caracteres do VisuAlg.


Patch:
diff --git a/fontes/bibliotecas/dialetos/visualg/caracteres.ts b/fontes/bibliotecas/dialetos/visualg/caracteres.ts
new file mode 100644
index 00000000..f35eaa3c
--- /dev/null
+++ b/fontes/bibliotecas/dialetos/visualg/caracteres.ts
@@ -0,0 +1,71 @@
+import { FuncaoPadrao } from "../../../estruturas";
+import { PilhaEscoposExecucaoInterface } from "../../../interfaces/pilha-escopos-execucao-interface";
+import { InterpretadorVisuAlg } from "../../../interpretador/dialetos";
+
+export function registrarBibliotecaCaracteresVisuAlg(
+    interpretador: InterpretadorVisuAlg, 
+    pilhaEscoposExecucao: PilhaEscoposExecucaoInterface) 
+{
+    pilhaEscoposExecucao.definirVariavel(
+        'asc', 
+        new FuncaoPadrao(1, function(valor: string) {
+            return valor.charCodeAt(0);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'carac',
+        new FuncaoPadrao(1, function(valor: number) {
+            return String.fromCharCode(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'caracpnum',
+        new FuncaoPadrao(1, function(valor: string) {
+            return Number(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'compr',
+        new FuncaoPadrao(1, function(valor: string) {
+            return valor.length;
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'copia',
+        new FuncaoPadrao(3, function(valor: string, inicio: number, fim: number) {
+            return valor.substring(inicio, inicio + fim);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'maiusc',
+        new FuncaoPadrao(1, function(valor: string) {
+            return valor.toUpperCase();
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'minusc',
+        new FuncaoPadrao(1, function(valor: string) {
+            return valor.toLowerCase();
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'numpcarac',
+        new FuncaoPadrao(1, function(valor: number) {
+            return String(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'pos',
+        new FuncaoPadrao(2, function(busca: string, valor: string) {
+            return valor.indexOf(busca) + 1;
+        })
+    );
+}
\ No newline at end of file
diff --git a/fontes/bibliotecas/dialetos/visualg/index.ts b/fontes/bibliotecas/dialetos/visualg/index.ts
index c3f08285..7224e038 100644
--- a/fontes/bibliotecas/dialetos/visualg/index.ts
+++ b/fontes/bibliotecas/dialetos/visualg/index.ts
@@ -1,141 +1,2 @@
-import { FuncaoPadrao } from "../../../estruturas";
-import { PilhaEscoposExecucaoInterface } from "../../../interfaces/pilha-escopos-execucao-interface";
-import { InterpretadorVisuAlg } from "../../../interpretador/dialetos";
-
-export function registrarBibliotecaGlobalVisuAlg(
-    interpretador: InterpretadorVisuAlg, 
-    pilhaEscoposExecucao: PilhaEscoposExecucaoInterface) 
-{
-    pilhaEscoposExecucao.definirVariavel(
-        'abs', 
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.abs(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'arccos', 
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.acos(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'arcsen',
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.asin(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'arctan',
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.atan(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'cos',
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.cos(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'cotan',
-        new FuncaoPadrao(1, function(valor: number) {
-            return 1 / Math.tan(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'exp',
-        new FuncaoPadrao(2, function(base: number, expoente: number) {
-            return Math.pow(base, expoente);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'grauprad',
-        new FuncaoPadrao(1, function(valor: number) {
-            return valor * Math.PI / 180;
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'int',
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.floor(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'log',
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.log10(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'logn',
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.log(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'pi',
-        new FuncaoPadrao(0, function() {
-            return Math.PI;
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'quad',
-        new FuncaoPadrao(1, function(valor: number) {
-            return valor * valor;
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'radpgrau',
-        new FuncaoPadrao(1, function(valor: number) {
-            return valor * 180 / Math.PI;
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'raizq',
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.sqrt(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'rand',
-        new FuncaoPadrao(0, function() {
-            return Math.random();
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'randi',
-        new FuncaoPadrao(2, function(limite: number) {
-            return Math.floor(Math.random() * limite);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'sen',
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.sin(valor);
-        })
-    );
-
-    pilhaEscoposExecucao.definirVariavel(
-        'tan',
-        new FuncaoPadrao(1, function(valor: number) {
-            return Math.tan(valor);
-        })
-    );
-}
\ No newline at end of file
+export * from './caracteres';
+export * from './numerica';
\ No newline at end of file
diff --git a/fontes/bibliotecas/dialetos/visualg/numerica.ts b/fontes/bibliotecas/dialetos/visualg/numerica.ts
new file mode 100644
index 00000000..f3aeecd0
--- /dev/null
+++ b/fontes/bibliotecas/dialetos/visualg/numerica.ts
@@ -0,0 +1,141 @@
+import { FuncaoPadrao } from "../../../estruturas";
+import { PilhaEscoposExecucaoInterface } from "../../../interfaces/pilha-escopos-execucao-interface";
+import { InterpretadorVisuAlg } from "../../../interpretador/dialetos";
+
+export function registrarBibliotecaNumericaVisuAlg(
+    interpretador: InterpretadorVisuAlg, 
+    pilhaEscoposExecucao: PilhaEscoposExecucaoInterface) 
+{
+    pilhaEscoposExecucao.definirVariavel(
+        'abs', 
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.abs(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'arccos', 
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.acos(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'arcsen',
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.asin(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'arctan',
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.atan(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'cos',
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.cos(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'cotan',
+        new FuncaoPadrao(1, function(valor: number) {
+            return 1 / Math.tan(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'exp',
+        new FuncaoPadrao(2, function(base: number, expoente: number) {
+            return Math.pow(base, expoente);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'grauprad',
+        new FuncaoPadrao(1, function(valor: number) {
+            return valor * Math.PI / 180;
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'int',
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.floor(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'log',
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.log10(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'logn',
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.log(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'pi',
+        new FuncaoPadrao(0, function() {
+            return Math.PI;
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'quad',
+        new FuncaoPadrao(1, function(valor: number) {
+            return valor * valor;
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'radpgrau',
+        new FuncaoPadrao(1, function(valor: number) {
+            return valor * 180 / Math.PI;
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'raizq',
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.sqrt(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'rand',
+        new FuncaoPadrao(0, function() {
+            return Math.random();
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'randi',
+        new FuncaoPadrao(2, function(limite: number) {
+            return Math.floor(Math.random() * limite);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'sen',
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.sin(valor);
+        })
+    );
+
+    pilhaEscoposExecucao.definirVariavel(
+        'tan',
+        new FuncaoPadrao(1, function(valor: number) {
+            return Math.tan(valor);
+        })
+    );
+}
\ No newline at end of file
diff --git a/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts b/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts
index eca10337..01af6290 100644
--- a/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts
+++ b/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts
@@ -2,11 +2,12 @@ import { Construto, Variavel } from '../../../construtos';
 import { Escreva, EscrevaMesmaLinha, Fazer, Leia } from '../../../declaracoes';
 import { InterpretadorBase } from '../..';
 import { ContinuarQuebra, Quebra } from '../../../quebras';
-import { registrarBibliotecaGlobalVisuAlg } from '../../../bibliotecas/dialetos/visualg';
+import { registrarBibliotecaNumericaVisuAlg } from '../../../bibliotecas/dialetos/visualg/numerica';
 import { VariavelInterface } from '../../../interfaces';
 import { inferirTipoVariavel } from '../../inferenciador';
 
 import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg';
+import { registrarBibliotecaCaracteresVisuAlg } from '../../../bibliotecas/dialetos/visualg';
 
 /**
  * O Interpretador VisuAlg possui algumas diferenças em relação ao
@@ -26,7 +27,8 @@ export class InterpretadorVisuAlg extends InterpretadorBase {
         super(diretorioBase, performance, funcaoDeRetorno, funcaoDeRetornoMesmaLinha);
         this.mensagemPrompt = '> ';
 
-        registrarBibliotecaGlobalVisuAlg(this, this.pilhaEscoposExecucao);
+        registrarBibliotecaNumericaVisuAlg(this, this.pilhaEscoposExecucao);
+        registrarBibliotecaCaracteresVisuAlg(this, this.pilhaEscoposExecucao);
     }
 
     private async avaliarArgumentosEscrevaVisuAlg(argumentos: Construto[]): Promise<string> {
@@ -139,11 +141,11 @@ export class InterpretadorVisuAlg extends InterpretadorBase {
 
             // No VisuAlg, uma variável pode resolver para função porque funções não precisam ter parênteses.
             // Esta parte evita o problema.
-            if (valorEsquerdo.hasOwnProperty('funcao')) {
+            if (valorEsquerdo && valorEsquerdo.hasOwnProperty('funcao')) {
                 valorEsquerdo = valorEsquerdo.funcao();
             }
 
-            if (valorDireito.hasOwnProperty('funcao')) {
+            if (valorDireito && valorDireito.hasOwnProperty('funcao')) {
                 valorDireito = valorDireito.funcao();
             }
 


Test patch:
diff --git a/testes/visualg/biblioteca-global.test.ts b/testes/visualg/biblioteca-global.test.ts
index 651a907d..e852698a 100644
--- a/testes/visualg/biblioteca-global.test.ts
+++ b/testes/visualg/biblioteca-global.test.ts
@@ -1,5 +1,5 @@
 import { AvaliadorSintaticoVisuAlg } from '../../fontes/avaliador-sintatico/dialetos';
-import { registrarBibliotecaGlobalVisuAlg } from '../../fontes/bibliotecas/dialetos/visualg';
+import { registrarBibliotecaCaracteresVisuAlg, registrarBibliotecaNumericaVisuAlg } from '../../fontes/bibliotecas/dialetos/visualg';
 import { DeleguaFuncao, FuncaoPadrao } from '../../fontes/estruturas';
 import { SimboloInterface, VariavelInterface } from '../../fontes/interfaces';
 import { EscopoExecucao } from '../../fontes/interfaces/escopo-execucao';
@@ -76,11 +76,11 @@ const mockPilha: PilhaEscoposExecucaoInterface = {
     }
 };
 
-describe('Biblioteca Global', () => {
+describe('Biblioteca Numérica', () => {
     let interpretador: InterpretadorVisuAlg;
 
     beforeAll(() => {
-        registrarBibliotecaGlobalVisuAlg(interpretador, mockPilha);
+        registrarBibliotecaNumericaVisuAlg(interpretador, mockPilha);
     });
 
     describe('Testes triviais', () => {
@@ -182,7 +182,7 @@ describe('Biblioteca Global', () => {
         });
     });
 
-    describe('Testes con fonte completo', () => {
+    describe('Testes com fonte completo', () => {
         let lexador: LexadorVisuAlg;
         let avaliadorSintatico: AvaliadorSintaticoVisuAlg;
         let interpretador: InterpretadorVisuAlg;
@@ -209,6 +209,103 @@ describe('Biblioteca Global', () => {
                 'escreval( int( b / ( a + c ) ) )',
                 'Fimalgoritmo'
             ], -1);
+
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador);
+
+            const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+            expect(retornoInterpretador.erros).toHaveLength(0);
+        });
+    });
+});
+
+describe('Biblioteca de caracteres', () => {
+    let interpretador: InterpretadorVisuAlg;
+
+    beforeAll(() => {
+        registrarBibliotecaCaracteresVisuAlg(interpretador, mockPilha);
+    });
+
+    describe('Testes triviais', () => {
+        it('asc', () => {
+            const funcaoAsc = funcoes['asc'].funcao;
+            expect(funcaoAsc('a')).toBe(97);
+        });
+
+        it('carac', () => {
+            const funcaoCarac = funcoes['carac'].funcao;
+            expect(funcaoCarac(97)).toBe('a');
+        });
+
+        it('caracpnum', () => {
+            const funcaoCaracPNum = funcoes['caracpnum'].funcao;
+            expect(funcaoCaracPNum('97')).toBe(97);
+        });
+
+        it('compr', () => {
+            const funcaoCompr = funcoes['compr'].funcao;
+            expect(funcaoCompr('a')).toBe(1);
+        });
+
+        it('copia', () => {
+            const funcaoCopia = funcoes['copia'].funcao;
+            expect(funcaoCopia('Uma cadeia de caracteres', 4, 6)).toBe('cadeia');
+        });
+
+        it('maiusc', () => {
+            const funcaoMaiusc = funcoes['maiusc'].funcao;
+            expect(funcaoMaiusc('a')).toBe('A');
+        });
+
+        it('minusc', () => {
+            const funcaoMinusc = funcoes['minusc'].funcao;
+            expect(funcaoMinusc('A')).toBe('a');
+        });
+
+        it('numpcarac', () => {
+            const funcaoNumPCarac = funcoes['numpcarac'].funcao;
+            expect(funcaoNumPCarac(1)).toBe('1');
+        });
+
+        it('pos', () => {
+            const funcaoPos = funcoes['pos'].funcao;
+            expect(funcaoPos('a', 'a')).toBe(1);
+        });
+    });
+
+    describe('Testes com fonte completo', () => {
+        let lexador: LexadorVisuAlg;
+        let avaliadorSintatico: AvaliadorSintaticoVisuAlg;
+        let interpretador: InterpretadorVisuAlg;
+
+        beforeEach(() => {
+            lexador = new LexadorVisuAlg();
+            avaliadorSintatico = new AvaliadorSintaticoVisuAlg();
+            interpretador = new InterpretadorVisuAlg(process.cwd());
+        });
+        
+        it('Chamadas diversas', async () => {
+            const retornoLexador = lexador.mapear([
+                'Algoritmo "exemplo_funcoes2"',
+                'var',
+                'a, b, c : caractere',
+                'inicio',
+                'a <- "2"',
+                'b <- "9"',
+                'escreval( b + a ) // será escrito "92" na tela',
+                'escreval( caracpnum(b) + caracpnum(a) ) // será escrito 11 na tela',
+                'escreval( numpcarac(3+3) + a ) // será escrito "62" na tela',
+                'c <- "Brasil"',
+                'escreval(maiusc(c)) // será escrito "BRASIL" na tela',
+                'escreval(compr(c)) // será escrito 6 na tela',
+                'b <- "O melhor do Brasil"',
+                'escreval(pos(c,b)) // será escrito 13 na tela',
+                'escreval(asc(c)) // será escrito 66 na tela - código ASCII de "B"',
+                'a <- carac(65) + carac(66) + carac(67)',
+                'escreval(a) // será escrito "ABC" na tela',
+                'Fimalgoritmo'
+            ], -1);
+
             const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador);
 
             const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);