コード例 #1
0
        //When an expression is parsed in Algo.
        public override object VisitExpr([NotNull] algoParser.ExprContext context)
        {
            //Is it an addition?
            if (context.ADD_OP() != null)
            {
                //Yes. Evaluate the left hand expression.
                AlgoValue left = (AlgoValue)VisitExpr(context.expr());

                //Evaluate the right hand term.
                AlgoValue right = (AlgoValue)VisitTerm(context.term());

                //Perform an add operation, based on type.
                return(AlgoOperators.Add(context, left, right));
            }
            else if (context.TAKE_OP() != null)
            {
                //Take operation.
                //Evaluate the left hand expression.
                AlgoValue left = (AlgoValue)VisitExpr(context.expr());

                //Evaluate the right hand term.
                AlgoValue right = (AlgoValue)VisitTerm(context.term());

                //Perform a take operation, based on type.
                return(AlgoOperators.Sub(context, left, right));
            }
            else
            {
                //No, just a term, evaluate.
                return((AlgoValue)VisitTerm(context.term()));
            }
        }
コード例 #2
0
ファイル: AlgoScopes.cs プロジェクト: c272/algo-lang
        //Checks whether a variable exists.
        public bool VariableExists(string varname)
        {
            if (varname.Contains('.'))
            {
                //Validate it by fake value grabbing.
                List <string> parts      = varname.Split('.').ToList();
                AlgoValue     partParent = GetVariable(parts[0]);
                if (partParent == null || (partParent.Type != AlgoValueType.Object && parts.Count > 1))
                {
                    return(false);
                }

                //If the variable is known to exist and no points, this is just a sanity check to make sure nothing slips through.
                if (parts.Count == 1)
                {
                    return(true);
                }

                //Iterate through children recursively to check they all exist.
                AlgoObject currentObj = (AlgoObject)partParent.Value;
                parts.RemoveAt(0);
                string childString = string.Join(".", parts.ToArray());

                //Recursive return.
                return(currentObj.ObjectScopes.VariableExists(childString));
            }
            return(GetVariable(varname) != null);
        }
コード例 #3
0
        //Converts an Algo Rational to an Algo Float.
        public static BigFloat RationalToFloat(AlgoValue rational)
        {
            BigInteger numerator   = ((BigRational)rational.Value).FractionalPart.Numerator;
            BigInteger denominator = ((BigRational)rational.Value).FractionalPart.Denominator;

            return(BigFloat.Divide(new BigFloat(numerator), new BigFloat(denominator)));
        }
コード例 #4
0
        //Get boolean value for the given AlgoValue.
        public static bool GetBooleanValue(AlgoValue value, ParserRuleContext context)
        {
            switch (value.Type)
            {
            case AlgoValueType.Boolean:
                return((bool)value.Value);

            case AlgoValueType.Integer:
                if ((BigInteger)value.Value == 1)
                {
                    return(true);
                }
                else if ((BigInteger)value.Value == 0)
                {
                    return(false);
                }
                else
                {
                    Error.Fatal(context, "Cannot implicitly cast an integer that is not one or zero to boolean.");
                    return(false);
                }

            default:
                Error.Fatal(context, "Cannot implicitly cast type " + value.Type.ToString() + " to a boolean.");
                return(false);
            }
        }
コード例 #5
0
ファイル: AlgoScopes.cs プロジェクト: c272/algo-lang
        //Returns the value of a referenced object within an object string.
        private AlgoValue GetValueFromObjectString(string objString)
        {
            //Splitting the string by "." to get individual variable parts.
            string[] objParts = objString.Split('.');
            if (objParts.Length == 1)
            {
                if (!VariableExists(objString))
                {
                    return(null);
                }

                return(GetVariable(objString));
            }

            //Loop and get value.
            if (!VariableExists(objParts[0]))
            {
                return(null);
            }

            //Get the first parent object.
            AlgoValue currentObjValue = GetVariable(objParts[0]);

            if (currentObjValue.Type != AlgoValueType.Object)
            {
                return(null);
            }

            //Getting the deepest scope.
            AlgoObject currentObj = (AlgoObject)currentObjValue.Value;

            for (int i = 1; i < objParts.Length - 1; i++)
            {
                //Attempt to get the child.
                if (!currentObj.ObjectScopes.VariableExists(objParts[i]))
                {
                    return(null);
                }
                currentObjValue = currentObj.ObjectScopes.GetVariable(objParts[i]);

                //Check if it's an object.
                if (currentObjValue.Type != AlgoValueType.Object)
                {
                    return(null);
                }

                //Set current object.
                currentObj = (AlgoObject)currentObjValue.Value;
            }

            //Getting the variable referenced at the deepest scope.
            if (!currentObj.ObjectScopes.VariableExists(objParts[objParts.Length - 1]))
            {
                return(null);
            }

            //Returning it.
            return(currentObj.ObjectScopes.GetVariable(objParts[objParts.Length - 1]));
        }
