@designliquido/delegua
Version:
Linguagem de programação simples e moderna usando português estruturado.
208 lines • 11.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Interpretador = void 0;
const estruturas_1 = require("../estruturas");
const interpretador_base_1 = require("./interpretador-base");
const primitivas_dicionario_1 = __importDefault(require("../bibliotecas/primitivas-dicionario"));
const primitivas_numero_1 = __importDefault(require("../bibliotecas/primitivas-numero"));
const primitivas_texto_1 = __importDefault(require("../bibliotecas/primitivas-texto"));
const primitivas_vetor_1 = __importDefault(require("../bibliotecas/primitivas-vetor"));
const primitivos_1 = __importDefault(require("../tipos-de-dados/primitivos"));
const delegua_1 = __importDefault(require("../tipos-de-dados/delegua"));
const inferenciador_1 = require("../inferenciador");
const excecoes_1 = require("../excecoes");
/**
* O interpretador de Delégua.
*/
class Interpretador extends interpretador_base_1.InterpretadorBase {
async visitarExpressaoAcessoMetodo(expressao) {
let variavelObjeto = await this.avaliar(expressao.objeto);
// Este caso acontece quando há encadeamento de métodos.
// Por exemplo, `objeto1.metodo1().metodo2()`.
// Como `RetornoQuebra` também possui `valor`, precisamos extrair o
// valor dele primeiro.
if (variavelObjeto.constructor.name === 'RetornoQuebra') {
variavelObjeto = variavelObjeto.valor;
}
const objeto = variavelObjeto.hasOwnProperty('valor') ? variavelObjeto.valor : variavelObjeto;
// Outro caso que `instanceof` simplesmente não funciona para casos em Liquido,
// então testamos também o nome do construtor.
if (objeto instanceof estruturas_1.ObjetoDeleguaClasse || objeto.constructor.name === 'ObjetoDeleguaClasse') {
return objeto.obterMetodo(expressao.nomeMetodo) || null;
}
// Objeto simples do JavaScript, ou dicionário de Delégua.
if (objeto.constructor === Object) {
if (expressao.nomeMetodo in primitivas_dicionario_1.default) {
const metodoDePrimitivaDicionario = primitivas_dicionario_1.default[expressao.nomeMetodo].implementacao;
return new estruturas_1.MetodoPrimitiva(objeto, metodoDePrimitivaDicionario);
}
return objeto[expressao.nomeMetodo] || null;
}
// Casos em que o objeto possui algum outro tipo que não o de objeto simples.
// Normalmente executam quando uma biblioteca é importada, e estamos tentando
// obter alguma propriedade ou método desse objeto.
// Caso 1: Função tradicional do JavaScript.
if (typeof objeto[expressao.nomeMetodo] === primitivos_1.default.FUNCAO) {
return objeto[expressao.nomeMetodo];
}
// Caso 2: Objeto tradicional do JavaScript.
if (typeof objeto[expressao.nomeMetodo] === primitivos_1.default.OBJETO) {
return objeto[expressao.nomeMetodo];
}
// A partir daqui, presume-se que o objeto é uma das estruturas
// de Delégua.
if (objeto instanceof estruturas_1.DeleguaModulo) {
return objeto.componentes[expressao.nomeMetodo] || null;
}
let tipoObjeto = variavelObjeto.tipo;
if (tipoObjeto === null || tipoObjeto === undefined) {
tipoObjeto = (0, inferenciador_1.inferirTipoVariavel)(variavelObjeto);
}
// Como internamente um dicionário de Delégua é simplesmente um objeto de
// JavaScript, as primitivas de dicionário, especificamente, são tratadas
// mais acima.
switch (tipoObjeto) {
case delegua_1.default.INTEIRO:
case delegua_1.default.NUMERO:
case delegua_1.default.NÚMERO:
const metodoDePrimitivaNumero = primitivas_numero_1.default[expressao.nomeMetodo].implementacao;
if (metodoDePrimitivaNumero) {
return new estruturas_1.MetodoPrimitiva(objeto, metodoDePrimitivaNumero);
}
break;
case delegua_1.default.TEXTO:
const metodoDePrimitivaTexto = primitivas_texto_1.default[expressao.nomeMetodo].implementacao;
if (metodoDePrimitivaTexto) {
return new estruturas_1.MetodoPrimitiva(objeto, metodoDePrimitivaTexto);
}
break;
case delegua_1.default.VETOR:
case delegua_1.default.VETOR_NUMERO:
case delegua_1.default.VETOR_NÚMERO:
case delegua_1.default.VETOR_TEXTO:
const metodoDePrimitivaVetor = primitivas_vetor_1.default[expressao.nomeMetodo].implementacao;
if (metodoDePrimitivaVetor) {
return new estruturas_1.MetodoPrimitiva(objeto, metodoDePrimitivaVetor);
}
break;
}
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(null, `Método para objeto ou primitiva não encontrado: ${expressao.nomeMetodo}.`, expressao.linha));
}
async visitarExpressaoAcessoPropriedade(expressao) {
let variavelObjeto = await this.avaliar(expressao.objeto);
// Este caso acontece quando há encadeamento de métodos.
// Por exemplo, `objeto1.metodo1().metodo2()`.
// Como `RetornoQuebra` também possui `valor`, precisamos extrair o
// valor dele primeiro.
if (variavelObjeto.constructor.name === 'RetornoQuebra') {
variavelObjeto = variavelObjeto.valor;
}
const objeto = variavelObjeto.hasOwnProperty('valor') ? variavelObjeto.valor : variavelObjeto;
// Outro caso que `instanceof` simplesmente não funciona para casos em Liquido,
// então testamos também o nome do construtor.
if (objeto instanceof estruturas_1.ObjetoDeleguaClasse || objeto.constructor.name === 'ObjetoDeleguaClasse') {
return objeto.obterMetodo(expressao.nomePropriedade) || null;
}
// Objeto simples do JavaScript, ou dicionário de Delégua.
if (objeto.constructor === Object) {
if (expressao.nomePropriedade in primitivas_dicionario_1.default) {
const metodoDePrimitivaDicionario = primitivas_dicionario_1.default[expressao.nomePropriedade].implementacao;
return new estruturas_1.MetodoPrimitiva(objeto, metodoDePrimitivaDicionario);
}
return objeto[expressao.nomePropriedade] || null;
}
// Casos em que o objeto possui algum outro tipo que não o de objeto simples.
// Normalmente executam quando uma biblioteca é importada, e estamos tentando
// obter alguma propriedade ou método desse objeto.
// Caso 1: Função tradicional do JavaScript.
if (typeof objeto[expressao.nomePropriedade] === primitivos_1.default.FUNCAO) {
return objeto[expressao.nomePropriedade];
}
// Caso 2: Objeto tradicional do JavaScript.
if (typeof objeto[expressao.nomePropriedade] === primitivos_1.default.OBJETO) {
return objeto[expressao.nomePropriedade];
}
// A partir daqui, presume-se que o objeto é uma das estruturas
// de Delégua.
if (objeto instanceof estruturas_1.DeleguaModulo) {
return objeto.componentes[expressao.nomePropriedade] || null;
}
let tipoObjeto = variavelObjeto.tipo;
if (tipoObjeto === null || tipoObjeto === undefined) {
tipoObjeto = (0, inferenciador_1.inferirTipoVariavel)(variavelObjeto);
}
// Como internamente um dicionário de Delégua é simplesmente um objeto de
// JavaScript, as primitivas de dicionário, especificamente, são tratadas
// mais acima.
switch (tipoObjeto) {
case delegua_1.default.INTEIRO:
case delegua_1.default.NUMERO:
case delegua_1.default.NÚMERO:
const metodoDePrimitivaNumero = primitivas_numero_1.default[expressao.nomePropriedade].implementacao;
if (metodoDePrimitivaNumero) {
return new estruturas_1.MetodoPrimitiva(objeto, metodoDePrimitivaNumero);
}
break;
case delegua_1.default.TEXTO:
const metodoDePrimitivaTexto = primitivas_texto_1.default[expressao.nomePropriedade].implementacao;
if (metodoDePrimitivaTexto) {
return new estruturas_1.MetodoPrimitiva(objeto, metodoDePrimitivaTexto);
}
break;
case delegua_1.default.VETOR:
case delegua_1.default.VETOR_NUMERO:
case delegua_1.default.VETOR_NÚMERO:
case delegua_1.default.VETOR_TEXTO:
const metodoDePrimitivaVetor = primitivas_vetor_1.default[expressao.nomePropriedade].implementacao;
if (metodoDePrimitivaVetor) {
return new estruturas_1.MetodoPrimitiva(objeto, metodoDePrimitivaVetor);
}
break;
}
return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(null, `Método para objeto ou primitiva não encontrado: ${expressao.nomePropriedade}.`, expressao.linha));
}
async visitarExpressaoTipoDe(expressao) {
let valorTipoDe = expressao.valor;
switch (valorTipoDe.constructor.name) {
case 'AcessoIndiceVariavel':
case 'Agrupamento':
case 'Binario':
case 'Chamada':
case 'Dicionario':
case 'Unario':
valorTipoDe = await this.avaliar(valorTipoDe);
return valorTipoDe.tipo || (0, inferenciador_1.inferirTipoVariavel)(valorTipoDe);
case 'AcessoMetodo':
const acessoMetodo = valorTipoDe;
return `método<${acessoMetodo.tipoRetornoMetodo}>`;
case 'AcessoPropriedade':
const acessoPropriedade = valorTipoDe;
return acessoPropriedade.tipoRetornoPropriedade;
case 'AcessoMetodoOuPropriedade':
// TODO: Deve ser removido mais futuramente.
// Apenas `AcessoMetodo` e `AcessoPropriedade` devem funcionar aqui.
throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simbolo, "Não deveria cair aqui.");
case 'Escreva':
return 'função<vazio>';
case 'Leia':
return 'função<texto>';
case 'Literal':
const tipoLiteral = valorTipoDe;
return tipoLiteral.tipo;
case 'TipoDe':
const alvoTipoDe = await this.avaliar(valorTipoDe);
return `tipo de<${alvoTipoDe}>`;
case 'Variavel':
return valorTipoDe.tipo;
case 'Vetor':
return (0, inferenciador_1.inferirTipoVariavel)(valorTipoDe === null || valorTipoDe === void 0 ? void 0 : valorTipoDe.valores);
default:
return (0, inferenciador_1.inferirTipoVariavel)(valorTipoDe);
}
}
}
exports.Interpretador = Interpretador;
//# sourceMappingURL=interpretador.js.map