1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Linq.Expressions;
19 using Microsoft.Scripting.Ast;
22 using System.Diagnostics;
23 using Microsoft.Scripting.Utils;
25 namespace Microsoft.Scripting.Generation {
27 public static class ConstantCheck {
30 /// Tests to see if the expression is a constant with the given value.
32 /// <param name="expression">The expression to examine</param>
33 /// <param name="value">The constant value to check for.</param>
34 /// <returns>true/false</returns>
35 public static bool Check(Expression expression, object value) {
36 ContractUtils.RequiresNotNull(expression, "expression");
37 return IsConstant(expression, value);
42 /// Tests to see if the expression is a constant with the given value.
44 /// <param name="e">The expression to examine</param>
45 /// <param name="value">The constant value to check for.</param>
46 /// <returns>true/false</returns>
47 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
48 internal static bool IsConstant(Expression e, object value) {
50 case ExpressionType.AndAlso:
51 return CheckAndAlso((BinaryExpression)e, value);
53 case ExpressionType.OrElse:
54 return CheckOrElse((BinaryExpression)e, value);
56 case ExpressionType.Constant:
57 return CheckConstant((ConstantExpression)e, value);
59 case ExpressionType.TypeIs:
60 return Check((TypeBinaryExpression)e, value);
68 internal static bool IsNull(Expression e) {
69 return IsConstant(e, null);
73 private static bool CheckAndAlso(BinaryExpression node, object value) {
74 Debug.Assert(node.NodeType == ExpressionType.AndAlso);
76 if (node.Method != null) {
79 //TODO: we can propagate through conversion, but it may not worth it.
80 if (node.Conversion != null) {
86 return IsConstant(node.Left, true) && IsConstant(node.Right, true);
88 // if left isn't a constant it has to be evaluated
89 return IsConstant(node.Left, false);
95 private static bool CheckOrElse(BinaryExpression node, object value) {
96 Debug.Assert(node.NodeType == ExpressionType.OrElse);
98 if (node.Method != null) {
104 return IsConstant(node.Left, true);
106 return IsConstant(node.Left, false) && IsConstant(node.Right, false);
112 private static bool CheckConstant(ConstantExpression node, object value) {
114 return node.Value == null;
116 return value.Equals(node.Value);
120 private static bool Check(TypeBinaryExpression node, object value) {
121 // allow constant TypeIs expressions to be optimized away
122 if (value is bool && ((bool)value) == true) {
123 return node.TypeOperand.IsAssignableFrom(node.Expression.Type);