コード例 #6
0
        //Less than.
        public static bool LessThan(ParserRuleContext context, AlgoValue left, AlgoValue right, bool equalTo)
        {
            //Get the values for both left and right in a specific format.
            //(Statements must be in order of casting heirarchy, top down).
            if (left.Type == AlgoValueType.Float || right.Type == AlgoValueType.Float)
            {
                //Convert both to float.
                AlgoValue leftConverted  = AlgoOperators.ConvertType(context, left, AlgoValueType.Float);
                AlgoValue rightConverted = AlgoOperators.ConvertType(context, right, AlgoValueType.Float);

                //Check if the left is less than the right.
                if (equalTo)
                {
                    return((BigFloat)left.Value <= (BigFloat)right.Value);
                }
                else
                {
                    return((BigFloat)left.Value < (BigFloat)right.Value);
                }
            }
            else if (left.Type == AlgoValueType.Rational || right.Type == AlgoValueType.Rational)
            {
                //Convert both to rational.
                AlgoValue leftConverted  = AlgoOperators.ConvertType(context, left, AlgoValueType.Rational);
                AlgoValue rightConverted = AlgoOperators.ConvertType(context, right, AlgoValueType.Rational);

                //Check if the left is less than the right.
                if (equalTo)
                {
                    return((BigRational)left.Value <= (BigRational)right.Value);
                }
                else
                {
                    return((BigRational)left.Value < (BigRational)right.Value);
                }
            }
            else if (left.Type == AlgoValueType.Integer || right.Type == AlgoValueType.Integer)
            {
                //Convert both to integer.
                AlgoValue leftConverted  = AlgoOperators.ConvertType(context, left, AlgoValueType.Integer);
                AlgoValue rightConverted = AlgoOperators.ConvertType(context, right, AlgoValueType.Integer);

                //Check if the left is less than the right.
                if (equalTo)
                {
                    return((BigInteger)left.Value <= (BigInteger)right.Value);
                }
                else
                {
                    return((BigInteger)left.Value < (BigInteger)right.Value);
                }
            }
            else
            {
                Error.Fatal(context, "Cannot compare values with type " + left.Type.ToString() + " and " + right.Type.ToString() + ".");
                return(false);
            }
        }
コード例 #7
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);
        }
コード例 #8
0
        //Evaluate a check into a raw boolean (no value wrapper).
        public override object VisitCheck([NotNull] algoParser.CheckContext context)
        {
            //Switch for the type of check.
            if (context.BIN_AND() != null)
            {
                //Binary AND.
                //Evaluate the left and right values.
                AlgoValue left  = (AlgoValue)VisitCheck(context.check());
                AlgoValue right = (AlgoValue)VisitCheckfrag(context.checkfrag());

                //Return the comparison result of these two (as AlgoValue).
                return(new AlgoValue()
                {
                    Type = AlgoValueType.Boolean,
                    Value = AlgoComparators.AND(context, left, right),
                });
            }
            else if (context.BIN_OR() != null)
            {
                //Binary OR.
                //Evaluate the left and right values.
                AlgoValue left  = (AlgoValue)VisitCheck(context.check());
                AlgoValue right = (AlgoValue)VisitCheckfrag(context.checkfrag());

                //Return an OR on these values.
                return(new AlgoValue()
                {
                    Type = AlgoValueType.Boolean,
                    Value = AlgoComparators.OR(context, left, right),
                });
            }
            else if (context.LBRACKET() != null)
            {
                //Bracketed check.
                return((AlgoValue)VisitCheck(context.check()));
            }
            else if (context.INVERT_SYM() != null)
            {
                //Boolean invert.
                AlgoValue evaled = (AlgoValue)VisitCheck(context.check());

                //Get the boolean value for the evaluated value.
                bool evaledBool = AlgoComparators.GetBooleanValue(evaled, context);

                //Return the inverted bool.
                return(new AlgoValue()
                {
                    Type = AlgoValueType.Boolean,
                    Value = !evaledBool,
                });
            }
            else
            {
                //Just a checkfrag. Evaluate and return.
                return((AlgoValue)VisitCheckfrag(context.checkfrag()));
            }
        }
