Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(540)

Unified Diff: sdk/lib/_internal/compiler/implementation/dart_backend/logical_rewriter.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/dart_backend/logical_rewriter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/logical_rewriter.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/logical_rewriter.dart
deleted file mode 100644
index 8689aaa02b34a5756854f7ae0d86a46c6d39c54b..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/logical_rewriter.dart
+++ /dev/null
@@ -1,453 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library logical_rewriter;
-
-import '../constants/values.dart' as values;
-import 'tree_ir_nodes.dart';
-
-/// Rewrites logical expressions to be more compact in the Tree IR.
-///
-/// In this class an expression is said to occur in "boolean context" if
-/// its result is immediately applied to boolean conversion.
-///
-/// IF STATEMENTS:
-///
-/// We apply the following two rules to [If] statements (see [visitIf]).
-///
-/// if (E) {} else S ==> if (!E) S else {} (else can be omitted)
-/// if (!E) S1 else S2 ==> if (E) S2 else S1 (unless previous rule applied)
-///
-/// NEGATION:
-///
-/// De Morgan's Laws are used to rewrite negations of logical operators so
-/// negations are closer to the root:
-///
-/// !x && !y --> !(x || y)
-///
-/// This is to enable other rewrites, such as branch swapping in an if. In some
-/// contexts, the rule is reversed because we do not expect to apply a rewrite
-/// rule to the result. For example:
-///
-/// z = !(x || y) ==> z = !x && !y;
-///
-/// CONDITIONALS:
-///
-/// Conditionals with boolean constant operands occur frequently in the input.
-/// They can often the re-written to logical operators, for instance:
-///
-/// if (x ? y : false) S1 else S2
-/// ==>
-/// if (x && y) S1 else S2
-///
-/// Conditionals are tricky to rewrite when they occur out of boolean context.
-/// Here we must apply more conservative rules, such as:
-///
-/// x ? true : false ==> !!x
-///
-/// If an operand is known to be a boolean, we can introduce a logical operator:
-///
-/// x ? y : false ==> x && y (if y is known to be a boolean)
-///
-/// The following sequence of rewrites demonstrates the merit of these rules:
-///
-/// x ? (y ? true : false) : false
-/// x ? !!y : false (double negation introduced by [toBoolean])
-/// x && !!y (!!y validated by [isBooleanValued])
-/// x && y (double negation removed by [putInBooleanContext])
-///
-class LogicalRewriter extends Visitor<Statement, Expression> {
-
- /// Statement to be executed next by natural fallthrough. Although fallthrough
- /// is not introduced in this phase, we need to reason about fallthrough when
- /// evaluating the benefit of swapping the branches of an [If].
- Statement fallthrough;
-
- void rewrite(FunctionDefinition definition) {
- if (definition.isAbstract) return;
-
- definition.body = visitStatement(definition.body);
- }
-
- Statement visitLabeledStatement(LabeledStatement node) {
- Statement savedFallthrough = fallthrough;
- fallthrough = node.next;
- node.body = visitStatement(node.body);
- fallthrough = savedFallthrough;
- node.next = visitStatement(node.next);
- return node;
- }
-
- Statement visitAssign(Assign node) {
- node.definition = visitExpression(node.definition);
- node.next = visitStatement(node.next);
- return node;
- }
-
- Statement visitReturn(Return node) {
- node.value = visitExpression(node.value);
- return node;
- }
-
- Statement visitBreak(Break node) {
- return node;
- }
-
- Statement visitContinue(Continue node) {
- return node;
- }
-
- bool isFallthroughBreak(Statement node) {
- return node is Break && node.target.binding.next == fallthrough;
- }
-
- Statement visitIf(If node) {
- // If one of the branches is empty (i.e. just a fallthrough), then that
- // branch should preferrably be the 'else' so we won't have to print it.
- // In other words, we wish to perform this rewrite:
- // if (E) {} else {S}
- // ==>
- // if (!E) {S}
- // In the tree language, empty statements do not exist yet, so we must check
- // if one branch contains a break that can be eliminated by fallthrough.
-
- // Swap branches if then is a fallthrough break.
- if (isFallthroughBreak(node.thenStatement)) {
- node.condition = new Not(node.condition);
- Statement tmp = node.thenStatement;
- node.thenStatement = node.elseStatement;
- node.elseStatement = tmp;
- }
-
- // Can the else part be eliminated?
- // (Either due to the above swap or if the break was already there).
- bool emptyElse = isFallthroughBreak(node.elseStatement);
-
- node.condition = makeCondition(node.condition, true, liftNots: !emptyElse);
- node.thenStatement = visitStatement(node.thenStatement);
- node.elseStatement = visitStatement(node.elseStatement);
-
- // If neither branch is empty, eliminate a negation in the condition
- // if (!E) S1 else S2
- // ==>
- // if (E) S2 else S1
- if (!emptyElse && node.condition is Not) {
- node.condition = (node.condition as Not).operand;
- Statement tmp = node.thenStatement;
- node.thenStatement = node.elseStatement;
- node.elseStatement = tmp;
- }
-
- return node;
- }
-
- Statement visitWhileTrue(WhileTrue node) {
- node.body = visitStatement(node.body);
- return node;
- }
-
- Statement visitWhileCondition(WhileCondition node) {
- node.condition = makeCondition(node.condition, true, liftNots: false);
- node.body = visitStatement(node.body);
- node.next = visitStatement(node.next);
- return node;
- }
-
- Statement visitExpressionStatement(ExpressionStatement node) {
- node.expression = visitExpression(node.expression);
- node.next = visitStatement(node.next);
- return node;
- }
-
-
- Expression visitVariable(Variable node) {
- return node;
- }
-
- Expression visitInvokeStatic(InvokeStatic node) {
- _rewriteList(node.arguments);
- return node;
- }
-
- Expression visitInvokeMethod(InvokeMethod node) {
- node.receiver = visitExpression(node.receiver);
- _rewriteList(node.arguments);
- return node;
- }
-
- Expression visitInvokeSuperMethod(InvokeSuperMethod node) {
- _rewriteList(node.arguments);
- return node;
- }
-
- Expression visitInvokeConstructor(InvokeConstructor node) {
- _rewriteList(node.arguments);
- return node;
- }
-
- Expression visitConcatenateStrings(ConcatenateStrings node) {
- _rewriteList(node.arguments);
- return node;
- }
-
- Expression visitLiteralList(LiteralList node) {
- _rewriteList(node.values);
- return node;
- }
-
- Expression visitLiteralMap(LiteralMap node) {
- node.entries.forEach((LiteralMapEntry entry) {
- entry.key = visitExpression(entry.key);
- entry.value = visitExpression(entry.value);
- });
- return node;
- }
-
- Expression visitTypeOperator(TypeOperator node) {
- node.receiver = visitExpression(node.receiver);
- return node;
- }
-
- Expression visitConstant(Constant node) {
- return node;
- }
-
- Expression visitThis(This node) {
- return node;
- }
-
- Expression visitReifyTypeVar(ReifyTypeVar node) {
- return node;
- }
-
- Expression visitFunctionExpression(FunctionExpression node) {
- new LogicalRewriter().rewrite(node.definition);
- return node;
- }
-
- Statement visitFunctionDeclaration(FunctionDeclaration node) {
- new LogicalRewriter().rewrite(node.definition);
- node.next = visitStatement(node.next);
- return node;
- }
-
- Expression visitNot(Not node) {
- return toBoolean(makeCondition(node.operand, false, liftNots: false));
- }
-
- Expression visitConditional(Conditional node) {
- // node.condition will be visited after the then and else parts, because its
- // polarity depends on what rewrite we use.
- node.thenExpression = visitExpression(node.thenExpression);
- node.elseExpression = visitExpression(node.elseExpression);
-
- // In the following, we must take care not to eliminate or introduce a
- // boolean conversion.
-
- // x ? true : false --> !!x
- if (isTrue(node.thenExpression) && isFalse(node.elseExpression)) {
- return toBoolean(makeCondition(node.condition, true, liftNots: false));
- }
- // x ? false : true --> !x
- if (isFalse(node.thenExpression) && isTrue(node.elseExpression)) {
- return toBoolean(makeCondition(node.condition, false, liftNots: false));
- }
-
- // x ? y : false ==> x && y (if y is known to be a boolean)
- if (isBooleanValued(node.thenExpression) && isFalse(node.elseExpression)) {
- return new LogicalOperator.and(
- makeCondition(node.condition, true, liftNots:false),
- putInBooleanContext(node.thenExpression));
- }
- // x ? y : true ==> !x || y (if y is known to be a boolean)
- if (isBooleanValued(node.thenExpression) && isTrue(node.elseExpression)) {
- return new LogicalOperator.or(
- makeCondition(node.condition, false, liftNots: false),
- putInBooleanContext(node.thenExpression));
- }
- // x ? true : y ==> x || y (if y if known to be boolean)
- if (isBooleanValued(node.elseExpression) && isTrue(node.thenExpression)) {
- return new LogicalOperator.or(
- makeCondition(node.condition, true, liftNots: false),
- putInBooleanContext(node.elseExpression));
- }
- // x ? false : y ==> !x && y (if y is known to be a boolean)
- if (isBooleanValued(node.elseExpression) && isFalse(node.thenExpression)) {
- return new LogicalOperator.and(
- makeCondition(node.condition, false, liftNots: false),
- putInBooleanContext(node.elseExpression));
- }
-
- node.condition = makeCondition(node.condition, true);
-
- // !x ? y : z ==> x ? z : y
- if (node.condition is Not) {
- node.condition = (node.condition as Not).operand;
- Expression tmp = node.thenExpression;
- node.thenExpression = node.elseExpression;
- node.elseExpression = tmp;
- }
-
- return node;
- }
-
- Expression visitLogicalOperator(LogicalOperator node) {
- node.left = makeCondition(node.left, true);
- node.right = makeCondition(node.right, true);
- return node;
- }
-
- /// True if the given expression is known to evaluate to a boolean.
- /// This will not recursively traverse [Conditional] expressions, but if
- /// applied to the result of [visitExpression] conditionals will have been
- /// rewritten anyway.
- bool isBooleanValued(Expression e) {
- return isTrue(e) || isFalse(e) || e is Not || e is LogicalOperator;
- }
-
- /// Rewrite an expression that was originally processed in a non-boolean
- /// context.
- Expression putInBooleanContext(Expression e) {
- if (e is Not && e.operand is Not) {
- return (e.operand as Not).operand;
- } else {
- return e;
- }
- }
-
- /// Forces a boolean conversion of the given expression.
- Expression toBoolean(Expression e) {
- if (isBooleanValued(e))
- return e;
- else
- return new Not(new Not(e));
- }
-
- /// Creates an equivalent boolean expression. The expression must occur in a
- /// context where its result is immediately subject to boolean conversion.
- /// If [polarity] if false, the negated condition will be created instead.
- /// If [liftNots] is true (default) then Not expressions will be lifted toward
- /// the root the condition so they can be eliminated by the caller.
- Expression makeCondition(Expression e, bool polarity, {bool liftNots:true}) {
- if (e is Not) {
- // !!E ==> E
- return makeCondition(e.operand, !polarity, liftNots: liftNots);
- }
- if (e is LogicalOperator) {
- // If polarity=false, then apply the rewrite !(x && y) ==> !x || !y
- e.left = makeCondition(e.left, polarity);
- e.right = makeCondition(e.right, polarity);
- if (!polarity) {
- e.isAnd = !e.isAnd;
- }
- // !x && !y ==> !(x || y) (only if lifting nots)
- if (e.left is Not && e.right is Not && liftNots) {
- e.left = (e.left as Not).operand;
- e.right = (e.right as Not).operand;
- e.isAnd = !e.isAnd;
- return new Not(e);
- }
- return e;
- }
- if (e is Conditional) {
- // Handle polarity by: !(x ? y : z) ==> x ? !y : !z
- // Rewrite individual branches now. The condition will be rewritten
- // when we know what polarity to use (depends on which rewrite is used).
- e.thenExpression = makeCondition(e.thenExpression, polarity);
- e.elseExpression = makeCondition(e.elseExpression, polarity);
-
- // x ? true : false ==> x
- if (isTrue(e.thenExpression) && isFalse(e.elseExpression)) {
- return makeCondition(e.condition, true, liftNots: liftNots);
- }
- // x ? false : true ==> !x
- if (isFalse(e.thenExpression) && isTrue(e.elseExpression)) {
- return makeCondition(e.condition, false, liftNots: liftNots);
- }
- // x ? true : y ==> x || y
- if (isTrue(e.thenExpression)) {
- return makeOr(makeCondition(e.condition, true),
- e.elseExpression,
- liftNots: liftNots);
- }
- // x ? false : y ==> !x && y
- if (isFalse(e.thenExpression)) {
- return makeAnd(makeCondition(e.condition, false),
- e.elseExpression,
- liftNots: liftNots);
- }
- // x ? y : true ==> !x || y
- if (isTrue(e.elseExpression)) {
- return makeOr(makeCondition(e.condition, false),
- e.thenExpression,
- liftNots: liftNots);
- }
- // x ? y : false ==> x && y
- if (isFalse(e.elseExpression)) {
- return makeAnd(makeCondition(e.condition, true),
- e.thenExpression,
- liftNots: liftNots);
- }
-
- e.condition = makeCondition(e.condition, true);
-
- // !x ? y : z ==> x ? z : y
- if (e.condition is Not) {
- e.condition = (e.condition as Not).operand;
- Expression tmp = e.thenExpression;
- e.thenExpression = e.elseExpression;
- e.elseExpression = tmp;
- }
- // x ? !y : !z ==> !(x ? y : z) (only if lifting nots)
- if (e.thenExpression is Not && e.elseExpression is Not && liftNots) {
- e.thenExpression = (e.thenExpression as Not).operand;
- e.elseExpression = (e.elseExpression as Not).operand;
- return new Not(e);
- }
- return e;
- }
- if (e is Constant && e.value.isBool) {
- // !true ==> false
- if (!polarity) {
- values.BoolConstantValue value = e.value;
- return new Constant.primitive(value.negate());
- }
- return e;
- }
- e = visitExpression(e);
- return polarity ? e : new Not(e);
- }
-
- bool isTrue(Expression e) {
- return e is Constant && e.value.isTrue;
- }
-
- bool isFalse(Expression e) {
- return e is Constant && e.value.isFalse;
- }
-
- Expression makeAnd(Expression e1, Expression e2, {bool liftNots: true}) {
- if (e1 is Not && e2 is Not && liftNots) {
- return new Not(new LogicalOperator.or(e1.operand, e2.operand));
- } else {
- return new LogicalOperator.and(e1, e2);
- }
- }
-
- Expression makeOr(Expression e1, Expression e2, {bool liftNots: true}) {
- if (e1 is Not && e2 is Not && liftNots) {
- return new Not(new LogicalOperator.and(e1.operand, e2.operand));
- } else {
- return new LogicalOperator.or(e1, e2);
- }
- }
-
- /// Destructively updates each entry of [l] with the result of visiting it.
- void _rewriteList(List<Expression> l) {
- for (int i = 0; i < l.length; i++) {
- l[i] = visitExpression(l[i]);
- }
- }
-}
-

Powered by Google App Engine
This is Rietveld 408576698