コード例 #1
0
        //Remove an item from a given list.
        public override object VisitStat_list_remove([NotNull] algoParser.Stat_list_removeContext context)
        {
            //Get the value that needs to be removed.
            AlgoValue toRemove = (AlgoValue)VisitExpr(context.expr());

            //Get the variable.
            var listVar = Particles.ParseParticleBlock(this, context, context.IDENTIFIER(), context.particle());

            if (listVar == null)
            {
                Error.Fatal(context, "No variable was returned to remove an item from, so can't remove an item from it.");
                return(null);
            }

            //Variable exists, so get the list value from it.
            if (listVar.Type != AlgoValueType.List)
            {
                Error.Fatal(context, "Variable given is not list, so can't remove an item from it.");
                return(null);
            }

            //Get the value of the list.
            List <AlgoValue> toSet = (List <AlgoValue>)listVar.Value;

            if (context.FROM_SYM() != null)
            {
                //Remove a given value from the list.
                //Check if the list contains the value.
                if (!toSet.Any(x => x.Value.Equals(toRemove.Value)))
                {
                    Error.Fatal(context, "The list selected does not contain an item with value given to remove.");
                    return(null);
                }

                //Remove the value.
                int index = toSet.FindIndex(x => x._Equals(toRemove));
                toSet.RemoveAt(index);
            }
            else
            {
                //Is the index valid?
                if (toRemove.Type != AlgoValueType.Integer)
                {
                    Error.Fatal(context, "The index given to remove at is not an integer.");
                    return(null);
                }

                if ((BigInteger)toRemove.Value < 0 || (BigInteger)toRemove.Value > toSet.Count)
                {
                    Error.Fatal(context, "Index to remove out of range for the given list.");
                }

                //Yes, remove there.
                toSet.RemoveAt(int.Parse(((BigInteger)toRemove.Value).ToString()));
            }

            return(null);
        }
コード例 #2
0
ファイル: AlgoVariableHandler.cs プロジェクト: c272/algo-lang
        //When a variable is modified using a postfix operator.
        public override object VisitStat_setvar_postfix([NotNull] algoParser.Stat_setvar_postfixContext context)
        {
            //Get variable name.
            AlgoValue oldValue = Particles.ParseParticleBlock(this, context, context.IDENTIFIER(), context.particle());

            if (oldValue == null)
            {
                Error.Fatal(context, "No value returned to modify with operator.");
                return(null);
            }

            //Switch on the operator type.
            int toAdd = 0;

            if (context.postfix_op().ADD_PFOP() != null)
            {
                //Increment.
                toAdd = 1;
            }
            else
            {
                //Decrement.
                toAdd = -1;
            }

            //Apply the operator.
            AlgoValue newValue = null;

            switch (oldValue.Type)
            {
            case AlgoValueType.Integer:
            case AlgoValueType.Float:
            case AlgoValueType.Rational:
                newValue = AlgoOperators.Add(context, oldValue, new AlgoValue()
                {
                    Type  = AlgoValueType.Integer,
                    Value = new BigInteger(toAdd)
                });

                break;

            default:
                Error.Fatal(context, "Cannot increment a variable of type " + oldValue.Type.ToString() + ".");
                return(null);
            }

            //Set the variable value.
            oldValue.Value = newValue.Value;
            oldValue.Type  = newValue.Type;
            return(null);
        }
コード例 #3
0
ファイル: AlgoVariableHandler.cs プロジェクト: c272/algo-lang
        //When a variable value is changed by a self modifying operator.
        public override object VisitStat_setvar_op([NotNull] algoParser.Stat_setvar_opContext context)
        {
            //Get variable reference.
            AlgoValue oldValue = Particles.ParseParticleBlock(this, context, context.IDENTIFIER(), context.particle());

            if (oldValue == null)
            {
                Error.Fatal(context, "No value returned to modify with operator.");
                return(null);
            }

            //Does, evaluate the expression to set the value.
            AlgoValue value = (AlgoValue)VisitExpr(context.expr());

            //Switching on selfmod value.
            AlgoValue newValue;

            if (context.selfmod_op().ADDFROM_OP() != null)
            {
                //Attempt to add.
                newValue = AlgoOperators.Add(context, oldValue, value);
            }
            else if (context.selfmod_op().DIVFROM_OP() != null)
            {
                //Attempt to divide.
                newValue = AlgoOperators.Div(context, oldValue, value);
            }
            else if (context.selfmod_op().MULFROM_OP() != null)
            {
                //Attempt to multiply.
                newValue = AlgoOperators.Mul(context, oldValue, value);
            }
            else if (context.selfmod_op().TAKEFROM_OP() != null)
            {
                //Attempt to subtract.
                newValue = AlgoOperators.Sub(context, oldValue, value);
            }
            else
            {
                //Invalid operator type, oopsie! Implemented in parser but not here.
                Error.Fatal(context, "Invalid operator given for self modifying variable, implemented in parser but not in interpreter.");
                return(null);
            }

            //Set the value of the variable.
            oldValue.Value = newValue.Value;
            oldValue.Type  = newValue.Type;
            return(null);
        }