コード例 #9
0
        //Binary OR.
        public static bool OR(ParserRuleContext context, AlgoValue left, AlgoValue right)
        {
            //Get value for left and right type.
            bool leftBV  = GetBooleanValue(left, context);
            bool rightBV = GetBooleanValue(right, context);

            //Check if one of these are true.
            return(leftBV || rightBV);
        }
コード例 #10
0
ファイル: AlgoScopes.cs プロジェクト: c272/algo-lang
        //Add a variable to the scope.
        public void AddVariable(string name, AlgoValue value, ParserRuleContext context = null)
        {
            //Is it an object member?
            if (!name.Contains("."))
            {
                //Check if a variable with this name already exists.
                if (VariableExistsLowest(name))
                {
                    Error.Fatal(context, "A variable with this name already exists, cannot create one.");
                    return;
                }

                //Nope, add it to the lowest scope.
                Scopes[Scopes.Count - 1].Add(name, value);
            }
            else
            {
                //Object member, a more complicated procedure.
                //Get the parent object that the member is being assigned to.
                string        objTxt   = name;
                List <string> objParts = objTxt.Split('.').ToList();
                string        final    = objParts.Last();
                objParts.RemoveAt(objParts.Count - 1);
                objTxt = string.Join(".", objParts.ToArray());

                if (!VariableExists(objTxt))
                {
                    Error.Fatal(context, "Cannot create an object member for nonexistant object '" + objTxt + "'.");
                }

                //Check if the variable is an object.
                AlgoValue objVal = GetVariable(objTxt);
                if (objVal.Type != AlgoValueType.Object)
                {
                    Error.Fatal(context, "Cannot create an object member of non-object value '" + objTxt + "'.");
                }
                AlgoObject obj = (AlgoObject)objVal.Value;

                //Check if the variable has the new member already defined.
                if (obj.ObjectScopes.VariableExists(final))
                {
                    Error.Fatal(context, "An object member with that name already exists.");
                }

                //Create the variable.
                obj.ObjectScopes.AddVariable(final, value);

                //Set the object parent.
                SetVariable(objTxt, new AlgoValue()
                {
                    Type  = AlgoValueType.Object,
                    Value = obj
                });
            }
        }
コード例 #11
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);
        }
コード例 #12
0
        //Convert an Algo list to JSON.
        public static string ListToJsonStr(ParserRuleContext context, AlgoValue listVal)
        {
            //Enumerate over object members, and add them to the string.
            string json = "[";

            foreach (var prop in (List <AlgoValue>)listVal.Value)
            {
                AppendValueString(context, prop, ref json);
                json += ", ";
            }
            json = json.Trim(',', ' ') + "]";
            return(json);
        }
コード例 #13
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);
        }
コード例 #14
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);
        }
コード例 #15
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);
        }
コード例 #16
0
        //When an error is manually thrown by a user.
        public override object VisitStat_throw([NotNull] algoParser.Stat_throwContext context)
        {
            //Evaluate the expression.
            AlgoValue throwStr = (AlgoValue)VisitExpr(context.expr());

            //Is it a string?
            if (throwStr.Type != AlgoValueType.String)
            {
                Error.Fatal(context, "Error message to throw must be a string.");
                return(null);
            }

            //Throw the error.
            Error.Fatal(context, (string)throwStr.Value);
            return(null);
        }
コード例 #17
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);
        }
コード例 #18
0
ファイル: AlgoScopes.cs プロジェクト: c272/algo-lang
        //Remove a variable from the scope.
        public void RemoveVariable(string name)
        {
            //Check if a variable with this name exists.
            if (!VariableExists(name))
            {
                Error.FatalNoContext("No variable with this name exists, so can't destroy it.");
                return;
            }

            //If the name contains a '.', got to go to deepest scope recursively.
            if (name.Contains('.'))
            {
                //Get the parent.
                List <string> parts      = name.Split('.').ToList();
                AlgoValue     partParent = GetVariable(parts[0]);

                //Checking if it's an object.
                if (partParent.Type != AlgoValueType.Object)
                {
                    Error.FatalNoContext("The value given is not an object, so cannot remove children.");
                    return;
                }

                //Remove variable from this scope recursively.
                parts.RemoveAt(0);
                string     newPartString = string.Join(".", parts.ToList());
                AlgoObject partObj       = (AlgoObject)partParent.Value;
                partObj.ObjectScopes.RemoveVariable(newPartString);
            }
            else
            {
                //Literal variable in this scope, check through all scopes (from deepest) and delete.
                for (int i = Scopes.Count - 1; i >= 0; i--)
                {
                    if (Scopes[i].ContainsKey(name))
                    {
                        Scopes[i].Remove(name);
                        return;
                    }
                }
            }

            //Could not find.
            Error.FatalNoContext("Could not find variable to delete, despite the fact it exists.");
        }
