Repository: DesignLiquido/delegua
Pull request #750 (2025-05-11 18:17:31)

Pituguês - Correções em várias primitivas
Quando corrigimos algo em Delégua, abrimos uma Pull Request como esta. Para me manter honesto, coloco revisores para ler o código e entender o que foi corrigido. 

Aqui corrijo uma série de problemas reportados no seu relatório do dia 9 de maio.

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: 73.56%">73.74% (+0.17% 🔼)</div> | 6806/9230 |
| 🟡 | Branches | <div title="Base coverage is: 63.41%">63.62% (+0.21% 🔼)</div> | 2189/3441 |
| 🟡 | Functions | <div title="Base coverage is: 63.37%">63.5% (+0.13% 🔼)</div> | 981/1545 |
| 🟡 | Lines | <div title="Base coverage is: 73.95%">74.13% (+0.19% 🔼)</div> | 6640/8957 |


## Test suite run success
576 tests passing in 35 suites.

<p align="right">Report generated by <a href="https://github.com/ArtiomTr/jest-coverage-report-action">🧪jest coverage report action</a> from 9a271ea1a300c4e2780fd7ea6dbb725e200c9f12</p>
<!-- Sticky Pull Request Comment -->

Patch:
diff --git a/fontes/avaliador-sintatico/avaliador-sintatico.ts b/fontes/avaliador-sintatico/avaliador-sintatico.ts
index 4e855fed..34fa4119 100644
--- a/fontes/avaliador-sintatico/avaliador-sintatico.ts
+++ b/fontes/avaliador-sintatico/avaliador-sintatico.ts
@@ -255,7 +255,7 @@ export class AvaliadorSintatico
                 valores = [];
 
                 if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_DIREITO)) {
-                    return new Vetor(this.hashArquivo, Number(simboloAtual.linha), [], 0, 'qualquer');
+                    return new Vetor(this.hashArquivo, Number(simboloAtual.linha), [], 0, 'qualquer[]');
                 }
 
                 while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_DIREITO)) {
diff --git a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.ts b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.ts
index 123c8697..5da5d0d4 100644
--- a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.ts
+++ b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.ts
@@ -52,6 +52,8 @@ import { RetornoPrimario } from '../retornos';
 
 import tiposDeSimbolos from '../../tipos-de-simbolos/pitugues';
 import { Simbolo } from '../../lexador';
+import { inferirTipoVariavel, TipoInferencia, tipoInferenciaParaTipoDadosElementar } from '../../inferenciador';
+import { TipoDadosElementar } from '../../tipo-dados-elementar';
 
 /**
  * O avaliador sintático (_Parser_) é responsável por transformar os símbolos do Lexador em estruturas de alto nível.
@@ -71,7 +73,7 @@ export class AvaliadorSintaticoPitugues implements AvaliadorSintaticoInterface<S
     blocos: number;
     escopos: number[];
     performance: boolean;
-    superclassseAtual: string | undefined;
+    superclasseAtual: string | undefined;
 
     constructor(performance = false) {
         this.atual = 0;
@@ -97,7 +99,63 @@ export class AvaliadorSintaticoPitugues implements AvaliadorSintaticoInterface<S
     }
 
     declaracaoDeConstantes(): Const[] {
-        throw new Error('Método não implementado.');
+        const identificadores: SimboloInterface[] = [];
+        let tipo: string = 'qualquer';
+
+        // TODO: Desestruturação em Python não requer chaves.
+        // Exemplo: const a, b, c = vetor;
+        // Pensar em algo equivalente para Pituguês.
+        /* if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CHAVE_ESQUERDA)) {
+            return this.declaracaoDesestruturacaoConstante();
+        } */
+
+        do {
+            identificadores.push(this.consumir(tiposDeSimbolos.IDENTIFICADOR, 'Esperado nome da constante.'));
+        } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));
+
+        // TODO: Discutir com comunidade como seria melhor fazer
+        // dicas de tipos.
+        /* if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DOIS_PONTOS)) {
+            tipo = this.verificarDefinicaoTipoAtual();
+            this.avancarEDevolverAnterior();
+        } */
+
+        this.consumir(tiposDeSimbolos.IGUAL, "Esperado '=' após identificador em instrução 'constante'.");
+
+        const inicializadores = [];
+        do {
+            inicializadores.push(this.expressao());
+        } while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));
+
+        // TODO: Muito provavelmente, com desestruturação, essa validação
+        // não será necessária.
+        /* if (identificadores.length !== inicializadores.length) {
+            throw this.erro(
+                this.simbolos[this.atual],
+                'Quantidade de identificadores à esquerda do igual é diferente da quantidade de valores à direita.'
+            );
+        } */
+
+        let retorno: Const[] = [];
+        for (let [indice, identificador] of identificadores.entries()) {
+            // Se tipo ainda não foi definido, infere.
+            // tipo = this.logicaComumInferenciaTiposVariaveisEConstantes(inicializadores[indice], tipo);
+
+            // this.pilhaEscopos.definirTipoVariavel(identificador.lexema, tipo);
+            retorno.push(
+                new Const(
+                    identificador,
+                    inicializadores[indice],
+                    tipo as TipoDadosElementar,
+                    // TODO: Discutir decoradores com comunidade.
+                    // Array.from(this.pilhaDecoradores)
+                )
+            );
+        }
+
+        // this.pilhaDecoradores = [];
+
+        return retorno;
     }
 
     declaracaoDeVariavel(): Var {
@@ -217,80 +275,85 @@ export class AvaliadorSintaticoPitugues implements AvaliadorSintaticoInterface<S
     }
 
     primario(): RetornoPrimario {
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.SUPER)) {
-            const simboloChave = this.simboloAnterior();
-            /* 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, this.superclassseAtual);
-        }
-
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_ESQUERDO)) {
-            const valores = [];
-
-            if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_DIREITO)) {
-                return new Vetor(this.hashArquivo, 0, []);
-            }
-
-            while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_DIREITO)) {
-                const valor = this.atribuir();
-                valores.push(valor);
-                if (this.simboloAtual().tipo !== tiposDeSimbolos.COLCHETE_DIREITO) {
-                    this.consumir(tiposDeSimbolos.VIRGULA, 'Esperado vírgula antes da próxima expressão.');
+        const simboloAtual = this.simbolos[this.atual];
+        let valores = [];
+        switch (simboloAtual.tipo) {
+            case tiposDeSimbolos.SUPER:
+                const simboloSuper = this.avancarEDevolverAnterior();
+                return new Super(this.hashArquivo, simboloSuper, this.superclasseAtual);
+            case tiposDeSimbolos.COLCHETE_ESQUERDO:
+                this.avancarEDevolverAnterior();
+                if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_DIREITO)) {
+                    return new Vetor(this.hashArquivo, simboloAtual.linha, [], 0, 'qualquer[]');
                 }
-            }
-
-            return new Vetor(this.hashArquivo, 0, valores);
-        }
-
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CHAVE_ESQUERDA)) {
-            const chaves = [];
-            const valores = [];
 
-            if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CHAVE_DIREITA)) {
-                return new Dicionario(this.hashArquivo, 0, [], []);
-            }
-
-            while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CHAVE_DIREITA)) {
-                const chave = this.atribuir();
-                this.consumir(tiposDeSimbolos.DOIS_PONTOS, "Esperado ':' entre chave e valor.");
-                const valor = this.atribuir();
+                while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_DIREITO)) {
+                    const valor = this.atribuir();
+                    valores.push(valor);
+                    if (this.simbolos[this.atual].tipo !== tiposDeSimbolos.COLCHETE_DIREITO) {
+                        this.consumir(tiposDeSimbolos.VIRGULA, 'Esperado vírgula antes da próxima expressão.');
+                    }
+                }
 
-                chaves.push(chave);
-                valores.push(valor);
+                const tipoVetor = inferirTipoVariavel(valores);
+                return new Vetor(this.hashArquivo, simboloAtual.linha, valores, valores.length, tipoVetor);
+            case tiposDeSimbolos.CHAVE_ESQUERDA:
+                this.avancarEDevolverAnterior();
+                const chaves = [];
 
-                if (this.simboloAtual().tipo !== tiposDeSimbolos.CHAVE_DIREITA) {
-                    this.consumir(tiposDeSimbolos.VIRGULA, 'Esperado vírgula antes da próxima expressão.');
+                if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CHAVE_DIREITA)) {
+                    return new Dicionario(this.hashArquivo, simboloAtual.linha, [], []);
                 }
-            }
 
-            return new Dicionario(this.hashArquivo, 0, chaves, valores);
-        }
+                while (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CHAVE_DIREITA)) {
+                    const chave = this.atribuir();
+                    this.consumir(tiposDeSimbolos.DOIS_PONTOS, "Esperado ':' entre chave e valor.");
+                    const valor = this.atribuir();
 
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.FALSO)) return new Literal(this.hashArquivo, 0, false);
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VERDADEIRO))
-            return new Literal(this.hashArquivo, 0, true);
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.NULO)) return new Literal(this.hashArquivo, 0, null);
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.ISTO))
-            return new Isto(this.hashArquivo, 0, this.simboloAnterior());
+                    chaves.push(chave);
+                    valores.push(valor);
 
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.NUMERO, tiposDeSimbolos.TEXTO)) {
-            const simboloAnterior: SimboloInterface = this.simboloAnterior();
-            return new Literal(this.hashArquivo, Number(simboloAnterior.linha), simboloAnterior.literal);
-        }
-
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IDENTIFICADOR)) {
-            return new Variavel(this.hashArquivo, this.simboloAnterior());
-        }
+                    if (this.simboloAtual().tipo !== tiposDeSimbolos.CHAVE_DIREITA) {
+                        this.consumir(tiposDeSimbolos.VIRGULA, 'Esperado vírgula antes da próxima expressão.');
+                    }
+                }
 
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARENTESE_ESQUERDO)) {
-            const expressao = this.expressao();
-            this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após a expressão.");
+                return new Dicionario(this.hashArquivo, simboloAtual.linha, chaves, valores);
+            case tiposDeSimbolos.FALSO:
+            case tiposDeSimbolos.VERDADEIRO:
+                const simboloLogico = this.avancarEDevolverAnterior();
+                return new Literal(this.hashArquivo, simboloAtual.linha, simboloLogico.tipo === tiposDeSimbolos.VERDADEIRO, 'lógico');
+            case tiposDeSimbolos.FUNCAO:
+            case tiposDeSimbolos.FUNÇÃO:
+                const simboloFuncao = this.avancarEDevolverAnterior();
+                const corpoDaFuncao = this.corpoDaFuncao(simboloFuncao.lexema);
+                // this.pilhaEscopos.definirTipoVariavel(simboloFuncao.lexema, 'função');
+                return corpoDaFuncao;
+            case tiposDeSimbolos.NULO:
+                this.avancarEDevolverAnterior();
+                return new Literal(this.hashArquivo, simboloAtual.linha, null);
+            case tiposDeSimbolos.ISTO:
+                const simboloIsto = this.avancarEDevolverAnterior();
+                return new Isto(this.hashArquivo, simboloAtual.linha, simboloIsto);
+            case tiposDeSimbolos.NUMERO: 
+            case tiposDeSimbolos.TEXTO:
+                const simboloLiteral: SimboloInterface = this.avancarEDevolverAnterior();
+                const tipoInferido = inferirTipoVariavel(simboloLiteral.literal);
+                const tipoDadosElementar = tipoInferenciaParaTipoDadosElementar(tipoInferido as TipoInferencia);
+                return new Literal(this.hashArquivo, Number(simboloLiteral.linha), simboloLiteral.literal, tipoDadosElementar);
+            case tiposDeSimbolos.IDENTIFICADOR:
+                const simboloIdentificador = this.avancarEDevolverAnterior();
+                return new Variavel(this.hashArquivo, simboloIdentificador);
+            case tiposDeSimbolos.PARENTESE_ESQUERDO:
+                this.avancarEDevolverAnterior();
+                const expressao = this.expressao();
+                this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após a expressão.");
 
-            return new Agrupamento(this.hashArquivo, 0, expressao);
+                return new Agrupamento(this.hashArquivo, simboloAtual.linha, expressao);
+            case tiposDeSimbolos.IMPORTAR:
+                return this.declaracaoImportar();
         }
 
-        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IMPORTAR)) return this.declaracaoImportar();
-
         throw this.erro(this.simboloAtual(), 'Esperado expressão.');
     }
 
@@ -759,6 +822,7 @@ export class AvaliadorSintaticoPitugues implements AvaliadorSintaticoInterface<S
     }
 
     declaracaoImportar(): Importar {
+        this.avancarEDevolverAnterior();
         this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, "Esperado '(' após declaração.");
         const caminho = this.expressao();
         this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após declaração.");
@@ -958,7 +1022,7 @@ export class AvaliadorSintaticoPitugues implements AvaliadorSintaticoInterface<S
         let superClasse = null;
         if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.HERDA)) {
             const simboloSuperclasse = this.consumir(tiposDeSimbolos.IDENTIFICADOR, 'Esperado nome da Superclasse.');
-            this.superclassseAtual = simboloSuperclasse.lexema;
+            this.superclasseAtual = simboloSuperclasse.lexema;
             superClasse = new Variavel(this.hashArquivo, this.simboloAnterior());
         }
 
@@ -976,7 +1040,7 @@ export class AvaliadorSintaticoPitugues implements AvaliadorSintaticoInterface<S
             metodos.push(this.funcao('método', this.simbolos[this.atual - 1].tipo === tiposDeSimbolos.CONSTRUTOR));
         }
 
-        this.superclassseAtual = undefined;
+        this.superclasseAtual = undefined;
         return new Classe(simbolo, superClasse, metodos);
     }
 


Test patch:
diff --git a/testes/pitugues/interpretador.test.ts b/testes/pitugues/interpretador.test.ts
index aee97f20..e222583e 100644
--- a/testes/pitugues/interpretador.test.ts
+++ b/testes/pitugues/interpretador.test.ts
@@ -1,17 +1,23 @@
 import { AvaliadorSintaticoPitugues } from "../../fontes/avaliador-sintatico/dialetos";
-import { InterpretadorBase } from "../../fontes/interpretador";
+import { Interpretador } from "../../fontes/interpretador";
 import { LexadorPitugues } from "../../fontes/lexador/dialetos";
 
 describe('Interpretador (Pituguês)', () => {
     describe('interpretar()', () => {
         let lexador: LexadorPitugues;
         let avaliadorSintatico: AvaliadorSintaticoPitugues;
-        let interpretador: InterpretadorBase;
+        let interpretador: Interpretador;
+
+        let _saidas: string[] = [];
+        const funcaoSaida = (texto: string) => {
+            _saidas.push(texto);
+        }
 
         beforeEach(() => {
+            _saidas = [];
             lexador = new LexadorPitugues();
             avaliadorSintatico = new AvaliadorSintaticoPitugues();
-            interpretador = new InterpretadorBase(process.cwd());
+            interpretador = new Interpretador(process.cwd(), false, funcaoSaida, funcaoSaida);
         });
 
         describe('Cenários de sucesso', () => {
@@ -28,6 +34,17 @@ describe('Interpretador (Pituguês)', () => {
                     expect(retornoInterpretador.erros).toHaveLength(0);
                 });
 
+                it('Constantes', async () => {
+                    const retornoLexador = lexador.mapear([
+                        "const g, h, i = 1, '2', 3",
+                    ], -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                });
+
                 it('Vetor', async () => {
                     const retornoLexador = lexador.mapear(["var a = [1, 2, 3]"], -1);
                     const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
@@ -252,6 +269,203 @@ describe('Interpretador (Pituguês)', () => {
                     expect(retornoInterpretador.erros).toHaveLength(0);
                 });
             });
+
+            describe('Uso de bibliotecas', () => {
+                it('mapear', async () => {
+                    const codigo = [
+                        'var vetor = [1, 2, 3]',
+                        'var fn = funcao(valor):',
+                        '    retorna valor * 2',
+                        'escreva(mapear(vetor, fn))'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(1);
+                    expect(_saidas[0]).toBe('[2, 4, 6]');
+                });
+            });
+
+            describe('Uso de primitivas de número', () => {
+                it('arredondarParaBaixo', async () => {
+                    const codigo = [
+                        'var n1 = 3.1415',
+                        'escreva(n1.arredondarParaBaixo())'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(1);
+                    expect(_saidas[0]).toBe('3');
+                });
+
+                it('arredondarParaCima', async () => {
+                    const codigo = [
+                        'var n1 = 3.1415',
+                        'escreva(n1.arredondarParaCima())'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(1);
+                    expect(_saidas[0]).toBe('4');
+                });
+            });
+
+            describe('Uso de primitivas de texto', () => {
+                it('aparar', async () => {
+                    const codigo = [
+                        'escreva("   texto com espaços        ".aparar())'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(1);
+                    expect(_saidas[0]).toBe('texto com espaços');
+                });
+
+                it('concatenar', async () => {
+                    const codigo = [
+                        'var t1 = "um texto"',
+                        'var t2 = " concatenado com outro"',
+                        'escreva(t1.concatenar(t2))'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(1);
+                    expect(_saidas[0]).toBe('um texto concatenado com outro');
+                });
+
+                it('dividir', async () => {
+                    const codigo = [
+                        'var t1 = "um dois três"',
+                        'escreva(t1.dividir(" "))'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(1);
+                    expect(_saidas[0]).toBe("['um', 'dois', 'três']");
+                });
+
+                it('maiusculo', async () => {
+                    const codigo = [
+                        'var t1 = "um dois três"',
+                        'escreva(t1.maiusculo())'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(1);
+                    expect(_saidas[0]).toBe("UM DOIS TRÊS");
+                });
+
+                it('minusculo', async () => {
+                    const codigo = [
+                        'var t1 = "UM DOIS TRÊS"',
+                        'escreva(t1.minusculo())'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(1);
+                    expect(_saidas[0]).toBe("um dois três");
+                });
+            });
+
+            describe('Uso de primitivas de vetor', () => {
+                it('fatiar', async () => {
+                    const codigo = [
+                        'var lista = ["Ser", "ou", "não", "ser"]',
+                        'escreva(lista.fatiar(2))',
+                        'escreva(lista.fatiar(1, 2))'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(2);
+                    expect(_saidas[0]).toBe("['não', 'ser']");
+                    expect(_saidas[1]).toBe("['ou']");
+                });
+
+                it('inclui', async () => {
+                    const codigo = [
+                        'var lista = [1, 2, 3, 4, 5, 6]',
+                        'var lista2 = ["Ser", "ou", "não", "ser"]',
+                        'escreva(lista.inclui(5))',
+                        'escreva(lista2.inclui("ser"))',
+                        'escreva(lista2.inclui("abc"))'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(3);
+                    expect(_saidas[0]).toBe("verdadeiro");
+                    expect(_saidas[1]).toBe("verdadeiro");
+                    expect(_saidas[2]).toBe("falso");
+                });
+
+                it('substituir', async () => {
+                    const codigo = [
+                        'var t = "Ser ou não ser, eis a questão"',
+                        'escreva(t.substituir("Ser", "Salmão"));'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(1);
+                    expect(_saidas[0]).toBe("Salmão ou não ser, eis a questão");
+                });
+
+                it('subtexto', async () => {
+                    const codigo = [
+                        'var t = "Ser ou não ser, eis a questão"',
+                        'escreva(t.subtexto(4, 10))'
+                    ];
+                    const retornoLexador = lexador.mapear(codigo, -1);
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toHaveLength(1);
+                    expect(_saidas[0]).toBe("ou não");
+                });
+            });
         });
 
         describe('Cenários de falha', () => {