Beispiel #1
0
 public override bool Eval(PCBObject Obj)
 {
     if (LeftExpression.Eval(Obj) == true)
     {
         return(true);
     }
     return(RightExpression.Eval(Obj));
 }
Beispiel #2
0
 public override bool Eval(IPrincipal principal)
 {
     return(LeftExpression.Eval(principal) && RightExpression.Eval(principal));
 }
Beispiel #3
0
        public override object Eval(TemplateContext context)
        {
            // evaluate both parts
            object lv = LeftExpression.Eval(context);
            object rv = RightExpression.Eval(context);

            // equality/not-equality
            if (op == TokenType.Equal)
            {
                if (lv == null && rv == null)
                {
                    return(true);
                }
                else if (lv != null)
                {
                    return(lv.Equals(rv));
                }
            }
            else if (op == TokenType.NotEqual)
            {
                if (lv == null && rv == null)
                {
                    return(false);
                }
                else if (lv != null)
                {
                    return(!lv.Equals(rv));
                }
            }

            // arithmetic operation
            else if (op == TokenType.Mult ||
                     op == TokenType.Div ||
                     op == TokenType.Mod ||
                     op == TokenType.Plus ||
                     op == TokenType.Minus ||
                     op == TokenType.Less ||
                     op == TokenType.LessOrEqual ||
                     op == TokenType.Greater ||
                     op == TokenType.GreaterOrEqual)
            {
                if (!((lv is Decimal || lv is Int32) && (rv is Decimal || rv is Int32)))
                {
                    throw new ParserException("Arithmetic and logical operations can be applied to operands or integer and decimal types only.",
                                              Line, Column);
                }


                bool   dec = lv is Decimal || rv is Decimal;
                object val = null;
                if (op == TokenType.Mult)
                {
                    val = dec ? (Decimal)lv * (Decimal)rv : (Int32)lv * (Int32)rv;
                }
                else if (op == TokenType.Div)
                {
                    val = dec ? (Decimal)lv / (Decimal)rv : (Int32)lv / (Int32)rv;
                }
                else if (op == TokenType.Mod)
                {
                    val = dec ? (Decimal)lv % (Decimal)rv : (Int32)lv % (Int32)rv;
                }
                else if (op == TokenType.Plus)
                {
                    val = dec ? (Decimal)lv + (Decimal)rv : (Int32)lv + (Int32)rv;
                }
                else if (op == TokenType.Minus)
                {
                    val = dec ? (Decimal)lv - (Decimal)rv : (Int32)lv - (Int32)rv;
                }
                else if (op == TokenType.Less)
                {
                    val = dec ? (Decimal)lv < (Decimal)rv : (Int32)lv < (Int32)rv;
                }
                else if (op == TokenType.LessOrEqual)
                {
                    val = dec ? (Decimal)lv <= (Decimal)rv : (Int32)lv <= (Int32)rv;
                }
                else if (op == TokenType.Greater)
                {
                    val = dec ? (Decimal)lv > (Decimal)rv : (Int32)lv > (Int32)rv;
                }
                else if (op == TokenType.GreaterOrEqual)
                {
                    val = dec ? (Decimal)lv >= (Decimal)rv : (Int32)lv >= (Int32)rv;
                }

                if (val is Boolean)
                {
                    bool ret = Convert.ToBoolean(val);
                    return(ret);
                }
                else if (dec)
                {
                    decimal ret = Convert.ToDecimal(val);
                    return(ret);
                }
                else
                {
                    int ret = Convert.ToInt32(val);
                    return(ret);
                }
            }
            else if (op == TokenType.Or || op == TokenType.And)
            {
                if (!(lv is Boolean && rv is Boolean))
                {
                    throw new ParserException("Logical operation can be applied to operands of boolean type only", Line, Column);
                }

                if (op == TokenType.Or)
                {
                    return((Boolean)lv || (Boolean)rv);
                }
                else if (op == TokenType.And)
                {
                    return((Boolean)lv && (Boolean)rv);
                }
            }

            return(0);
        }
