//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())); } }
//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); } }
//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); }
//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); }
//Rational. public static AlgoValue ConvertRat(ParserRuleContext context, params AlgoValue[] args) { //Is it a string? if (args[0].Type == AlgoValueType.String) { //Return a parsed bigint. return(new AlgoValue() { Type = AlgoValueType.Rational, Value = BigRational.Parse((string)args[0].Value) }); } //Nah, then just cast. return(AlgoOperators.ConvertType(context, args[0], AlgoValueType.Rational)); }
//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."); }
//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); }
//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); }
public void NullConversion() { //Create a test conversion for all of types from null. AlgoValue nullVal = AlgoValue.Null; ANTLRDebug.EnterTestMode(); //Test all conversions (these are expected to throw). for (int i = 0; i < Enum.GetNames(typeof(AlgoValueType)).Length; i++) { try { var attemptConv = AlgoOperators.ConvertType(null, nullVal, (AlgoValueType)i); } catch { Assert.Pass(); } } Assert.Fail(); }
public void StringConversions() { //Create test conversions for strings. AlgoValue stringVal = new AlgoValue() { Type = AlgoValueType.String, Value = "the quick brown fox jumps over the lazy dog" }; ANTLRDebug.EnterTestMode(); //Values that should pass. AlgoValue testVal; try { testVal = AlgoOperators.ConvertType(null, stringVal, AlgoValueType.String); } catch { Assert.Fail(); } //Values that should fail. for (int i = 0; i < Enum.GetNames(typeof(AlgoValueType)).Length; i++) { if ((AlgoValueType)i == AlgoValueType.String) { continue; } try { testVal = AlgoOperators.ConvertType(null, stringVal, (AlgoValueType)i); Assert.Fail(); } catch { } } Assert.Pass(); }
//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."); }
//Bytes public static AlgoValue ConvertBytes(ParserRuleContext context, params AlgoValue[] args) { //Just return convertType, no special cases here. return(AlgoOperators.ConvertType(context, args[0], AlgoValueType.Bytes)); }