コード例 #1
0
ファイル: AlgoParticles.cs プロジェクト: c272/algo-lang
        /// <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);
            }
        }
コード例 #2
0
        //An "if" statement.
        public override object VisitStat_if([NotNull] algoParser.Stat_ifContext context)
        {
            //Evaluate the check.
            AlgoValue checkReturned = (AlgoValue)VisitCheck(context.check());
            bool      mainCheck     = AlgoComparators.GetBooleanValue(checkReturned, context);

            //Did it pass? If so, eval the if.
            if (mainCheck)
            {
                //Create scope.
                Scopes.AddScope();

                //Evaluate the main statement body.
                foreach (var statement in context.statement())
                {
                    AlgoValue returned = (AlgoValue)VisitStatement(statement);
                    if (returned != null)
                    {
                        Scopes.RemoveScope();
                        return(returned);
                    }
                }

                //Delete scope.
                Scopes.RemoveScope();

                //Return.
                return(null);
            }

            //Maincheck failed, complete all the "else if" checks if they exist.
            if (context.stat_elif().Length != 0)
            {
                foreach (var elseifblock in context.stat_elif())
                {
                    //Does the check pass?
                    var       checkContext      = elseifblock.check();
                    AlgoValue elifCheckReturned = (AlgoValue)VisitCheck(checkContext);
                    bool      elseifCheck       = AlgoComparators.GetBooleanValue(elifCheckReturned, context);

                    if (elseifCheck)
                    {
                        //Create scope.
                        Scopes.AddScope();

                        //Evaluate statements.
                        foreach (var statement in elseifblock.statement())
                        {
                            AlgoValue returned = (AlgoValue)VisitStatement(statement);
                            if (returned != null)
                            {
                                Scopes.RemoveScope();
                                return(returned);
                            }
                        }

                        //Remove scope.
                        Scopes.RemoveScope();

                        //Return.
                        return(null);
                    }
                }
            }

            //Is there an else?
            if (context.stat_else() != null)
            {
                //Create a scope.
                Scopes.AddScope();

                //Evaluate statements.
                foreach (var statement in context.stat_else().statement())
                {
                    AlgoValue returned = (AlgoValue)VisitStatement(statement);
                    if (returned != null)
                    {
                        Scopes.RemoveScope();
                        return(returned);
                    }
                }

                //Deleting scope.
                Scopes.RemoveScope();
            }

            //Returning.
            return(null);
        }
コード例 #3
0
        //When a try/catch block is executed.
        public override object VisitStat_try_catch([NotNull] algoParser.Stat_try_catchContext context)
        {
            //Turn on execution catch mode.
            AlgoRuntimeInformation.CatchExceptions = true;

            //Loop over the statements, execute all.
            bool   foundError   = false;
            string errorMessage = "";

            Scopes.AddScope();
            foreach (var statement in context.block()[0].statement())
            {
                //Execute statement.
                AlgoValue returned = null;

                try
                {
                    returned = (AlgoValue)VisitStatement(statement);
                }
                catch (Exception e)
                {
                    //C# error somewhere up the heirarchy, 90% means an error has been thrown.
                    foundError   = true;
                    errorMessage = "Internal Language Error: " + e.Message;
                }

                //Check if an error has been found.
                if (AlgoRuntimeInformation.ExceptionCaught())
                {
                    //Yep, break out to the catch block.
                    foundError   = true;
                    errorMessage = AlgoRuntimeInformation.GetExceptionMessage();
                    AlgoRuntimeInformation.CatchExceptions = false;
                    break;
                }

                //If something was actually returned, return it up.
                if (returned != null)
                {
                    AlgoRuntimeInformation.CatchExceptions = false;
                    Scopes.RemoveScope();
                    return(returned);
                }
            }
            Scopes.RemoveScope();

            //Turn off error catching.
            AlgoRuntimeInformation.CatchExceptions = false;

            //Done executing try statements, did an error come back?
            if (!foundError)
            {
                return(null);
            }

            //Yep, get the identifier to use for the error message, check it doesn't exist.
            if (Scopes.VariableExists(context.IDENTIFIER().GetText()))
            {
                Error.Fatal(context, "A variable already exists named '" + context.IDENTIFIER().GetText() + "', cannot use for catch parameter.");
                return(null);
            }

            //Create it, assign it the caught value.
            Scopes.AddScope();
            Scopes.AddVariable(context.IDENTIFIER().GetText(), new AlgoValue()
            {
                Type  = AlgoValueType.String,
                Value = errorMessage
            }, context);

            //Execute what's in the catch scope.
            foreach (var statement in context.block()[1].statement())
            {
                AlgoValue returned = (AlgoValue)VisitStatement(statement);
                if (returned != null)
                {
                    Scopes.RemoveScope();
                    return(returned);
                }
            }

            //Finished!
            return(null);
        }