コード例 #4
0
ファイル: AlgoVariableHandler.cs プロジェクト: c272/algo-lang
        //When a variable's value is changed.
        public override object VisitStat_setvar([NotNull] algoParser.Stat_setvarContext context)
        {
            //Get the variable/object reference.
            AlgoValue varToSet = Particles.ParseParticleBlock(this, context, context.IDENTIFIER(), context.particle());

            if (varToSet == null)
            {
                Error.Fatal(context, "No value returned to set.");
                return(null);
            }

            //Does, evaluate the expression to set the value.
            AlgoValue value = (AlgoValue)VisitExpr(context.expr());

            //Check if there's a rounding expression.
            if (context.rounding_expr() != null)
            {
                //Evaluate rounding number expression.
                AlgoValue roundingNum = (AlgoValue)VisitExpr(context.rounding_expr().expr());
                if (roundingNum.Type != AlgoValueType.Integer)
                {
                    Error.Warning(context, "Rounding expression did not return an integer to round by, so rounding was ignored.");
                }
                else if ((BigInteger)roundingNum.Value > int.MaxValue)
                {
                    Error.Warning(context, "Rounding number too large, so rounding was ignored.");
                }
                else
                {
                    //Getting rounding integer.
                    int roundingInt = int.Parse(((BigInteger)roundingNum.Value).ToString());

                    //Rounding the value, setting.
                    Scopes.SetVariable(context.IDENTIFIER().GetText(), AlgoOperators.Round(context, value, roundingInt));

                    return(null);
                }
            }

            //Set variable.
            varToSet.Value = value.Value;
            varToSet.Type  = value.Type;

            return(null);
        }
