UNPKG

@designliquido/delegua

Version:

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

145 lines 6.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DeleguaFuncao = void 0; const chamavel_1 = require("./chamavel"); const espaco_variaveis_1 = require("../espaco-variaveis"); const quebras_1 = require("../quebras"); const inferenciador_1 = require("../inferenciador"); const declaracoes_1 = require("../declaracoes"); /** * Qualquer função declarada em código é uma DeleguaFuncao. */ class DeleguaFuncao extends chamavel_1.Chamavel { constructor(nome, declaracao, instancia = undefined, eInicializador = false) { super(); this.nome = nome; this.declaracao = declaracao; this.instancia = instancia; this.eInicializador = eInicializador; } aridade() { var _a, _b; return ((_b = (_a = this.declaracao) === null || _a === void 0 ? void 0 : _a.parametros) === null || _b === void 0 ? void 0 : _b.length) || 0; } /** * Método utilizado por Delégua para representar esta função quando impressa. * @returns {string} A representação da função como texto. */ paraTexto() { var _a; if (!this.nome) return '<função>'; let resultado = `<função ${this.nome}`; let parametros = ''; let retorno = ''; for (let parametro of this.declaracao.parametros) { parametros += `${parametro.nome.lexema}: ${parametro.tipoDado || 'qualquer'}, `; } if (this.declaracao.parametros.length > 0) { parametros = `argumentos=<${parametros.slice(0, -2)}>`; } const retorna = this.declaracao.corpo.filter((c) => c instanceof declaracoes_1.Retorna)[0]; if (retorna instanceof declaracoes_1.Retorna) { const valor = (_a = retorna === null || retorna === void 0 ? void 0 : retorna.valor) === null || _a === void 0 ? void 0 : _a.valor; retorno = `retorna=<${typeof valor === 'number' ? valor : `'${valor}'`}>`; } if (parametros) { resultado += ` ${parametros}`; } if (retorno) { resultado += ` ${retorno}`; } resultado += '>'; return resultado; } /** * Método utilizado pelo VSCode para inspecionar esta função em depuração. * @returns {string} A representação da função como texto. */ toString() { return this.paraTexto(); } resolverParametrosEspalhados(argumentos, indiceArgumentoAtual) { const argumentosResolvidos = []; for (let i = indiceArgumentoAtual; i < argumentos.length; i++) { const argumentoAtual = argumentos[i]; argumentosResolvidos.push(argumentoAtual && argumentoAtual.hasOwnProperty('valor') ? argumentoAtual.valor : argumentoAtual); } return argumentosResolvidos; } resolverAmbiente(argumentos) { const ambiente = new espaco_variaveis_1.EspacoVariaveis(); const parametros = this.declaracao.parametros || []; for (let i = 0; i < parametros.length; i++) { const parametro = parametros[i]; const nome = parametro['nome'].lexema; if (parametro.abrangencia === 'multiplo') { const argumentosResolvidos = this.resolverParametrosEspalhados(argumentos, i); // TODO: Verificar se `imutavel` é `true` aqui mesmo. ambiente.valores[nome] = { tipo: 'vetor', valor: argumentosResolvidos, imutavel: true }; } else { let argumento = argumentos[i]; if (argumentos[i] === null) { argumento = parametro['padrao'] ? parametro['padrao'].valor : null; } ambiente.valores[nome] = argumento && argumento.hasOwnProperty('valor') ? argumento.valor : argumento; } } return ambiente; } async chamar(visitante, argumentos) { const ambiente = this.resolverAmbiente(argumentos); if (this.instancia !== undefined) { ambiente.valores['isto'] = { valor: this.instancia, tipo: 'objeto', imutavel: false, }; // TODO: Apenass Potigol usa isso até então. // Estudar mover isso para o dialeto. if (this.instancia.classe.dialetoRequerExpansaoPropriedadesEspacoVariaveis && this.nome !== 'construtor') { for (let [nomeCampo, valorCampo] of Object.entries(this.instancia.propriedades)) { ambiente.valores[nomeCampo] = { valor: valorCampo, tipo: (0, inferenciador_1.inferirTipoVariavel)(valorCampo), imutavel: false, }; } } } // TODO: Repensar essa dinâmica para análise semântica. const interpretador = visitante; interpretador.proximoEscopo = 'funcao'; const retornoBloco = await interpretador.executarBloco(this.declaracao.corpo, ambiente); const referencias = this.declaracao.parametros .map((p, indice) => { if (p.referencia) { return { indice: indice, parametro: p, }; } }) .filter((r) => r); const pilha = interpretador.pilhaEscoposExecucao; for (let referencia of referencias) { let argumentoReferencia = ambiente.valores[referencia.parametro.nome.lexema]; pilha.atribuirVariavel({ lexema: argumentos[referencia.indice].nome, }, argumentoReferencia.valor); } if (retornoBloco instanceof quebras_1.RetornoQuebra) { return retornoBloco.valor; } if (this.eInicializador) { return this.instancia; } return retornoBloco; } funcaoPorMetodoDeClasse(instancia) { return new DeleguaFuncao(this.nome, this.declaracao, instancia, this.eInicializador); } } exports.DeleguaFuncao = DeleguaFuncao; //# sourceMappingURL=delegua-funcao.js.map