Repository: DesignLiquido/delegua
Pull request #748 (2025-04-23 16:54:20)

Implementação do mecanismo de currying
- Resolve https://github.com/DesignLiquido/delegua/issues/623
- Demais implementações relacionadas ao impacto do novo mecanismo de referência de funções.


Patch:
diff --git a/fontes/analisador-semantico/analisador-semantico-base.ts b/fontes/analisador-semantico/analisador-semantico-base.ts
index a2e22b72..4ac86d74 100644
--- a/fontes/analisador-semantico/analisador-semantico-base.ts
+++ b/fontes/analisador-semantico/analisador-semantico-base.ts
@@ -25,6 +25,8 @@ import {
     Comentario,
     AcessoMetodo,
     AcessoPropriedade,
+    ArgumentoReferenciaFuncao,
+    ReferenciaFuncao,
 } from '../construtos';
 import {
     Declaracao,
@@ -67,7 +69,6 @@ import { ContinuarQuebra, RetornoQuebra, SustarQuebra } from '../quebras';
  * simplesmente passa por ele (`return Promise.resolve()`).
  */
 export abstract class AnalisadorSemanticoBase implements AnalisadorSemanticoInterface {
-    
     diagnosticos: DiagnosticoAnalisadorSemantico[];
 
     abstract analisar(declaracoes: Declaracao[]): RetornoAnalisadorSemantico;
@@ -86,6 +87,14 @@ export abstract class AnalisadorSemanticoBase implements AnalisadorSemanticoInte
         });
     }
 
