OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library tree_ir.optimization.logical_rewriter; | 5 library tree_ir.optimization.logical_rewriter; |
6 | 6 |
7 import '../tree_ir_nodes.dart'; | 7 import '../tree_ir_nodes.dart'; |
8 import 'optimization.dart' show Pass; | 8 import 'optimization.dart' show Pass; |
9 import '../../constants/values.dart' as values; | 9 import '../../constants/values.dart' as values; |
10 | 10 |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 node.left = makeCondition(node.left, true); | 203 node.left = makeCondition(node.left, true); |
204 node.right = makeCondition(node.right, true); | 204 node.right = makeCondition(node.right, true); |
205 return node; | 205 return node; |
206 } | 206 } |
207 | 207 |
208 /// True if the given expression is known to evaluate to a boolean. | 208 /// True if the given expression is known to evaluate to a boolean. |
209 /// This will not recursively traverse [Conditional] expressions, but if | 209 /// This will not recursively traverse [Conditional] expressions, but if |
210 /// applied to the result of [visitExpression] conditionals will have been | 210 /// applied to the result of [visitExpression] conditionals will have been |
211 /// rewritten anyway. | 211 /// rewritten anyway. |
212 bool isBooleanValued(Expression e) { | 212 bool isBooleanValued(Expression e) { |
213 return isTrue(e) || isFalse(e) || e is Not || e is LogicalOperator; | 213 return isTrue(e) || |
| 214 isFalse(e) || |
| 215 e is Not || |
| 216 e is LogicalOperator || |
| 217 e is ApplyBuiltinOperator && operatorReturnsBool(e.operator); |
| 218 } |
| 219 |
| 220 /// True if the given operator always returns `true` or `false`. |
| 221 bool operatorReturnsBool(BuiltinOperator operator) { |
| 222 switch (operator) { |
| 223 case BuiltinOperator.StrictEq: |
| 224 case BuiltinOperator.StrictNeq: |
| 225 case BuiltinOperator.LooseEq: |
| 226 case BuiltinOperator.LooseNeq: |
| 227 case BuiltinOperator.NumLt: |
| 228 case BuiltinOperator.NumLe: |
| 229 case BuiltinOperator.NumGt: |
| 230 case BuiltinOperator.NumGe: |
| 231 return true; |
| 232 default: |
| 233 return false; |
| 234 } |
| 235 } |
| 236 |
| 237 BuiltinOperator negateBuiltin(BuiltinOperator operator) { |
| 238 switch (operator) { |
| 239 case BuiltinOperator.StrictEq: return BuiltinOperator.StrictNeq; |
| 240 case BuiltinOperator.StrictNeq: return BuiltinOperator.StrictEq; |
| 241 case BuiltinOperator.LooseEq: return BuiltinOperator.LooseNeq; |
| 242 case BuiltinOperator.LooseNeq: return BuiltinOperator.LooseEq; |
| 243 |
| 244 // Because of NaN, these do not have a negated form. |
| 245 case BuiltinOperator.NumLt: |
| 246 case BuiltinOperator.NumLe: |
| 247 case BuiltinOperator.NumGt: |
| 248 case BuiltinOperator.NumGe: |
| 249 return null; |
| 250 |
| 251 default: |
| 252 return null; |
| 253 } |
214 } | 254 } |
215 | 255 |
216 /// Rewrite an expression that was originally processed in a non-boolean | 256 /// Rewrite an expression that was originally processed in a non-boolean |
217 /// context. | 257 /// context. |
218 Expression putInBooleanContext(Expression e) { | 258 Expression putInBooleanContext(Expression e) { |
219 if (e is Not && e.operand is Not) { | 259 if (e is Not && e.operand is Not) { |
220 return (e.operand as Not).operand; | 260 return (e.operand as Not).operand; |
221 } else { | 261 } else { |
222 return e; | 262 return e; |
223 } | 263 } |
(...skipping 26 matching lines...) Expand all Loading... |
250 } | 290 } |
251 // !x && !y ==> !(x || y) (only if lifting nots) | 291 // !x && !y ==> !(x || y) (only if lifting nots) |
252 if (e.left is Not && e.right is Not && liftNots) { | 292 if (e.left is Not && e.right is Not && liftNots) { |
253 e.left = (e.left as Not).operand; | 293 e.left = (e.left as Not).operand; |
254 e.right = (e.right as Not).operand; | 294 e.right = (e.right as Not).operand; |
255 e.isAnd = !e.isAnd; | 295 e.isAnd = !e.isAnd; |
256 return new Not(e); | 296 return new Not(e); |
257 } | 297 } |
258 return e; | 298 return e; |
259 } | 299 } |
| 300 if (e is ApplyBuiltinOperator && polarity == false) { |
| 301 BuiltinOperator negated = negateBuiltin(e.operator); |
| 302 if (negated != null) { |
| 303 e.operator = negated; |
| 304 return visitExpression(e); |
| 305 } else { |
| 306 return new Not(visitExpression(e)); |
| 307 } |
| 308 } |
260 if (e is Conditional) { | 309 if (e is Conditional) { |
261 // Handle polarity by: !(x ? y : z) ==> x ? !y : !z | 310 // Handle polarity by: !(x ? y : z) ==> x ? !y : !z |
262 // Rewrite individual branches now. The condition will be rewritten | 311 // Rewrite individual branches now. The condition will be rewritten |
263 // when we know what polarity to use (depends on which rewrite is used). | 312 // when we know what polarity to use (depends on which rewrite is used). |
264 e.thenExpression = makeCondition(e.thenExpression, polarity); | 313 e.thenExpression = makeCondition(e.thenExpression, polarity); |
265 e.elseExpression = makeCondition(e.elseExpression, polarity); | 314 e.elseExpression = makeCondition(e.elseExpression, polarity); |
266 | 315 |
267 // x ? true : false ==> x | 316 // x ? true : false ==> x |
268 if (isTrue(e.thenExpression) && isFalse(e.elseExpression)) { | 317 if (isTrue(e.thenExpression) && isFalse(e.elseExpression)) { |
269 return makeCondition(e.condition, true, liftNots: liftNots); | 318 return makeCondition(e.condition, true, liftNots: liftNots); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 | 393 |
345 Expression makeOr(Expression e1, Expression e2, {bool liftNots: true}) { | 394 Expression makeOr(Expression e1, Expression e2, {bool liftNots: true}) { |
346 if (e1 is Not && e2 is Not && liftNots) { | 395 if (e1 is Not && e2 is Not && liftNots) { |
347 return new Not(new LogicalOperator.and(e1.operand, e2.operand)); | 396 return new Not(new LogicalOperator.and(e1.operand, e2.operand)); |
348 } else { | 397 } else { |
349 return new LogicalOperator.or(e1, e2); | 398 return new LogicalOperator.or(e1, e2); |
350 } | 399 } |
351 } | 400 } |
352 } | 401 } |
353 | 402 |
OLD | NEW |