コード例 #19
0
        //When a single term is parsed in Algo.
        public override object VisitTerm([NotNull] algoParser.TermContext context)
        {
            //Is it a multiplication?
            if (context.MUL_OP() != null)
            {
                //Multiplication.
                //Evaluate the left side (term).
                AlgoValue left = (AlgoValue)VisitTerm(context.term());

                //Evaluate the right side.
                AlgoValue right = (AlgoValue)VisitFactor(context.factor());

                //Perform multiplication.
                return(AlgoOperators.Mul(context, left, right));
            }
            else if (context.DIV_OP() != null)
            {
                //Division.
                //Evaluate the left side (term).
                AlgoValue left = (AlgoValue)VisitTerm(context.term());

                //Evaluate the right side.
                AlgoValue right = (AlgoValue)VisitFactor(context.factor());

                //Perform division.
                return(AlgoOperators.Div(context, left, right));
            }
            else if (context.MOD_OP() != null)
            {
                //Modulus.
                AlgoValue left  = (AlgoValue)VisitTerm(context.term());
                AlgoValue right = (AlgoValue)VisitFactor(context.factor());

                //Perform modulus.
                return(AlgoOperators.Mod(context, left, right));
            }
            else
            {
                //No, just a factor, evaluate.
                return((AlgoValue)VisitFactor(context.factor()));
            }

            //Error.
            throw new Exception("Invalid expression type.");
        }
コード例 #20
0
ファイル: AlgoIO.cs プロジェクト: c272/algo-lang
        //A "print" statement.
        public override object VisitStat_print([NotNull] algoParser.Stat_printContext context)
        {
            //Evaluate the expression.
            AlgoValue toPrint = (AlgoValue)VisitExpr(context.expr());

            //Depending on the type, set string accordingly via. casts.
            string printString = "";

            printString = AlgoConversion.GetStringRepresentation(toPrint);

            //Check if a rounding expression is present.
            if (context.rounding_expr() != null)
            {
                //Evaluate the rounding expression.
                AlgoValue roundingNum = (AlgoValue)VisitExpr(context.rounding_expr().expr());

                //Check if it's an integer.
                if (roundingNum.Type != AlgoValueType.Integer)
                {
                    Error.Warning(context, "Given rounding expression is not an integer, so can't round. Rounding was ignored.");
                }
                else
                {
                    //Check if the rounding value is too large.
                    if ((BigInteger)roundingNum.Value > int.MaxValue)
                    {
                        Error.Warning(context, "Given rounding number is too large to process, so rounding was ignored.");
                    }
                    else
                    {
                        //Round the actual value.
                        int roundingInt = int.Parse(((BigInteger)roundingNum.Value).ToString());
                        toPrint = AlgoOperators.Round(context, toPrint, roundingInt);

                        //Set print string.
                        printString = AlgoConversion.GetStringRepresentation(toPrint);
                    }
                }
            }

            //Print and return.
            Console.WriteLine(printString);
            return(null);
        }
コード例 #21
0
        //Override for checking whether AlgoValues are equal.
        public bool _Equals(AlgoValue obj)
        {
            //Check if value types are the same.
            if (Type != obj.Type)
            {
                //No.
                return(false);
            }

            //Are the actual values themselves the same?
            var objVal = obj.Value;

            switch (Type)
            {
            case AlgoValueType.String:
                return((string)Value == (string)objVal);

            case AlgoValueType.Boolean:
                return((bool)Value == (bool)objVal);

            case AlgoValueType.Float:
                return(((BigFloat)Value).Equals((BigFloat)objVal));

            case AlgoValueType.Integer:
                return(((BigInteger)Value).Equals((BigInteger)objVal));

            case AlgoValueType.List:
                return(AlgoComparators.ListsEqual(this, obj));

            case AlgoValueType.Null:
                return(true);

            case AlgoValueType.Object:
                return(AlgoComparators.ObjectsEqual(this, obj));

            case AlgoValueType.Rational:
                return(((BigRational)Value).Equals((BigRational)objVal));

            default:
                Error.FatalNoContext("Cannot compare whether two " + Type.ToString() + " values are equal.");
                return(false);
            }
        }
