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) || isFalse(e) || e is Not || e is LogicalOperator || |
214 e is ApplyBuiltinOperator && operatorReturnsBool(e.operator); | |
Kevin Millikin (Google)
2015/06/12 12:19:10
I like parens around the && subexpression. I usua
asgerf
2015/06/15 09:26:18
What if we just split the line like this? Then the
Kevin Millikin (Google)
2015/06/15 10:24:09
It's OK this way.
| |
215 } | |
216 | |
217 /// True if the given operator always returns `true` or `false`. | |
218 bool operatorReturnsBool(BuiltinOperator operator) { | |
219 switch (operator) { | |
220 case BuiltinOperator.StrictEq: | |
221 case BuiltinOperator.StrictNeq: | |
222 case BuiltinOperator.LooseEq: | |
223 case BuiltinOperator.LooseNeq: | |
224 case BuiltinOperator.NumLt: | |
225 case BuiltinOperator.NumLe: | |
226 case BuiltinOperator.NumGt: | |
227 case BuiltinOperator.NumGe: | |
228 return true; | |
229 default: | |
230 return false; | |
231 } | |
232 } | |
233 | |
234 BuiltinOperator negateBuiltin(BuiltinOperator operator) { | |
235 switch (operator) { | |
236 case BuiltinOperator.StrictEq: return BuiltinOperator.StrictNeq; | |
237 case BuiltinOperator.StrictNeq: return BuiltinOperator.StrictEq; | |
238 case BuiltinOperator.LooseEq: return BuiltinOperator.LooseNeq; | |
239 case BuiltinOperator.LooseNeq: return BuiltinOperator.LooseEq; | |
240 | |
241 // Because of NaN, these do not have a negated form. | |
242 case BuiltinOperator.NumLt: | |
243 case BuiltinOperator.NumLe: | |
244 case BuiltinOperator.NumGt: | |
245 case BuiltinOperator.NumGe: | |
246 return null; | |
247 | |
248 default: | |
249 return null; | |
250 } | |
214 } | 251 } |
215 | 252 |
216 /// Rewrite an expression that was originally processed in a non-boolean | 253 /// Rewrite an expression that was originally processed in a non-boolean |
217 /// context. | 254 /// context. |
218 Expression putInBooleanContext(Expression e) { | 255 Expression putInBooleanContext(Expression e) { |
219 if (e is Not && e.operand is Not) { | 256 if (e is Not && e.operand is Not) { |
220 return (e.operand as Not).operand; | 257 return (e.operand as Not).operand; |
221 } else { | 258 } else { |
222 return e; | 259 return e; |
223 } | 260 } |
(...skipping 26 matching lines...) Expand all Loading... | |
250 } | 287 } |
251 // !x && !y ==> !(x || y) (only if lifting nots) | 288 // !x && !y ==> !(x || y) (only if lifting nots) |
252 if (e.left is Not && e.right is Not && liftNots) { | 289 if (e.left is Not && e.right is Not && liftNots) { |
253 e.left = (e.left as Not).operand; | 290 e.left = (e.left as Not).operand; |
254 e.right = (e.right as Not).operand; | 291 e.right = (e.right as Not).operand; |
255 e.isAnd = !e.isAnd; | 292 e.isAnd = !e.isAnd; |
256 return new Not(e); | 293 return new Not(e); |
257 } | 294 } |
258 return e; | 295 return e; |
259 } | 296 } |
297 if (e is ApplyBuiltinOperator && polarity == false) { | |
298 BuiltinOperator negated = negateBuiltin(e.operator); | |
299 if (negated != null) { | |
300 e.operator = negated; | |
301 return visitExpression(e); | |
302 } else { | |
303 return new Not(visitExpression(e)); | |
304 } | |
305 } | |
260 if (e is Conditional) { | 306 if (e is Conditional) { |
261 // Handle polarity by: !(x ? y : z) ==> x ? !y : !z | 307 // Handle polarity by: !(x ? y : z) ==> x ? !y : !z |
262 // Rewrite individual branches now. The condition will be rewritten | 308 // Rewrite individual branches now. The condition will be rewritten |
263 // when we know what polarity to use (depends on which rewrite is used). | 309 // when we know what polarity to use (depends on which rewrite is used). |
264 e.thenExpression = makeCondition(e.thenExpression, polarity); | 310 e.thenExpression = makeCondition(e.thenExpression, polarity); |
265 e.elseExpression = makeCondition(e.elseExpression, polarity); | 311 e.elseExpression = makeCondition(e.elseExpression, polarity); |
266 | 312 |
267 // x ? true : false ==> x | 313 // x ? true : false ==> x |
268 if (isTrue(e.thenExpression) && isFalse(e.elseExpression)) { | 314 if (isTrue(e.thenExpression) && isFalse(e.elseExpression)) { |
269 return makeCondition(e.condition, true, liftNots: liftNots); | 315 return makeCondition(e.condition, true, liftNots: liftNots); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
344 | 390 |
345 Expression makeOr(Expression e1, Expression e2, {bool liftNots: true}) { | 391 Expression makeOr(Expression e1, Expression e2, {bool liftNots: true}) { |
346 if (e1 is Not && e2 is Not && liftNots) { | 392 if (e1 is Not && e2 is Not && liftNots) { |
347 return new Not(new LogicalOperator.and(e1.operand, e2.operand)); | 393 return new Not(new LogicalOperator.and(e1.operand, e2.operand)); |
348 } else { | 394 } else { |
349 return new LogicalOperator.or(e1, e2); | 395 return new LogicalOperator.or(e1, e2); |
350 } | 396 } |
351 } | 397 } |
352 } | 398 } |
353 | 399 |
OLD | NEW |