Beispiel #4
0
        /// <inheritdoc />
        protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame)
        {
            var leftCandidate = LeftExpression.Eval(context, env, frame);

            if (leftCandidate.IsErrorValue)
            {
                return(EvaluationResult.Error);
            }

            EvaluationResult left  = leftCandidate;
            EvaluationResult right = default(EvaluationResult);

            if (OperatorKind != BinaryOperator.And && OperatorKind != BinaryOperator.Or)
            {
                // Don't eval right expression for And and Or operators due to possible short circuit.
                var rightCandidate = RightExpression.Eval(context, env, frame);

                if (rightCandidate.IsErrorValue)
                {
                    return(EvaluationResult.Error);
                }

                right = rightCandidate;
            }

            try
            {
                checked
                {
                    int leftNumber;
                    int rightNumber;

                    switch (OperatorKind)
                    {
                    case BinaryOperator.Addition:
                        // Different cases:

                        // 1. If left OR right is a string result is a string
                        // 2. If left AND right are numbers - result is a number
                        string leftString  = left.Value as string;
                        string rightString = right.Value as string;

                        // First case: if any of the frame is string
                        if (leftString != null)
                        {
                            if (rightString != null)
                            {
                                return(EvaluationResult.Create(leftString + rightString));
                            }

                            return(EvaluationResult.Create(leftString + ToStringConverter.ObjectToString(context, right)));
                        }

                        if (rightString != null)
                        {
                            return(EvaluationResult.Create(ToStringConverter.ObjectToString(context, left) + rightString));
                        }

                        // Expecting numbers, but can't report type mismatch error, because in this case string or number are allowed.
                        if (TryGetNumbers(left, right, out leftNumber, out rightNumber))
                        {
                            return(EvaluationResult.Create(leftNumber + rightNumber));
                        }

                        context.Errors.ReportUnexpectedValueType(env, LeftExpression, left, typeof(int), typeof(string));
                        return(EvaluationResult.Error);

                    // Math operators
                    case BinaryOperator.Remainder:
                        return(EvaluationResult.Create(Converter.ExpectNumber(left, position: 0) % Converter.ExpectNumber(right, position: 1)));

                    case BinaryOperator.Multiplication:
                        return(EvaluationResult.Create(Converter.ExpectNumber(left, position: 0) * Converter.ExpectNumber(right, position: 1)));

                    case BinaryOperator.Subtraction:
                        return(EvaluationResult.Create(Converter.ExpectNumber(left, position: 0) - Converter.ExpectNumber(right, position: 1)));

                    case BinaryOperator.Exponentiation:
                        return(NumberOperations.Power(context, Converter.ExpectNumber(left), Converter.ExpectNumber(right), LocationForLogging(context, env)));

                    // Equality + Comparison
                    case BinaryOperator.Equal:
                        return(EvaluationResult.Create(left.Equals(right)));

                    case BinaryOperator.NotEqual:
                        return(EvaluationResult.Create(!left.Equals(right)));

                    case BinaryOperator.GreaterThanOrEqual:
                        return(EvaluationResult.Create(Converter.ExpectNumber(left, position: 0) >= Converter.ExpectNumber(right, position: 1)));

                    case BinaryOperator.GreaterThan:
                        return(EvaluationResult.Create(Converter.ExpectNumber(left, position: 0) > Converter.ExpectNumber(right, position: 1)));

                    case BinaryOperator.LessThanOrEqual:
                        return(EvaluationResult.Create(Converter.ExpectNumber(left, position: 0) <= Converter.ExpectNumber(right, position: 1)));

                    case BinaryOperator.LessThan:
                        return(EvaluationResult.Create(Converter.ExpectNumber(left, position: 0) < Converter.ExpectNumber(right, position: 1)));

                    // Conditionals
                    case BinaryOperator.Or:
                        return(EvalOr(context, env, frame, left));

                    case BinaryOperator.And:
                        return(EvalAnd(context, env, frame, left));

                    // Bitwise operations
                    // For all bitwise operations call to ToEnumValueIfNeeded is required to convert
                    // numeric representation to enum value if left hand side is enum
                    // (ExpectNumberOrEnums will make sure that left and right operands have the same type).
                    case BinaryOperator.BitWiseOr:
                        if (ExpectNumbersOrEnums(context, env, left, right, out leftNumber, out rightNumber))
                        {
                            return(Converter.ToEnumValueIfNeeded(left.GetType(), leftNumber | rightNumber));
                        }

                        return(EvaluationResult.Error);

                    case BinaryOperator.BitWiseAnd:
                        if (ExpectNumbersOrEnums(context, env, left, right, out leftNumber, out rightNumber))
                        {
                            return(Converter.ToEnumValueIfNeeded(left.GetType(), leftNumber & rightNumber));
                        }

                        return(EvaluationResult.Error);

                    case BinaryOperator.BitWiseXor:
                        if (ExpectNumbersOrEnums(context, env, left, right, out leftNumber, out rightNumber))
                        {
                            return(Converter.ToEnumValueIfNeeded(left.GetType(), leftNumber ^ rightNumber));
                        }

                        break;

                    case BinaryOperator.LeftShift:
                        return(EvaluationResult.Create(Converter.ExpectNumber(left, position: 0) << Converter.ExpectNumber(right, position: 1)));

                    case BinaryOperator.SignPropagatingRightShift:
                        return(EvaluationResult.Create(NumberOperations.SignPropagatingRightShift(
                                                           Converter.ExpectNumber(left, position: 0),
                                                           Converter.ExpectNumber(right, position: 1)).Value));

                    case BinaryOperator.ZeroFillingRightShift:
                        return(EvaluationResult.Create(NumberOperations.ZeroFillingRightShift(
                                                           Converter.ExpectNumber(left, position: 0),
                                                           Converter.ExpectNumber(right, position: 1)).Value));

                    default:
                        // And and Or operator should have been replaced by the ite expression.
                        // case BinaryOperator.And:
                        // case BinaryOperator.Or:
                        //    return (bool)l && (bool)RightExpression.Eval(context, env, frame);
                        //    return (bool) l || (bool) RightExpression.Eval(context, env, frame);
                        Contract.Assert(false);
                        break;
                    }
                }
            }
            catch (OverflowException)
            {
                context.Logger.ReportArithmeticOverflow(
                    context.LoggingContext,
                    LocationForLogging(context, env),
                    this.ToDisplayString(context));
            }
            catch (ConvertException convertException)
            {
                context.Errors.ReportUnexpectedValueType(
                    env,
                    convertException.ErrorContext.Pos == 0 ? LeftExpression : RightExpression,
                    convertException.Value, convertException.ExpectedTypesToString(context));
            }
            catch (DivideByZeroException)
            {
                context.Errors.ReportDivideByZeroException(env, this, Location);
            }

            return(EvaluationResult.Error);
        }
Beispiel #5
0
 public override bool Eval(PCBObject Obj)
 {
     return(LeftExpression.Eval(Obj) ^ RightExpression.Eval(Obj));
 }