@designliquido/delegua
Version:
Linguagem de programação simples e moderna usando português estruturado.
751 lines • 32.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InterpretadorPortugolIpt = void 0;
const construtos_1 = require("../../../construtos");
const declaracoes_1 = require("../../../declaracoes");
const espaco_memoria_1 = require("../../espaco-memoria");
const estruturas_1 = require("../../estruturas");
const excecoes_1 = require("../../../excecoes");
const quebras_1 = require("../../../quebras");
const pilha_escopos_execucao_1 = require("../../pilha-escopos-execucao");
const inferenciador_1 = require("../../../inferenciador");
const portugol_ipt_1 = __importDefault(require("../../../tipos-de-simbolos/portugol-ipt"));
class InterpretadorPortugolIpt {
constructor(diretorioBase, funcaoDeRetorno = null, funcaoDeRetornoMesmaLinha = null) {
this.funcaoDeRetorno = null;
this.funcaoDeRetornoMesmaLinha = null;
this.classeAtualEmExecucao = null;
this.resultadoInterpretador = [];
this.diretorioBase = diretorioBase;
this.funcaoDeRetorno = funcaoDeRetorno || console.log;
this.funcaoDeRetornoMesmaLinha =
funcaoDeRetornoMesmaLinha || process.stdout.write.bind(process.stdout);
this.erros = [];
this.declaracoes = [];
this.pilhaEscoposExecucao = new pilha_escopos_execucao_1.PilhaEscoposExecucao();
const escopoExecucao = {
declaracoes: [],
declaracaoAtual: 0,
espacoMemoria: new espaco_memoria_1.EspacoMemoria(),
finalizado: false,
tipo: 'outro',
emLacoRepeticao: false,
};
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
}
// ── Utilitários ─────────────────────────────────────────────────────────────
resolverValor(objeto) {
if (objeto === null || objeto === undefined)
return objeto;
if (objeto.hasOwnProperty('valor'))
return objeto.valor;
return objeto;
}
eVerdadeiro(objeto) {
if (objeto === null)
return false;
if (typeof objeto === 'boolean')
return Boolean(objeto);
if (objeto.hasOwnProperty('valor'))
return Boolean(objeto.valor);
return true;
}
eIgual(esquerda, direita) {
if (esquerda === null && direita === null)
return true;
if (esquerda === null)
return false;
return esquerda === direita;
}
verificarOperandosNumeros(operador, direita, esquerda) {
const valorDireita = this.resolverValor(direita);
const valorEsquerda = this.resolverValor(esquerda);
const tipoDireita = direita?.tipo ?? (typeof valorDireita === 'number' ? 'número' : String(NaN));
const tipoEsquerda = esquerda?.tipo ?? (typeof valorEsquerda === 'number' ? 'número' : String(NaN));
const tiposNumericos = ['inteiro', 'numero', 'número', 'real'];
const eNumericoOuQualquer = (tipo, valor) => tiposNumericos.includes(tipo.toLowerCase()) ||
(tipo === 'qualquer' && typeof valor === 'number');
if (eNumericoOuQualquer(tipoDireita, valorDireita) &&
eNumericoOuQualquer(tipoEsquerda, valorEsquerda))
return;
throw new excecoes_1.ErroEmTempoDeExecucao(operador, 'Operadores precisam ser números.', operador.linha);
}
paraTexto(objeto) {
if (objeto === null || objeto === undefined)
return 'nulo';
if (typeof objeto === 'boolean')
return objeto ? 'verdadeiro' : 'falso';
if (objeto instanceof Date) {
return Intl.DateTimeFormat('pt', { dateStyle: 'full', timeStyle: 'full' }).format(objeto);
}
if (Array.isArray(objeto))
return objeto;
if (objeto.valor instanceof estruturas_1.ObjetoPadrao)
return objeto.valor.paraTexto();
if (typeof objeto === 'object')
return JSON.stringify(objeto);
return objeto.toString();
}
// ── Expressões ──────────────────────────────────────────────────────────────
visitarExpressaoLiteral(expressao) {
return Promise.resolve(expressao.valor);
}
async visitarExpressaoAgrupamento(expressao) {
return await this.avaliar(expressao.expressao);
}
async visitarExpressaoBinaria(expressao) {
try {
const esquerda = await this.avaliar(expressao.esquerda);
const direita = await this.avaliar(expressao.direita);
const valorEsquerdo = this.resolverValor(esquerda);
const valorDireito = this.resolverValor(direita);
const tipoEsquerdo = esquerda?.hasOwnProperty('tipo')
? esquerda.tipo
: (0, inferenciador_1.inferirTipoVariavel)(esquerda);
const tipoDireito = direita?.hasOwnProperty('tipo')
? direita.tipo
: (0, inferenciador_1.inferirTipoVariavel)(direita);
const tiposNumericos = ['inteiro', 'numero', 'número', 'real'];
const ambosNumericos = (tiposNumericos.includes(tipoEsquerdo) ||
(tipoEsquerdo === 'qualquer' && typeof valorEsquerdo === 'number')) &&
(tiposNumericos.includes(tipoDireito) ||
(tipoDireito === 'qualquer' && typeof valorDireito === 'number'));
switch (expressao.operador.tipo) {
case portugol_ipt_1.default.EXPONENCIACAO:
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
return Math.pow(valorEsquerdo, valorDireito);
case portugol_ipt_1.default.MAIOR:
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
return Number(valorEsquerdo) > Number(valorDireito);
case portugol_ipt_1.default.MAIOR_IGUAL:
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
return Number(valorEsquerdo) >= Number(valorDireito);
case portugol_ipt_1.default.MENOR:
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
return Number(valorEsquerdo) < Number(valorDireito);
case portugol_ipt_1.default.MENOR_IGUAL:
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
return Number(valorEsquerdo) <= Number(valorDireito);
case portugol_ipt_1.default.SUBTRACAO:
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
return Number(valorEsquerdo) - Number(valorDireito);
case portugol_ipt_1.default.ADICAO:
if (ambosNumericos) {
return Number(valorEsquerdo) + Number(valorDireito);
}
return String(valorEsquerdo) + String(valorDireito);
case portugol_ipt_1.default.DIVISAO:
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
return Number(valorEsquerdo) / Number(valorDireito);
case portugol_ipt_1.default.DIVISAO_INTEIRA:
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
return Math.floor(Number(valorEsquerdo) / Number(valorDireito));
case portugol_ipt_1.default.MULTIPLICACAO:
if (tipoEsquerdo === 'texto' || tipoDireito === 'texto') {
if (tipoEsquerdo === 'texto' && tipoDireito === 'texto') {
return Number(valorEsquerdo) * Number(valorDireito);
}
if (tipoEsquerdo === 'texto')
return valorEsquerdo.repeat(Number(valorDireito));
return valorDireito.repeat(Number(valorEsquerdo));
}
return Number(valorEsquerdo) * Number(valorDireito);
case portugol_ipt_1.default.MODULO:
this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
return Number(valorEsquerdo) % Number(valorDireito);
case portugol_ipt_1.default.DIFERENTE:
return !this.eIgual(valorEsquerdo, valorDireito);
case portugol_ipt_1.default.IGUAL:
return this.eIgual(valorEsquerdo, valorDireito);
}
}
catch (erro) {
return Promise.reject(erro);
}
}
async visitarExpressaoLogica(expressao) {
const esquerda = await this.avaliar(expressao.esquerda);
switch (expressao.operador.tipo) {
case portugol_ipt_1.default.OU:
if (this.eVerdadeiro(esquerda))
return true;
return this.eVerdadeiro(await this.avaliar(expressao.direita));
case portugol_ipt_1.default.XOU: {
const ve = this.eVerdadeiro(esquerda);
const vd = this.eVerdadeiro(await this.avaliar(expressao.direita));
return ve !== vd;
}
case portugol_ipt_1.default.E:
if (!this.eVerdadeiro(esquerda))
return false;
return this.eVerdadeiro(await this.avaliar(expressao.direita));
}
return await this.avaliar(expressao.direita);
}
async visitarExpressaoUnaria(expressao) {
const operando = await this.avaliar(expressao.operando);
const valor = this.resolverValor(operando);
switch (expressao.operador.tipo) {
case portugol_ipt_1.default.SUBTRACAO:
return -Number(valor);
case portugol_ipt_1.default.NEGACAO:
case portugol_ipt_1.default.NAO:
return !this.eVerdadeiro(valor);
}
throw new excecoes_1.ErroEmTempoDeExecucao(expressao.operador, `Operador unário desconhecido: ${expressao.operador.lexema}`, expressao.operador.linha);
}
async visitarExpressaoDeAtribuicao(expressao) {
const valor = await this.avaliar(expressao.valor);
const valorFinal = this.resolverValor(valor);
const alvo = expressao.alvo;
this.pilhaEscoposExecucao.atribuirVariavel(alvo.simbolo, valorFinal);
return valorFinal;
}
visitarExpressaoDeVariavel(expressao) {
return this.pilhaEscoposExecucao.obterValorVariavel(expressao.simbolo);
}
async visitarExpressaoLeia(expressao) {
for (const arg of expressao.argumentos) {
const resposta = await new Promise((resolve) => this.interfaceEntradaSaida.question('> ', (r) => resolve(r)));
// arg é um Expressao (declaração) envolvendo um Variavel
const construto = arg instanceof declaracoes_1.Expressao ? arg.expressao : arg;
if (construto instanceof construtos_1.Variavel) {
const valorConvertido = typeof resposta === 'string' && !Number.isNaN(Number(resposta))
? Number(resposta)
: resposta;
this.pilhaEscoposExecucao.atribuirVariavel(construto.simbolo, valorConvertido);
}
}
return null;
}
async visitarExpressaoFormatacaoEscrita(declaracao) {
const conteudo = await this.avaliar(declaracao.expressao);
const valorConteudo = this.resolverValor(conteudo);
const tipoConteudo = conteudo.hasOwnProperty('tipo')
? conteudo.tipo
: typeof conteudo;
let resultado = valorConteudo;
if (['número', 'number'].includes(tipoConteudo) && declaracao.casasDecimais > 0) {
resultado = valorConteudo.toLocaleString('pt', {
maximumFractionDigits: declaracao.casasDecimais,
});
}
if (declaracao.espacos > 0)
resultado += ' '.repeat(declaracao.espacos);
return resultado;
}
// ── Acesso a vetores ────────────────────────────────────────────────────────
async visitarExpressaoAcessoIndiceVariavel(expressao) {
const objetoAvaliado = await this.avaliar(expressao.entidadeChamada);
const indiceAvaliado = await this.avaliar(expressao.indice);
const objeto = this.resolverValor(objetoAvaliado);
const indice = this.resolverValor(indiceAvaliado);
if (Array.isArray(objeto)) {
if (indice < 0 || indice >= objeto.length) {
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Índice do vetor fora do intervalo.', expressao.linha));
}
return objeto[indice];
}
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Acesso por índice só é suportado em vetores.', expressao.linha));
}
async visitarExpressaoAtribuicaoPorIndice(expressao) {
const objetoAvaliado = await this.avaliar(expressao.objeto);
const indiceAvaliado = await this.avaliar(expressao.indice);
const valorAvaliado = await this.avaliar(expressao.valor);
const objeto = this.resolverValor(objetoAvaliado);
const indice = this.resolverValor(indiceAvaliado);
const valor = this.resolverValor(valorAvaliado);
if (Array.isArray(objeto)) {
objeto[indice] = valor;
return valor;
}
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(null, 'Atribuição por índice só é suportada em vetores.', expressao.linha));
}
// ── Chamadas de funções embutidas ───────────────────────────────────────────
async visitarExpressaoDeChamada(expressao) {
const callee = expressao.entidadeChamada;
if (!(callee instanceof construtos_1.Variavel)) {
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(null, 'Chamada de função inválida.', expressao.linha));
}
const nome = callee.simbolo.lexema.toUpperCase();
const args = [];
for (const arg of expressao.argumentos) {
args.push(this.resolverValor(await this.avaliar(arg)));
}
return this.chamarFuncaoEmbutida(nome, args, expressao.linha);
}
chamarFuncaoEmbutida(nome, args, linha) {
switch (nome) {
// ── 0 argumentos ──
case 'ALEATORIO':
return Math.random();
// ── 1 argumento ──
case 'SEN':
return Math.sin(args[0]);
case 'COS':
return Math.cos(args[0]);
case 'TAN':
return Math.tan(args[0]);
case 'CTG':
return 1 / Math.tan(args[0]);
case 'ASEN':
return Math.asin(args[0]);
case 'ACOS':
return Math.acos(args[0]);
case 'ATAN':
return Math.atan(args[0]);
case 'ACTG':
return 1 / Math.atan(args[0]);
case 'SENH':
return Math.sinh(args[0]);
case 'COSH':
return Math.cosh(args[0]);
case 'TANH':
return Math.tanh(args[0]);
case 'CTGH':
return 1 / Math.tanh(args[0]);
case 'EXP':
return Math.exp(args[0]);
case 'ABS':
return Math.abs(args[0]);
case 'RAIZ':
return Math.sqrt(args[0]);
case 'LOG':
return Math.log10(args[0]);
case 'LN':
return Math.log(args[0]);
case 'INT':
return Math.trunc(args[0]);
case 'FRAC':
return args[0] - Math.trunc(args[0]);
case 'ARRED':
return Math.round(args[0]);
// ── 2 argumentos ──
case 'POTENCIA':
return Math.pow(args[0], args[1]);
// ── Texto ──
case 'COMPRIMENTO':
return String(args[0]).length;
case 'LETRA':
return String(args[0]).charAt(Number(args[1]));
default:
throw new excecoes_1.ErroEmTempoDeExecucao(null, `Função embutida desconhecida: '${nome}'.`, linha);
}
}
// ── Declarações ─────────────────────────────────────────────────────────────
async visitarDeclaracaoDeExpressao(declaracao) {
return declaracao.expressao.aceitar(this);
}
async visitarDeclaracaoEscreva(declaracao) {
try {
const formatoTexto = await this.avaliarArgumentosEscreva(declaracao.argumentos);
this.funcaoDeRetorno(formatoTexto);
return null;
}
catch (erro) {
this.erros.push({
erroInterno: erro,
linha: declaracao.linha,
hashArquivo: declaracao.hashArquivo,
});
}
}
async visitarDeclaracaoEscrevaMesmaLinha(declaracao) {
try {
const formatoTexto = await this.avaliarArgumentosEscreva(declaracao.argumentos);
this.funcaoDeRetornoMesmaLinha(formatoTexto);
return null;
}
catch (erro) {
this.erros.push({
erroInterno: erro,
linha: declaracao.linha,
hashArquivo: declaracao.hashArquivo,
});
}
}
async avaliarArgumentosEscreva(argumentos) {
let formatoTexto = '';
for (const argumento of argumentos) {
const resultado = await this.avaliar(argumento);
formatoTexto += `${this.paraTexto(this.resolverValor(resultado))} `;
}
return formatoTexto.trimEnd();
}
async visitarDeclaracaoVar(declaracao) {
let valorFinal = null;
if (declaracao.inicializador !== null) {
const avaliado = await this.avaliar(declaracao.inicializador);
if (avaliado !== null && avaliado !== undefined) {
valorFinal = this.resolverValor(avaliado);
}
}
this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, valorFinal, declaracao.tipo);
return null;
}
async visitarDeclaracaoConst(declaracao) {
let valorFinal = null;
if (declaracao.inicializador !== null) {
const avaliado = await this.avaliar(declaracao.inicializador);
if (avaliado !== null && avaliado !== undefined) {
valorFinal = this.resolverValor(avaliado);
}
}
this.pilhaEscoposExecucao.definirConstante(declaracao.simbolo.lexema, valorFinal, declaracao.tipo);
return null;
}
async visitarDeclaracaoSe(declaracao) {
if (this.eVerdadeiro(await this.avaliar(declaracao.condicao))) {
return await this.executar(declaracao.caminhoEntao);
}
if (declaracao.caminhoSenao !== null) {
return await this.executar(declaracao.caminhoSenao);
}
return null;
}
async visitarDeclaracaoEnquanto(declaracao) {
while (this.eVerdadeiro(await this.avaliar(declaracao.condicao))) {
try {
const resultado = await this.executar(declaracao.corpo);
if (resultado instanceof quebras_1.SustarQuebra)
return null;
if (resultado instanceof quebras_1.ContinuarQuebra)
continue;
if (resultado instanceof quebras_1.Quebra)
break;
}
catch (erro) {
this.erros.push({
erroInterno: erro,
linha: declaracao.linha,
hashArquivo: declaracao.hashArquivo,
});
return Promise.reject(erro);
}
}
return null;
}
async visitarDeclaracaoPara(declaracao) {
const inicializador = Array.isArray(declaracao.inicializador)
? declaracao.inicializador[0]
: declaracao.inicializador;
if (inicializador)
await this.avaliar(inicializador);
while (true) {
if (declaracao.condicao && !this.eVerdadeiro(await this.avaliar(declaracao.condicao)))
break;
try {
const resultado = await this.executar(declaracao.corpo);
if (resultado instanceof quebras_1.SustarQuebra)
return null;
if (resultado instanceof quebras_1.ContinuarQuebra) {
/* continua para incremento */
}
else if (resultado instanceof quebras_1.Quebra)
break;
}
catch (erro) {
this.erros.push({
erroInterno: erro,
linha: declaracao.linha,
hashArquivo: declaracao.hashArquivo,
});
return Promise.reject(erro);
}
if (declaracao.incrementar)
await this.avaliar(declaracao.incrementar);
}
return null;
}
async visitarDeclaracaoFazer(declaracao) {
do {
try {
const resultado = await this.executar(declaracao.caminhoFazer);
if (resultado instanceof quebras_1.SustarQuebra)
return null;
if (resultado instanceof quebras_1.ContinuarQuebra)
continue;
if (resultado instanceof quebras_1.Quebra)
break;
}
catch (erro) {
this.erros.push({
erroInterno: erro,
linha: declaracao.linha,
hashArquivo: declaracao.hashArquivo,
});
return Promise.reject(erro);
}
} while (this.eVerdadeiro(await this.avaliar(declaracao.condicaoEnquanto)));
return null;
}
async visitarDeclaracaoEscolha(declaracao) {
const valorCondicao = this.resolverValor(await this.avaliar(declaracao.identificadorOuLiteral));
let encontrado = false;
for (const caminho of declaracao.caminhos) {
for (const condicao of caminho.condicoes) {
const valorCondicaoAvaliado = this.resolverValor(await this.avaliar(condicao));
if (valorCondicaoAvaliado === valorCondicao) {
encontrado = true;
await this.executarBloco(caminho.declaracoes);
break;
}
}
if (encontrado)
break;
}
if (!encontrado && declaracao.caminhoPadrao) {
await this.executarBloco(declaracao.caminhoPadrao.declaracoes);
}
return null;
}
visitarDeclaracaoComentario(declaracao) {
return Promise.resolve();
}
// ── Bloco e escopo ───────────────────────────────────────────────────────────
async executarBloco(declaracoes, ambiente) {
const escopoExecucao = {
declaracoes: declaracoes,
declaracaoAtual: 0,
espacoMemoria: ambiente || new espaco_memoria_1.EspacoMemoria(),
finalizado: false,
tipo: 'outro',
emLacoRepeticao: false,
};
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
return await this.executarUltimoEscopo();
}
async visitarExpressaoBloco(declaracao) {
return await this.executarBloco(declaracao.declaracoes);
}
// ── Métodos obrigatórios da interface não usados em Portugol IPT ────────────
/* istanbul ignore next */
visitarExpressaoTuplaN(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoAcessoIntervaloVariavel(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoTextoDocumentacao(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoSeparador(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoComentario(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoArgumentoReferenciaFuncao(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoReferenciaFuncao(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoAcessoMetodo(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoAcessoPropriedade(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoTendoComo(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoInicioAlgoritmo(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoCabecalhoPrograma(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoTupla(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoAcessoElementoMatriz(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoAtribuicaoPorIndicesMatriz(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoExpressaoRegular(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoTipoDe(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoFalhar(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoParaCada(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoVarMultiplo(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoConstMultiplo(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoContinua(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoSustar(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoRetornar(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoFuncaoConstruto(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoDefinirValor(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoDefinicaoFuncao(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoClasse(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoAcessoMetodoOuPropriedade(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoIsto(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoDicionario(_expressao) {
throw new Error('Método não implementado.');
}
async visitarExpressaoVetor(expressao) {
const valores = [];
for (const elemento of expressao.valores) {
const avaliado = await this.avaliar(elemento);
valores.push(this.resolverValor(avaliado));
}
return valores;
}
/* istanbul ignore next */
visitarExpressaoSuper(_expressao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarExpressaoFimPara(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoTente(_declaracao) {
throw new Error('Método não implementado.');
}
/* istanbul ignore next */
visitarDeclaracaoImportar(_declaracao) {
throw new Error('Método não implementado.');
}
// ── Motor de execução ────────────────────────────────────────────────────────
async avaliar(expressao) {
return await expressao.aceitar(this);
}
procurarVariavel(simbolo) {
return this.pilhaEscoposExecucao.obterValorVariavel(simbolo);
}
async executar(declaracao, mostrarResultado = false) {
const resultado = await declaracao.aceitar(this);
if (mostrarResultado)
this.funcaoDeRetorno(this.paraTexto(resultado));
if (resultado || typeof resultado === 'boolean') {
this.resultadoInterpretador.push(this.paraTexto(resultado));
}
return resultado;
}
async executarUltimoEscopo(manterAmbiente = false) {
const ultimoEscopo = this.pilhaEscoposExecucao.topoDaPilha();
try {
let retornoExecucao;
for (; !(retornoExecucao instanceof quebras_1.Quebra) &&
ultimoEscopo.declaracaoAtual < ultimoEscopo.declaracoes.length; ultimoEscopo.declaracaoAtual++) {
retornoExecucao = await this.executar(ultimoEscopo.declaracoes[ultimoEscopo.declaracaoAtual]);
}
return retornoExecucao;
}
catch (erro) {
return Promise.reject(erro);
}
finally {
this.pilhaEscoposExecucao.removerUltimo();
if (manterAmbiente) {
const escopoAnterior = this.pilhaEscoposExecucao.topoDaPilha();
escopoAnterior.espacoMemoria.valores = Object.assign(escopoAnterior.espacoMemoria.valores, ultimoEscopo.espacoMemoria.valores);
}
}
}
async executarChamavel(chamavel, argumentos) {
if (chamavel instanceof estruturas_1.FuncaoPadrao) {
return chamavel.chamar(this, argumentos, null);
}
const argumentosFormatados = argumentos.map((valor) => ({
nome: null,
valor,
}));
return chamavel.chamar(this, argumentosFormatados, null);
}
async interpretar(declaracoes, manterAmbiente) {
this.erros = [];
const escopoExecucao = {
declaracoes: declaracoes,
declaracaoAtual: 0,
espacoMemoria: new espaco_memoria_1.EspacoMemoria(),
finalizado: false,
tipo: 'outro',
emLacoRepeticao: false,
};
this.pilhaEscoposExecucao.empilhar(escopoExecucao);
try {
const retornoOuErro = await this.executarUltimoEscopo(manterAmbiente);
if (retornoOuErro instanceof excecoes_1.ErroEmTempoDeExecucao) {
this.erros.push(retornoOuErro);
}
}
catch (erro) {
this.erros.push(erro);
}
finally {
const retorno = {
erros: this.erros,
resultado: this.resultadoInterpretador,
};
this.resultadoInterpretador = [];
return retorno;
}
}
}
exports.InterpretadorPortugolIpt = InterpretadorPortugolIpt;
//# sourceMappingURL=interpretador-portugol-ipt.js.map