コード例 #22
0
        public static void AppendValueString(ParserRuleContext context, AlgoValue prop, ref string json)
        {
            switch (prop.Type)
            {
            case AlgoValueType.Boolean:
                json += ((bool)prop.Value).ToString();
                break;

            case AlgoValueType.Float:
                json += ((BigFloat)prop.Value).ToString();
                break;

            case AlgoValueType.Integer:
                json += ((BigInteger)prop.Value).ToString();
                break;

            case AlgoValueType.List:
                json += ListToJsonStr(context, prop);
                break;

            case AlgoValueType.Null:
                json += "null";
                break;

            case AlgoValueType.Object:
                json += ObjToJsonStr(context, prop);
                break;

            case AlgoValueType.Rational:
                AlgoValue rational_as_float = new AlgoValue()
                {
                    Type  = AlgoValueType.Float,
                    Value = RationalToFloat(prop)
                };
                json += rational_as_float.ToString();
                break;

            case AlgoValueType.String:
                json += "\"" + (string)prop.Value + "\"";
                break;
            }
        }
コード例 #23
0
        //When a value is returned from a function.
        public override object VisitStat_return([NotNull] algoParser.Stat_returnContext context)
        {
            //Evaluate the expression to return.
            AlgoValue toReturn;

            if (context.expr() != null)
            {
                toReturn = (AlgoValue)VisitExpr(context.expr());
            }
            else
            {
                toReturn = new AlgoValue()
                {
                    Type  = AlgoValueType.Null,
                    Value = null
                };
            }

            //Return it.
            return(toReturn);
        }
コード例 #24
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);
        }
コード例 #25
0
        //Converts an Algo Object to JSON string.
        public static string ObjToJsonStr(ParserRuleContext context, AlgoValue objVal)
        {
            //Enumerate over object members, and add them to the string.
            string json = "{ ";

            foreach (var prop in ((AlgoObject)objVal.Value).ObjectScopes.GetDeepestScope())
            {
                json += "\"" + prop.Key + "\": ";
                AppendValueString(context, prop.Value, ref json);
                json += ", ";
            }
            json = json.Trim(',', ' ') + " }";

            //Fix empty objects having a double space.
            if (json == "{  }")
            {
                json = "{}";
            }

            //Return.
            return(json);
        }
コード例 #26
0
        //Checks whether two lists are equal to each other.
        public static bool ListsEqual(AlgoValue leftval, AlgoValue rightval)
        {
            //Casting.
            var left  = (List <AlgoValue>)leftval.Value;
            var right = (List <AlgoValue>)rightval.Value;

            //Simple length check.
            if (left.Count != right.Count)
            {
                return(false);
            }

            //Loop over, check.
            for (int i = 0; i < left.Count; i++)
            {
                if (!left[i]._Equals(right[i]))
                {
                    return(false);
                }
            }

            return(true);
        }
コード例 #27
0
        //When a single factor is parsed in Algo.
        public override object VisitFactor([NotNull] algoParser.FactorContext context)
        {
            //Is there a power?
            if (context.POW_OP() != null)
            {
                //Yes.
                //Evaluate left factor.
                AlgoValue left = (AlgoValue)VisitFactor(context.factor());

                //Evaluate right sub.
                AlgoValue right = (AlgoValue)VisitSub(context.sub());

                //Perform a power.
                return(AlgoOperators.Pow(context, left, right));
            }
            else
            {
                //No, just evaluate the sub.
                return((AlgoValue)VisitSub(context.sub()));
            }

            //Error.
            throw new Exception("Invalid expression type.");
        }
コード例 #28
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
                });
            }
        }
