コード例 #1
0
ファイル: AlgoVariableHandler.cs プロジェクト: c272/algo-lang
        //When a variable is first defined.
        public override object VisitStat_define([NotNull] algoParser.Stat_defineContext context)
        {
            //Get the name of the identifier/objtext.
            string name = Particles.StitchVariableName(context, context.IDENTIFIER().GetText(), context.particle());

            //Evaluate the expression on the right side of the define.
            AlgoValue value = (AlgoValue)VisitExpr(context.expr());

            //Create the variable at the current scope.
            Scopes.AddVariable(name, value);
            return(null);
        }
コード例 #2
0
ファイル: AlgoLibraryManager.cs プロジェクト: c272/algo-lang
        //When an external or internal plugin library function is loaded.
        public override object VisitStat_loadFuncExt([NotNull] algoParser.Stat_loadFuncExtContext context)
        {
            //Get the value of the function.
            AlgoValue func = Plugins.GetEmulatedFuncValue(context);

            //Check if a variable with the supplied name already exists in scope.
            if (Scopes.VariableExists(context.IDENTIFIER()[0].GetText()))
            {
                Error.Fatal(context, "A variable with the name '" + context.IDENTIFIER()[0].GetText() + "' already exists, can't redefine it.");
                return(null);
            }

            //Add to scope.
            Scopes.AddVariable(context.IDENTIFIER()[0].GetText(), func);
            return(null);
        }
コード例 #3
0
ファイル: AlgoVariableHandler.cs プロジェクト: c272/algo-lang
        //When an enum is first defined.
        public override object VisitStat_enumDef([NotNull] algoParser.Stat_enumDefContext context)
        {
            //Check if the variable already exists at local scope.
            if (Scopes.VariableExistsLowest(context.IDENTIFIER().GetText()))
            {
                Error.Fatal(context, "A variable with the name '" + context.IDENTIFIER().GetText() + "'already exists, cannot create a duplicate.");
                return(null);
            }

            //Create an object for the enum.
            AlgoObject enumObj = new AlgoObject();

            //For each enum member, create a child in the object with an integer value.
            BigInteger enumIndex = 0;

            if (context.abstract_params() != null)
            {
                foreach (var id in context.abstract_params().IDENTIFIER())
                {
                    //Does a member with this name already exist?
                    if (enumObj.ObjectScopes.VariableExists(id.GetText()))
                    {
                        Error.Fatal(context, "An enum member with the name '" + id.GetText() + "' already exists.");
                        return(null);
                    }

                    //Add member.
                    enumObj.ObjectScopes.AddVariable(id.GetText(), new AlgoValue()
                    {
                        Type  = AlgoValueType.Integer,
                        Value = enumIndex
                    });

                    enumIndex++;
                }
            }

            //Create an enum variable with this name.
            Scopes.AddVariable(context.IDENTIFIER().GetText(), new AlgoValue()
            {
                Type  = AlgoValueType.Object,
                Value = enumObj
            });

            return(null);
        }
コード例 #4
0
        //When a function is defined.
        public override object VisitStat_functionDef([NotNull] algoParser.Stat_functionDefContext context)
        {
            //Does a variable with this name already exist?
            if (Scopes.VariableExistsLowest(context.IDENTIFIER().GetText()))
            {
                Error.Fatal(context, "A variable with this name already exists, cannot create function with this name.");
                return(null);
            }

            //Getting parameters.
            List <string> params_ = new List <string>();

            if (context.abstract_params() != null)
            {
                foreach (var param in context.abstract_params().IDENTIFIER())
                {
                    //Check if param already exists.
                    if (params_.Contains(param.GetText()))
                    {
                        Error.Fatal(context, "The parameter with name '" + param.GetText() + "' is already defined in the function.");
                        return(null);
                    }

                    params_.Add(param.GetText());
                }
            }

            //No, it doesn't exist. Define it.
            AlgoFunction func      = new AlgoFunction(context.statement().ToList(), params_, context.IDENTIFIER().GetText());
            AlgoValue    funcValue = new AlgoValue()
            {
                Type  = AlgoValueType.Function,
                Value = func
            };

            //Add to scope.
            Scopes.AddVariable(context.IDENTIFIER().GetText(), funcValue);
            return(null);
        }
コード例 #5
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);
            }
        }
コード例 #6
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);
        }