OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library loop_rewriter; | |
6 | |
7 import 'tree_ir_nodes.dart'; | |
8 | |
9 /// Rewrites [WhileTrue] statements with an [If] body into a [WhileCondition], | |
10 /// in situations where only one of the branches contains a [Continue] to the | |
11 /// loop. Schematically: | |
12 /// | |
13 /// L: | |
14 /// while (true) { | |
15 /// if (E) { | |
16 /// S1 (has references to L) | |
17 /// } else { | |
18 /// S2 (has no references to L) | |
19 /// } | |
20 /// } | |
21 /// ==> | |
22 /// L: | |
23 /// while (E) { | |
24 /// S1 | |
25 /// }; | |
26 /// S2 | |
27 /// | |
28 /// A similar transformation is used when S2 occurs in the 'then' position. | |
29 /// | |
30 /// Note that the above pattern needs no iteration since nested ifs | |
31 /// have been collapsed previously in the [StatementRewriter] phase. | |
32 class LoopRewriter extends RecursiveVisitor { | |
33 | |
34 Set<Label> usedContinueLabels = new Set<Label>(); | |
35 | |
36 void rewrite(FunctionDefinition function) { | |
37 if (function.isAbstract) return; | |
38 | |
39 function.body = visitStatement(function.body); | |
40 } | |
41 | |
42 Statement visitLabeledStatement(LabeledStatement node) { | |
43 node.body = visitStatement(node.body); | |
44 node.next = visitStatement(node.next); | |
45 return node; | |
46 } | |
47 | |
48 Statement visitAssign(Assign node) { | |
49 // Clean up redundant assignments left behind in the previous phase. | |
50 if (node.variable == node.definition) { | |
51 --node.variable.readCount; | |
52 --node.variable.writeCount; | |
53 return visitStatement(node.next); | |
54 } | |
55 visitExpression(node.definition); | |
56 node.next = visitStatement(node.next); | |
57 return node; | |
58 } | |
59 | |
60 Statement visitReturn(Return node) { | |
61 visitExpression(node.value); | |
62 return node; | |
63 } | |
64 | |
65 Statement visitBreak(Break node) { | |
66 return node; | |
67 } | |
68 | |
69 Statement visitContinue(Continue node) { | |
70 usedContinueLabels.add(node.target); | |
71 return node; | |
72 } | |
73 | |
74 Statement visitIf(If node) { | |
75 visitExpression(node.condition); | |
76 node.thenStatement = visitStatement(node.thenStatement); | |
77 node.elseStatement = visitStatement(node.elseStatement); | |
78 return node; | |
79 } | |
80 | |
81 Statement visitWhileTrue(WhileTrue node) { | |
82 assert(!usedContinueLabels.contains(node.label)); | |
83 if (node.body is If) { | |
84 If body = node.body; | |
85 body.thenStatement = visitStatement(body.thenStatement); | |
86 bool thenHasContinue = usedContinueLabels.remove(node.label); | |
87 body.elseStatement = visitStatement(body.elseStatement); | |
88 bool elseHasContinue = usedContinueLabels.remove(node.label); | |
89 if (thenHasContinue && !elseHasContinue) { | |
90 node.label.binding = null; // Prepare to rebind the label. | |
91 return new WhileCondition( | |
92 node.label, | |
93 body.condition, | |
94 body.thenStatement, | |
95 body.elseStatement); | |
96 } else if (!thenHasContinue && elseHasContinue) { | |
97 node.label.binding = null; | |
98 return new WhileCondition( | |
99 node.label, | |
100 new Not(body.condition), | |
101 body.elseStatement, | |
102 body.thenStatement); | |
103 } | |
104 } else { | |
105 node.body = visitStatement(node.body); | |
106 usedContinueLabels.remove(node.label); | |
107 } | |
108 return node; | |
109 } | |
110 | |
111 Statement visitWhileCondition(WhileCondition node) { | |
112 // Note: not reachable but the implementation is trivial | |
113 visitExpression(node.condition); | |
114 node.body = visitStatement(node.body); | |
115 node.next = visitStatement(node.next); | |
116 return node; | |
117 } | |
118 | |
119 Statement visitExpressionStatement(ExpressionStatement node) { | |
120 visitExpression(node.expression); | |
121 node.next = visitStatement(node.next); | |
122 return node; | |
123 } | |
124 | |
125 Statement visitFunctionDeclaration(FunctionDeclaration node) { | |
126 new LoopRewriter().rewrite(node.definition); | |
127 node.next = visitStatement(node.next); | |
128 return node; | |
129 } | |
130 | |
131 void visitFunctionExpression(FunctionExpression node) { | |
132 new LoopRewriter().rewrite(node.definition); | |
133 } | |
134 } | |
OLD | NEW |