コード例 #5
0
        //When a single value is visited in Algo.
        public override object VisitValue([NotNull] algoParser.ValueContext context)
        {
            //Check what type the value is.
            if (context.INTEGER() != null)
            {
                //INTEGER
                return(new AlgoValue()
                {
                    Type = AlgoValueType.Integer,
                    Value = BigInteger.Parse(context.INTEGER().GetText()),
                });
            }
            else if (context.FLOAT() != null)
            {
                //FLOAT
                return(new AlgoValue()
                {
                    Type = AlgoValueType.Float,
                    Value = BigFloat.Parse(context.FLOAT().GetText()),
                });
            }
            else if (context.STRING() != null)
            {
                //STRING
                return(new AlgoValue()
                {
                    Type = AlgoValueType.String,
                    Value = context.STRING().GetText().Substring(1, context.STRING().GetText().Length - 2)
                            //text escape codes
                            .Replace("\\n", "\n")
                            .Replace("\\t", "\t")
                            .Replace("\\r", "\r")
                            .Replace("\\q", "\"")
                });
            }
            else if (context.RATIONAL() != null)
            {
                //RATIONAL
                //Get the two integer halves from the rational.
                string[] halves      = context.RATIONAL().GetText().Split('/');
                string   numerator   = halves[0];
                string   denominator = halves[1];

                return(new AlgoValue()
                {
                    Type = AlgoValueType.Rational,
                    Value = new BigRational(BigInteger.Zero, new Fraction(BigInteger.Parse(numerator), BigInteger.Parse(denominator))),
                });
            }
            else if (context.BOOLEAN() != null)
            {
                //BOOLEAN
                return(new AlgoValue()
                {
                    Type = AlgoValueType.Boolean,
                    Value = (context.BOOLEAN().GetText() == "true"),
                });
            }
            else if (context.HEX() != null)
            {
                //BYTES
                return(new AlgoValue()
                {
                    Type = AlgoValueType.Bytes,
                    Value = context.HEX().GetText().ToByteArray()
                });
            }
            else if (context.NULL() != null)
            {
                //NULL VALUE
                return(new AlgoValue()
                {
                    Type = AlgoValueType.Null,
                    Value = null,
                });
            }
            else if (context.IDENTIFIER() != null)
            {
                //VARIABLE/OBJECT
                return(Particles.ParseParticleBlock(this, context, context.IDENTIFIER(), context.particle()));
            }
            else if (context.stat_functionCall() != null)
            {
                //FUNCTION CALL
                AlgoValue value = (AlgoValue)VisitStat_functionCall(context.stat_functionCall());
                if (value != null)
                {
                    return(value);
                }
                else
                {
                    //Return a null value.
                    return(new AlgoValue()
                    {
                        Type = AlgoValueType.Null,
                        Value = null,
                    });
                }
            }
            else if (context.array() != null)
            {
                //LIST.

                //Evaluate all list items as expressions.
                List <AlgoValue> list = new List <AlgoValue>();
                foreach (var item in context.array().value())
                {
                    list.Add((AlgoValue)VisitValue(item));
                }

                //Return as a single value.
                return(new AlgoValue()
                {
                    Type = AlgoValueType.List,
                    Value = list
                });
            }
            else if (context.@object() != null)
            {
                //OBJECT DEFINITION

                //Create a new object.
                AlgoObject toReturn = new AlgoObject();

                //Anything to enumerate?
                if (context.@object().obj_child_definitions() == null)
                {
                    //Nope.
                    return(new AlgoValue()
                    {
                        Type = AlgoValueType.Object,
                        Value = toReturn
                    });
                }

                //Enumerate through all the define statements and evaluate their values.
                foreach (var value in context.@object().obj_child_definitions().obj_vardefine())
                {
                    //Check if the variable already exists.
                    if (toReturn.ObjectScopes.VariableExists(value.IDENTIFIER().GetText()))
                    {
                        Error.Fatal(context, "The variable with name '" + value.IDENTIFIER().GetText() + "' is defined twice or more in an object.");
                        return(null);
                    }

                    //Evaluate the value on the right.
                    AlgoValue evaluated = (AlgoValue)VisitExpr(value.expr());

                    //Add the variable to scope.
                    toReturn.ObjectScopes.AddVariable(value.IDENTIFIER().GetText(), evaluated);
                }

                //Enumerate through all functions and define them.
                foreach (var value in context.@object().obj_child_definitions().obj_funcdefine())
                {
                    //Check if the variable already exists.
                    if (toReturn.ObjectScopes.VariableExists(value.IDENTIFIER().GetText()))
                    {
                        Error.Fatal(context, "The variable with name '" + value.IDENTIFIER().GetText() + "' is defined twice or more in an object.");
                        return(null);
                    }

                    //Create a list of parameters.
                    List <string> params_ = new List <string>();
                    if (value.abstract_params() != null)
                    {
                        foreach (var param in value.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());
                        }
                    }

                    //Create a function, push.
                    AlgoFunction func      = new AlgoFunction(value.statement().ToList(), params_, value.IDENTIFIER().GetText());
                    AlgoValue    funcValue = new AlgoValue()
                    {
                        Type  = AlgoValueType.Function,
                        Value = func,
                    };

                    toReturn.ObjectScopes.AddVariable(value.IDENTIFIER().GetText(), funcValue);
                }

                //Enumerate all external functions defined.
                foreach (var ext in context.@object().obj_child_definitions().obj_externdefine())
                {
                    //Get the value of the function.
                    var       loadFuncStat = ext.stat_loadFuncExt();
                    AlgoValue func         = Plugins.GetEmulatedFuncValue(loadFuncStat);

                    //Check if a variable with this name already exists.
                    if (toReturn.ObjectScopes.VariableExists(loadFuncStat.IDENTIFIER()[0].GetText()))
                    {
                        Error.Fatal(context, "A variable with the name '" + loadFuncStat.IDENTIFIER()[0].GetText() + "' already exists in this object. Cannot duplicate.");
                        return(null);
                    }

                    //Add that function to the return object.
                    toReturn.ObjectScopes.AddVariable(loadFuncStat.IDENTIFIER()[0].GetText(), func);
                }

                //Return the object.
                return(new AlgoValue()
                {
                    Type = AlgoValueType.Object,
                    Value = toReturn
                });
            }
            else
            {
                //No proper detected value type.
                Error.Fatal(context, "Unknown or invalid type given for value.");
                return(new AlgoValue()
                {
                    Type = AlgoValueType.Null,
                    Value = null
                });
            }
        }
