@designliquido/delegua
Version:
Linguagem de programação simples e moderna usando português estruturado.
454 lines • 16.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResolvedorEguaClassico = void 0;
const erro_resolvedor_1 = require("./erro-resolvedor");
const pilha_escopos_1 = require("./pilha-escopos");
const TipoFuncao = {
NENHUM: 'NENHUM',
FUNÇÃO: 'FUNÇÃO',
CONSTRUTOR: 'CONSTRUTOR',
METODO: 'METODO',
};
const TipoClasse = {
NENHUM: 'NENHUM',
CLASSE: 'CLASSE',
SUBCLASSE: 'SUBCLASSE',
};
const TipoLoop = {
NENHUM: 'NENHUM',
ENQUANTO: 'ENQUANTO',
ESCOLHA: 'ESCOLHA',
PARA: 'PARA',
FAZER: 'FAZER',
};
/**
* O Resolvedor (Resolver) é responsável por catalogar todos os identificadores complexos, como por exemplo: funções, classes, variáveis,
* e delimitar os escopos onde esses identificadores existem.
*
* Exemplo: uma classe A declara dois métodos chamados M e N. Todas as variáveis declaradas dentro de M não podem ser vistas por N, e vice-versa.
* No entanto, todas as variáveis declaradas dentro da classe A podem ser vistas tanto por M quanto por N.
*
* Não faz sentido ser implementado nos outros interpretadores pelos outros optarem por uma pilha de execução que
* espera importar qualquer coisa a qualquer momento.
*/
class ResolvedorEguaClassico {
constructor() {
this.interfaceEntradaSaida = null;
this.erros = [];
this.escopos = new pilha_escopos_1.PilhaEscopos();
this.locais = new Map();
this.funcaoAtual = TipoFuncao.NENHUM;
this.classeAtual = TipoClasse.NENHUM;
this.cicloAtual = TipoClasse.NENHUM;
}
visitarExpressaoDeleguaFuncao(declaracao) {
throw new Error('Método não implementado.');
}
visitarExpressaoArgumentoReferenciaFuncao(expressao) {
throw new Error('Método não implementado.');
}
visitarExpressaoReferenciaFuncao(expressao) {
throw new Error('Método não implementado.');
}
visitarExpressaoAcessoPropriedade(expressao) {
throw new Error('Método não implementado.');
}
visitarExpressaoAcessoMetodo(expressao) {
throw new Error('Método não implementado.');
}
visitarDeclaracaoComentario(declaracao) {
return Promise.resolve();
}
visitarDeclaracaoTendoComo(declaracao) {
throw new Error('Método não implementado.');
}
visitarDeclaracaoInicioAlgoritmo(declaracao) {
throw new Error('Método não implementado.');
}
visitarDeclaracaoCabecalhoPrograma(declaracao) {
throw new Error('Método não implementado.');
}
visitarExpressaoTupla(expressao) {
throw new Error('Método não implementado.');
}
visitarExpressaoAcessoElementoMatriz(expressao) {
throw new Error('Método não implementado.');
}
visitarExpressaoAtribuicaoPorIndicesMatriz(expressao) {
throw new Error('Método não implementado.');
}
visitarExpressaoExpressaoRegular(expressao) {
throw new Error('Método não implementado.');
}
visitarExpressaoTipoDe(expressao) {
throw new Error('Método não implementado.');
}
visitarExpressaoFalhar(expressao) {
throw new Error('Método não implementado.');
}
visitarDeclaracaoParaCada(declaracao) {
throw new Error('Método não implementado.');
}
visitarDeclaracaoConst(declaracao) {
throw new Error('Método não implementado.');
}
visitarDeclaracaoConstMultiplo(declaracao) {
throw new Error('Método não implementado.');
}
visitarExpressaoFimPara(declaracao) {
throw new Error('Método não implementado.');
}
visitarExpressaoFormatacaoEscrita(declaracao) {
throw new Error('Método não implementado.');
}
visitarDeclaracaoEscrevaMesmaLinha(declaracao) {
throw new Error('Método não implementado.');
}
avaliar(expressao) {
throw new Error('Método não implementado.');
}
eVerdadeiro(objeto) {
throw new Error('Método não implementado.');
}
verificarOperandoNumero(operador, operando) {
throw new Error('Método não implementado.');
}
eIgual(esquerda, direita) {
throw new Error('Método não implementado.');
}
verificarOperandosNumeros(operador, direita, esquerda) {
throw new Error('Método não implementado.');
}
procurarVariavel(nome, expressao) {
throw new Error('Método não implementado.');
}
visitarExpressaoLeia(expressao) {
throw new Error('Método não implementado.');
}
executarBloco(declaracoes, ambiente) {
throw new Error('Método não implementado.');
}
paraTexto(objeto) {
throw new Error('Método não implementado.');
}
executar(declaracao, mostrarResultado) {
throw new Error('Método não implementado.');
}
interpretar(declaracoes, manterAmbiente) {
throw new Error('Método não implementado.');
}
finalizacao() {
throw new Error('Método não implementado.');
}
definir(simbolo) {
if (this.escopos.eVazio())
return;
this.escopos.topoDaPilha()[simbolo.lexema] = true;
}
declarar(simbolo) {
if (this.escopos.eVazio())
return;
const escopo = this.escopos.topoDaPilha();
if (escopo.hasOwnProperty(simbolo.lexema)) {
const erro = new erro_resolvedor_1.ErroResolvedor(simbolo, 'Variável com esse nome já declarada neste escopo.');
this.erros.push(erro);
}
escopo[simbolo.lexema] = false;
}
inicioDoEscopo() {
this.escopos.empilhar({});
}
finalDoEscopo() {
this.escopos.removerUltimo();
}
resolverLocal(expressao, simbolo) {
for (let i = this.escopos.pilha.length - 1; i >= 0; i--) {
if (this.escopos.pilha[i].hasOwnProperty(simbolo.lexema)) {
this.locais.set(expressao, this.escopos.pilha.length - 1 - i);
}
}
}
visitarExpressaoBloco(declaracao) {
this.inicioDoEscopo();
this.resolver(declaracao.declaracoes);
this.finalDoEscopo();
return null;
}
visitarExpressaoDeVariavel(expressao) {
if (!this.escopos.eVazio() &&
this.escopos.topoDaPilha()[expressao.simbolo.lexema] === false) {
const erro = new erro_resolvedor_1.ErroResolvedor(expressao.simbolo, 'Não é possível ler a variável local em seu próprio inicializador.');
this.erros.push(erro);
throw erro;
}
this.resolverLocal(expressao, expressao.simbolo);
return null;
}
visitarDeclaracaoVar(declaracao) {
this.declarar(declaracao.simbolo);
if (declaracao.inicializador !== null) {
this.resolver(declaracao.inicializador);
}
this.definir(declaracao.simbolo);
return null;
}
visitarDeclaracaoVarMultiplo(declaracao) {
throw new Error('Método não implementado.');
}
visitarExpressaoDeAtribuicao(expressao) {
this.resolver(expressao.valor);
const alvoVariavel = expressao.alvo;
this.resolverLocal(expressao, alvoVariavel.simbolo);
return null;
}
resolverFuncao(funcao, funcType) {
const enclosingFunc = this.funcaoAtual;
this.funcaoAtual = funcType;
this.inicioDoEscopo();
const parametros = funcao.parametros;
if (parametros && parametros.length > 0) {
for (let i = 0; i < parametros.length; i++) {
this.declarar(parametros[i]['nome']);
this.definir(parametros[i]['nome']);
}
}
this.resolver(funcao.corpo);
this.finalDoEscopo();
this.funcaoAtual = enclosingFunc;
}
visitarDeclaracaoDefinicaoFuncao(declaracao) {
this.declarar(declaracao.simbolo);
this.definir(declaracao.simbolo);
this.resolverFuncao(declaracao.funcao, TipoFuncao.FUNÇÃO);
return null;
}
visitarExpressaoFuncaoConstruto(declaracao) {
this.resolverFuncao(declaracao, TipoFuncao.FUNÇÃO);
return null;
}
visitarDeclaracaoTente(declaracao) {
this.resolver(declaracao.caminhoTente);
if (declaracao.caminhoPegue !== null)
this.resolver(declaracao.caminhoPegue);
if (declaracao.caminhoSenao !== null)
this.resolver(declaracao.caminhoSenao);
if (declaracao.caminhoFinalmente !== null)
this.resolver(declaracao.caminhoFinalmente);
}
visitarDeclaracaoClasse(declaracao) {
const enclosingClass = this.classeAtual;
this.classeAtual = TipoClasse.CLASSE;
this.declarar(declaracao.simbolo);
this.definir(declaracao.simbolo);
if (declaracao.superClasse !== null &&
declaracao.simbolo.lexema === declaracao.superClasse.simbolo.lexema) {
const erro = new erro_resolvedor_1.ErroResolvedor(declaracao.simbolo, 'Uma classe não pode herdar de si mesma.');
this.erros.push(erro);
}
if (declaracao.superClasse !== null) {
this.classeAtual = TipoClasse.SUBCLASSE;
this.resolver(declaracao.superClasse);
}
if (declaracao.superClasse !== null) {
this.inicioDoEscopo();
this.escopos.topoDaPilha()['super'] = true;
}
this.inicioDoEscopo();
this.escopos.topoDaPilha()['isto'] = true;
const metodos = declaracao.metodos;
for (let i = 0; i < metodos.length; i++) {
let declaracao = TipoFuncao.METODO;
if (metodos[i].simbolo.lexema === 'isto') {
declaracao = TipoFuncao.CONSTRUTOR;
}
this.resolverFuncao(metodos[i].funcao, declaracao);
}
this.finalDoEscopo();
if (declaracao.superClasse !== null)
this.finalDoEscopo();
this.classeAtual = enclosingClass;
return null;
}
visitarExpressaoSuper(expressao) {
if (this.classeAtual === TipoClasse.NENHUM) {
const erro = new erro_resolvedor_1.ErroResolvedor(expressao.simboloChave, "Não pode usar 'super' fora de uma classe.");
this.erros.push(erro);
}
else if (this.classeAtual !== TipoClasse.SUBCLASSE) {
const erro = new erro_resolvedor_1.ErroResolvedor(expressao.simboloChave, "Não se usa 'super' numa classe sem SuperClasse.");
this.erros.push(erro);
}
this.resolverLocal(expressao, expressao.simboloChave);
return null;
}
visitarExpressaoAcessoMetodoOuPropriedade(expressao) {
this.resolver(expressao.objeto);
return null;
}
visitarDeclaracaoDeExpressao(declaracao) {
this.resolver(declaracao.expressao);
return null;
}
visitarDeclaracaoSe(declaracao) {
this.resolver(declaracao.condicao);
this.resolver(declaracao.caminhoEntao);
for (let i = 0; i < declaracao.caminhosSeSenao.length; i++) {
this.resolver(declaracao.caminhosSeSenao[i].condicao);
this.resolver(declaracao.caminhosSeSenao[i].branch);
}
if (declaracao.caminhoSenao !== null)
this.resolver(declaracao.caminhoSenao);
return null;
}
async visitarDeclaracaoImportar(declaracao) {
this.resolver(declaracao.caminho);
}
async visitarDeclaracaoEscreva(declaracao) {
this.resolver(declaracao.expressao);
}
visitarExpressaoRetornar(declaracao) {
if (this.funcaoAtual === TipoFuncao.NENHUM) {
const erro = new erro_resolvedor_1.ErroResolvedor(declaracao.palavraChave, 'Não é possível retornar do código do escopo superior.');
this.erros.push(erro);
}
if (declaracao.valor !== null) {
if (this.funcaoAtual === TipoFuncao.CONSTRUTOR) {
const erro = new erro_resolvedor_1.ErroResolvedor(declaracao.palavraChave, 'Não pode retornar o valor do construtor.');
this.erros.push(erro);
}
this.resolver(declaracao.valor);
}
return null;
}
async visitarDeclaracaoEscolha(declaracao) {
const enclosingType = this.cicloAtual;
this.cicloAtual = TipoLoop.ESCOLHA;
const caminhos = declaracao.caminhos;
const caminhoPadrao = declaracao.caminhoPadrao;
for (let i = 0; i < caminhos.length; i++) {
this.resolver(caminhos[i]['declaracoes']);
}
if (caminhoPadrao !== null)
this.resolver(caminhoPadrao['declaracoes']);
this.cicloAtual = enclosingType;
}
visitarDeclaracaoEnquanto(declaracao) {
this.resolver(declaracao.condicao);
this.resolver(declaracao.corpo);
return null;
}
visitarDeclaracaoPara(declaracao) {
if (declaracao.inicializador !== null) {
this.resolver(declaracao.inicializador);
}
if (declaracao.condicao !== null) {
this.resolver(declaracao.condicao);
}
if (declaracao.incrementar !== null) {
this.resolver(declaracao.incrementar);
}
const enclosingType = this.cicloAtual;
this.cicloAtual = TipoLoop.ENQUANTO;
this.resolver(declaracao.corpo);
this.cicloAtual = enclosingType;
return null;
}
visitarDeclaracaoFazer(declaracao) {
this.resolver(declaracao.condicaoEnquanto);
const enclosingType = this.cicloAtual;
this.cicloAtual = TipoLoop.FAZER;
this.resolver(declaracao.caminhoFazer);
this.cicloAtual = enclosingType;
return null;
}
visitarExpressaoBinaria(expressao) {
this.resolver(expressao.esquerda);
this.resolver(expressao.direita);
return null;
}
visitarExpressaoDeChamada(expressao) {
this.resolver(expressao.entidadeChamada);
const argumentos = expressao.argumentos;
for (let i = 0; i < argumentos.length; i++) {
this.resolver(argumentos[i]);
}
return null;
}
visitarExpressaoAgrupamento(expressao) {
this.resolver(expressao.expressao);
return null;
}
visitarExpressaoDicionario(expressao) {
for (let i = 0; i < expressao.chaves.length; i++) {
this.resolver(expressao.chaves[i]);
this.resolver(expressao.valores[i]);
}
return null;
}
visitarExpressaoVetor(expressao) {
for (let i = 0; i < expressao.valores.length; i++) {
this.resolver(expressao.valores[i]);
}
return null;
}
visitarExpressaoAcessoIndiceVariavel(expressao) {
this.resolver(expressao.entidadeChamada);
this.resolver(expressao.indice);
return null;
}
visitarExpressaoContinua(declaracao) {
return null;
}
visitarExpressaoSustar(declaracao) {
return null;
}
visitarExpressaoAtribuicaoPorIndice(expressao) {
return null;
}
visitarExpressaoLiteral(expressao) {
return null;
}
visitarExpressaoLogica(expressao) {
this.resolver(expressao.esquerda);
this.resolver(expressao.direita);
return null;
}
visitarExpressaoUnaria(expressao) {
this.resolver(expressao.direita);
return null;
}
visitarExpressaoDefinirValor(expressao) {
this.resolver(expressao.valor);
this.resolver(expressao.objeto);
return null;
}
visitarExpressaoIsto(expressao) {
if (this.classeAtual == TipoClasse.NENHUM) {
const erro = new erro_resolvedor_1.ErroResolvedor(expressao.palavraChave, "Não pode usar 'isto' fora da classe.");
this.erros.push(erro);
}
this.resolverLocal(expressao, expressao.palavraChave);
return null;
}
visitarDeclaracaoAleatorio(declaracao) {
throw new Error('Método não implementado.');
}
async resolver(declaracoes) {
if (Array.isArray(declaracoes)) {
for (let i = 0; i < declaracoes.length; i++) {
if (declaracoes[i] && declaracoes[i].aceitar) {
await declaracoes[i].aceitar(this);
}
}
}
else if (declaracoes) {
await declaracoes.aceitar(this);
}
return {
erros: this.erros,
locais: this.locais,
};
}
}
exports.ResolvedorEguaClassico = ResolvedorEguaClassico;
//# sourceMappingURL=resolvedor.js.map