@designliquido/delegua
Version:
Linguagem de programação simples e moderna usando português estruturado.
145 lines • 6.14 kB
JavaScript
;
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