コード例 #29
0
        //Returns the string representation of a given Algo value.
        public static string GetStringRepresentation(AlgoValue toPrint)
        {
            string printString = "";

            switch (toPrint.Type)
            {
            case AlgoValueType.Null:
                printString = "null";
                break;

            case AlgoValueType.Boolean:
                printString = ((bool)toPrint.Value).ToString().ToLower();
                break;

            case AlgoValueType.Float:
                printString = ((BigFloat)toPrint.Value).ToString();
                break;

            case AlgoValueType.Integer:
                printString = ((BigInteger)toPrint.Value).ToString();
                break;

            case AlgoValueType.Rational:
                printString = ((BigRational)toPrint.Value).ToString();
                break;

            case AlgoValueType.Bytes:
                printString = ((byte[])toPrint.Value).ToHexString();
                break;

            case AlgoValueType.String:
                printString = (string)toPrint.Value;
                break;

            case AlgoValueType.List:

                //Evaluate each of the list values one by one.
                printString += '[';
                foreach (var listVal in (List <AlgoValue>)toPrint.Value)
                {
                    printString += GetStringRepresentation(listVal) + ", ";
                }

                //Only trim commas if there are actually items.
                if (((List <AlgoValue>)toPrint.Value).Count > 0)
                {
                    printString = printString.Substring(0, printString.Length - 2);
                }
                printString += ']';
                break;

            case AlgoValueType.Object:
                printString += "{ ";
                foreach (var prop in (Dictionary <string, AlgoValue>)((AlgoObject)(toPrint.Value)).ObjectScopes.GetScopes().Last())
                {
                    printString += prop.Key + ": " + GetStringRepresentation(prop.Value) + ", ";
                }
                printString  = printString.Trim(',', ' ');
                printString += " }";
                return(printString);

            default:
                //Just return the type name.
                return("types." + toPrint.Type.ToString());
            }

            return(printString);
        }
コード例 #30
0
ファイル: AlgoLibraryManager.cs プロジェクト: c272/algo-lang
        //When a file is imported.
        public override object VisitStat_import([NotNull] algoParser.Stat_importContext context)
        {
            //The following are checked for the parent library, in order:
            //1. Executing directory of the script + whatever referenced folder path.
            //2. Packages directory for Algo.
            //3. Standard libraries.

            //Make sure they're not trying to import multiple as a single identifier.
            if (context.literal_params().expr().Length > 1 && context.AS_SYM() != null)
            {
                Error.Warning(context, "Failed to import scripts, cannot import multiple scripts as a single identifier.");
                return(null);
            }

            //Import each.
            foreach (var item in context.literal_params().expr())
            {
                //Getting directory tree text.
                string importLoc = "";

                //Evaluating the statement to get dir text.
                AlgoValue locVal = (AlgoValue)VisitExpr(item);
                if (locVal.Type != AlgoValueType.String)
                {
                    Error.Fatal(context, "Given file path to import was not a string.");
                    return(null);
                }
                importLoc = (string)locVal.Value;

                List <string> fileParts = importLoc.Split('/').ToList();

                //Append the extension to the end (imports don't require an extension).
                if (!fileParts[fileParts.Count - 1].EndsWith(".ag"))
                {
                    fileParts[fileParts.Count - 1] = fileParts.Last() + ".ag";
                }

                //Is the import being placed into a different scope?
                string importScope = "";
                if (context.AS_SYM() != null)
                {
                    //Yes, get the name of the scope.
                    importScope = context.IDENTIFIER().GetText();
                }

                //Test 1: Executing directory of the script.
                string[] dirParts = new string[] { Environment.CurrentDirectory }.Concat(fileParts).ToArray();
                string   dirToCheck = CPFilePath.GetPlatformFilePath(dirParts);

                //Is it there?
                if (File.Exists(dirToCheck))
                {
                    //Yes! Run the load function.
                    RunAlgoScript(dirToCheck, importScope);
                    continue;
                }

                //Nope.
                //Test 2: Packages directory for Algo.
                dirParts   = DefaultDirectories.PackagesDirectory.Concat(fileParts).ToArray();
                dirToCheck = CPFilePath.GetPlatformFilePath(dirParts);

                //Is it there?
                if (File.Exists(dirToCheck))
                {
                    //Yep, load it.
                    RunAlgoScript(dirToCheck, importScope);
                    continue;
                }

                //Nope.
                //Test 3: Standard libraries.
                dirParts   = DefaultDirectories.StandardLibDirectory.Concat(fileParts).ToArray();
                dirToCheck = CPFilePath.GetPlatformFilePath(dirParts);

                //Is it there?
                if (File.Exists(dirToCheck))
                {
                    //Yep, load it.
                    RunAlgoScript(dirToCheck, importScope);
                    continue;
                }

                //No, nowhere else to check from, so throw a linking warning.
                Error.Warning(context, "Failed to link the Algo script '" + importLoc + "'. It has not been loaded.");
            }

            return(null);
        }