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); }
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); }
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); }
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); }
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); }
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); }
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)); }