/// <summary> /// Ejecuta una función a partir de una expresión /// </summary> internal async Task <VariableModel> ExecuteFunctionAsync(ExpressionFunction expression, CancellationToken cancellationToken) { VariableModel result = null; // Busca la función y la ejecuta if (string.IsNullOrWhiteSpace(expression.Function)) { AddError("Cant find the name funcion for call"); } else { BaseFunctionModel function = Context.Actual.FunctionsTable.GetIfExists(expression.Function); if (function == null) { AddError($"Cant find the function to call: {expression.Function}"); } else { result = await ExecuteFunctionAsync(function, expression.Arguments, true, cancellationToken); } } // Devuelve el resultado de la función return(result); }
/// <summary> /// Ejecuta una llamada a una función /// </summary> private async Task ExecuteFunctionCallAsync(SentenceCallFunction sentence, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(sentence.Function)) { AddError("Cant find the name function for call"); } else { BaseFunctionModel function = Context.Actual.FunctionsTable.GetIfExists(sentence.Function); if (function == null) { AddError($"Cant find the function to call: {sentence.Function}"); } else { await ExecuteFunctionAsync(function, sentence.Arguments, false, cancellationToken); } } }
/// <summary> /// Ejecuta una función /// </summary> private async Task <VariableModel> ExecuteFunctionAsync(BaseFunctionModel function, System.Collections.Generic.List <ExpressionsCollection> arguments, bool waitReturn, CancellationToken cancellationToken) { VariableModel result = null; // Crea un nuevo contexto Context.Add(); // Añade los argumentos al contexto foreach (SymbolModel argument in function.Arguments) { if (!Stopped) { int index = function.Arguments.IndexOf(argument); // Si el argumento corresponde a un parámetro, se añade al contexto esa variable con el valor if (arguments.Count > index) { VariableModel argumentResult = await ExecuteExpressionAsync(arguments[index], cancellationToken); if (argumentResult != null) { Context.Actual.VariablesTable.Add(argument.Name, ConvertSymbolType(argument.Type), argumentResult.Value); } } else { AddError($"Cant find any call value for argument {argument.Name}"); } } } // Si no ha habido errores al calcular los argumentos, ejecuta realmente las sentencias de la función (o llama a la función implícita) if (!Stopped) { // Ejecuta las sentencias de la función switch (function) { case ImplicitFunctionModel implicitFunction: result = await ExecuteAsync(implicitFunction, cancellationToken); break; case UserDefinedFunctionModel userDefinedFunction: // Añade el nombre que debe tener el valor de retorno Context.Actual.ScopeFuntionResultVariable = "Return_" + Guid.NewGuid().ToString(); // Ejecuta la sentencia await ExecuteAsync(userDefinedFunction.Sentences, cancellationToken); // Si es una función, no una subrutina, obtiene el resultado if (waitReturn) { // y obtiene el resultado result = Context.Actual.VariablesTable.Get(Context.Actual.ScopeFuntionResultVariable); // Si no se ha obtenido ningún resultado (faltaba la sentencia return), añade un error if (result == null) { AddError($"Cant find result for funcion {function.Definition.Name}. Check if define return sentence"); } } break; } } // Elimina el contexto Context.Pop(); // Devuelve el resultado de la función return(result); }
public FunctionModel(BaseFunctionModel model) { Model = model; }