/// <summary> /// Evaluates a single function call particle, and returns the result as a value (NOT using particle manager). /// </summary> public override object VisitFunctionCall_particle([NotNull] algoParser.FunctionCall_particleContext context) { //Set up an old scope. AlgoScopeCollection oldScope = null; //Get the previous particle output. var current = Particles.GetParticleResult(); //Right length of parameters? var paramCtx = context.literal_params(); int givenNumParams = 0; if (paramCtx != null) { givenNumParams = paramCtx.expr().Length; } else if (current.Type == AlgoValueType.EmulatedFunction) { var func = ((AlgoPluginFunction)current.Value); int paramNum = func.ParameterCount; if (givenNumParams != paramNum) { Error.Fatal(context, "Invalid number of parameters for function '" + func.Name + "' (Expected " + func.ParameterCount + ", got " + givenNumParams + ")."); return(null); } } else if (current.Type == AlgoValueType.Function) { var func = ((AlgoFunction)current.Value); int paramNum = func.Parameters.Count; if (givenNumParams != paramNum) { Error.Fatal(context, "Invalid number of parameters for function '" + func.Name + "' (Expected " + func.Parameters.Count + ", got " + givenNumParams + ")."); return(null); } } //Evaluate all the parameters, in the paramScope if necessary. if (Particles.funcArgumentScopes != null) { oldScope = Scopes; Scopes = Particles.funcArgumentScopes; } List <AlgoValue> params_ = new List <AlgoValue>(); if (paramCtx != null) { foreach (var paramToEval in paramCtx.expr()) { params_.Add((AlgoValue)VisitExpr(paramToEval)); } } //Switch back scopes. if (Particles.funcArgumentScopes != null) { Scopes = oldScope; } //Depending on the type of function, execute. if (current.Type == AlgoValueType.Function) { //STANDARD FUNCTION var func = (AlgoFunction)current.Value; //Create a new scope, add the parameters to it. Scopes.AddScope(); for (int i = 0; i < params_.Count; i++) { Scopes.AddVariable(func.Parameters[i], params_[i], context); } //Running the function's body. foreach (var statement in func.Body) { AlgoValue returned = (AlgoValue)VisitStatement(statement); if (returned != null) { //Normal function, remove scope and return. Scopes.RemoveScope(); return(returned); } } //Remove the scope. Scopes.RemoveScope(); //Return nothing, no result. return(null); } else if (current.Type == AlgoValueType.EmulatedFunction) { //EMULATED FUNCTION var func = (AlgoPluginFunction)current.Value; //Attempt to evaluate, and return result. AlgoValue returned = null; try { returned = func.Function(context, params_.ToArray()); } catch (Exception e) { Error.Fatal(context, "External function returned an error, " + e.Message); return(null); } return(returned); } else { //Unsupported uncaught function type. Error.Internal("Unsupported uncaught function type detected (" + current.Type.ToString() + "), cannot execute."); return(null); } }
/// <summary> /// Visit a parse tree produced by <see cref="algoParser.functionCall_particle"/>. /// <para> /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/> /// on <paramref name="context"/>. /// </para> /// </summary> /// <param name="context">The parse tree.</param> /// <return>The visitor result.</return> public virtual Result VisitFunctionCall_particle([NotNull] algoParser.FunctionCall_particleContext context) { return(VisitChildren(context)); }
/// <summary> /// Exit a parse tree produced by <see cref="algoParser.functionCall_particle"/>. /// <para>The default implementation does nothing.</para> /// </summary> /// <param name="context">The parse tree.</param> public virtual void ExitFunctionCall_particle([NotNull] algoParser.FunctionCall_particleContext context) { }