UNPKG

@designliquido/delegua

Version:

Linguagem de programação simples e moderna usando português estruturado.

372 lines 20.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.visitarExpressaoAcessoMetodo = visitarExpressaoAcessoMetodo; exports.visitarExpressaoAcessoMetodoOuPropriedade = visitarExpressaoAcessoMetodoOuPropriedade; exports.visitarExpressaoAcessoPropriedade = visitarExpressaoAcessoPropriedade; exports.resolverInterpolacoes = resolverInterpolacoes; exports.visitarExpressaoAcessoIntervaloVariavel = visitarExpressaoAcessoIntervaloVariavel; exports.visitarExpressaoTuplaN = visitarExpressaoTuplaN; const construtos_1 = require("../../../construtos"); const inferenciador_1 = require("../../../inferenciador"); const quebras_1 = require("../../../quebras"); const estruturas_1 = require("../../estruturas"); const excecoes_1 = require("../../../excecoes"); const primitivas_dicionario_1 = __importDefault(require("../../../bibliotecas/dialetos/pitugues/primitivas-dicionario")); const primitivas_numero_1 = __importDefault(require("../../../bibliotecas/dialetos/pitugues/primitivas-numero")); const primitivas_texto_1 = __importDefault(require("../../../bibliotecas/dialetos/pitugues/primitivas-texto")); const primitivas_vetor_1 = __importDefault(require("../../../bibliotecas/dialetos/pitugues/primitivas-vetor")); const primitivas_tupla_1 = __importDefault(require("../../../bibliotecas/dialetos/pitugues/primitivas-tupla")); const primitivos_1 = __importDefault(require("../../../tipos-de-dados/primitivos")); const pitugues_1 = __importDefault(require("../../../tipos-de-dados/dialetos/pitugues")); async function visitarExpressaoAcessoMetodo(interpretador, expressao) { var _a; const nomeObjeto = interpretador.resolverNomeObjectoAcessado(expressao.objeto); let variavelObjeto = await interpretador.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 && variavelObjeto.constructor === quebras_1.RetornoQuebra) { variavelObjeto = variavelObjeto.valor; } const objeto = interpretador.resolverValor(variavelObjeto); if (Array.isArray(objeto)) { const metodoDePrimitivaVetor = (_a = primitivas_vetor_1.default[expressao.nomeMetodo]) === null || _a === void 0 ? void 0 : _a.implementacao; if (metodoDePrimitivaVetor) { return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaVetor, expressao.nomeMetodo, 'vetor'); } } if (objeto.constructor === estruturas_1.ObjetoDeleguaClasse) { return objeto.obterMetodo(expressao.nomeMetodo) || null; } if (objeto instanceof construtos_1.TuplaN || objeto.constructor.name === 'TuplaN') { const metodoDePrimitivaTupla = primitivas_tupla_1.default[expressao.nomeMetodo]; if (metodoDePrimitivaTupla) { return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaTupla.implementacao, expressao.nomeMetodo, 'tupla'); } } // 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(nomeObjeto, objeto, metodoDePrimitivaDicionario, expressao.nomeMetodo, 'dicionário'); } 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 pitugues_1.default.INTEIRO: case pitugues_1.default.NUMERO: case pitugues_1.default.NÚMERO: const metodoDePrimitivaNumero = primitivas_numero_1.default[expressao.nomeMetodo].implementacao; if (metodoDePrimitivaNumero) { return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaNumero, expressao.nomeMetodo, tipoObjeto); } break; case pitugues_1.default.TEXTO: const metodoDePrimitivaTexto = primitivas_texto_1.default[expressao.nomeMetodo].implementacao; if (metodoDePrimitivaTexto) { return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaTexto, expressao.nomeMetodo, 'texto'); } break; case pitugues_1.default.VETOR: case pitugues_1.default.VETOR_NUMERO: case pitugues_1.default.VETOR_NÚMERO: case pitugues_1.default.VETOR_TEXTO: const metodoDePrimitivaVetor = primitivas_vetor_1.default[expressao.nomeMetodo].implementacao; if (metodoDePrimitivaVetor) { return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaVetor, expressao.nomeMetodo, tipoObjeto); } break; } return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao({ hashArquivo: interpretador.hashArquivoDeclaracaoAtual, linha: interpretador.linhaDeclaracaoAtual, }, `Método para objeto ou primitiva não encontrado: ${expressao.nomeMetodo}.`, expressao.linha)); } /** * Casos que ocorrem aqui: * * - Quando o método ou propriedade é ou 'qualquer', ou vetor * de 'qualquer' ('qualquer[]'), e uma primitiva é usada. * - Quando o objeto é uma classe definida em código. * @param {AcessoMetodoOuPropriedade} expressao A expressão de acesso a método ou propriedade. * @returns A primitiva encontrada. */ async function visitarExpressaoAcessoMetodoOuPropriedade(interpretador, expressao) { const nomeObjeto = interpretador.resolverNomeObjectoAcessado(expressao.objeto); let variavelObjeto = await interpretador.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 === quebras_1.RetornoQuebra) { const retornoQuebra = variavelObjeto; variavelObjeto = retornoQuebra.valor; } const objeto = interpretador.resolverValor(variavelObjeto, true); if (Array.isArray(objeto)) { if (expressao.simbolo.lexema in primitivas_vetor_1.default) { const metodoDePrimitivaVetor = primitivas_vetor_1.default[expressao.simbolo.lexema].implementacao; return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaVetor, expressao.simbolo.lexema, 'vetor'); } } if (objeto.constructor === estruturas_1.ObjetoDeleguaClasse) { return await objeto.obter(expressao.simbolo, interpretador); } if (objeto instanceof construtos_1.TuplaN || objeto.constructor.name === 'TuplaN') { const metodoDePrimitivaTupla = primitivas_tupla_1.default[expressao.simbolo.lexema]; if (metodoDePrimitivaTupla) { return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaTupla.implementacao, expressao.simbolo.lexema, 'tupla'); } } // Objeto simples do JavaScript, ou dicionário de Delégua. if (objeto.constructor === Object) { if (expressao.simbolo.lexema in primitivas_dicionario_1.default) { const metodoDePrimitivaDicionario = primitivas_dicionario_1.default[expressao.simbolo.lexema].implementacao; return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaDicionario, expressao.simbolo.lexema, 'dicionário'); } return objeto[expressao.simbolo.lexema]; } // String do JavaScript, ou seja, primitiva de texto. if (objeto.constructor === String) { if (!(expressao.simbolo.lexema in primitivas_texto_1.default)) { throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simbolo, `Método de primitiva '${expressao.simbolo.lexema}' não existe para o tipo texto.`); } const metodoDePrimitivaTexto = primitivas_texto_1.default[expressao.simbolo.lexema].implementacao; return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaTexto, expressao.simbolo.lexema, 'texto'); } // A partir daqui, presume-se que o objeto é uma das estruturas // de Delégua. if (objeto instanceof estruturas_1.DeleguaModulo) { return objeto.componentes[expressao.simbolo.lexema] || 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 pitugues_1.default.INTEIRO: case pitugues_1.default.NUMERO: case pitugues_1.default.NÚMERO: if (!(expressao.simbolo.lexema in primitivas_numero_1.default)) { throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simbolo, `Método de primitiva '${expressao.simbolo.lexema}' não existe para o tipo ${tipoObjeto}.`); } const metodoDePrimitivaNumero = primitivas_numero_1.default[expressao.simbolo.lexema].implementacao; if (metodoDePrimitivaNumero) { return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaNumero, expressao.simbolo.lexema, tipoObjeto); } break; case pitugues_1.default.TEXTO: if (!(expressao.simbolo.lexema in primitivas_texto_1.default)) { throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simbolo, `Método de primitiva '${expressao.simbolo.lexema}' não existe para o tipo ${tipoObjeto}.`); } const metodoDePrimitivaTexto = primitivas_texto_1.default[expressao.simbolo.lexema].implementacao; if (metodoDePrimitivaTexto) { return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaTexto, expressao.simbolo.lexema, 'texto'); } break; case pitugues_1.default.VETOR: case pitugues_1.default.VETOR_INTEIRO: case pitugues_1.default.VETOR_LOGICO: case pitugues_1.default.VETOR_LÓGICO: case pitugues_1.default.VETOR_NUMERO: case pitugues_1.default.VETOR_NÚMERO: case pitugues_1.default.VETOR_QUALQUER: case pitugues_1.default.VETOR_TEXTO: if (!(expressao.simbolo.lexema in primitivas_vetor_1.default)) { throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simbolo, `Método de primitiva '${expressao.simbolo.lexema}' não existe para o tipo ${tipoObjeto}.`); } const metodoDePrimitivaVetor = primitivas_vetor_1.default[expressao.simbolo.lexema].implementacao; if (metodoDePrimitivaVetor) { return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoDePrimitivaVetor, expressao.simbolo.lexema, tipoObjeto); } break; } // Objeto de uma classe JavaScript regular (ou seja, com construtor e propriedades) // que possua a propriedade. // Exemplos: classes de LinConEs, como `RetornoComando`, ou bibliotecas globais com objetos próprios. if (objeto.hasOwnProperty && objeto.hasOwnProperty(expressao.simbolo.lexema)) { return objeto[expressao.simbolo.lexema]; } // Último caso: objeto simples, sem construtor, sem protótipo. Exemplo: {'a': 1, 'b': 2} if (typeof objeto[expressao.simbolo.lexema] !== 'undefined') { return objeto[expressao.simbolo.lexema]; } return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(null, `Método ou propriedade para objeto ou primitiva não encontrado: ${expressao.simbolo.lexema}.`, expressao.linha)); } async function visitarExpressaoAcessoPropriedade(interpretador, expressao) { const nomeObjeto = interpretador.resolverNomeObjectoAcessado(expressao.objeto); let variavelObjeto = await interpretador.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 && variavelObjeto.constructor === quebras_1.RetornoQuebra) { variavelObjeto = variavelObjeto.valor; } const objeto = interpretador.resolverValor(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 === estruturas_1.ObjetoDeleguaClasse) { return objeto.obterMetodo(expressao.nomePropriedade) || null; } if (objeto instanceof construtos_1.TuplaN || objeto.constructor.name === 'TuplaN') { const metodoPrimitivaTupla = primitivas_tupla_1.default[expressao.nomePropriedade]; if (metodoPrimitivaTupla) { return new estruturas_1.MetodoPrimitiva(nomeObjeto, objeto, metodoPrimitivaTupla.implementacao, expressao.nomePropriedade, 'tupla'); } } // 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(nomeObjeto, objeto, metodoDePrimitivaDicionario, expressao.nomePropriedade, 'dicionário'); } 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); } return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(null, `Propriedade para objeto ou primitiva não encontrado: ${expressao.nomePropriedade}.`, expressao.linha)); } async function resolverInterpolacoes(interpretador, textoOriginal, linha) { const regexInterpolacao = /\$\{[a-zA-Z_][a-zA-Z0-9_]*\}/g; const variaveis = textoOriginal.match(regexInterpolacao); if (!variaveis) return []; const resultadosAvaliacaoSintatica = variaveis.map((s) => { // s tem a forma "${identificador}" — removemos apenas os dois primeiros e o último caractere const expressaoInterpolacao = s.slice(2, -1); let microLexador = interpretador.microLexador.mapear(expressaoInterpolacao); const resultadoMicroAvaliadorSintatico = interpretador.microAvaliadorSintatico.analisar(microLexador, linha); return { expressaoInterpolacao, resultadoMicroAvaliadorSintatico, }; }); const resolucoesPromises = await Promise.all(resultadosAvaliacaoSintatica .flatMap((r) => r.resultadoMicroAvaliadorSintatico.declaracoes) .map((d) => interpretador.avaliar(d))); return resolucoesPromises.map((item, indice) => ({ expressaoInterpolacao: resultadosAvaliacaoSintatica[indice].expressaoInterpolacao, valor: item, })); } async function visitarExpressaoAcessoIntervaloVariavel(interpretador, expressao) { const resultadoEntidade = await interpretador.avaliar(expressao.entidadeChamada); const objeto = interpretador.resolverValor(resultadoEntidade); let tamanho = 0; let itens; const ehTexto = typeof objeto === 'string'; if (objeto instanceof construtos_1.TuplaN) { itens = objeto.elementos; tamanho = objeto.elementos.length; } else if (Array.isArray(objeto) || ehTexto) { itens = objeto; tamanho = objeto.length; } else { throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'Acesso por intervalo só é suportado em vetores, textos e tuplas.', expressao.linha); } let passo = 1; if (expressao.indicePasso) { const resPasso = await interpretador.avaliar(expressao.indicePasso); passo = interpretador.resolverValor(resPasso); } if (passo === 0) { throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloFechamento, 'O passo do fatiamento não pode ser zero.', expressao.linha); } let inicio = passo > 0 ? 0 : tamanho - 1; if (expressao.indiceInicio) { const resInicio = await interpretador.avaliar(expressao.indiceInicio); inicio = interpretador.resolverValor(resInicio); if (inicio < 0) inicio = tamanho + inicio; } let fim = passo > 0 ? tamanho : -1; if (expressao.indiceFim) { const resFim = await interpretador.avaliar(expressao.indiceFim); fim = interpretador.resolverValor(resFim); if (fim < 0) fim = tamanho + fim; } // Lógica de fatiamento para suportar "passo", pois o TypeScript não suporta nativamente const resultadoFatiado = []; if (passo > 0) { for (let i = inicio; i < fim; i += passo) { if (i >= 0 && i < tamanho) { resultadoFatiado.push(itens[i]); } } } else { for (let i = inicio; i > fim; i += passo) { if (i >= 0 && i < tamanho) { resultadoFatiado.push(itens[i]); } } } if (objeto instanceof construtos_1.TuplaN) { return new construtos_1.TuplaN(objeto.hashArquivo, objeto.linha, resultadoFatiado); } if (ehTexto) return resultadoFatiado.join(''); return resultadoFatiado; } async function visitarExpressaoTuplaN(interpretador, expressao) { const elementos = []; for (let i = 0; i < expressao.elementos.length; i++) { const res = await interpretador.avaliar(expressao.elementos[i]); elementos.push(interpretador.resolverValor(res)); } const elementosComoConstrutos = elementos.map((valor) => new construtos_1.Literal(expressao.hashArquivo, expressao.linha, valor)); return new construtos_1.TuplaN(expressao.hashArquivo, expressao.linha, elementosComoConstrutos); } //# sourceMappingURL=comum.js.map