コード例 #6
0
        //Adding an item to a list.
        public override object VisitStat_list_add([NotNull] algoParser.Stat_list_addContext context)
        {
            //Evaluate the value to be added to the list.
            AlgoValue toAdd = (AlgoValue)VisitExpr(context.expr()[0]);

            //Get the list variable from the identifier and particle.
            AlgoValue listVar = Particles.ParseParticleBlock(this, context, context.IDENTIFIER(), context.particle());

            if (listVar == null)
            {
                Error.Fatal(context, "No list value returned to add to from particle block.");
                return(null);
            }

            //Check the type is actually a list.
            if (listVar.Type != AlgoValueType.List)
            {
                Error.Fatal(context, "Variable given is not list, so can't remove an item from it.");
                return(null);
            }

            //Add a value to the list, either at a specific index or to the end.
            List <AlgoValue> toReturn = (List <AlgoValue>)listVar.Value;

            if (context.AT_SYM() != null)
            {
                //Evaluate the index.
                AlgoValue index = (AlgoValue)VisitExpr(context.expr()[1]);

                //Is it an integer?
                if (index.Type == AlgoValueType.Integer)
                {
                    Error.Fatal(context, "The index supplied to insert at was not an integer.");
                    return(null);
                }

                //Is it 0 or above?
                if ((BigInteger)index.Value < 0)
                {
                    Error.Fatal(context, "The index supplied is below zero, out of range.");
                    return(null);
                }

                //Is the index greater than the length of the list?
                if ((BigInteger)index.Value > ((List <AlgoValue>)listVar.Value).Count || (BigInteger)index.Value > int.MaxValue)
                {
                    Error.Fatal(context, "The index supplied was out of range (too large).");
                    return(null);
                }

                //Insert.
                toReturn.Insert(int.Parse(((BigInteger)index.Value).ToString()), toAdd);
            }
            else
            {
                toReturn.Add(toAdd);
            }

            //Set the variable via. reference (TEST ME!).
            listVar.Value = toReturn;
            return(null);
        }
コード例 #7
0
        //When a function is called.
        public override object VisitStat_functionCall([NotNull] algoParser.Stat_functionCallContext context)
        {
            //If there are particles, get the last value.
            AlgoValue currentVal = null; bool isLibraryTopLevelCall = false;

            if (context.IDENTIFIER() != null)
            {
                //Is the identifier a library and has no particles?
                if (!Scopes.VariableExists(context.IDENTIFIER().GetText()) &&
                    Scopes.LibraryExists(context.IDENTIFIER().GetText()) &&
                    (context.particle() == null || context.particle().Length == 0))
                {
                    //Library top level call, so don't evaluate like normal particles.
                    isLibraryTopLevelCall = true;

                    //Just get the very last function like a normal variable, but from the library.
                    string libName = context.IDENTIFIER().GetText();
                    string name    = context.functionCall_particle().IDENTIFIER().GetText();
                    var    lib     = Scopes.GetLibrary(libName);

                    if (!lib.VariableExists(name))
                    {
                        Error.Fatal(context, "No variable named '" + name + "' exists in library '" + libName + "'.");
                        return(null);
                    }

                    currentVal = lib.GetVariable(name);
                }
                else
                {
                    //Not a library top level call, so execute like a normal particle block.
                    currentVal = Particles.ParseParticleBlock(this, context, context.IDENTIFIER(), context.particle());
                }
            }
            else
            {
                //No particles, just grab the value as an identifier.
                string name = context.functionCall_particle().IDENTIFIER().GetText();
                if (!Scopes.VariableExists(name))
                {
                    Error.Fatal(context, "No function exists with name '" + name + "'.");
                    return(null);
                }

                currentVal = Scopes.GetVariable(name);
            }

            //Attempt to execute the final function on the result.
            if (context.IDENTIFIER() == null || isLibraryTopLevelCall)
            {
                //Visit and execute THIS value, not a child value (this was a straight normal call).
                Particles.SetParticleInput(currentVal);
                return(VisitFunctionCall_particle(context.functionCall_particle()));
            }
            else
            {
                //There were particles, visit and execute CHILD value.
                if (currentVal.Type != AlgoValueType.Object)
                {
                    Error.Fatal(context, "Cannot call a child function on a value with no children (given value was not an object).");
                    return(null);
                }

                //Get the child, see if it's a function.
                AlgoObject thisObj   = currentVal.Value as AlgoObject;
                string     funcName  = context.IDENTIFIER().GetText();
                AlgoValue  childFunc = thisObj.ObjectScopes.GetVariable(funcName);
                if (childFunc == null || (childFunc.Type != AlgoValueType.Function && childFunc.Type != AlgoValueType.EmulatedFunction))
                {
                    Error.Fatal(context, "No child function exists with name '" + funcName + "'.");
                    return(null);
                }

                //Set the particle result as the function value, call the function call particle.
                Particles.SetParticleInput(childFunc);
                return(VisitFunctionCall_particle(context.functionCall_particle()));
            }
        }