@designliquido/delegua 0.11.14 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/package.json +1 -1
- package/fontes/construtos/atribuir.js +1 -1
- package/fontes/construtos/atribuir.js.map +1 -1
- package/fontes/construtos/chamada.d.ts +2 -0
- package/fontes/construtos/chamada.js +20 -0
- package/fontes/construtos/chamada.js.map +1 -1
- package/fontes/declaracoes/classe.js +1 -1
- package/fontes/declaracoes/classe.js.map +1 -1
- package/fontes/declaracoes/enquanto.js +1 -1
- package/fontes/declaracoes/enquanto.js.map +1 -1
- package/fontes/declaracoes/escolha.js +1 -1
- package/fontes/declaracoes/escolha.js.map +1 -1
- package/fontes/declaracoes/escreva.js +1 -1
- package/fontes/declaracoes/escreva.js.map +1 -1
- package/fontes/declaracoes/fazer.js +1 -1
- package/fontes/declaracoes/fazer.js.map +1 -1
- package/fontes/declaracoes/funcao.js +1 -1
- package/fontes/declaracoes/funcao.js.map +1 -1
- package/fontes/declaracoes/importar.js +1 -1
- package/fontes/declaracoes/importar.js.map +1 -1
- package/fontes/declaracoes/para.js +1 -1
- package/fontes/declaracoes/para.js.map +1 -1
- package/fontes/declaracoes/se.js +1 -1
- package/fontes/declaracoes/se.js.map +1 -1
- package/fontes/declaracoes/tente.js +1 -1
- package/fontes/declaracoes/tente.js.map +1 -1
- package/fontes/declaracoes/var.js +1 -1
- package/fontes/declaracoes/var.js.map +1 -1
- package/fontes/depuracao/servidor-depuracao.d.ts +2 -1
- package/fontes/depuracao/servidor-depuracao.js +43 -13
- package/fontes/depuracao/servidor-depuracao.js.map +1 -1
- package/fontes/espaco-variaveis.d.ts +12 -0
- package/fontes/espaco-variaveis.js +10 -0
- package/fontes/espaco-variaveis.js.map +1 -1
- package/fontes/estruturas/delegua-funcao.d.ts +3 -0
- package/fontes/estruturas/delegua-funcao.js +3 -0
- package/fontes/estruturas/delegua-funcao.js.map +1 -1
- package/fontes/interfaces/escopo-execucao.d.ts +4 -0
- package/fontes/interfaces/interpretador-com-depuracao-interface.d.ts +7 -5
- package/fontes/interfaces/interpretador-interface.d.ts +12 -18
- package/fontes/interfaces/pilha-escopos-execucao-interface.d.ts +2 -1
- package/fontes/interfaces/resolvedor-interface.d.ts +0 -12
- package/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.d.ts +12 -12
- package/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.js +19 -13
- package/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.js.map +1 -1
- package/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.d.ts +12 -12
- package/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.js +12 -12
- package/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.js.map +1 -1
- package/fontes/interpretador/dialetos/visualg.d.ts +1 -1
- package/fontes/interpretador/dialetos/visualg.js +1 -1
- package/fontes/interpretador/dialetos/visualg.js.map +1 -1
- package/fontes/interpretador/interpretador-com-depuracao.d.ts +83 -12
- package/fontes/interpretador/interpretador-com-depuracao.js +238 -111
- package/fontes/interpretador/interpretador-com-depuracao.js.map +1 -1
- package/fontes/interpretador/interpretador.d.ts +25 -24
- package/fontes/interpretador/interpretador.js +35 -21
- package/fontes/interpretador/interpretador.js.map +1 -1
- package/fontes/interpretador/pilha-escopos-execucao.d.ts +2 -1
- package/fontes/interpretador/pilha-escopos-execucao.js +10 -1
- package/fontes/interpretador/pilha-escopos-execucao.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { EspacoVariaveis } from '../espaco-variaveis';
|
|
2
|
-
import { Declaracao } from '../declaracoes';
|
|
2
|
+
import { Declaracao, Retorna, Var } from '../declaracoes';
|
|
3
3
|
import { PontoParada } from '../depuracao';
|
|
4
|
-
import { ImportadorInterface, InterpretadorComDepuracaoInterface } from '../interfaces';
|
|
4
|
+
import { ComandoDepurador, ImportadorInterface, InterpretadorComDepuracaoInterface } from '../interfaces';
|
|
5
|
+
import { TipoEscopoExecucao } from '../interfaces/escopo-execucao';
|
|
6
|
+
import { RetornoQuebra } from '../quebras';
|
|
5
7
|
import { Interpretador } from './interpretador';
|
|
6
8
|
import { RetornoInterpretador } from '../interfaces/retornos/retorno-interpretador';
|
|
9
|
+
import { Atribuir, Chamada } from '../construtos';
|
|
7
10
|
/**
|
|
8
11
|
* Implementação do Interpretador com suporte a depuração.
|
|
9
12
|
* Herda o Interpretador padrão de Delégua e implementa métodos a mais, que são
|
|
@@ -29,9 +32,42 @@ export declare class InterpretadorComDepuracao extends Interpretador implements
|
|
|
29
32
|
finalizacaoDaExecucao: Function;
|
|
30
33
|
pontoDeParadaAtivo: boolean;
|
|
31
34
|
escopoAtual: number;
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
comando?: ComandoDepurador;
|
|
36
|
+
executandoChamada: boolean;
|
|
37
|
+
proximoEscopo?: TipoEscopoExecucao;
|
|
38
|
+
idChamadaAtual?: string;
|
|
39
|
+
passos: number;
|
|
34
40
|
constructor(importador: ImportadorInterface, diretorioBase: string, funcaoDeRetorno: Function);
|
|
41
|
+
private gerarIdResolucaoChamada;
|
|
42
|
+
visitarExpressaoDeChamada(expressao: Chamada): Promise<any>;
|
|
43
|
+
/**
|
|
44
|
+
* A execução de uma atribuição de variável no interpretador com depuração pode ser em duas etapas.
|
|
45
|
+
* O desenvolvedor pode inspecionar o lado direito e ir parando a execução usando
|
|
46
|
+
* F10, por exemplo. Neste caso, a instrução aqui é executada duas vezes:
|
|
47
|
+
* A primeira para armazenar o valor do lado direito em `this.valorRetornoEscopoAnterior`, e a
|
|
48
|
+
* segunda para efetivamente atribuir o valor da variável.
|
|
49
|
+
* @param expressao
|
|
50
|
+
* @returns
|
|
51
|
+
*/
|
|
52
|
+
visitarDeclaracaoDeAtribuicao(expressao: Atribuir): Promise<any>;
|
|
53
|
+
/**
|
|
54
|
+
* A execução de `var` no interpretador com depuração pode ser em duas etapas.
|
|
55
|
+
* O desenvolvedor pode inspecionar o lado direito e ir parando a execução usando
|
|
56
|
+
* F10, por exemplo. Neste caso, a instrução aqui é executada duas vezes:
|
|
57
|
+
* A primeira para armazenar o valor do lado direito em `this.valorRetornoEscopoAnterior`, e a
|
|
58
|
+
* segunda para efetivamente atribuir o valor da variável.
|
|
59
|
+
* @param declaracao A declaração Var
|
|
60
|
+
* @returns O valor do resultado resolvido, se a declaração resolveu.
|
|
61
|
+
* Nulo ou indefinido em caso contrário.
|
|
62
|
+
*/
|
|
63
|
+
visitarDeclaracaoVar(declaracao: Var): Promise<any>;
|
|
64
|
+
/**
|
|
65
|
+
* Ao executar um retorno, manter o valor retornado no Interpretador para
|
|
66
|
+
* uso por linhas que foram executadas com o comando `próximo` do depurador.
|
|
67
|
+
* @param declaracao Uma declaracao Retorna
|
|
68
|
+
* @returns O resultado da execução da visita.
|
|
69
|
+
*/
|
|
70
|
+
visitarExpressaoRetornar(declaracao: Retorna): Promise<RetornoQuebra>;
|
|
35
71
|
/**
|
|
36
72
|
* Se bloco de execução já foi instanciado antes (por exemplo, quando há um ponto de parada e a
|
|
37
73
|
* execução do código é retomada pelo depurador), retoma a execução do bloco do ponto em que havia parado.
|
|
@@ -48,7 +84,21 @@ export declare class InterpretadorComDepuracao extends Interpretador implements
|
|
|
48
84
|
* @param declaracao A declaração a ser executada.
|
|
49
85
|
* @returns True quando execução deve parar. False caso contrário.
|
|
50
86
|
*/
|
|
51
|
-
verificarPontoParada
|
|
87
|
+
private verificarPontoParada;
|
|
88
|
+
/**
|
|
89
|
+
* No interpretador com depuração, este método é dividido em dois outros métodos privados:
|
|
90
|
+
* - `this.executarUmPassoNoEscopo`, que executa apenas uma instrução e nada mais;
|
|
91
|
+
* - `this.executarUltimoEscopoComandoContinuar`, que é a execução trivial de um escopo inteiro,
|
|
92
|
+
* ou com todas as instruções, ou até encontrar um ponto de parada.
|
|
93
|
+
* @param manterAmbiente Se verdadeiro, junta elementos do último escopo com o escopo
|
|
94
|
+
* imediatamente abaixo.
|
|
95
|
+
* @param naoVerificarPrimeiraExecucao Booleano que pede ao Interpretador para não
|
|
96
|
+
* verificar o ponto de parada na primeira execução.
|
|
97
|
+
* Normalmente usado pelo Servidor de Depuração para continuar uma linha.
|
|
98
|
+
* @returns O retorno da execução.
|
|
99
|
+
*/
|
|
100
|
+
executarUltimoEscopo(manterAmbiente?: boolean, naoVerificarPrimeiraExecucao?: boolean): Promise<any>;
|
|
101
|
+
private executarUmPassoNoEscopo;
|
|
52
102
|
/**
|
|
53
103
|
* Continua a interpretação parcial do último ponto em que parou.
|
|
54
104
|
* Pode ser tanto o começo da execução inteira, ou pós comando do depurador
|
|
@@ -60,7 +110,7 @@ export declare class InterpretadorComDepuracao extends Interpretador implements
|
|
|
60
110
|
* Normalmente usado pelo Servidor de Depuração para continuar uma linha.
|
|
61
111
|
* @returns Um objeto de retorno, com erros encontrados se houverem.
|
|
62
112
|
*/
|
|
63
|
-
|
|
113
|
+
private executarUltimoEscopoComandoContinuar;
|
|
64
114
|
/**
|
|
65
115
|
* Continua a interpretação, conforme comando do depurador.
|
|
66
116
|
* Quando um ponto de parada é ativado, a pilha de execução do TypeScript é perdida.
|
|
@@ -69,34 +119,55 @@ export declare class InterpretadorComDepuracao extends Interpretador implements
|
|
|
69
119
|
* Diferentemente de `executarUltimoEscopo`, este método descarta apenas um escopo (o que foi chamado).
|
|
70
120
|
* @see executarBloco
|
|
71
121
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
122
|
+
instrucaoContinuarInterpretacao(): Promise<any>;
|
|
123
|
+
/**
|
|
124
|
+
* Empilha um escopo se for possível.
|
|
125
|
+
* Se não for, apenas executa a instrução corrente.
|
|
126
|
+
*/
|
|
127
|
+
adentrarEscopo(): Promise<any>;
|
|
74
128
|
/**
|
|
75
129
|
* Interpreta apenas uma instrução a partir do ponto de parada ativo, conforme comando do depurador.
|
|
76
130
|
* Esse método cria uma nova pilha de execução do lado do JS, começando do último elemento executado do
|
|
77
131
|
* primeiro escopo, subindo até o último elemento executado do último escopo.
|
|
78
132
|
* @param escopo Indica o escopo a ser visitado. Usado para construir uma pilha de chamadas do lado JS.
|
|
79
133
|
*/
|
|
80
|
-
|
|
134
|
+
instrucaoPasso(escopo?: number): Promise<any>;
|
|
81
135
|
/**
|
|
82
136
|
* Interpreta restante do bloco de execução em que o ponto de parada está, conforme comando do depurador.
|
|
83
137
|
* Se houver outros pontos de parada no mesmo escopo à frente da instrução atual, todos são ignorados.
|
|
84
138
|
* @param escopo Indica o escopo a ser visitado. Usado para construir uma pilha de chamadas do lado JS.
|
|
85
139
|
*/
|
|
86
|
-
|
|
140
|
+
instrucaoProximoESair(): Promise<void>;
|
|
87
141
|
/**
|
|
88
142
|
* Prepara a pilha de escopos para uma situação de depuração.
|
|
89
143
|
* Não há execução de código neste caso.
|
|
90
144
|
* @param declaracoes Um vetor de declarações.
|
|
91
145
|
*/
|
|
92
146
|
prepararParaDepuracao(declaracoes: Declaracao[]): void;
|
|
147
|
+
private abrirNovoBlocoEscopo;
|
|
148
|
+
/**
|
|
149
|
+
* Reimplementando este método aqui porque a execução por depuração não requer
|
|
150
|
+
* mostrar o resultado em momento algum, ou lidar com o retorno.
|
|
151
|
+
* @param declaracao A declaracao a ser executada.
|
|
152
|
+
* @param mostrarResultado Sempre falso.
|
|
153
|
+
* @returns O resultado da execução.
|
|
154
|
+
*/
|
|
155
|
+
executar(declaracao: Declaracao, mostrarResultado?: boolean): Promise<any>;
|
|
93
156
|
/**
|
|
94
|
-
* Interpretação utilizada pelo depurador
|
|
95
|
-
* ponto de parada ou não.
|
|
157
|
+
* Interpretação utilizada pelo depurador para avaliar valores de variáveis.
|
|
96
158
|
* Diferentemente da interpretação tradicional, não possui indicadores
|
|
97
159
|
* de performance porque eles não fazem sentido aqui.
|
|
98
160
|
* @param declaracoes Um vetor de declarações.
|
|
99
161
|
* @returns Um objeto de retorno, com erros encontrados se houverem.
|
|
100
162
|
*/
|
|
101
163
|
interpretar(declaracoes: Declaracao[], manterAmbiente?: boolean): Promise<RetornoInterpretador>;
|
|
164
|
+
/**
|
|
165
|
+
* Obtém o valor de uma variável por nome.
|
|
166
|
+
* Em versões anteriores, o mecanismo de avaliação fazia toda a avaliação tradicional,
|
|
167
|
+
* passando por Lexador, Avaliador Sintático e Interpretador.
|
|
168
|
+
* Isso tem sua cota de problemas, sobretudo porque a avaliação insere e descarta escopos,
|
|
169
|
+
* entrando em condição de corrida com a interpretação com depuração.
|
|
170
|
+
* @param nome O nome da variável.
|
|
171
|
+
*/
|
|
172
|
+
obterVariavel(nome: string): any;
|
|
102
173
|
}
|
|
@@ -4,6 +4,8 @@ exports.InterpretadorComDepuracao = void 0;
|
|
|
4
4
|
const espaco_variaveis_1 = require("../espaco-variaveis");
|
|
5
5
|
const quebras_1 = require("../quebras");
|
|
6
6
|
const interpretador_1 = require("./interpretador");
|
|
7
|
+
const construtos_1 = require("../construtos");
|
|
8
|
+
const inferenciador_1 = require("./inferenciador");
|
|
7
9
|
/**
|
|
8
10
|
* Implementação do Interpretador com suporte a depuração.
|
|
9
11
|
* Herda o Interpretador padrão de Delégua e implementa métodos a mais, que são
|
|
@@ -30,8 +32,101 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
30
32
|
this.pontosParada = [];
|
|
31
33
|
this.pontoDeParadaAtivo = false;
|
|
32
34
|
this.escopoAtual = 0;
|
|
33
|
-
this.
|
|
34
|
-
this.
|
|
35
|
+
this.executandoChamada = false;
|
|
36
|
+
this.passos = 0;
|
|
37
|
+
}
|
|
38
|
+
async gerarIdResolucaoChamada(expressao) {
|
|
39
|
+
const argumentosResolvidos = [];
|
|
40
|
+
for (let argumento of expressao.argumentos) {
|
|
41
|
+
argumentosResolvidos.push(await this.avaliar(argumento));
|
|
42
|
+
}
|
|
43
|
+
return argumentosResolvidos.reduce((acumulador, argumento) => acumulador += `,${argumento.hasOwnProperty('valor') ? argumento.valor : argumento}`, expressao.id);
|
|
44
|
+
}
|
|
45
|
+
async visitarExpressaoDeChamada(expressao) {
|
|
46
|
+
const _idChamadaComArgumentos = await this.gerarIdResolucaoChamada(expressao);
|
|
47
|
+
// Usado na abertura do bloco de escopo da chamada.
|
|
48
|
+
this.idChamadaAtual = _idChamadaComArgumentos;
|
|
49
|
+
this.executandoChamada = true;
|
|
50
|
+
this.proximoEscopo = 'funcao';
|
|
51
|
+
const retorno = await super.visitarExpressaoDeChamada(expressao);
|
|
52
|
+
this.executandoChamada = false;
|
|
53
|
+
const escopoAtual = this.pilhaEscoposExecucao.topoDaPilha();
|
|
54
|
+
escopoAtual.ambiente.resolucoesChamadas[_idChamadaComArgumentos] = retorno;
|
|
55
|
+
return retorno;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A execução de uma atribuição de variável no interpretador com depuração pode ser em duas etapas.
|
|
59
|
+
* O desenvolvedor pode inspecionar o lado direito e ir parando a execução usando
|
|
60
|
+
* F10, por exemplo. Neste caso, a instrução aqui é executada duas vezes:
|
|
61
|
+
* A primeira para armazenar o valor do lado direito em `this.valorRetornoEscopoAnterior`, e a
|
|
62
|
+
* segunda para efetivamente atribuir o valor da variável.
|
|
63
|
+
* @param expressao
|
|
64
|
+
* @returns
|
|
65
|
+
*/
|
|
66
|
+
async visitarDeclaracaoDeAtribuicao(expressao) {
|
|
67
|
+
if (expressao.valor instanceof construtos_1.Chamada) {
|
|
68
|
+
const escopoAtual = this.pilhaEscoposExecucao.topoDaPilha();
|
|
69
|
+
const idChamadaComArgumentos = await this.gerarIdResolucaoChamada(expressao.valor);
|
|
70
|
+
if (escopoAtual.ambiente.resolucoesChamadas.hasOwnProperty(idChamadaComArgumentos)) {
|
|
71
|
+
const retornar = escopoAtual.ambiente.resolucoesChamadas[idChamadaComArgumentos];
|
|
72
|
+
this.pilhaEscoposExecucao.atribuirVariavel(expressao.simbolo, retornar);
|
|
73
|
+
delete escopoAtual.ambiente.resolucoesChamadas[idChamadaComArgumentos];
|
|
74
|
+
return retornar;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const valor = await this.avaliar(expressao.valor);
|
|
78
|
+
this.pilhaEscoposExecucao.atribuirVariavel(expressao.simbolo, valor);
|
|
79
|
+
return valor;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* A execução de `var` no interpretador com depuração pode ser em duas etapas.
|
|
83
|
+
* O desenvolvedor pode inspecionar o lado direito e ir parando a execução usando
|
|
84
|
+
* F10, por exemplo. Neste caso, a instrução aqui é executada duas vezes:
|
|
85
|
+
* A primeira para armazenar o valor do lado direito em `this.valorRetornoEscopoAnterior`, e a
|
|
86
|
+
* segunda para efetivamente atribuir o valor da variável.
|
|
87
|
+
* @param declaracao A declaração Var
|
|
88
|
+
* @returns O valor do resultado resolvido, se a declaração resolveu.
|
|
89
|
+
* Nulo ou indefinido em caso contrário.
|
|
90
|
+
*/
|
|
91
|
+
async visitarDeclaracaoVar(declaracao) {
|
|
92
|
+
if (declaracao.inicializador instanceof construtos_1.Chamada) {
|
|
93
|
+
const escopoAtual = this.pilhaEscoposExecucao.topoDaPilha();
|
|
94
|
+
const idChamadaComArgumentos = await this.gerarIdResolucaoChamada(declaracao.inicializador);
|
|
95
|
+
if (escopoAtual.ambiente.resolucoesChamadas.hasOwnProperty(idChamadaComArgumentos)) {
|
|
96
|
+
const retornar = escopoAtual.ambiente.resolucoesChamadas[idChamadaComArgumentos];
|
|
97
|
+
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, retornar);
|
|
98
|
+
delete escopoAtual.ambiente.resolucoesChamadas[idChamadaComArgumentos];
|
|
99
|
+
return retornar;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const valorFinal = await this.avaliacaoDeclaracaoVar(declaracao);
|
|
103
|
+
if (valorFinal !== null && valorFinal !== undefined) {
|
|
104
|
+
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, valorFinal);
|
|
105
|
+
}
|
|
106
|
+
return valorFinal;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Ao executar um retorno, manter o valor retornado no Interpretador para
|
|
110
|
+
* uso por linhas que foram executadas com o comando `próximo` do depurador.
|
|
111
|
+
* @param declaracao Uma declaracao Retorna
|
|
112
|
+
* @returns O resultado da execução da visita.
|
|
113
|
+
*/
|
|
114
|
+
async visitarExpressaoRetornar(declaracao) {
|
|
115
|
+
const retorno = await super.visitarExpressaoRetornar(declaracao);
|
|
116
|
+
// O escopo atual é marcado como finalizado, para notificar a
|
|
117
|
+
// instrução de que deve ser descartado.
|
|
118
|
+
const escopoAtual = this.pilhaEscoposExecucao.topoDaPilha();
|
|
119
|
+
escopoAtual.finalizado = true;
|
|
120
|
+
// Acha o primeiro escopo de função.
|
|
121
|
+
const escopoFuncao = this.pilhaEscoposExecucao.obterEscopoPorTipo('funcao');
|
|
122
|
+
if (escopoFuncao === undefined) {
|
|
123
|
+
return Promise.reject('retorna() chamado fora de execução de função.');
|
|
124
|
+
}
|
|
125
|
+
if (escopoFuncao.idChamada !== undefined) {
|
|
126
|
+
escopoAtual.ambiente.resolucoesChamadas[escopoFuncao.idChamada] =
|
|
127
|
+
retorno && retorno.hasOwnProperty('valor') ? retorno.valor : retorno;
|
|
128
|
+
}
|
|
129
|
+
return retorno;
|
|
35
130
|
}
|
|
36
131
|
/**
|
|
37
132
|
* Se bloco de execução já foi instanciado antes (por exemplo, quando há um ponto de parada e a
|
|
@@ -44,6 +139,7 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
44
139
|
* @param ambiente O ambiente de execução quando houver, como parâmetros, argumentos, etc.
|
|
45
140
|
*/
|
|
46
141
|
async executarBloco(declaracoes, ambiente) {
|
|
142
|
+
// Se o escopo atual não é o último.
|
|
47
143
|
if (this.escopoAtual < this.pilhaEscoposExecucao.elementos() - 1) {
|
|
48
144
|
this.escopoAtual++;
|
|
49
145
|
const proximoEscopo = this.pilhaEscoposExecucao.naPosicao(this.escopoAtual);
|
|
@@ -59,25 +155,26 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
59
155
|
break;
|
|
60
156
|
}
|
|
61
157
|
retornoExecucao = await this.executar(proximoEscopo.declaracoes[proximoEscopo.declaracaoAtual]);
|
|
158
|
+
// Um ponto de parada ativo pode ter vindo de um escopo mais interno.
|
|
159
|
+
// Por isso verificamos outra parada aqui para evitar que
|
|
160
|
+
// `this.declaracaoAtual` seja incrementado.
|
|
161
|
+
if (this.pontoDeParadaAtivo) {
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
62
164
|
}
|
|
63
165
|
this.pilhaEscoposExecucao.removerUltimo();
|
|
64
166
|
this.escopoAtual--;
|
|
65
167
|
return retornoExecucao;
|
|
66
168
|
}
|
|
67
169
|
else {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
|
|
74
|
-
this.escopoAtual++;
|
|
75
|
-
if (this.comandoProximo) {
|
|
76
|
-
// Quando o comando for 'próximo', não executa.
|
|
77
|
-
// Aguarda o usuário com a próxima instrução vinda do depurador.
|
|
78
|
-
return null;
|
|
170
|
+
this.abrirNovoBlocoEscopo(declaracoes, ambiente, this.proximoEscopo || 'outro');
|
|
171
|
+
const ultimoEscopo = this.pilhaEscoposExecucao.topoDaPilha();
|
|
172
|
+
if (this.idChamadaAtual) {
|
|
173
|
+
ultimoEscopo.idChamada = this.idChamadaAtual;
|
|
174
|
+
this.idChamadaAtual = undefined;
|
|
79
175
|
}
|
|
80
|
-
|
|
176
|
+
this.proximoEscopo = undefined;
|
|
177
|
+
if (this.comando !== 'adentrarEscopo') {
|
|
81
178
|
return await this.executarUltimoEscopo();
|
|
82
179
|
}
|
|
83
180
|
}
|
|
@@ -91,11 +188,68 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
91
188
|
const buscaPontoParada = this.pontosParada.filter((p) => p.hashArquivo === declaracao.hashArquivo &&
|
|
92
189
|
p.linha === declaracao.linha);
|
|
93
190
|
if (buscaPontoParada.length > 0) {
|
|
94
|
-
console.log(
|
|
191
|
+
console.log(`Ponto de parada encontrado. Linha: ${declaracao.linha}.`);
|
|
95
192
|
return true;
|
|
96
193
|
}
|
|
97
194
|
return false;
|
|
98
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* No interpretador com depuração, este método é dividido em dois outros métodos privados:
|
|
198
|
+
* - `this.executarUmPassoNoEscopo`, que executa apenas uma instrução e nada mais;
|
|
199
|
+
* - `this.executarUltimoEscopoComandoContinuar`, que é a execução trivial de um escopo inteiro,
|
|
200
|
+
* ou com todas as instruções, ou até encontrar um ponto de parada.
|
|
201
|
+
* @param manterAmbiente Se verdadeiro, junta elementos do último escopo com o escopo
|
|
202
|
+
* imediatamente abaixo.
|
|
203
|
+
* @param naoVerificarPrimeiraExecucao Booleano que pede ao Interpretador para não
|
|
204
|
+
* verificar o ponto de parada na primeira execução.
|
|
205
|
+
* Normalmente usado pelo Servidor de Depuração para continuar uma linha.
|
|
206
|
+
* @returns O retorno da execução.
|
|
207
|
+
*/
|
|
208
|
+
async executarUltimoEscopo(manterAmbiente = false, naoVerificarPrimeiraExecucao = false) {
|
|
209
|
+
switch (this.comando) {
|
|
210
|
+
case 'adentrarEscopo':
|
|
211
|
+
case 'proximo':
|
|
212
|
+
if (!this.executandoChamada) {
|
|
213
|
+
return this.executarUmPassoNoEscopo();
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
return this.executarUltimoEscopoComandoContinuar(manterAmbiente, naoVerificarPrimeiraExecucao);
|
|
217
|
+
}
|
|
218
|
+
default:
|
|
219
|
+
return this.executarUltimoEscopoComandoContinuar(manterAmbiente, naoVerificarPrimeiraExecucao);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
async executarUmPassoNoEscopo() {
|
|
223
|
+
const ultimoEscopo = this.pilhaEscoposExecucao.topoDaPilha();
|
|
224
|
+
let retornoExecucao;
|
|
225
|
+
if (this.passos > 0) {
|
|
226
|
+
this.passos--;
|
|
227
|
+
retornoExecucao = await this.executar(ultimoEscopo.declaracoes[ultimoEscopo.declaracaoAtual]);
|
|
228
|
+
if (!this.pontoDeParadaAtivo) {
|
|
229
|
+
ultimoEscopo.declaracaoAtual++;
|
|
230
|
+
}
|
|
231
|
+
if (ultimoEscopo.declaracaoAtual >= ultimoEscopo.declaracoes.length || ultimoEscopo.finalizado) {
|
|
232
|
+
let outroEscopo = this.pilhaEscoposExecucao.topoDaPilha();
|
|
233
|
+
if (retornoExecucao instanceof quebras_1.RetornoQuebra) {
|
|
234
|
+
while (outroEscopo.tipo !== 'funcao') {
|
|
235
|
+
this.pilhaEscoposExecucao.removerUltimo();
|
|
236
|
+
const escopoAnterior = this.pilhaEscoposExecucao.topoDaPilha();
|
|
237
|
+
escopoAnterior.ambiente.resolucoesChamadas = Object.assign(escopoAnterior.ambiente.resolucoesChamadas, outroEscopo.ambiente.resolucoesChamadas);
|
|
238
|
+
this.escopoAtual--;
|
|
239
|
+
outroEscopo = this.pilhaEscoposExecucao.topoDaPilha();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
this.pilhaEscoposExecucao.removerUltimo();
|
|
243
|
+
const escopoAnterior = this.pilhaEscoposExecucao.topoDaPilha();
|
|
244
|
+
escopoAnterior.ambiente.resolucoesChamadas = Object.assign(escopoAnterior.ambiente.resolucoesChamadas, outroEscopo.ambiente.resolucoesChamadas);
|
|
245
|
+
this.escopoAtual--;
|
|
246
|
+
}
|
|
247
|
+
if (this.pilhaEscoposExecucao.elementos() === 1) {
|
|
248
|
+
this.finalizacaoDaExecucao();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return retornoExecucao;
|
|
252
|
+
}
|
|
99
253
|
/**
|
|
100
254
|
* Continua a interpretação parcial do último ponto em que parou.
|
|
101
255
|
* Pode ser tanto o começo da execução inteira, ou pós comando do depurador
|
|
@@ -107,10 +261,10 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
107
261
|
* Normalmente usado pelo Servidor de Depuração para continuar uma linha.
|
|
108
262
|
* @returns Um objeto de retorno, com erros encontrados se houverem.
|
|
109
263
|
*/
|
|
110
|
-
async
|
|
264
|
+
async executarUltimoEscopoComandoContinuar(manterAmbiente = false, naoVerificarPrimeiraExecucao = false) {
|
|
111
265
|
const ultimoEscopo = this.pilhaEscoposExecucao.topoDaPilha();
|
|
266
|
+
let retornoExecucao;
|
|
112
267
|
try {
|
|
113
|
-
let retornoExecucao;
|
|
114
268
|
for (; !(retornoExecucao instanceof quebras_1.Quebra) &&
|
|
115
269
|
ultimoEscopo.declaracaoAtual < ultimoEscopo.declaracoes.length; ultimoEscopo.declaracaoAtual++) {
|
|
116
270
|
if (naoVerificarPrimeiraExecucao) {
|
|
@@ -123,14 +277,21 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
123
277
|
}
|
|
124
278
|
}
|
|
125
279
|
retornoExecucao = await this.executar(ultimoEscopo.declaracoes[ultimoEscopo.declaracaoAtual]);
|
|
280
|
+
// Um ponto de parada ativo pode ter vindo de um escopo mais interno.
|
|
281
|
+
// Por isso verificamos outra parada aqui para evitar que
|
|
282
|
+
// `this.declaracaoAtual` seja incrementado.
|
|
283
|
+
if (this.pontoDeParadaAtivo) {
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
126
286
|
}
|
|
127
287
|
return retornoExecucao;
|
|
128
288
|
}
|
|
129
289
|
finally {
|
|
130
|
-
if (!this.pontoDeParadaAtivo) {
|
|
290
|
+
if (!this.pontoDeParadaAtivo && this.comando !== 'adentrarEscopo') {
|
|
131
291
|
this.pilhaEscoposExecucao.removerUltimo();
|
|
292
|
+
const escopoAnterior = this.pilhaEscoposExecucao.topoDaPilha();
|
|
293
|
+
escopoAnterior.ambiente.resolucoesChamadas = Object.assign(escopoAnterior.ambiente.resolucoesChamadas, ultimoEscopo.ambiente.resolucoesChamadas);
|
|
132
294
|
if (manterAmbiente) {
|
|
133
|
-
const escopoAnterior = this.pilhaEscoposExecucao.topoDaPilha();
|
|
134
295
|
escopoAnterior.ambiente.valores = Object.assign(escopoAnterior.ambiente.valores, ultimoEscopo.ambiente.valores);
|
|
135
296
|
}
|
|
136
297
|
this.escopoAtual--;
|
|
@@ -148,45 +309,15 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
148
309
|
* Diferentemente de `executarUltimoEscopo`, este método descarta apenas um escopo (o que foi chamado).
|
|
149
310
|
* @see executarBloco
|
|
150
311
|
*/
|
|
151
|
-
async
|
|
152
|
-
this.
|
|
153
|
-
const primeiroEscopo = this.pilhaEscoposExecucao.naPosicao(1);
|
|
154
|
-
let retornoExecucao;
|
|
155
|
-
// Primeira execução sempre ocorre, independente de pontos de parada.
|
|
156
|
-
retornoExecucao = await this.executar(primeiroEscopo.declaracoes[primeiroEscopo.declaracaoAtual]);
|
|
157
|
-
primeiroEscopo.declaracaoAtual++;
|
|
158
|
-
for (; !(retornoExecucao instanceof quebras_1.Quebra) &&
|
|
159
|
-
primeiroEscopo.declaracaoAtual < primeiroEscopo.declaracoes.length; primeiroEscopo.declaracaoAtual++) {
|
|
160
|
-
this.pontoDeParadaAtivo = this.verificarPontoParada(primeiroEscopo.declaracoes[primeiroEscopo.declaracaoAtual]);
|
|
161
|
-
if (this.pontoDeParadaAtivo) {
|
|
162
|
-
break;
|
|
163
|
-
}
|
|
164
|
-
retornoExecucao = await this.executar(primeiroEscopo.declaracoes[primeiroEscopo.declaracaoAtual]);
|
|
165
|
-
}
|
|
166
|
-
if (primeiroEscopo.declaracaoAtual >= primeiroEscopo.declaracoes.length) {
|
|
167
|
-
this.pilhaEscoposExecucao.removerUltimo();
|
|
168
|
-
}
|
|
169
|
-
if (this.pilhaEscoposExecucao.elementos() === 1) {
|
|
170
|
-
this.finalizacaoDaExecucao();
|
|
171
|
-
}
|
|
312
|
+
async instrucaoContinuarInterpretacao() {
|
|
313
|
+
this.executarUltimoEscopoComandoContinuar(false, true);
|
|
172
314
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
numeroEscopo == this.pilhaEscoposExecucao.pilha.length - 1) {
|
|
180
|
-
let numeroEscopoAtual = numeroEscopo;
|
|
181
|
-
while (numeroEscopoAtual > 0) {
|
|
182
|
-
const escopo = this.pilhaEscoposExecucao.pilha[numeroEscopoAtual];
|
|
183
|
-
if (escopo.declaracoes.length == escopo.declaracaoAtual) {
|
|
184
|
-
this.pilhaEscoposExecucao.removerUltimo();
|
|
185
|
-
this.escopoAtual--;
|
|
186
|
-
}
|
|
187
|
-
numeroEscopoAtual--;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
315
|
+
/**
|
|
316
|
+
* Empilha um escopo se for possível.
|
|
317
|
+
* Se não for, apenas executa a instrução corrente.
|
|
318
|
+
*/
|
|
319
|
+
async adentrarEscopo() {
|
|
320
|
+
throw new Error('Método não implementado.');
|
|
190
321
|
}
|
|
191
322
|
/**
|
|
192
323
|
* Interpreta apenas uma instrução a partir do ponto de parada ativo, conforme comando do depurador.
|
|
@@ -194,28 +325,20 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
194
325
|
* primeiro escopo, subindo até o último elemento executado do último escopo.
|
|
195
326
|
* @param escopo Indica o escopo a ser visitado. Usado para construir uma pilha de chamadas do lado JS.
|
|
196
327
|
*/
|
|
197
|
-
async
|
|
328
|
+
async instrucaoPasso(escopo = 1) {
|
|
329
|
+
this.passos = 1;
|
|
198
330
|
const escopoVisitado = this.pilhaEscoposExecucao.naPosicao(escopo);
|
|
331
|
+
if (escopoVisitado.declaracaoAtual >= escopoVisitado.declaracoes.length || escopoVisitado.finalizado) {
|
|
332
|
+
this.pilhaEscoposExecucao.removerUltimo();
|
|
333
|
+
}
|
|
334
|
+
if (this.pilhaEscoposExecucao.elementos() === 1) {
|
|
335
|
+
return this.finalizacaoDaExecucao();
|
|
336
|
+
}
|
|
199
337
|
if (escopo < this.escopoAtual) {
|
|
200
|
-
this.
|
|
338
|
+
this.instrucaoPasso(escopo + 1);
|
|
201
339
|
}
|
|
202
340
|
else {
|
|
203
|
-
|
|
204
|
-
await this.executar(declaracaoAtual);
|
|
205
|
-
if (this.comandoAdentrarEscopo) {
|
|
206
|
-
// Depurador comandou instrução 'adentrar-escopo', ou bloco de escopo
|
|
207
|
-
// não é de uma função.
|
|
208
|
-
// Instrução só foi realmente executada se não abriu novo bloco de escopo.
|
|
209
|
-
// Por isso, `declaracaoAtual` não deve ser incrementada aqui.
|
|
210
|
-
this.comandoAdentrarEscopo = false;
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
escopoVisitado.declaracaoAtual++;
|
|
214
|
-
}
|
|
215
|
-
this.descartarEscoposFinalizados(escopo, escopoVisitado);
|
|
216
|
-
}
|
|
217
|
-
if (this.pilhaEscoposExecucao.elementos() === 1) {
|
|
218
|
-
this.finalizacaoDaExecucao();
|
|
341
|
+
await this.executarUmPassoNoEscopo();
|
|
219
342
|
}
|
|
220
343
|
}
|
|
221
344
|
/**
|
|
@@ -223,30 +346,8 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
223
346
|
* Se houver outros pontos de parada no mesmo escopo à frente da instrução atual, todos são ignorados.
|
|
224
347
|
* @param escopo Indica o escopo a ser visitado. Usado para construir uma pilha de chamadas do lado JS.
|
|
225
348
|
*/
|
|
226
|
-
async
|
|
227
|
-
|
|
228
|
-
if (escopo < this.escopoAtual - 1) {
|
|
229
|
-
this.proximoESair(escopo + 1);
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
const ultimoEscopo = this.pilhaEscoposExecucao.topoDaPilha();
|
|
233
|
-
let retornoExecucao;
|
|
234
|
-
for (; !(retornoExecucao instanceof quebras_1.Quebra) &&
|
|
235
|
-
ultimoEscopo.declaracaoAtual < ultimoEscopo.declaracoes.length; ultimoEscopo.declaracaoAtual++) {
|
|
236
|
-
retornoExecucao = await this.executar(ultimoEscopo.declaracoes[ultimoEscopo.declaracaoAtual]);
|
|
237
|
-
}
|
|
238
|
-
this.pilhaEscoposExecucao.removerUltimo();
|
|
239
|
-
this.escopoAtual--;
|
|
240
|
-
escopoVisitado.declaracaoAtual++;
|
|
241
|
-
}
|
|
242
|
-
// Se última instrução do escopo atual foi executada, descartar escopo.
|
|
243
|
-
if (escopoVisitado.declaracoes.length <= escopoVisitado.declaracaoAtual) {
|
|
244
|
-
this.pilhaEscoposExecucao.removerUltimo();
|
|
245
|
-
this.escopoAtual--;
|
|
246
|
-
}
|
|
247
|
-
if (this.pilhaEscoposExecucao.elementos() === 1) {
|
|
248
|
-
this.finalizacaoDaExecucao();
|
|
249
|
-
}
|
|
349
|
+
async instrucaoProximoESair() {
|
|
350
|
+
this.executarUltimoEscopoComandoContinuar(false, true);
|
|
250
351
|
}
|
|
251
352
|
/**
|
|
252
353
|
* Prepara a pilha de escopos para uma situação de depuração.
|
|
@@ -255,17 +356,31 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
255
356
|
*/
|
|
256
357
|
prepararParaDepuracao(declaracoes) {
|
|
257
358
|
this.declaracoes = declaracoes;
|
|
359
|
+
this.abrirNovoBlocoEscopo(declaracoes);
|
|
360
|
+
}
|
|
361
|
+
abrirNovoBlocoEscopo(declaracoes, ambiente, tipoEscopo = 'outro') {
|
|
258
362
|
const escopoExecucao = {
|
|
259
363
|
declaracoes: declaracoes,
|
|
260
364
|
declaracaoAtual: 0,
|
|
261
|
-
ambiente: new espaco_variaveis_1.EspacoVariaveis(),
|
|
365
|
+
ambiente: ambiente || new espaco_variaveis_1.EspacoVariaveis(),
|
|
366
|
+
finalizado: false,
|
|
367
|
+
tipo: tipoEscopo
|
|
262
368
|
};
|
|
263
369
|
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
|
|
264
370
|
this.escopoAtual++;
|
|
265
371
|
}
|
|
266
372
|
/**
|
|
267
|
-
*
|
|
268
|
-
*
|
|
373
|
+
* Reimplementando este método aqui porque a execução por depuração não requer
|
|
374
|
+
* mostrar o resultado em momento algum, ou lidar com o retorno.
|
|
375
|
+
* @param declaracao A declaracao a ser executada.
|
|
376
|
+
* @param mostrarResultado Sempre falso.
|
|
377
|
+
* @returns O resultado da execução.
|
|
378
|
+
*/
|
|
379
|
+
async executar(declaracao, mostrarResultado = false) {
|
|
380
|
+
return await declaracao.aceitar(this);
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Interpretação utilizada pelo depurador para avaliar valores de variáveis.
|
|
269
384
|
* Diferentemente da interpretação tradicional, não possui indicadores
|
|
270
385
|
* de performance porque eles não fazem sentido aqui.
|
|
271
386
|
* @param declaracoes Um vetor de declarações.
|
|
@@ -274,21 +389,33 @@ class InterpretadorComDepuracao extends interpretador_1.Interpretador {
|
|
|
274
389
|
async interpretar(declaracoes, manterAmbiente = false) {
|
|
275
390
|
this.erros = [];
|
|
276
391
|
this.declaracoes = declaracoes;
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
};
|
|
282
|
-
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
|
|
283
|
-
this.escopoAtual++;
|
|
284
|
-
await this.executarUltimoEscopo(manterAmbiente);
|
|
392
|
+
this.abrirNovoBlocoEscopo(declaracoes);
|
|
393
|
+
const resultado = await super.executarUltimoEscopo(manterAmbiente);
|
|
394
|
+
// Corrigir contador de escopos
|
|
395
|
+
this.escopoAtual--;
|
|
285
396
|
const retorno = {
|
|
286
397
|
erros: this.erros,
|
|
287
|
-
resultado: this.resultadoInterpretador
|
|
398
|
+
// resultado: this.resultadoInterpretador // Removido para simplificar `this.executar()`.
|
|
399
|
+
resultado: [resultado]
|
|
288
400
|
};
|
|
289
401
|
this.resultadoInterpretador = [];
|
|
290
402
|
return retorno;
|
|
291
403
|
}
|
|
404
|
+
/**
|
|
405
|
+
* Obtém o valor de uma variável por nome.
|
|
406
|
+
* Em versões anteriores, o mecanismo de avaliação fazia toda a avaliação tradicional,
|
|
407
|
+
* passando por Lexador, Avaliador Sintático e Interpretador.
|
|
408
|
+
* Isso tem sua cota de problemas, sobretudo porque a avaliação insere e descarta escopos,
|
|
409
|
+
* entrando em condição de corrida com a interpretação com depuração.
|
|
410
|
+
* @param nome O nome da variável.
|
|
411
|
+
*/
|
|
412
|
+
obterVariavel(nome) {
|
|
413
|
+
const valorOuVariavel = this.pilhaEscoposExecucao.obterValorVariavel({ lexema: nome });
|
|
414
|
+
return valorOuVariavel.hasOwnProperty('valor') ? valorOuVariavel : {
|
|
415
|
+
valor: valorOuVariavel,
|
|
416
|
+
tipo: (0, inferenciador_1.inferirTipoVariavel)(valorOuVariavel)
|
|
417
|
+
};
|
|
418
|
+
}
|
|
292
419
|
}
|
|
293
420
|
exports.InterpretadorComDepuracao = InterpretadorComDepuracao;
|
|
294
421
|
//# sourceMappingURL=interpretador-com-depuracao.js.map
|