2 // BoxedExpressionExtensions.cs
5 // Alexander Chebaturkin (chebaturkin@gmail.com)
7 // Copyright (C) 2011 Alexander Chebaturkin
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using Mono.CodeContracts.Static.AST;
32 using Mono.CodeContracts.Static.DataStructures;
34 namespace Mono.CodeContracts.Static.Proving
36 static class BoxedExpressionExtensions
38 public static bool IsConstantIntOrNull(this BoxedExpression e, out int res)
42 IConvertible convertible = e.Constant as IConvertible;
43 if (convertible != null) {
44 if (e.Constant is string || e.Constant is float || e.Constant is double)
48 res = convertible.ToInt32 (null);
53 if (e.Constant == null)
59 public static bool IsConstantBool(this BoxedExpression e, out bool result)
61 if (e.IsConstant && e.Constant is bool)
62 return true.With ((bool) e.Constant, out result);
64 return false.Without (out result);
67 public static bool IsTrivialCondition(this BoxedExpression e, out bool result)
70 if (e.IsConstantIntOrNull (out value))
71 return true.With (value != 0, out result);
72 if (e.IsConstantBool (out result))
77 BoxedExpression right;
78 if (e.IsBinaryExpression (out bop, out left, out right)) {
80 var isLeftInt = left.IsConstantIntOrNull (out l);
81 var isRightInt = right.IsConstantIntOrNull (out r);
82 if (bop == BinaryOperator.Ceq) {
83 if (isLeftInt && isRightInt)
84 return true.With (l == r, out result);
86 if (isRightInt && r == 0 && left.IsTrivialCondition (out leftResult))
87 return true.With (!leftResult, out result);
90 if (isLeftInt && l == 0 && right.IsTrivialCondition (out rightResult))
91 return true.With (!rightResult, out result);
93 return false.Without (out result);
97 case BinaryOperator.Add:
98 case BinaryOperator.Add_Ovf:
99 case BinaryOperator.Add_Ovf_Un:
100 return true.With (l + r != 0, out result);
101 case BinaryOperator.And:
102 return true.With ((l & r) != 0, out result);
103 case BinaryOperator.Cne_Un:
104 return true.With (l != r, out result);
105 case BinaryOperator.Cge:
106 return true.With (l >= r, out result);
107 case BinaryOperator.Cge_Un:
108 return true.With ((uint) l >= (uint) r, out result);
109 case BinaryOperator.Cgt:
110 return true.With (l > r, out result);
111 case BinaryOperator.Cgt_Un:
112 return true.With ((uint) l > (uint) r, out result);
113 case BinaryOperator.Cle:
114 return true.With (l <= r, out result);
115 case BinaryOperator.Cle_Un:
116 return true.With ((uint) l <= (uint) r, out result);
117 case BinaryOperator.Clt:
118 return true.With (l < r, out result);
119 case BinaryOperator.Clt_Un:
120 return true.With ((uint) l < (uint) r, out result);
121 case BinaryOperator.Div:
123 return false.Without (out result);
124 return true.With (l / r != 0, out result);
125 case BinaryOperator.Div_Un:
127 return false.Without (out result);
128 return true.With ((uint) l / (uint) r != 0, out result);
129 case BinaryOperator.LogicalAnd:
130 return true.With (l != 0 && r != 0, out result);
131 case BinaryOperator.LogicalOr:
132 return true.With (l != 0 || r != 0, out result);
133 case BinaryOperator.Mul:
134 case BinaryOperator.Mul_Ovf:
135 case BinaryOperator.Mul_Ovf_Un:
136 return true.With (l * r != 0, out result);
137 case BinaryOperator.Or:
138 return true.With ((l | r) != 0, out result);
139 case BinaryOperator.Rem:
141 return false.Without (out result);
142 return true.With (l % r != 0, out result);
143 case BinaryOperator.Rem_Un:
145 return false.Without (out result);
146 return true.With (((uint) l) % ((uint) r) != 0, out result);
147 case BinaryOperator.Shl:
148 return true.With (l << r != 0, out result);
149 case BinaryOperator.Shr:
150 return true.With (l >> r != 0, out result);
151 case BinaryOperator.Shr_Un:
152 return true.With (((uint) l) >> r != 0, out result);
153 case BinaryOperator.Sub:
154 case BinaryOperator.Sub_Ovf:
155 case BinaryOperator.Sub_Ovf_Un:
156 return true.With (l - r != 0, out result);
157 case BinaryOperator.Xor:
158 return true.With ((l ^ r) != 0, out result);
160 return false.Without (out result);
164 return false.Without (out result);