+    visitarExpressaoArgumentoReferenciaFuncao(expressao: ArgumentoReferenciaFuncao): Promise<any> | void {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoReferenciaFuncao(expressao: ReferenciaFuncao): Promise<any> | void {
+        return Promise.resolve();
+    }
+
     visitarExpressaoAcessoMetodo(expressao: AcessoMetodo): Promise<any> | void {
         return Promise.resolve();
     }
@@ -215,7 +224,7 @@ export abstract class AnalisadorSemanticoBase implements AnalisadorSemanticoInte
     }
 
     visitarExpressaoContinua(declaracao?: Continua): ContinuarQuebra {
-        return Promise.resolve();
+        return null;
     }
 
     visitarExpressaoDeChamada(expressao: Chamada): Promise<any> {
@@ -283,7 +292,7 @@ export abstract class AnalisadorSemanticoBase implements AnalisadorSemanticoInte
     }
 
     visitarExpressaoSustar(declaracao?: Sustar): SustarQuebra {
-        return Promise.resolve();
+        return null;
     }
 
     visitarExpressaoTupla(expressao: Tupla): Promise<any> {
diff --git a/fontes/analisador-semantico/analisador-semantico.ts b/fontes/analisador-semantico/analisador-semantico.ts
index 24ce3777..ccfccd26 100644
--- a/fontes/analisador-semantico/analisador-semantico.ts
+++ b/fontes/analisador-semantico/analisador-semantico.ts
@@ -1,5 +1,6 @@
 import {
     Agrupamento,
+    ArgumentoReferenciaFuncao,
     Atribuir,
     Binario,
     Chamada,
@@ -7,6 +8,7 @@ import {
     FuncaoConstruto,
     Literal,
     Logico,
+    ReferenciaFuncao,
     TipoDe,
     Variavel,
     Vetor,
@@ -24,7 +26,7 @@ import {
     Retorna,
     Var,
 } from '../declaracoes';
-import { SimboloInterface } from '../interfaces';
+import { ParametroInterface, SimboloInterface } from '../interfaces';
 import { DiagnosticoAnalisadorSemantico, DiagnosticoSeveridade } from '../interfaces/erros';
 import { RetornoAnalisadorSemantico } from '../interfaces/retornos/retorno-analisador-semantico';
 import { RetornoQuebra } from '../quebras';
@@ -39,7 +41,7 @@ interface VariavelHipoteticaInterface {
 }
 
 interface FuncaoHipoteticaInterface {
-    valor: any;
+    valor: FuncaoConstruto;
 }
 
 export class AnalisadorSemantico extends AnalisadorSemanticoBase {
@@ -140,16 +142,20 @@ export class AnalisadorSemantico extends AnalisadorSemanticoBase {
     }
 
     private verificarTipoDe(valor: Construto): Promise<any> {
-        if (valor instanceof Binario) {
-            this.verificarTipoDe(valor.direita);
-            this.verificarTipoDe(valor.esquerda);
-        }
-        if (valor instanceof Agrupamento) {
-            return this.verificarTipoDe(valor.expressao);
-        }
-        if (valor instanceof Variavel) {
-            return this.verificarVariavel(valor);
+        switch (valor.constructor.name) {
+            case 'Agrupamento':
+                const valorAgrupamento = valor as Agrupamento;
+                return this.verificarTipoDe(valorAgrupamento.expressao);
+            case 'Binario':
+                const valorBinario = valor as Binario;
+                this.verificarTipoDe(valorBinario.direita);
+                this.verificarTipoDe(valorBinario.esquerda);
+                break;
+            case 'Variavel':
+                const valorVariavel = valor as Variavel;
+                return this.verificarVariavel(valorVariavel);
         }
+        
         return Promise.resolve();
     }
 
@@ -171,49 +177,108 @@ export class AnalisadorSemantico extends AnalisadorSemanticoBase {
         return Promise.resolve();
     }
 
-    visitarExpressaoDeChamada(expressao: Chamada) {
-        if (expressao.entidadeChamada instanceof Variavel) {
-            const variavel = expressao.entidadeChamada as Variavel;
-            const funcaoChamada = this.variaveis[variavel.simbolo.lexema] || this.funcoes[variavel.simbolo.lexema];
-            if (!funcaoChamada) {
-                this.erro(
-                    expressao.entidadeChamada.simbolo,
-                    `Chamada da função '${expressao.entidadeChamada.simbolo.lexema}' não existe.`
-                );
-                return Promise.resolve();
-            }
-
-            const funcao = funcaoChamada.valor as FuncaoConstruto;
-            if (funcao.parametros.length !== expressao.argumentos.length) {
-                this.erro(
-                    expressao.entidadeChamada.simbolo,
-                    `Função '${expressao.entidadeChamada.simbolo.lexema}' espera ${funcao.parametros.length} parâmetros. Atual: ${expressao.argumentos.length}.`
-                );
-            }
+    comparacaoArgumentosContraParametrosFuncao(
+        simboloFuncao: SimboloInterface, 
+        parametros: ParametroInterface[], 
+        argumentos: Construto[]
+    ) {
+        if (parametros.length !== argumentos.length) {
+            this.erro(
+                simboloFuncao,
+                `Função '${simboloFuncao.lexema}' espera ${parametros.length} parâmetros. Atual: ${argumentos.length}.`
+            );
+        }
 
-            for (let [indice, parametro] of funcao.parametros.entries()) {
-                // TODO: `argumento` pode ser Literal (tipo já resolvido) ou variável (tipo inferido em outra etapa).
-                const argumento = expressao.argumentos[indice] as any;
-                if (argumento) {
-                    if (parametro.tipoDado === 'texto' && argumento.tipo !== 'texto') {
+        for (let [indice, parametro] of parametros.entries()) {
+            // TODO: `argumento` pode ser Literal (tipo já resolvido) ou variável (tipo inferido em outra etapa).
+            const argumento = argumentos[indice] as any;
+            if (argumento) {
+                if (parametro.tipoDado === 'texto' && argumento.tipo !== 'texto') {
+                    this.erro(
+                        simboloFuncao,
+                        `O valor passado para o parâmetro '${parametro.nome.lexema}' (${parametro.tipoDado}) é diferente do esperado pela função (${argumento.tipo}).`
+                    );
+                } else if (['inteiro', 'número', 'real'].includes(parametro.tipoDado)) {
+                    // Aqui, se houver diferença entre os tipos do parâmetro e do argumento, não há erro,
+                    // porque Delégua pode trabalhar com conversões implícitas.
+                    // Isso pode ou não mudar no futuro.
+                    if (!['inteiro', 'número', 'real'].includes(argumento.tipo)) {
                         this.erro(
-                            expressao.entidadeChamada.simbolo,
+                            simboloFuncao,
                             `O valor passado para o parâmetro '${parametro.nome.lexema}' (${parametro.tipoDado}) é diferente do esperado pela função (${argumento.tipo}).`
                         );
-                    } else if (['inteiro', 'número', 'real'].includes(parametro.tipoDado)) {
-                        // Aqui, se houver diferença entre os tipos do parâmetro e do argumento, não há erro,
-                        // porque Delégua pode trabalhar com conversões implícitas.
-                        // Isso pode ou não mudar no futuro.
-                        if (!['inteiro', 'número', 'real'].includes(argumento.tipo)) {
-                            this.erro(
-                                expressao.entidadeChamada.simbolo,
-                                `O valor passado para o parâmetro '${parametro.nome.lexema}' (${parametro.tipoDado}) é diferente do esperado pela função (${argumento.tipo}).`
-                            );
-                        }
                     }
                 }
             }
         }
+    }
+
+    visitarChamadaPorArgumentoReferenciaFuncao(
+        argumentoReferenciaFuncao: ArgumentoReferenciaFuncao,
+        argumentos: Construto[]
+    ) {
+        const variavelCorrespondente: FuncaoConstruto = this.variaveis[argumentoReferenciaFuncao.simboloFuncao.lexema].valor;
+        if (!variavelCorrespondente) {
+            return;
+        }
+
+        this.comparacaoArgumentosContraParametrosFuncao(
+            argumentoReferenciaFuncao.simboloFuncao,
+            variavelCorrespondente.parametros,
+            argumentos
+        );
+    }
+
+    visitarChamadaPorReferenciaFuncao(
+        referenciaFuncao: ReferenciaFuncao,
+        argumentos: Construto[]
+    ) {
+        const funcaoCorrespondente: FuncaoHipoteticaInterface = this.funcoes[referenciaFuncao.simboloFuncao.lexema];
+        if (!funcaoCorrespondente) {
+            return;
+        }
+
+        this.comparacaoArgumentosContraParametrosFuncao(
+            referenciaFuncao.simboloFuncao,
+            funcaoCorrespondente.valor.parametros,
+            argumentos
+        );
+    }
+
+    visitarChamadaPorVariavel(entidadeChamadaVariavel: Variavel, argumentos: Construto[]) {
+        const variavel = entidadeChamadaVariavel as Variavel;
+        const funcaoChamada = this.variaveis[variavel.simbolo.lexema] || this.funcoes[variavel.simbolo.lexema];
+        if (!funcaoChamada) {
+            this.erro(
+                entidadeChamadaVariavel.simbolo,
+                `Chamada da função '${entidadeChamadaVariavel.simbolo.lexema}' não existe.`
+            );
+            return Promise.resolve();
+        }
+
+        const funcao = funcaoChamada.valor as FuncaoConstruto;
+        this.comparacaoArgumentosContraParametrosFuncao(
+            entidadeChamadaVariavel.simbolo,
+            funcao.parametros,
+            argumentos
+        );
+    }
+
+    visitarExpressaoDeChamada(expressao: Chamada) {
+        switch (expressao.entidadeChamada.constructor.name) {
+            case 'ArgumentoReferenciaFuncao':
+                const entidadeChamadaArgumentoReferenciaFuncao = expressao.entidadeChamada as ArgumentoReferenciaFuncao;
+                this.visitarChamadaPorArgumentoReferenciaFuncao(entidadeChamadaArgumentoReferenciaFuncao, expressao.argumentos);
+                break;
+            case 'ReferenciaFuncao':
+                const entidadeChamadaReferenciaFuncao = expressao.entidadeChamada as ReferenciaFuncao;
+                this.visitarChamadaPorReferenciaFuncao(entidadeChamadaReferenciaFuncao, expressao.argumentos);
+                break;
+            case 'Variavel':
+                const entidadeChamadaVariavel = expressao.entidadeChamada as Variavel;
+                this.visitarChamadaPorVariavel(entidadeChamadaVariavel, expressao.argumentos);
+                break;
+        }
 
         return Promise.resolve();
     }
@@ -411,9 +476,13 @@ export class AnalisadorSemantico extends AnalisadorSemanticoBase {
     }
 
     private verificarChamada(chamada: Chamada): Promise<void> {
-        let funcaoChamada = chamada.entidadeChamada as Variavel;
-        if (!this.funcoes[funcaoChamada.simbolo.lexema]) {
-            this.erro(funcaoChamada.simbolo, `Chamada da função '${funcaoChamada.simbolo.lexema}' não existe.`);
+        switch (chamada.entidadeChamada.constructor.name) {
+            case 'Variavel':
+                let entidadeChamadaVariavel = chamada.entidadeChamada as Variavel;
+                if (!this.funcoes[entidadeChamadaVariavel.simbolo.lexema]) {
+                    this.erro(entidadeChamadaVariavel.simbolo, `Chamada da função '${entidadeChamadaVariavel.simbolo.lexema}' não existe.`);
+                }
+                break;
         }
 
         return Promise.resolve();
@@ -488,22 +557,25 @@ export class AnalisadorSemantico extends AnalisadorSemanticoBase {
     visitarDeclaracaoVar(declaracao: Var): Promise<any> {
         this.verificarTipoAtribuido(declaracao);
 
-        if (declaracao.inicializador instanceof FuncaoConstruto) {
-            const funcao = declaracao.inicializador;
-            if (funcao.parametros.length >= 255) {
-                this.erro(declaracao.simbolo, 'Função não pode ter mais de 255 parâmetros.');
+        if (declaracao.inicializador) {
+            switch (declaracao.inicializador.constructor.name) {
+                case 'FuncaoConstruto':
+                    const funcaoConstruto = declaracao.inicializador as FuncaoConstruto;
+                    if (funcaoConstruto.parametros.length >= 255) {
+                        this.erro(declaracao.simbolo, 'Função não pode ter mais de 255 parâmetros.');
+                    }
+                    break;
             }
         }
+        
+        const valorInicializador = declaracao.inicializador && declaracao.inicializador.valor ? 
+            declaracao.inicializador.valor : 
+            declaracao.inicializador;
 
         this.variaveis[declaracao.simbolo.lexema] = {
             imutavel: false,
             tipo: declaracao.tipo,
-            valor:
-                declaracao.inicializador !== null
-                    ? declaracao.inicializador.valor !== undefined
-                        ? declaracao.inicializador.valor
-                        : declaracao.inicializador
-                    : undefined,
+            valor: valorInicializador || undefined,
         };
 
         return Promise.resolve();
@@ -514,7 +586,7 @@ export class AnalisadorSemantico extends AnalisadorSemanticoBase {
     }
 
     visitarDeclaracaoDefinicaoFuncao(declaracao: FuncaoDeclaracao) {
-        if (declaracao.funcao.tipoRetorno === undefined) {
+        if (declaracao.funcao.tipo === undefined) {
             this.erro(declaracao.simbolo, `Declaração de retorno da função é inválido.`);
         }
 
@@ -522,7 +594,7 @@ export class AnalisadorSemantico extends AnalisadorSemanticoBase {
             this.erro(declaracao.simbolo, 'Função não pode ter mais de 255 parâmetros.');
         }
 
-        let tipoRetornoFuncao = declaracao.funcao.tipoRetorno;
+        let tipoRetornoFuncao = declaracao.funcao.tipo;
         if (tipoRetornoFuncao) {
             let funcaoContemRetorno = declaracao.funcao.corpo.find((c) => c instanceof Retorna) as Retorna;
             if (funcaoContemRetorno) {
diff --git a/fontes/avaliador-sintatico/avaliador-sintatico.ts b/fontes/avaliador-sintatico/avaliador-sintatico.ts
index f8e41399..f031f352 100644
--- a/fontes/avaliador-sintatico/avaliador-sintatico.ts
+++ b/fontes/avaliador-sintatico/avaliador-sintatico.ts
@@ -6,6 +6,7 @@ import {
     AcessoMetodoOuPropriedade,
     AcessoPropriedade,
     Agrupamento,
+    ArgumentoReferenciaFuncao,
     AtribuicaoPorIndice,
     Atribuir,
     Binario,
@@ -21,6 +22,7 @@ import {
     Isto,
     Literal,
     Logico,
+    ReferenciaFuncao,
     Super,
     TipoDe,
     Unario,
@@ -99,6 +101,7 @@ export class AvaliadorSintatico
     tiposDefinidosEmCodigo: { [key: string]: Declaracao };
     pilhaEscopos: PilhaEscopos;
     tiposDeFerramentasExternas: {[key: string]: {[key: string]: string}};
+    primitivasConhecidas: string[];
 
     hashArquivo: number;
     atual: number;
@@ -115,6 +118,14 @@ export class AvaliadorSintatico
         this.performance = performance;
         this.tiposDefinidosEmCodigo = {};
         this.tiposDeFerramentasExternas = {};
+        this.primitivasConhecidas = [
+            ...Object.keys(primitivasDicionario),
+            ...Object.keys(primitivasNumero),
+            ...Object.keys(primitivasTexto),
+            ...Object.keys(primitivasVetor),
+            'inteiro',
+            'texto'
+        ];
         this.pilhaEscopos = new PilhaEscopos();
     }
 
@@ -261,7 +272,9 @@ export class AvaliadorSintatico
             case tiposDeSimbolos.FUNCAO:
             case tiposDeSimbolos.FUNÇÃO:
                 const simboloFuncao = this.avancarEDevolverAnterior();
-                return this.corpoDaFuncao(simboloFuncao.lexema);
+                const corpoDaFuncao = this.corpoDaFuncao(simboloFuncao.lexema);
+                this.pilhaEscopos.definirTipoVariavel(simboloFuncao.lexema, 'função');
+                return corpoDaFuncao;
 
             case tiposDeSimbolos.IDENTIFICADOR:
                 const simboloIdentificador: SimboloInterface = this.avancarEDevolverAnterior();
@@ -435,7 +448,7 @@ export class AvaliadorSintatico
                                         construtoTipado.hashArquivo,
                                         construtoTipado.objeto,
                                         construtoTipado.simbolo.lexema,
-                                        possivelMetodo[0].tipoRetorno
+                                        possivelMetodo[0].tipo
                                     );
                                     break;
                                 }
@@ -597,6 +610,43 @@ export class AvaliadorSintatico
         return entidadeChamadaResolvida;
     }
 
+    protected resolverEntidadeChamada(entidadeChamada: Construto): Construto {
+        if (entidadeChamada.constructor.name === 'Variavel') {
+            const entidadeChamadaResolvidaVariavel = entidadeChamada as Variavel;
+
+            if (this.primitivasConhecidas.includes(entidadeChamadaResolvidaVariavel.simbolo.lexema)) {
+                return entidadeChamadaResolvidaVariavel;
+            }
+
+            if (entidadeChamadaResolvidaVariavel.simbolo.lexema in this.tiposDefinidosEmCodigo) {
+                return entidadeChamadaResolvidaVariavel;
+            }
+
+            const possivelReferencia = this.pilhaEscopos.obterReferenciaFuncao(entidadeChamadaResolvidaVariavel.simbolo.lexema);
+            if (possivelReferencia !== null) {
+                return new ReferenciaFuncao(
+                    entidadeChamada.hashArquivo, 
+                    entidadeChamada.linha, 
+                    entidadeChamadaResolvidaVariavel.simbolo,
+                    entidadeChamadaResolvidaVariavel.tipo,
+                    possivelReferencia.id
+                );
+            }
+
+            return new ArgumentoReferenciaFuncao(
+                entidadeChamada.hashArquivo, 
+                entidadeChamada.linha, 
+                entidadeChamadaResolvidaVariavel.simbolo
+            )
+        }
+
+        if (entidadeChamada.constructor.name === 'AcessoMetodoOuPropriedade') {
+            return this.resolverEntidadeChamadaAcessoMetodoOuPropriedade(entidadeChamada as AcessoMetodoOuPropriedade);
+        }
+
+        return entidadeChamada;
+    }
+
     override finalizarChamada(entidadeChamada: Construto): Chamada {
         const argumentos: Array<Construto> = [];
 
@@ -613,13 +663,12 @@ export class AvaliadorSintatico
         this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após os argumentos.");
 
         // Toda chamada precisa saber de antemão qual o tipo resolvido.
-        let entidadeChamadaResolvida = entidadeChamada;
-        if (entidadeChamadaResolvida.constructor.name === 'AcessoMetodoOuPropriedade') {
-            entidadeChamadaResolvida = this.resolverEntidadeChamadaAcessoMetodoOuPropriedade(entidadeChamadaResolvida as AcessoMetodoOuPropriedade);
-        }
+        const entidadeChamadaResolvida = this.resolverEntidadeChamada(entidadeChamada);
 
         // TODO: Criar forma de validar tipos dos argumentos da entidade chamada.
-        return new Chamada(this.hashArquivo, entidadeChamadaResolvida, argumentos);
+        const construtoChamada = new Chamada(this.hashArquivo, entidadeChamadaResolvida, argumentos);
+        construtoChamada.tipo = 'qualquer';
+        return construtoChamada;
     }
 
     override unario(): Construto {
@@ -681,6 +730,7 @@ export class AvaliadorSintatico
             const operador = this.simbolos[this.atual - 1];
 
             const direito = this.multiplicar();
+            // const tipoInferido = inferirTipoParaBinario(expressao, operador, direito);
             expressao = new Binario<TipoDeSimboloDelegua>(this.hashArquivo, expressao, operador, direito);
         }
 
@@ -825,13 +875,6 @@ export class AvaliadorSintatico
                         expressaoAcessoMetodoOuPropriedade.simbolo, 
                         valor
                     );
-                /* case 'Super':
-                    const expressaoSuper = expressao as Super;
-                    return new DefinirValor(
-                        this.hashArquivo,
-                        igual.linha,
-                        expressaoSuper.
-                    ); */
                 case 'AcessoIndiceVariavel':
                     const expressaoAcessoIndiceVariavel = expressao as AcessoIndiceVariavel;
                     return new AtribuicaoPorIndice(
@@ -1165,6 +1208,8 @@ export class AvaliadorSintatico
                 tiposDeSimbolos.CHAVE_ESQUERDA,
                 tiposDeSimbolos.COLCHETE_ESQUERDO,
                 tiposDeSimbolos.FALSO,
+                tiposDeSimbolos.FUNCAO,
+                tiposDeSimbolos.FUNÇÃO,
                 tiposDeSimbolos.IDENTIFICADOR,
                 tiposDeSimbolos.ISTO,
                 tiposDeSimbolos.NEGACAO,
@@ -1467,6 +1512,12 @@ export class AvaliadorSintatico
                     case 'AcessoPropriedade':
                         const entidadeChamadaAcessoPropriedade = entidadeChamadaChamada as AcessoPropriedade;
                         return entidadeChamadaAcessoPropriedade.tipoRetornoPropriedade;
+                    case 'ArgumentoReferenciaFuncao':
+                        // TODO: Voltar aqui se necessário.
+                        return 'qualquer';
+                    case 'ReferenciaFuncao':
+                        const entidadeChamadaReferenciaFuncao = entidadeChamadaChamada as ReferenciaFuncao;
+                        return entidadeChamadaReferenciaFuncao.tipo;
                     case 'Variavel':
                         const entidadeChamadaVariavel = entidadeChamadaChamada as Variavel;
                         return entidadeChamadaVariavel.tipo;
@@ -1475,7 +1526,7 @@ export class AvaliadorSintatico
                 break;
             case 'FuncaoConstruto':
                 const funcaoConstruto = inicializador as FuncaoConstruto;
-                return `função<${funcaoConstruto.tipoRetorno}>`;
+                return `função<${funcaoConstruto.tipo}>`;
             case 'Leia':
                 return 'texto';
             case 'Dupla':
@@ -1665,8 +1716,10 @@ export class AvaliadorSintatico
         this.pilhaEscopos.definirTipoVariavel(simbolo.lexema, 'qualquer');
 
         const corpoDaFuncao = this.corpoDaFuncao(tipo);
-        this.pilhaEscopos.definirTipoVariavel(simbolo.lexema, corpoDaFuncao.tipoRetorno);
-        return new FuncaoDeclaracao(simbolo, corpoDaFuncao, corpoDaFuncao.tipoRetorno, decoradores);
+        this.pilhaEscopos.definirTipoVariavel(simbolo.lexema, corpoDaFuncao.tipo);
+        const funcaoDeclaracao = new FuncaoDeclaracao(simbolo, corpoDaFuncao, corpoDaFuncao.tipo, decoradores);
+        this.pilhaEscopos.registrarReferenciaFuncao(simbolo.lexema, funcaoDeclaracao);
+        return funcaoDeclaracao;
     }
 
     protected logicaComumParametros(): ParametroInterface[] {
@@ -1784,6 +1837,7 @@ export class AvaliadorSintatico
         }
 
         const tiposRetornos = new Set(expressoesRetorna.map(e => e.tipo));
+        let retornaChamadoExplicitamente = tiposRetornos.size > 0;
         if (tiposRetornos.size > 1 && tipoRetorno !== 'qualquer') {
             let tiposEncontrados = Array.from(tiposRetornos).reduce((acumulador, valor) => acumulador += valor + ', ', '');
             tiposEncontrados = tiposEncontrados.slice(0, -2);
@@ -1801,7 +1855,7 @@ export class AvaliadorSintatico
                 // de retornos encontrados nos blocos internos da função.
                 const tipoRetornoDeduzido = tiposRetornos.values().next().value;
                 tipoRetorno = tipoRetornoDeduzido;
-            } else if (!definicaoExplicitaDeTipo) {
+            } else if (!retornaChamadoExplicitamente && !definicaoExplicitaDeTipo) {
                 // Ou, se esses retornos sequer existem, e o tipo explícito não é
                 // 'qualquer', o tipo inferido é 'vazio'.
                 tipoRetorno = 'vazio';
diff --git a/fontes/avaliador-sintatico/informacao-escopo.ts b/fontes/avaliador-sintatico/informacao-escopo.ts
index ffe4d454..9235333c 100644
--- a/fontes/avaliador-sintatico/informacao-escopo.ts
+++ b/fontes/avaliador-sintatico/informacao-escopo.ts
@@ -1,7 +1,11 @@
+import { FuncaoDeclaracao } from "../declaracoes";
+
 export class InformacaoEscopo {
     variaveisEConstantes: { [nome: string]: string };
+    referenciasFuncoes: { [nome: string]: FuncaoDeclaracao };
 
     constructor() {
         this.variaveisEConstantes = {};
+        this.referenciasFuncoes = {};
     }
 }
diff --git a/fontes/avaliador-sintatico/pilha-escopos.ts b/fontes/avaliador-sintatico/pilha-escopos.ts
index 01c590b7..591185c0 100644
--- a/fontes/avaliador-sintatico/pilha-escopos.ts
+++ b/fontes/avaliador-sintatico/pilha-escopos.ts
@@ -1,3 +1,4 @@
+import { FuncaoDeclaracao } from "../declaracoes";
 import { PilhaInterface, VariavelInterface } from "../interfaces";
 import { InformacaoEscopo } from "./informacao-escopo";
 
@@ -43,4 +44,20 @@ export class PilhaEscopos implements PilhaInterface<InformacaoEscopo> {
         const topoDaPilha = this.topoDaPilha();
         topoDaPilha.variaveisEConstantes[nomeVariavel] = tipo;
     }
+
+    registrarReferenciaFuncao(nome: string, definicao: FuncaoDeclaracao) {
+        const topoDaPilha = this.topoDaPilha();
+        topoDaPilha.referenciasFuncoes[nome] = definicao;
+    }
+
+    obterReferenciaFuncao(nome: string) {
+        for (let i = 1; i <= this.pilha.length; i++) {
+            const informacaoEscopo = this.pilha[this.pilha.length - i];
+            if (informacaoEscopo.referenciasFuncoes[nome] !== undefined) {
+                return informacaoEscopo.referenciasFuncoes[nome];
+            }
+        }
+
+        return null;
+    }
 }
\ No newline at end of file
diff --git a/fontes/construtos/argumento-referencia-funcao.ts b/fontes/construtos/argumento-referencia-funcao.ts
new file mode 100644
index 00000000..a40af844
--- /dev/null
+++ b/fontes/construtos/argumento-referencia-funcao.ts
@@ -0,0 +1,24 @@
+import { SimboloInterface, VisitanteComumInterface } from "../interfaces";
+import { Construto } from "./construto";
+
+/**
+ * Este construto é emitido pelo Avaliador Sintático, e indica para as 
+ * próximas etapas que este elemento é uma referência de função, mas 
+ * que não pode ser resolvido em tempo de avaliação sintática.
+ */
+export class ArgumentoReferenciaFuncao implements Construto {
+    linha: number;
+    hashArquivo: number;
+    simboloFuncao: SimboloInterface;
+    idFuncao: string | null;
+
+    constructor(hashArquivo: number, linha: number, simboloFuncao: SimboloInterface) {
+        this.linha = linha;
+        this.hashArquivo = hashArquivo;
+        this.simboloFuncao = simboloFuncao;
+    }
+
+    async aceitar(visitante: VisitanteComumInterface): Promise<any> {
+        return visitante.visitarExpressaoArgumentoReferenciaFuncao(this);
+    }
+}
diff --git a/fontes/construtos/chamada.ts b/fontes/construtos/chamada.ts
index 04dc6193..bc4e14b3 100644
--- a/fontes/construtos/chamada.ts
+++ b/fontes/construtos/chamada.ts
@@ -12,6 +12,7 @@ export class Chamada implements Construto {
 
     entidadeChamada: Construto;
     argumentos: Construto[];
+    tipo?: string;
 
     constructor(hashArquivo: number, entidadeChamada: Construto, argumentos: Construto[]) {
         this.id = uuidv4();
diff --git a/fontes/construtos/constante.ts b/fontes/construtos/constante.ts
index 5bb5da5a..dc9bc49e 100644
--- a/fontes/construtos/constante.ts
+++ b/fontes/construtos/constante.ts
@@ -9,6 +9,7 @@ export class Constante<TTipoSimbolo extends string = string> implements Construt
     hashArquivo: number;
 
     simbolo: SimboloInterface<TTipoSimbolo>;
+    idReferencia?: string;
 
     constructor(hashArquivo: number, simbolo: SimboloInterface<TTipoSimbolo>) {
         this.linha = Number(simbolo.linha);
diff --git a/fontes/construtos/funcao.ts b/fontes/construtos/funcao.ts
index 423c6582..235ded71 100644
--- a/fontes/construtos/funcao.ts
+++ b/fontes/construtos/funcao.ts
@@ -7,7 +7,7 @@ export class FuncaoConstruto implements Construto {
     hashArquivo: number;
 
     parametros: ParametroInterface[];
-    tipoRetorno?: string;
+    tipo?: string;
     corpo: Declaracao[];
 
     constructor(
@@ -21,7 +21,7 @@ export class FuncaoConstruto implements Construto {
         this.hashArquivo = hashArquivo;
 
         this.parametros = parametros;
-        this.tipoRetorno = tipoRetorno;
+        this.tipo = tipoRetorno;
         this.corpo = corpo;
     }
 
diff --git a/fontes/construtos/index.ts b/fontes/construtos/index.ts
index 45dc9b7d..bdcb5d3c 100644
--- a/fontes/construtos/index.ts
+++ b/fontes/construtos/index.ts
@@ -4,6 +4,7 @@ export * from './acesso-metodo';
 export * from './acesso-metodo-ou-propriedade';
 export * from './acesso-propriedade';
 export * from './agrupamento';
+export * from './argumento-referencia-funcao';
 export * from './atribuicao-por-indice';
 export * from './atribuicao-por-indices-matriz';
 export * from './atribuir';
@@ -23,6 +24,7 @@ export * from './funcao';
 export * from './isto';
 export * from './literal';
 export * from './logico';
+export * from './referencia-funcao';
 export * from './super';
 export * from './tipo-de';
 export * from './tuplas';
diff --git a/fontes/construtos/referencia-funcao.ts b/fontes/construtos/referencia-funcao.ts
new file mode 100644
index 00000000..d54eca42
--- /dev/null
+++ b/fontes/construtos/referencia-funcao.ts
@@ -0,0 +1,22 @@
+import { SimboloInterface, VisitanteComumInterface } from "../interfaces";
+import { Construto } from "./construto";
+
+export class ReferenciaFuncao implements Construto {
+    linha: number;
+    hashArquivo: number;
+    simboloFuncao: SimboloInterface;
+    tipo: string;
+    idFuncao: string;
+
+    constructor(hashArquivo: number, linha: number, simboloFuncao: SimboloInterface, tipo: string, idfuncao: string) {
+        this.linha = linha;
+        this.hashArquivo = hashArquivo;
+        this.simboloFuncao = simboloFuncao;
+        this.tipo = tipo;
+        this.idFuncao = idfuncao;
+    }
+
+    async aceitar(visitante: VisitanteComumInterface): Promise<any> {
+        return visitante.visitarExpressaoReferenciaFuncao(this);
+    }
+}
\ No newline at end of file
diff --git a/fontes/construtos/variavel.ts b/fontes/construtos/variavel.ts
index 7ca23319..e836cf37 100644
--- a/fontes/construtos/variavel.ts
+++ b/fontes/construtos/variavel.ts
@@ -6,6 +6,7 @@ export class Variavel<TTipoSimbolo extends string = string> implements Construto
     hashArquivo: number;
     simbolo: SimboloInterface<TTipoSimbolo>;
     tipo: string;
+    idReferencia?: string;
 
     constructor(hashArquivo: number, simbolo: SimboloInterface<TTipoSimbolo>, tipo: string = 'qualquer') {
         this.linha = Number(simbolo.linha);
diff --git a/fontes/declaracoes/funcao.ts b/fontes/declaracoes/funcao.ts
index 7ab7ceb9..cd5c4646 100644
--- a/fontes/declaracoes/funcao.ts
+++ b/fontes/declaracoes/funcao.ts
@@ -1,6 +1,7 @@
 import { VisitanteComumInterface, SimboloInterface } from '../interfaces';
 import { Declaracao } from './declaracao';
 import { Decorador, FuncaoConstruto } from '../construtos';
+import { uuidv4 } from '../geracao-identificadores';
 
 /**
  * Uma declaração de função. 
@@ -8,8 +9,9 @@ import { Decorador, FuncaoConstruto } from '../construtos';
 export class FuncaoDeclaracao extends Declaracao {
     simbolo: SimboloInterface;
     funcao: FuncaoConstruto;
-    tipoRetorno: string;
+    tipo: string;
     decoradores: Decorador[];
+    id: string;
 
     constructor(
         simbolo: SimboloInterface,
@@ -18,9 +20,10 @@ export class FuncaoDeclaracao extends Declaracao {
         decoradores: Decorador[] = []
     ) {
         super(Number(simbolo.linha), simbolo.hashArquivo);
+        this.id = uuidv4();
         this.simbolo = simbolo;
         this.funcao = funcao;
-        this.tipoRetorno = tipoRetorno;
+        this.tipo = tipoRetorno;
         this.decoradores = decoradores;
     }
 
diff --git a/fontes/declaracoes/index.ts b/fontes/declaracoes/index.ts
index e714cf98..8f86bda6 100644
--- a/fontes/declaracoes/index.ts
+++ b/fontes/declaracoes/index.ts
@@ -1,3 +1,4 @@
+export * from './aleatorio';
 export * from './bloco';
 export * from './cabecalho-programa';
 export * from './classe';
@@ -20,11 +21,10 @@ export * from './leia';
 export * from './para';
 export * from './para-cada';
 export * from './propriedade-classe';
-export * from './sustar';
 export * from './retorna';
 export * from './se';
+export * from './sustar';
 export * from './tendo-como';
 export * from './tente';
 export * from './var';
 export * from './var-multiplo';
-export * from './aleatorio';
diff --git a/fontes/espaco-variaveis.ts b/fontes/espaco-variaveis.ts
index d5fd043b..54ab4371 100644
--- a/fontes/espaco-variaveis.ts
+++ b/fontes/espaco-variaveis.ts
@@ -1,3 +1,4 @@
+import { DeleguaFuncao } from './estruturas';
 import { VariavelInterface } from './interfaces';
 
 /**
@@ -12,9 +13,11 @@ import { VariavelInterface } from './interfaces';
 export class EspacoVariaveis {
     valores: { [nome: string]: VariavelInterface };
     resolucoesChamadas: { [id: string]: any };
+    referencias: { [id: string]: DeleguaFuncao };
 
     constructor() {
         this.valores = {};
         this.resolucoesChamadas = {};
+        this.referencias = {};
     }
 }
diff --git a/fontes/estruturas/delegua-funcao.ts b/fontes/estruturas/delegua-funcao.ts
index fa979579..8d150394 100644
--- a/fontes/estruturas/delegua-funcao.ts
+++ b/fontes/estruturas/delegua-funcao.ts
@@ -92,7 +92,9 @@ export class DeleguaFuncao extends Chamavel {
         return argumentosResolvidos;
     }
 
-    protected resolverAmbiente(argumentos: Array<ArgumentoInterface>): EspacoVariaveis {
+    protected resolverAmbiente(
+        argumentos: Array<ArgumentoInterface>
+    ): EspacoVariaveis {
         const ambiente = new EspacoVariaveis();
         const parametros = this.declaracao.parametros || [];
 
@@ -112,6 +114,12 @@ export class DeleguaFuncao extends Chamavel {
                 }
 
                 ambiente.valores[nome] = argumento && argumento.hasOwnProperty('valor') ? argumento.valor : argumento;
+
+                // Se o argumento é `DeleguaFuncao`, para habilitar o recurso de _currying_, 
+                // copiamos seu valor para o escopo atual. Nem sempre podemos contar com a tipagem explícita aqui.
+                if (argumento.valor && ['funcao', 'função'].includes(argumento.valor.tipo)) {
+                    parametro.referencia = true;
+                }
             }
         }
 
@@ -141,7 +149,8 @@ export class DeleguaFuncao extends Chamavel {
             }
         }
 
-        // TODO: Repensar essa dinâmica para análise semântica.
+        // TODO: Repensar essa dinâmica para análise semântica (levar toda a lógica abaixo para
+        // o interpretador).
         const interpretador = visitante as any;
         interpretador.proximoEscopo = 'funcao';
         const retornoBloco: any = await interpretador.executarBloco(this.declaracao.corpo, ambiente);
@@ -160,11 +169,18 @@ export class DeleguaFuncao extends Chamavel {
 
         for (let referencia of referencias) {
             let argumentoReferencia = ambiente.valores[referencia.parametro.nome.lexema];
-            pilha.atribuirVariavel(
+            // TODO: Aparentemente, esta lógica foi implementada para algum dialeto que
+            // trabalha con referência, mas até então não encontrei este dialeto.
+            /* pilha.atribuirVariavel(
                 {
-                    lexema: argumentos[referencia.indice].nome,
+                    
+                    lexema: argumentos[referencia.indice].nome
                 } as any,
                 argumentoReferencia.valor
+            ); */
+            pilha.definirVariavel(
+                referencia.parametro.nome.lexema,
+                argumentoReferencia.valor
             );
         }
 
diff --git a/fontes/formatadores/formatador-delegua.ts b/fontes/formatadores/formatador-delegua.ts
index 7ce49a94..047bca76 100644
--- a/fontes/formatadores/formatador-delegua.ts
+++ b/fontes/formatadores/formatador-delegua.ts
@@ -4,6 +4,7 @@ import {
     AcessoMetodoOuPropriedade,
     AcessoPropriedade,
     Agrupamento,
+    ArgumentoReferenciaFuncao,
     AtribuicaoPorIndice,
     Atribuir,
     Binario,
@@ -19,6 +20,7 @@ import {
     Isto,
     Literal,
     Logico,
+    ReferenciaFuncao,
     Super,
     TipoDe,
     Tupla,
@@ -82,13 +84,21 @@ export class FormatadorDelegua implements VisitanteComumInterface {
         this.deveIndentar = true;
     }
 
-    visitarExpressaoAcessoMetodo(expressao: AcessoMetodo): Promise<any> | void {
+    visitarExpressaoArgumentoReferenciaFuncao(expressao: ArgumentoReferenciaFuncao): void {
+        this.codigoFormatado += expressao.simboloFuncao.lexema;
+    }
+
+    visitarExpressaoReferenciaFuncao(expressao: ReferenciaFuncao): void {
+        this.codigoFormatado += expressao.simboloFuncao.lexema;
+    }
+
+    visitarExpressaoAcessoMetodo(expressao: AcessoMetodo): void {
         this.formatarDeclaracaoOuConstruto(expressao.objeto);
         this.codigoFormatado += '.';
         this.codigoFormatado += expressao.nomeMetodo;
     }
 
-    visitarExpressaoAcessoPropriedade(expressao: AcessoPropriedade): Promise<any> | void {
+    visitarExpressaoAcessoPropriedade(expressao: AcessoPropriedade): void {
         this.formatarDeclaracaoOuConstruto(expressao.objeto);
         this.codigoFormatado += '.';
         this.codigoFormatado += expressao.nomePropriedade;
@@ -438,6 +448,9 @@ export class FormatadorDelegua implements VisitanteComumInterface {
             case tiposDeSimbolos.ADICAO:
                 this.codigoFormatado += ` + `;
                 break;
+            case tiposDeSimbolos.DIFERENTE:
+                this.codigoFormatado += ` != `;
+                break;
             case tiposDeSimbolos.DIVISAO:
                 this.codigoFormatado += ` / `;
                 break;
@@ -621,12 +634,17 @@ export class FormatadorDelegua implements VisitanteComumInterface {
         this.codigoFormatado += `)`;
     }
 
-    visitarExpressaoLiteral(expressao: Literal): any {
+    visitarExpressaoLiteral(expressao: Literal): void {
         if (typeof expressao.valor === 'string') {
             this.codigoFormatado += `'${expressao.valor}'`;
             return;
         }
 
+        if (['logico', 'lógico'].includes(expressao.tipo)) {
+            this.codigoFormatado += `${expressao.valor ? 'verdadeiro' : 'falso'}`;
+            return;
+        }
+
         this.codigoFormatado += expressao.valor;
     }
 
@@ -651,6 +669,10 @@ export class FormatadorDelegua implements VisitanteComumInterface {
         this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}retorna`;
         if (declaracao.valor) {
             this.codigoFormatado += ` `;
+            if (declaracao.valor.constructor.name === 'FuncaoConstruto') {
+                this.codigoFormatado += `função`;
+            }
+
             this.formatarDeclaracaoOuConstruto(declaracao.valor);
         }
 
@@ -722,6 +744,9 @@ export class FormatadorDelegua implements VisitanteComumInterface {
             case 'Agrupamento':
                 this.visitarExpressaoAgrupamento(declaracaoOuConstruto as Agrupamento);
                 break;
+            case 'ArgumentoReferenciaFuncao':
+                this.visitarExpressaoArgumentoReferenciaFuncao(declaracaoOuConstruto as ArgumentoReferenciaFuncao);
+                break;
             case 'AtribuicaoPorIndice':
                 this.visitarExpressaoAtribuicaoPorIndice(declaracaoOuConstruto as AtribuicaoPorIndice);
                 break;
@@ -797,6 +822,9 @@ export class FormatadorDelegua implements VisitanteComumInterface {
             case 'ParaCada':
                 this.visitarDeclaracaoParaCada(declaracaoOuConstruto as ParaCada);
                 break;
+            case 'ReferenciaFuncao':
+                this.visitarExpressaoReferenciaFuncao(declaracaoOuConstruto as ReferenciaFuncao);
+                break;
             case 'Retorna':
                 this.visitarExpressaoRetornar(declaracaoOuConstruto as Retorna);
                 break;
diff --git a/fontes/inferenciador.ts b/fontes/inferenciador.ts
index 783c32e6..6990d3ef 100644
--- a/fontes/inferenciador.ts
+++ b/fontes/inferenciador.ts
@@ -3,6 +3,7 @@ import tipoDeDadosPrimitivos from './tipos-de-dados/primitivos';
 import tipoDeDadosDelegua from './tipos-de-dados/delegua';
 import tiposDeSimbolos from './tipos-de-simbolos/delegua';
 import { TipoDadosElementar } from './tipo-dados-elementar';
+import { Construto } from './construtos';
 export type TipoInferencia =
     | 'cadeia'
     | 'caracter'
diff --git a/fontes/interfaces/pilha-escopos-execucao-interface.ts b/fontes/interfaces/pilha-escopos-execucao-interface.ts
index 7ac9e4a1..719a4234 100644
--- a/fontes/interfaces/pilha-escopos-execucao-interface.ts
+++ b/fontes/interfaces/pilha-escopos-execucao-interface.ts
@@ -12,10 +12,12 @@ export interface PilhaEscoposExecucaoInterface extends PilhaInterface<EscopoExec
     elementos(): number;
     naPosicao(posicao: number): EscopoExecucao;
     obterEscopoPorTipo(idChamada: string): EscopoExecucao | undefined;
+    obterTodasDeclaracoesClasse(): any;
     obterTodasVariaveis(todasVariaveis: any[]): { valor: any; nome: string; tipo: string }[];
+    obterTodasDeleguaFuncao(): { [nome: string]: DeleguaFuncao };
+    obterReferenciaFuncao(idFuncao: string): DeleguaFuncao;
     obterValorVariavel(simbolo: SimboloInterface): VariavelInterface;
     obterVariavelEm(distancia: number, nome: string): VariavelInterface;
     obterVariavelPorNome(nome: string): VariavelInterface;
-    obterTodasDeclaracaoClasse(): any;
-    obterTodasDeleguaFuncao(): { [nome: string]: DeleguaFuncao };
+    registrarReferenciaFuncao(idFuncao: string, funcao: DeleguaFuncao): void;
 }
diff --git a/fontes/interfaces/visitante-comum-interface.ts b/fontes/interfaces/visitante-comum-interface.ts
index d7cc50fd..e23245d9 100644
--- a/fontes/interfaces/visitante-comum-interface.ts
+++ b/fontes/interfaces/visitante-comum-interface.ts
@@ -5,6 +5,7 @@ import {
     AcessoMetodoOuPropriedade,
     AcessoPropriedade,
     Agrupamento,
+    ArgumentoReferenciaFuncao,
     AtribuicaoPorIndice,
     AtribuicaoPorIndicesMatriz,
     Atribuir,
@@ -21,6 +22,7 @@ import {
     Isto,
     Literal,
     Logico,
+    ReferenciaFuncao,
     Super,
     TipoDe,
     Tupla,
@@ -90,6 +92,7 @@ export interface VisitanteComumInterface {
     visitarExpressaoAcessoMetodoOuPropriedade(expressao: AcessoMetodoOuPropriedade): Promise<any> | void;
     visitarExpressaoAcessoPropriedade(expressao: AcessoPropriedade): Promise<any> | void;
     visitarExpressaoAgrupamento(expressao: Agrupamento): Promise<any> | void;
+    visitarExpressaoArgumentoReferenciaFuncao(expressao: ArgumentoReferenciaFuncao): Promise<any> | void;
     visitarExpressaoAtribuicaoPorIndice(expressao: AtribuicaoPorIndice): Promise<any> | void;
     visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: AtribuicaoPorIndicesMatriz): Promise<any> | void;
     visitarExpressaoBinaria(expressao: Binario): Promise<any> | void;
@@ -108,6 +111,7 @@ export interface VisitanteComumInterface {
     visitarExpressaoLeia(expressao: Leia): Promise<any> | void;
     visitarExpressaoLiteral(expressao: Literal): Promise<any> | void;
     visitarExpressaoLogica(expressao: Logico): Promise<any> | void;
+    visitarExpressaoReferenciaFuncao(expressao: ReferenciaFuncao): Promise<any> | void;
     visitarExpressaoRetornar(declaracao: Retorna): Promise<RetornoQuebra> | void;
     visitarExpressaoSuper(expressao: Super): Promise<any> | void;
     visitarExpressaoSustar(declaracao?: Sustar): SustarQuebra | void;
diff --git a/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts b/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts
index 144a25b6..57c7749a 100644
--- a/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts
+++ b/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts
@@ -11,6 +11,7 @@ import {
     AcessoIndiceVariavel,
     AcessoMetodo,
     AcessoPropriedade,
+    ArgumentoReferenciaFuncao,
     Atribuir,
     Comentario,
     Construto,
@@ -19,6 +20,7 @@ import {
     FormatacaoEscrita,
     Isto,
     Literal,
+    ReferenciaFuncao,
     Super,
     TipoDe,
     Tupla,
@@ -105,6 +107,14 @@ export class InterpretadorEguaClassico implements InterpretadorInterface {
         carregarBibliotecaGlobal(this, this.pilhaEscoposExecucao);
     }
 
+    visitarExpressaoArgumentoReferenciaFuncao(expressao: ArgumentoReferenciaFuncao): Promise<any> | void {
+        throw new Error('Método não implementado.');
+    }
+
+    visitarExpressaoReferenciaFuncao(expressao: ReferenciaFuncao): Promise<any> | void {
+        throw new Error('Método não implementado.');
+    }
+
     visitarExpressaoAcessoMetodo(expressao: AcessoMetodo): Promise<any> | void {
         throw new Error('Método não implementado.');
     }
diff --git a/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts b/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts
index 7642a262..f12def6d 100644
--- a/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts
+++ b/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts
@@ -1,12 +1,14 @@
 import {
     AcessoMetodoOuPropriedade,
     AcessoPropriedade,
+    ArgumentoReferenciaFuncao,
     Atribuir,
     Comentario,
     Construto,
     ExpressaoRegular,
     FimPara,
     FormatacaoEscrita,
+    ReferenciaFuncao,
     Super,
     TipoDe,
     Tupla,
@@ -91,6 +93,14 @@ export class ResolvedorEguaClassico implements ResolvedorInterface, Interpretado
         this.classeAtual = TipoClasse.NENHUM;
         this.cicloAtual = TipoClasse.NENHUM;
     }
+
+    visitarExpressaoArgumentoReferenciaFuncao(expressao: ArgumentoReferenciaFuncao): Promise<any> | void {
+        throw new Error('Método não implementado.');
+    }
+
+    visitarExpressaoReferenciaFuncao(expressao: ReferenciaFuncao): Promise<any> | void {
+        throw new Error('Método não implementado.');
+    }
     
     visitarExpressaoAcessoPropriedade(expressao: AcessoPropriedade): Promise<any> | void {
         throw new Error('Método não implementado.');
diff --git a/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts b/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts
index 611206f6..f789a9dd 100644
--- a/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts
+++ b/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts
@@ -1,6 +1,7 @@
 import {
     AcessoMetodo,
     AcessoPropriedade,
+    ArgumentoReferenciaFuncao,
     Atribuir,
     Comentario,
     Construto,
@@ -8,6 +9,7 @@ import {
     FimPara,
     FormatacaoEscrita,
     Literal,
+    ReferenciaFuncao,
     Super,
     TipoDe,
     Tupla,
@@ -51,11 +53,11 @@ import { PilhaEscoposExecucaoInterface } from '../../../interfaces/pilha-escopos
 import { RetornoInterpretador } from '../../../interfaces/retornos';
 import { ContinuarQuebra, Quebra, RetornoQuebra, SustarQuebra } from '../../../quebras';
 import { PilhaEscoposExecucao } from '../../pilha-escopos-execucao';
-
-import tiposDeSimbolos from '../../../tipos-de-simbolos/portugol-ipt';
 import { inferirTipoVariavel } from '../../../inferenciador';
 import { InicioAlgoritmo } from '../../../declaracoes/inicio-algoritmo';
 
+import tiposDeSimbolos from '../../../tipos-de-simbolos/portugol-ipt';
+
 export class InterpretadorPortugolIpt implements InterpretadorInterface {
     diretorioBase: any;
 
@@ -91,6 +93,14 @@ export class InterpretadorPortugolIpt implements InterpretadorInterface {
         this.pilhaEscoposExecucao.empilhar(escopoExecucao);
     }
 
+    visitarExpressaoArgumentoReferenciaFuncao(expressao: ArgumentoReferenciaFuncao): Promise<any> | void {
+        throw new Error('Método não implementado.');
+    }
+
+    visitarExpressaoReferenciaFuncao(expressao: ReferenciaFuncao): Promise<any> | void {
+        throw new Error('Método não implementado.');
+    }
+
     visitarExpressaoAcessoMetodo(expressao: AcessoMetodo): Promise<any> | void {
         throw new Error('Método não implementado.');
     }
diff --git a/fontes/interpretador/interpretador-base.ts b/fontes/interpretador/interpretador-base.ts
index c394236f..8fe5cdd4 100644
--- a/fontes/interpretador/interpretador-base.ts
+++ b/fontes/interpretador/interpretador-base.ts
@@ -44,6 +44,7 @@ import {
     AcessoMetodoOuPropriedade,
     AcessoPropriedade,
     Agrupamento,
+    ArgumentoReferenciaFuncao,
     AtribuicaoPorIndice,
     Atribuir,
     Chamada,
@@ -56,6 +57,7 @@ import {
     FuncaoConstruto,
     Literal,
     Logico,
+    ReferenciaFuncao,
     Super,
     TipoDe,
     Tupla,
@@ -80,7 +82,7 @@ import { MicroAvaliadorSintaticoBase } from '../avaliador-sintatico/micro-avalia
 import { EspacoVariaveis } from '../espaco-variaveis';
 import { carregarBibliotecasGlobais } from './comum';
 import { ErroEmTempoDeExecucao } from '../excecoes';
-import { InterpretadorInterface, ParametroInterface, SimboloInterface, VariavelInterface } from '../interfaces';
+import { InterpretadorInterface, SimboloInterface, VariavelInterface } from '../interfaces';
 
 import primitivasDicionario from '../bibliotecas/primitivas-dicionario';
 import primitivasNumero from '../bibliotecas/primitivas-numero';
@@ -174,6 +176,14 @@ export class InterpretadorBase implements InterpretadorInterface {
         carregarBibliotecasGlobais(this.pilhaEscoposExecucao);
     }
 
+    visitarExpressaoArgumentoReferenciaFuncao(expressao: ArgumentoReferenciaFuncao): Promise<any> | void {
+        throw new Error('Método não implementado.');
+    }
+
+    visitarExpressaoReferenciaFuncao(expressao: ReferenciaFuncao): Promise<any> | void {
+        throw new Error('Método não implementado.');
+    }
+
     visitarExpressaoAcessoMetodo(expressao: AcessoMetodo): Promise<any> | void {
         throw new Error('Método não implementado.');
     }
@@ -1667,16 +1677,19 @@ export class InterpretadorBase implements InterpretadorInterface {
                     }
                 }
         }
+
         if (typeof objeto === tipoDeDadosPrimitivos.OBJETO) {
-            for (const obj in objeto) {
-                let valor = objeto[obj];
+            const objetoEscrita = {};
+            for (const propriedade in objeto) {
+                let valor = objeto[propriedade];
                 if (typeof valor === tipoDeDadosPrimitivos.BOOLEANO) {
                     valor = valor ? 'verdadeiro' : 'falso';
-
-                    objeto[obj] = valor;
                 }
+
+                objetoEscrita[propriedade] = valor;
             }
-            return JSON.stringify(objeto);
+
+            return JSON.stringify(objetoEscrita);
         }
 
         return objeto.toString();
@@ -1712,8 +1725,8 @@ export class InterpretadorBase implements InterpretadorInterface {
      */
     async executarUltimoEscopo(manterAmbiente = false): Promise<any> {
         const ultimoEscopo = this.pilhaEscoposExecucao.topoDaPilha();
+        let retornoExecucao: any;
         try {
-            let retornoExecucao: any;
             for (
                 ;
                 !(retornoExecucao instanceof Quebra) && ultimoEscopo.declaracaoAtual < ultimoEscopo.declaracoes.length;
@@ -1738,7 +1751,7 @@ export class InterpretadorBase implements InterpretadorInterface {
             this.pilhaEscoposExecucao.removerUltimo();
             const escopoAnterior = this.pilhaEscoposExecucao.topoDaPilha();
 
-            if (manterAmbiente) {
+            if (manterAmbiente || (retornoExecucao && retornoExecucao.preservarEscopo === true)) {
                 escopoAnterior.ambiente.valores = Object.assign(
                     escopoAnterior.ambiente.valores,
                     ultimoEscopo.ambiente.valores
diff --git a/fontes/interpretador/interpretador.ts b/fontes/interpretador/interpretador.ts
index 2e44aac6..153528d7 100644
--- a/fontes/interpretador/interpretador.ts
+++ b/fontes/interpretador/interpretador.ts
@@ -1,7 +1,10 @@
-import { AcessoMetodo, AcessoPropriedade, Literal, TipoDe, Vetor } from "../construtos";
-import { DeleguaModulo, MetodoPrimitiva, ObjetoDeleguaClasse } from "../estruturas";
+import { AcessoMetodo, AcessoPropriedade, ArgumentoReferenciaFuncao, Chamada, Literal, ReferenciaFuncao, TipoDe, Vetor } from "../construtos";
+import { DeleguaFuncao, DeleguaModulo, MetodoPrimitiva, ObjetoDeleguaClasse } from "../estruturas";
 import { VariavelInterface } from "../interfaces";
 import { InterpretadorBase } from "./interpretador-base";
+import { inferirTipoVariavel } from "../inferenciador";
+import { ErroEmTempoDeExecucao } from "../excecoes";
+import { FuncaoDeclaracao, Retorna } from "../declaracoes";
 
 import primitivasDicionario from '../bibliotecas/primitivas-dicionario';
 import primitivasNumero from '../bibliotecas/primitivas-numero';
@@ -10,13 +13,20 @@ import primitivasVetor from '../bibliotecas/primitivas-vetor';
 
 import tipoDeDadosPrimitivos from '../tipos-de-dados/primitivos';
 import tipoDeDadosDelegua from '../tipos-de-dados/delegua';
-import { inferirTipoVariavel } from "../inferenciador";
-import { ErroEmTempoDeExecucao } from "../excecoes";
+import { RetornoQuebra } from "../quebras";
 
 /**
  * O interpretador de Delégua.
  */
 export class Interpretador extends InterpretadorBase {
+
+    override visitarDeclaracaoDefinicaoFuncao(declaracao: FuncaoDeclaracao) {
+        const funcao = new DeleguaFuncao(declaracao.simbolo.lexema, declaracao.funcao);
+        // TODO: Depreciar essa abordagem a favor do uso por referências.
+        this.pilhaEscoposExecucao.definirVariavel(declaracao.simbolo.lexema, funcao);
+        this.pilhaEscoposExecucao.registrarReferenciaFuncao(declaracao.id, funcao);
+    }
+
     override async visitarExpressaoAcessoMetodo(expressao: AcessoMetodo): Promise<any> {
         let variavelObjeto: VariavelInterface = await this.avaliar(expressao.objeto);
         
@@ -201,6 +211,34 @@ export class Interpretador extends InterpretadorBase {
         );
     }
 
+    override async visitarExpressaoArgumentoReferenciaFuncao(expressao: ArgumentoReferenciaFuncao): Promise<any> {
+        const deleguaFuncao = this.pilhaEscoposExecucao.obterVariavelPorNome(expressao.simboloFuncao.lexema);
+        return deleguaFuncao;
+    }
+
+    override async visitarExpressaoReferenciaFuncao(expressao: ReferenciaFuncao): Promise<any> {
+        const deleguaFuncao = this.pilhaEscoposExecucao.obterReferenciaFuncao(expressao.idFuncao);
+        return deleguaFuncao;
+    }
+
+    override async visitarExpressaoRetornar(declaracao: Retorna): Promise<RetornoQuebra> {
+        let valor = null;
+        if (declaracao.valor !== null) {
+            valor = await this.avaliar(declaracao.valor);
+        }
+
+        const retornoQuebra = new RetornoQuebra(valor);
+
+        // Se o retorno for uma função anônima, o escopo precisa ser preservado.
+        // Como quebras matam o topo da pilha de escopos, precisamos dizer
+        // para a finalização para copiar as variáveis para o escopo de baixo.
+        if (retornoQuebra.valor.constructor.name === 'DeleguaFuncao') {
+            retornoQuebra.preservarEscopo = true;
+        }
+
+        return retornoQuebra;
+    }
+
     override async visitarExpressaoTipoDe(expressao: TipoDe): Promise<string> {
         let valorTipoDe = expressao.valor;
 
diff --git a/fontes/interpretador/pilha-escopos-execucao.ts b/fontes/interpretador/pilha-escopos-execucao.ts
index ea0e68f5..3985df0e 100644
--- a/fontes/interpretador/pilha-escopos-execucao.ts
+++ b/fontes/interpretador/pilha-escopos-execucao.ts
@@ -264,7 +264,7 @@ export class PilhaEscoposExecucao implements PilhaEscoposExecucaoInterface {
      * Obtém todas as declarações de classe do último escopo.
      * @returns
      */
-    obterTodasDeclaracaoClasse(): any {
+    obterTodasDeclaracoesClasse(): any {
         const retorno = {};
         const ambiente = this.pilha[this.pilha.length - 1].ambiente;
         for (const [nome, corpo] of Object.entries(ambiente.valores)) {
@@ -276,4 +276,23 @@ export class PilhaEscoposExecucao implements PilhaEscoposExecucaoInterface {
 
         return retorno;
     }
+
+    registrarReferenciaFuncao(idFuncao: string, funcao: DeleguaFuncao): void {
+        const ambiente = this.pilha[this.pilha.length - 1].ambiente;
+        ambiente.referencias[idFuncao] = funcao;
+    }
+
+    obterReferenciaFuncao(idFuncao: string): DeleguaFuncao {
+        for (let i = 1; i <= this.pilha.length; i++) {
+            const ambiente = this.pilha[this.pilha.length - i].ambiente;
+            if (ambiente.referencias[idFuncao] !== undefined) {
+                return ambiente.referencias[idFuncao];
+            }
+        }
+
+        throw new ErroEmTempoDeExecucao(
+            new Simbolo('especial', idFuncao, idFuncao, -1, -1),
+            "Referência para função não encontrada: '" + idFuncao + "'."
+        );
+    }
 }
diff --git a/fontes/quebras/index.ts b/fontes/quebras/index.ts
index d4f1ac4e..e7368aa7 100644
--- a/fontes/quebras/index.ts
+++ b/fontes/quebras/index.ts
@@ -1,4 +1,10 @@
-export class Quebra {}
+export class Quebra {
+    preservarEscopo: boolean;
+
+    constructor() {
+        this.preservarEscopo = false;
+    }
+}
 
 export class RetornoQuebra extends Quebra {
     valor: any;
diff --git a/fontes/tradutores/tradutor-assemblyscript.ts b/fontes/tradutores/tradutor-assemblyscript.ts
index 09b16c8c..7eb378df 100644
--- a/fontes/tradutores/tradutor-assemblyscript.ts
+++ b/fontes/tradutores/tradutor-assemblyscript.ts
@@ -2,16 +2,19 @@ import {
     AcessoIndiceVariavel,
     AcessoMetodoOuPropriedade,
     Agrupamento,
+    ArgumentoReferenciaFuncao,
     AtribuicaoPorIndice,
     Atribuir,
     Binario,
     Chamada,
     Comentario,
+    Construto,
     DefinirValor,
     FuncaoConstruto,
     Isto,
     Literal,
     Logico,
+    ReferenciaFuncao,
     TipoDe,
     Unario,
     Variavel,
@@ -123,6 +126,35 @@ export class TradutorAssemblyScript {
         }
     }
 
+    traduzirConstrutoArgumentoReferenciaFuncao(
+        argumentoReferenciaFuncao: ArgumentoReferenciaFuncao,
+        argumentos: Construto[]
+    ): string {
+        const argumentosResolvidos: string[] = [];
+        for (const argumento of argumentos) {
+            const argumentoResolvido = this.dicionarioConstrutos[argumento.constructor.name](argumento);
+            argumentosResolvidos.push(argumentoResolvido);
+        }
+
+        let textoArgumentos = argumentosResolvidos.reduce((atual, proximo) => (atual += proximo + ', '), '');
+        textoArgumentos = textoArgumentos.slice(0, -2);
+
+        return `${argumentoReferenciaFuncao.simboloFuncao.lexema}(${textoArgumentos})`;
+    }
+
+    traduzirConstrutoReferenciaFuncao(referenciaFuncao: ReferenciaFuncao, argumentos: Construto[]): string {
+        const argumentosResolvidos: string[] = [];
+        for (const argumento of argumentos) {
+            const argumentoResolvido = this.dicionarioConstrutos[argumento.constructor.name](argumento);
+            argumentosResolvidos.push(argumentoResolvido);
+        }
+
+        let textoArgumentos = argumentosResolvidos.reduce((atual, proximo) => (atual += proximo + ', '), '');
+        textoArgumentos = textoArgumentos.slice(0, -2);
+
+        return `${referenciaFuncao.simboloFuncao.lexema}(${textoArgumentos})`;
+    }
+
     traduzirDeclaracaoEscreva(declaracaoEscreva: Escreva): string {
         let resultado = 'console.log(';
         for (const argumento of declaracaoEscreva.argumentos) {
@@ -573,7 +605,8 @@ export class TradutorAssemblyScript {
         let resultado = '';
 
         const retorno = `${this.dicionarioConstrutos[chamada.entidadeChamada.constructor.name](
-            chamada.entidadeChamada
+            chamada.entidadeChamada,
+            chamada.argumentos
         )}`;
 
         const instanciaClasse = this.declaracoesDeClasses.some((declaracao) => declaracao?.simbolo?.lexema === retorno);
@@ -651,11 +684,7 @@ export class TradutorAssemblyScript {
         return resultado;
     }
 
-    traduzirConstrutoAgrupamento(agrupamento: Agrupamento): string {
-        return this.dicionarioConstrutos[agrupamento.constructor.name](agrupamento.expressao || agrupamento);
-    }
-
-    trazudirConstrutoAcessoMetodo(acessoMetodo: AcessoMetodoOuPropriedade): string {
+    traduzirConstrutoAcessoMetodo(acessoMetodo: AcessoMetodoOuPropriedade): string {
         if (acessoMetodo.objeto instanceof Variavel) {
             let objetoVariavel = acessoMetodo.objeto as Variavel;
             return `${objetoVariavel.simbolo.lexema}.${this.traduzirFuncoesNativas(acessoMetodo.simbolo.lexema)}`;
@@ -663,7 +692,7 @@ export class TradutorAssemblyScript {
         return `this.${acessoMetodo.simbolo.lexema}`;
     }
 
-    traduzirAcessoIndiceVariavel(acessoIndiceVariavel: AcessoIndiceVariavel): string {
+    traduzirConstrutoAcessoIndiceVariavel(acessoIndiceVariavel: AcessoIndiceVariavel): string {
         let resultado = '';
 
         resultado += this.dicionarioConstrutos[acessoIndiceVariavel.entidadeChamada.constructor.name](
@@ -676,10 +705,15 @@ export class TradutorAssemblyScript {
         return resultado;
     }
 
+    traduzirConstrutoAgrupamento(agrupamento: Agrupamento): string {
+        return this.dicionarioConstrutos[agrupamento.constructor.name](agrupamento.expressao || agrupamento);
+    }
+
     dicionarioConstrutos = {
-        AcessoIndiceVariavel: this.traduzirAcessoIndiceVariavel.bind(this),
-        AcessoMetodoOuPropriedade: this.trazudirConstrutoAcessoMetodo.bind(this),
+        AcessoIndiceVariavel: this.traduzirConstrutoAcessoIndiceVariavel.bind(this),
+        AcessoMetodoOuPropriedade: this.traduzirConstrutoAcessoMetodo.bind(this),
         Agrupamento: this.traduzirConstrutoAgrupamento.bind(this),
+        ArgumentoReferenciaFuncao: this.traduzirConstrutoArgumentoReferenciaFuncao.bind(this),
         AtribuicaoPorIndice: this.traduzirConstrutoAtribuicaoPorIndice.bind(this),
         Atribuir: this.traduzirConstrutoAtribuir.bind(this),
         Binario: this.traduzirConstrutoBinario.bind(this),
@@ -690,6 +724,7 @@ export class TradutorAssemblyScript {
         Isto: () => 'this',
         Literal: this.traduzirConstrutoLiteral.bind(this),
         Logico: this.traduzirConstrutoLogico.bind(this),
+        ReferenciaFuncao: this.traduzirConstrutoReferenciaFuncao.bind(this),
         TipoDe: this.traduzirConstrutoTipoDe.bind(this),
         Unario: this.traduzirConstrutoUnario.bind(this),
         Variavel: this.traduzirConstrutoVariavel.bind(this),
diff --git a/fontes/tradutores/tradutor-javascript.ts b/fontes/tradutores/tradutor-javascript.ts
index b8f96736..4905b275 100644
--- a/fontes/tradutores/tradutor-javascript.ts
+++ b/fontes/tradutores/tradutor-javascript.ts
@@ -4,6 +4,7 @@ import {
     AcessoMetodoOuPropriedade,
     AcessoPropriedade,
     Agrupamento,
+    ArgumentoReferenciaFuncao,
     AtribuicaoPorIndice,
     Atribuir,
     Binario,
@@ -16,6 +17,7 @@ import {
     Isto,
     Literal,
     Logico,
+    ReferenciaFuncao,
     TipoDe,
     Unario,
     Variavel,
@@ -729,7 +731,7 @@ export class TradutorJavaScript implements TradutorInterface<Declaracao> {
         return resultado;
     }
 
-    traduzirAcessoIndiceVariavel(acessoIndiceVariavel: AcessoIndiceVariavel): string {
+    traduzirConstrutoAcessoIndiceVariavel(acessoIndiceVariavel: AcessoIndiceVariavel): string {
         let resultado = '';
 
         resultado += this.dicionarioConstrutos[acessoIndiceVariavel.entidadeChamada.constructor.name](
@@ -742,23 +744,36 @@ export class TradutorJavaScript implements TradutorInterface<Declaracao> {
         return resultado;
     }
 
-    traduzirConstrutoVetor(vetor: Vetor): string {
-        if (!vetor.valores.length) {
-            return '[]';
+    traduzirConstrutoArgumentoReferenciaFuncao(
+        argumentoReferenciaFuncao: ArgumentoReferenciaFuncao,
+        argumentos: Construto[]
+    ): string {
+        const argumentosResolvidos: string[] = [];
+        for (const argumento of argumentos) {
+            const argumentoResolvido = this.dicionarioConstrutos[argumento.constructor.name](argumento);
+            argumentosResolvidos.push(argumentoResolvido);
         }
 
-        let resultado = '[';
+        let textoArgumentos = argumentosResolvidos.reduce((atual, proximo) => atual += proximo + ', ', "");
+        textoArgumentos = textoArgumentos.slice(0, -2);
 
-        for (let valor of vetor.valores) {
-            resultado += `${this.dicionarioConstrutos[valor.constructor.name](valor)}, `;
-        }
-        if (vetor.valores.length > 0) {
-            resultado = resultado.slice(0, -2);
+        return `${argumentoReferenciaFuncao.simboloFuncao.lexema}(${textoArgumentos})`;
+    }
+
+    traduzirConstrutoReferenciaFuncao(
+        referenciaFuncao: ReferenciaFuncao,
+        argumentos: Construto[]
+    ): string {
+        const argumentosResolvidos: string[] = [];
+        for (const argumento of argumentos) {
+            const argumentoResolvido = this.dicionarioConstrutos[argumento.constructor.name](argumento);
+            argumentosResolvidos.push(argumentoResolvido);
         }
 
-        resultado += ']';
+        let textoArgumentos = argumentosResolvidos.reduce((atual, proximo) => atual += proximo + ', ', "");
+        textoArgumentos = textoArgumentos.slice(0, -2);
 
-        return resultado;
+        return `${referenciaFuncao.simboloFuncao.lexema}(${textoArgumentos})`;
     }
 
     traduzirConstrutoTipoDe(tipoDe: TipoDe): string {
@@ -781,9 +796,23 @@ export class TradutorJavaScript implements TradutorInterface<Declaracao> {
         return resultado;
     }
 
-    traduzirDeclaracaoFalhar(falhar: Falhar) {
-        const explicacao = this.dicionarioConstrutos[falhar.explicacao.constructor.name](falhar.explicacao);
-        return `throw ${explicacao}`;
+    traduzirConstrutoVetor(vetor: Vetor): string {
+        if (!vetor.valores.length) {
+            return '[]';
+        }
+
+        let resultado = '[';
+
+        for (let valor of vetor.valores) {
+            resultado += `${this.dicionarioConstrutos[valor.constructor.name](valor)}, `;
+        }
+        if (vetor.valores.length > 0) {
+            resultado = resultado.slice(0, -2);
+        }
+
+        resultado += ']';
+
+        return resultado;
     }
 
     traduzirConstrutoUnario(unario: Unario): string {
@@ -798,12 +827,18 @@ export class TradutorJavaScript implements TradutorInterface<Declaracao> {
         return resultado;
     }
 
+    traduzirDeclaracaoFalhar(falhar: Falhar) {
+        const explicacao = this.dicionarioConstrutos[falhar.explicacao.constructor.name](falhar.explicacao);
+        return `throw ${explicacao}`;
+    }
+
     dicionarioConstrutos = {
-        AcessoIndiceVariavel: this.traduzirAcessoIndiceVariavel.bind(this),
+        AcessoIndiceVariavel: this.traduzirConstrutoAcessoIndiceVariavel.bind(this),
         AcessoMetodo: this.traduzirConstrutoAcessoMetodo.bind(this),
         AcessoMetodoOuPropriedade: this.traduzirConstrutoAcessoMetodoOuPropriedade.bind(this),
         AcessoPropriedade: this.traduzirConstrutoAcessoPropriedade.bind(this),
         Agrupamento: this.traduzirConstrutoAgrupamento.bind(this),
+        ArgumentoReferenciaFuncao: this.traduzirConstrutoArgumentoReferenciaFuncao.bind(this),
         AtribuicaoPorIndice: this.traduzirConstrutoAtribuicaoPorIndice.bind(this),
         Atribuir: this.traduzirConstrutoAtribuir.bind(this),
         Binario: this.traduzirConstrutoBinario.bind(this),
@@ -815,6 +850,7 @@ export class TradutorJavaScript implements TradutorInterface<Declaracao> {
         Isto: () => 'this',
         Literal: this.traduzirConstrutoLiteral.bind(this),
         Logico: this.traduzirConstrutoLogico.bind(this),
+        ReferenciaFuncao: this.traduzirConstrutoReferenciaFuncao.bind(this),
         TipoDe: this.traduzirConstrutoTipoDe.bind(this),
         Unario: this.traduzirConstrutoUnario.bind(this),
         Variavel: this.traduzirConstrutoVariavel.bind(this),
diff --git a/fontes/tradutores/tradutor-python.ts b/fontes/tradutores/tradutor-python.ts
index 91ff6356..ceb78a62 100644
--- a/fontes/tradutores/tradutor-python.ts
+++ b/fontes/tradutores/tradutor-python.ts
@@ -4,6 +4,7 @@ import {
     AcessoMetodoOuPropriedade,
     AcessoPropriedade,
     Agrupamento,
+    ArgumentoReferenciaFuncao,
     AtribuicaoPorIndice,
     Atribuir,
     Binario,
@@ -15,6 +16,7 @@ import {
     Isto,
     Literal,
     Logico,
+    ReferenciaFuncao,
     Unario,
     Variavel,
     Vetor,
@@ -246,6 +248,23 @@ export class TradutorPython implements TradutorInterface<Declaracao> {
         return this.dicionarioConstrutos[agrupamento.constructor.name](agrupamento.expressao || agrupamento);
     }
 
+    traduzirConstrutoArgumentoReferenciaFuncao(
+        argumentoReferenciaFuncao: ArgumentoReferenciaFuncao,
+        argumentos: Construto[]
+    ): string {
+        const argumentosResolvidos: string[] = [];
+        const argumentosValidados = argumentos || [];
+        for (const argumento of argumentosValidados) {
+            const argumentoResolvido = this.dicionarioConstrutos[argumento.constructor.name](argumento);
+            argumentosResolvidos.push(argumentoResolvido);
+        }
+
+        let textoArgumentos = argumentosResolvidos.reduce((atual, proximo) => atual += proximo + ', ', "");
+        textoArgumentos = textoArgumentos.slice(0, -2);
+
+        return `${argumentoReferenciaFuncao.simboloFuncao.lexema}(${textoArgumentos})`;
+    }
+
     traduzirConstrutoAtribuicaoPorIndice(atribuicaoPorIndice: AtribuicaoPorIndice): string {
         const objeto = this.dicionarioConstrutos[atribuicaoPorIndice.objeto.constructor.name](
             atribuicaoPorIndice.objeto
@@ -359,6 +378,23 @@ export class TradutorPython implements TradutorInterface<Declaracao> {
         return `${esquerda} ${operador} ${direita}`;
     }
 
+    traduzirConstrutoReferenciaFuncao(
+        referenciaFuncao: ReferenciaFuncao,
+        argumentos: Construto[]
+    ): string {
+        const argumentosResolvidos: string[] = [];
+        const argumentosValidados = argumentos || [];
+        for (const argumento of argumentosValidados) {
+            const argumentoResolvido = this.dicionarioConstrutos[argumento.constructor.name](argumento);
+            argumentosResolvidos.push(argumentoResolvido);
+        }
+
+        let textoArgumentos = argumentosResolvidos.reduce((atual, proximo) => atual += proximo + ', ', "");
+        textoArgumentos = textoArgumentos.slice(0, -2);
+
+        return `${referenciaFuncao.simboloFuncao.lexema}(${textoArgumentos})`;
+    }
+
     traduzirConstrutoUnario(unario: Unario) {
         const operador = this.traduzirSimboloOperador(unario.operador);
         const operando = this.dicionarioConstrutos[unario.operando.constructor.name](unario.operando);
@@ -704,6 +740,7 @@ export class TradutorPython implements TradutorInterface<Declaracao> {
         AcessoPropriedade: this.traduzirConstrutoAcessoPropriedade.bind(this),
         AcessoIndiceVariavel: this.traduzirConstrutoAcessoIndiceVariavel.bind(this),
         Agrupamento: this.traduzirConstrutoAgrupamento.bind(this),
+        ArgumentoReferenciaFuncao: this.traduzirConstrutoArgumentoReferenciaFuncao.bind(this),
         AtribuicaoPorIndice: this.traduzirConstrutoAtribuicaoPorIndice.bind(this),
         Atribuir: this.traduzirConstrutoAtribuir.bind(this),
         Binario: this.traduzirConstrutoBinario.bind(this),
@@ -713,6 +750,7 @@ export class TradutorPython implements TradutorInterface<Declaracao> {
         Dicionario: this.traduzirConstrutoDicionario.bind(this),
         Literal: this.traduzirConstrutoLiteral.bind(this),
         Logico: this.traduzirConstrutoLogico.bind(this),
+        ReferenciaFuncao: this.traduzirConstrutoReferenciaFuncao.bind(this),
         Unario: this.traduzirConstrutoUnario.bind(this),
         Variavel: this.traduzirConstrutoVariavel.bind(this),
         Vetor: this.traduzirConstrutoVetor.bind(this),


Test patch:
diff --git a/testes/analisador-semantico.test.ts b/testes/analisador-semantico.test.ts
index 67c10cda..ed18df99 100644
--- a/testes/analisador-semantico.test.ts
+++ b/testes/analisador-semantico.test.ts
@@ -252,6 +252,7 @@ describe('Analisador semântico', () => {
                 const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
 
                 expect(retornoAnalisadorSemantico).toBeTruthy();
+                expect(retornoAnalisadorSemantico.diagnosticos).toBeTruthy();
                 expect(retornoAnalisadorSemantico.diagnosticos[0].mensagem).toBe('Função \'f\' espera 2 parâmetros. Atual: 1.');
             });
 
@@ -626,6 +627,7 @@ describe('Analisador semântico', () => {
                     ], -1);
                     const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
                     const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+
                     expect(retornoAnalisadorSemantico).toBeTruthy();
                     expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(0);
                 });
@@ -639,6 +641,7 @@ describe('Analisador semântico', () => {
                     ], -1);
                     const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
                     const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes);
+
                     expect(retornoAnalisadorSemantico).toBeTruthy();
                     expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1);
                     expect(retornoAnalisadorSemantico.diagnosticos.filter(item => item.severidade === DiagnosticoSeveridade.AVISO)).toHaveLength(1);
diff --git a/testes/avaliador-sintatico/avaliador-sintatico.test.ts b/testes/avaliador-sintatico/avaliador-sintatico.test.ts
index acc3f3d2..772e27cb 100644
--- a/testes/avaliador-sintatico/avaliador-sintatico.test.ts
+++ b/testes/avaliador-sintatico/avaliador-sintatico.test.ts
@@ -697,7 +697,7 @@ describe('Avaliador sintático', () => {
                     const construtoFuncao = declaracaoTipada.funcao;
                     expect(construtoFuncao.constructor.name).toBe('FuncaoConstruto');
                     const construtoFuncaoTipado = construtoFuncao as FuncaoConstruto;
-                    expect(construtoFuncaoTipado.tipoRetorno).toBe('inteiro');
+                    expect(construtoFuncaoTipado.tipo).toBe('inteiro');
                     expect(construtoFuncaoTipado.parametros).toHaveLength(2);
                     expect(construtoFuncaoTipado.parametros[0].tipoDado).toBe('inteiro');
                     expect(construtoFuncaoTipado.parametros[1].tipoDado).toBe('inteiro');
@@ -715,6 +715,27 @@ describe('Avaliador sintático', () => {
                     expect(corpoRetornaBinarioEsquerda.tipo).toBe('inteiro');
                     expect(corpoRetornaBinarioDireita.tipo).toBe('inteiro');
                 });
+
+                it('Função que retorna função', () => {
+                    const retornoLexador = lexador.mapear([
+                        "funcao some(a, b) {",
+                        "  retorna a + b",
+                        "}",
+                        "funcao facaCurrying(minhaFuncao) {",
+                        "  retorna funcao(a) {",
+                        "    retorna funcao(b) {",
+                        "      retorna minhaFuncao(a, b)",
+                        "    }",
+                        "  }",
+                        "}",
+                        "var someViaCurryng = facaCurrying(some)",
+                        "escreva(someViaCurryng(1)(2))"
+                    ], -1);
+
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+        
+                    expect(retornoAvaliadorSintatico.erros).toHaveLength(0);
+                });
             })
 
             describe('Declarações de tuplas', () => {
diff --git a/testes/biblioteca-global.test.ts b/testes/biblioteca-global.test.ts
index f92843b0..07b3d008 100644
--- a/testes/biblioteca-global.test.ts
+++ b/testes/biblioteca-global.test.ts
@@ -1,16 +1,16 @@
 import { AvaliadorSintatico } from "../fontes/avaliador-sintatico";
-import { InterpretadorBase } from "../fontes/interpretador";
+import { Interpretador, InterpretadorBase } from "../fontes/interpretador";
 import { Lexador } from "../fontes/lexador";
 
 describe('Biblioteca Global', () => {
     let lexador: Lexador;
     let avaliadorSintatico: AvaliadorSintatico;
-    let interpretador: InterpretadorBase;
+    let interpretador: Interpretador;
 
     beforeEach(() => {
         lexador = new Lexador();
         avaliadorSintatico = new AvaliadorSintatico();
-        interpretador = new InterpretadorBase(process.cwd());
+        interpretador = new Interpretador(process.cwd());
     });
 
     describe('aleatorio()', () => {
diff --git a/testes/formatadores/formatador-delegua.test.ts b/testes/formatadores/formatador-delegua.test.ts
index a2caf1a2..430f6c0d 100644
--- a/testes/formatadores/formatador-delegua.test.ts
+++ b/testes/formatadores/formatador-delegua.test.ts
@@ -199,6 +199,27 @@ describe('Formatadores > Delégua', () => {
         expect(linhasResultado).toHaveLength(4);
     });
 
+    it('Função que retorna função', async () => {
+        const retornoLexador = lexador.mapear([
+            "funcao some(a, b) {",
+            "  retorna a +b",
+            "}",
+            "funcao facaCurrying(minhaFuncao) {",
+            "  retorna funcao(a) {",
+            "retorna funcao(b) {",
+            " retorna minhaFuncao(a, b)",
+            "    } }}",
+            "var someViaCurryng=facaCurrying(some)",
+            "escreva(someViaCurryng(1)(2))"
+        ], -1);
+
+        const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+        const resultado = formatador.formatar(retornoAvaliadorSintatico.declaracoes);
+        const linhasResultado = resultado.split(sistemaOperacional.EOL);
+        
+        expect(linhasResultado).toHaveLength(15);
+    });
+
     it('Importar', () => {
         const resultadoLexador = lexador.mapear(
             [
diff --git a/testes/interpretador/interpretador.test.ts b/testes/interpretador/interpretador.test.ts
index 9c4a47d2..b82b7252 100644
--- a/testes/interpretador/interpretador.test.ts
+++ b/testes/interpretador/interpretador.test.ts
@@ -8,10 +8,16 @@ describe('Interpretador', () => {
         let avaliadorSintatico: AvaliadorSintatico;
         let interpretador: Interpretador;
 
+        let _saidas: string[] = [];
+        const funcaoSaida = (texto: string) => {
+            _saidas.push(texto);
+        }
+
         beforeEach(() => {
+            _saidas = [];
             lexador = new Lexador();
             avaliadorSintatico = new AvaliadorSintatico();
-            interpretador = new Interpretador(process.cwd());
+            interpretador = new Interpretador(process.cwd(), false, funcaoSaida, funcaoSaida);
         });
 
         describe('Cenários de sucesso', () => {
@@ -1608,6 +1614,37 @@ describe('Interpretador', () => {
 
                     expect(retornoInterpretador.erros).toHaveLength(0);
                 });
+
+                it('Função que retorna função', async () => {
+                    const retornoLexador = lexador.mapear([
+                        "funcao some(a, b) {",
+                        "  retorna a + b",
+                        "}",
+                        "funcao facaCurrying(minhaFuncao) {",
+                        "  retorna funcao(a) {",
+                        "    retorna funcao(b) {",
+                        "      retorna minhaFuncao(a, b)",
+                        "    }",
+                        "  }",
+                        "}",
+                        "var someViaCurryng = facaCurrying(some)",
+                        "escreva(someViaCurryng(1)(2))"
+                    ], -1);
+
+                    const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+        
+                    expect(retornoAvaliadorSintatico.erros).toHaveLength(0);
+
+                    let _saidas = "";
+                    interpretador.funcaoDeRetorno = (saida: any) => {
+                        _saidas += saida;
+                    };
+
+                    const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                    expect(retornoInterpretador.erros).toHaveLength(0);
+                    expect(_saidas).toBe('3');
+                });
             });
 
             describe('Entrada e saída', () => {
diff --git a/testes/tradutores/tradutor-python.test.ts b/testes/tradutores/tradutor-python.test.ts
index dbbd46cf..b6c488bf 100644
--- a/testes/tradutores/tradutor-python.test.ts
+++ b/testes/tradutores/tradutor-python.test.ts
@@ -925,7 +925,7 @@ describe('Tradutor Delégua -> Python', () => {
                 '    } senao {',
                 '        filaEstatica[indexFinal] = valorEntrada;',
                 '        escreva("Valor inserido com sucesso: " + texto(filaEstatica[indexFinal]));',
-                '        retorna indexFinal = indexFinal + 1;',
+                '        indexFinal = indexFinal + 1;',
                 '    }',
                 '}',
                 'função desenfileirar() {',
@@ -982,7 +982,7 @@ describe('Tradutor Delégua -> Python', () => {
         expect(resultado).toContain('    else:');
         expect(resultado).toContain('        filaEstatica[indexFinal] = valorEntrada');
         expect(resultado).toContain('        print(\'Valor inserido com sucesso: \' + str(filaEstatica[indexFinal]))');
-        expect(resultado).toContain('        return indexFinal = indexFinal + 1');
+        expect(resultado).toContain('        indexFinal = indexFinal + 1');
         expect(resultado).toContain('def desenfileirar():');
         expect(resultado).toContain('    if indexInicial == indexFinal:');
         expect(resultado).toContain('        print(\'Fila Vazia\')');