예제 #1
0
        public override ExpressionNode VisitUnaryExpression(UnaryExpression expression)
        {
            base.VisitUnaryExpression(expression);

            ConstantExpression operandAsConstant = expression.Operand as ConstantExpression;

            if (operandAsConstant != null)
            {
                // Ok, lets compute the result

                if (operandAsConstant.IsNullValue)
                {
                    return(LiteralExpression.FromTypedNull(expression.ExpressionType));
                }

                try
                {
                    return(LiteralExpression.FromTypedValue(expression.GetValue(), expression.ExpressionType));
                }
                catch (RuntimeException ex)
                {
                    _errorReporter.CannotFoldConstants(ex);
                }
            }

            // If we getting here we return the orginal one.

            return(expression);
        }
예제 #2
0
        public override ExpressionNode VisitCastExpression(CastExpression expression)
        {
            base.VisitCastExpression(expression);

            if (!Binder.ConversionNeeded(expression.Expression.ExpressionType, expression.ExpressionType))
            {
                return(expression.Expression);
            }

            ConstantExpression expressionAsConstant = expression.Expression as ConstantExpression;

            if (expressionAsConstant != null)
            {
                if (expressionAsConstant.IsNullValue)
                {
                    return(LiteralExpression.FromTypedNull(expression.ExpressionType));
                }

                try
                {
                    return(LiteralExpression.FromTypedValue(expression.GetValue(), expression.ExpressionType));
                }
                catch (RuntimeException ex)
                {
                    _errorReporter.CannotFoldConstants(ex);
                }
            }

            return(expression);
        }
예제 #3
0
        public override ExpressionNode VisitFunctionInvocationExpression(FunctionInvocationExpression expression)
        {
            base.VisitFunctionInvocationExpression(expression);

            // Constant folding must not be applied if the function is non-deterministic.
            if (!expression.Function.IsDeterministic)
            {
                return(expression);
            }

            // Check if all arguments are constants or at least one argument
            // is null.

            ConstantExpression[] constantArguments = new ConstantExpression[expression.Arguments.Length];
            bool allArgumentsAreConstants          = true;

            for (int i = 0; i < constantArguments.Length; i++)
            {
                constantArguments[i] = expression.Arguments[i] as ConstantExpression;

                if (constantArguments[i] == null)
                {
                    // Ok, one argument is not a constant
                    // But don't stop: If an argument is null we can still calculate the result!
                    allArgumentsAreConstants = false;
                }
                else if (constantArguments[i].IsNullValue)
                {
                    // We found a null. That means the invocation will also yield null.
                    return(LiteralExpression.FromTypedNull(expression.ExpressionType));
                }
            }

            if (allArgumentsAreConstants)
            {
                try
                {
                    return(LiteralExpression.FromTypedValue(expression.GetValue(), expression.ExpressionType));
                }
                catch (RuntimeException ex)
                {
                    _errorReporter.CannotFoldConstants(ex);
                }
            }

            return(expression);
        }
예제 #4
0
        public override ExpressionNode VisitPropertyAccessExpression(PropertyAccessExpression expression)
        {
            base.VisitPropertyAccessExpression(expression);

            if (expression.Target is ConstantExpression)
            {
                try
                {
                    return(LiteralExpression.FromTypedValue(expression.GetValue(), expression.ExpressionType));
                }
                catch (RuntimeException ex)
                {
                    _errorReporter.CannotFoldConstants(ex);
                }
            }

            return(expression);
        }
예제 #5
0
        public override AlgebraNode VisitAggregateAlgebraNode(AggregateAlgebraNode node)
        {
            node.Input = VisitAlgebraNode(node.Input);

            if (node.Input is NullScanAlgebraNode)
            {
                if (node.Groups != null && node.Groups.Length > 0)
                {
                    // Grouped queries return nothing on empty input.
                    return(CreateNullScan(node.OutputList));
                }
                else
                {
                    // Non-grouped aggregation. We return the result value of the aggregates
                    // executed against an empty input as a single row.

                    List <RowBufferEntry>          outputList     = new List <RowBufferEntry>();
                    List <ComputedValueDefinition> emptyValueList = new List <ComputedValueDefinition>();
                    foreach (AggregatedValueDefinition definedValue in node.DefinedValues)
                    {
                        IAggregator aggregator = definedValue.Aggregator;
                        aggregator.Init();
                        object emptyValue = aggregator.Terminate();

                        ComputedValueDefinition computedBufferedValue = new ComputedValueDefinition();
                        computedBufferedValue.Target     = definedValue.Target;
                        computedBufferedValue.Expression = LiteralExpression.FromTypedValue(emptyValue, aggregator.ReturnType);
                        emptyValueList.Add(computedBufferedValue);
                        outputList.Add(computedBufferedValue.Target);
                    }

                    ConstantScanAlgebraNode constantScanAlgebraNode = new ConstantScanAlgebraNode();
                    constantScanAlgebraNode.DefinedValues = emptyValueList.ToArray();
                    constantScanAlgebraNode.OutputList    = outputList.ToArray();
                    return(constantScanAlgebraNode);
                }
            }

            return(node);
        }
예제 #6
0
        public override ExpressionNode VisitBinaryExpression(BinaryExpression expression)
        {
            base.VisitBinaryExpression(expression);

            ConstantExpression leftConstant  = expression.Left as ConstantExpression;
            ConstantExpression rightConstant = expression.Right as ConstantExpression;

            if (leftConstant != null && rightConstant != null)
            {
                // Both operands are constants, compute the result and return a constant node.

                try
                {
                    return(LiteralExpression.FromTypedValue(expression.GetValue(), expression.ExpressionType));
                }
                catch (RuntimeException ex)
                {
                    _errorReporter.CannotFoldConstants(ex);
                }
            }
            else if ((leftConstant != null || rightConstant != null) && (expression.Op == BinaryOperator.LogicalAnd || expression.Op == BinaryOperator.LogicalOr))
            {
                // We have a boolean AND or OR expression where one operand is a constant. Check if we
                // already know the result.

                if (expression.Op == BinaryOperator.LogicalAnd)
                {
                    // Check if one operand is false

                    if (leftConstant != null && !leftConstant.IsNullValue && !leftConstant.AsBoolean ||
                        rightConstant != null && !rightConstant.IsNullValue && !rightConstant.AsBoolean)
                    {
                        return(LiteralExpression.FromBoolean(false));
                    }
                }
                else
                {
                    // Check if one operand is true

                    if (leftConstant != null && !leftConstant.IsNullValue && leftConstant.AsBoolean ||
                        rightConstant != null && !rightConstant.IsNullValue && rightConstant.AsBoolean)
                    {
                        return(LiteralExpression.FromBoolean(true));
                    }
                }

                // We don't know the result but we can throw away the and/or expression
                // by replacing it with the unknown part.

                if (leftConstant != null && !leftConstant.IsNullValue)
                {
                    return(expression.Right);
                }
                else if (rightConstant != null && !rightConstant.IsNullValue)
                {
                    return(expression.Left);
                }

                return(expression);
            }

            // If we getting here we return the orginal one.

            return(expression);
        }
예제 #7
0
 public override ExpressionNode VisitNamedConstantExpression(NamedConstantExpression expression)
 {
     // From now on there are no named constants in the tree. A constant value is always indicated
     // by a literal. This simplifies later phases (e.g. IL generation).
     return(LiteralExpression.FromTypedValue(expression.Constant.Value, expression.ExpressionType));
 }