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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart

Issue 318723002: dart2dart: Restore loops with conditions and updates in backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Kevin's comments + bugfix Created 6 years, 6 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 dart_tree; 5 library dart_tree;
6 6
7 import '../dart2jslib.dart' as dart2js; 7 import '../dart2jslib.dart' as dart2js;
8 import '../elements/elements.dart' 8 import '../elements/elements.dart'
9 show Element, FunctionElement, FunctionSignature, ParameterElement, 9 show Element, FunctionElement, FunctionSignature, ParameterElement,
10 ClassElement; 10 ClassElement;
(...skipping 20 matching lines...) Expand all
31 /** 31 /**
32 * The base class of all Tree nodes. 32 * The base class of all Tree nodes.
33 */ 33 */
34 abstract class Node { 34 abstract class Node {
35 } 35 }
36 36
37 /** 37 /**
38 * The base class of [Expression]s. 38 * The base class of [Expression]s.
39 */ 39 */
40 abstract class Expression extends Node { 40 abstract class Expression extends Node {
41 accept(Visitor v); 41 accept(ExpressionVisitor v);
42 42
43 /// Temporary variable used by [StatementRewriter]. 43 /// Temporary variable used by [StatementRewriter].
44 /// If set to true, this expression has already had enclosing assignments 44 /// If set to true, this expression has already had enclosing assignments
45 /// propagated into its variables, and should not be processed again. 45 /// propagated into its variables, and should not be processed again.
46 /// It is only set for expressions that are known to be in risk of redundant 46 /// It is only set for expressions that are known to be in risk of redundant
47 /// processing. 47 /// processing.
48 bool processed = false; 48 bool processed = false;
49 } 49 }
50 50
51 abstract class Statement extends Node { 51 abstract class Statement extends Node {
52 Statement get next; 52 Statement get next;
53 void set next(Statement s); 53 void set next(Statement s);
54 accept(Visitor v); 54 accept(StatementVisitor v);
55 } 55 }
56 56
57 /** 57 /**
58 * Labels name [LabeledStatement]s. 58 * Labels name [LabeledStatement]s.
59 */ 59 */
60 class Label { 60 class Label {
61 // A counter used to generate names. The counter is reset to 0 for each 61 // A counter used to generate names. The counter is reset to 0 for each
62 // function emitted. 62 // function emitted.
63 static int counter = 0; 63 static int counter = 0;
64 static String _newName() => 'L${counter++}'; 64 static String _newName() => 'L${counter++}';
65 65
66 String cachedName; 66 String cachedName;
67 67
68 String get name { 68 String get name {
69 if (cachedName == null) cachedName = _newName(); 69 if (cachedName == null) cachedName = _newName();
70 return cachedName; 70 return cachedName;
71 } 71 }
72 72
73 /// Number of [Break] statements that target this label. 73 /// Number of [Break] or [Continue] statements that target this label.
74 /// The [Break] constructor will increment this automatically, but the 74 /// The [Break] constructor will increment this automatically, but the
75 /// counter must be decremented by hand when a [Break] becomes orphaned. 75 /// counter must be decremented by hand when a [Break] becomes orphaned.
76 int breakCount = 0; 76 int useCount = 0;
77 77
78 /// The [LabeledStatement] binding this label. 78 /// The [LabeledStatement] or [WhileTrue] binding this label.
79 LabeledStatement binding; 79 JumpTarget binding;
80 } 80 }
81 81
82 /** 82 /**
83 * Variables are [Expression]s. 83 * Variables are [Expression]s.
84 */ 84 */
85 class Variable extends Expression { 85 class Variable extends Expression {
86 // A counter used to generate names. The counter is reset to 0 for each 86 // A counter used to generate names. The counter is reset to 0 for each
87 // function emitted. 87 // function emitted.
88 static int counter = 0; 88 static int counter = 0;
89 static String _newName() => 'v${counter++}'; 89 static String _newName() => 'v${counter++}';
90 90
91 Element element; 91 Element element;
92 String cachedName; 92 String cachedName;
93 93
94 String get name { 94 String get name {
95 if (cachedName != null) return cachedName; 95 if (cachedName != null) return cachedName;
96 return cachedName = ((element == null) ? _newName() : element.name); 96 return cachedName = ((element == null) ? _newName() : element.name);
97 } 97 }
98 98
99 Variable(this.element); 99 Variable(this.element);
100 100
101 accept(Visitor visitor) => visitor.visitVariable(this); 101 accept(ExpressionVisitor visitor) => visitor.visitVariable(this);
102 } 102 }
103 103
104 /** 104 /**
105 * Common interface for invocations with arguments. 105 * Common interface for invocations with arguments.
106 */ 106 */
107 abstract class Invoke { 107 abstract class Invoke {
108 List<Expression> get arguments; 108 List<Expression> get arguments;
109 Selector get selector; 109 Selector get selector;
110 } 110 }
111 111
112 /** 112 /**
113 * A call to a static target. 113 * A call to a static target.
114 * 114 *
115 * In contrast to the CPS-based IR, the arguments can be arbitrary expressions. 115 * In contrast to the CPS-based IR, the arguments can be arbitrary expressions.
116 */ 116 */
117 class InvokeStatic extends Expression implements Invoke { 117 class InvokeStatic extends Expression implements Invoke {
118 final FunctionElement target; 118 final FunctionElement target;
119 final List<Expression> arguments; 119 final List<Expression> arguments;
120 final Selector selector; 120 final Selector selector;
121 121
122 InvokeStatic(this.target, this.selector, this.arguments); 122 InvokeStatic(this.target, this.selector, this.arguments);
123 123
124 accept(Visitor visitor) => visitor.visitInvokeStatic(this); 124 accept(ExpressionVisitor visitor) => visitor.visitInvokeStatic(this);
125 } 125 }
126 126
127 /** 127 /**
128 * A call to a method, operator, getter, setter or index getter/setter. 128 * A call to a method, operator, getter, setter or index getter/setter.
129 * 129 *
130 * In contrast to the CPS-based IR, the receiver and arguments can be 130 * In contrast to the CPS-based IR, the receiver and arguments can be
131 * arbitrary expressions. 131 * arbitrary expressions.
132 */ 132 */
133 class InvokeMethod extends Expression implements Invoke { 133 class InvokeMethod extends Expression implements Invoke {
134 Expression receiver; 134 Expression receiver;
135 final Selector selector; 135 final Selector selector;
136 final List<Expression> arguments; 136 final List<Expression> arguments;
137 137
138 InvokeMethod(this.receiver, this.selector, this.arguments) { 138 InvokeMethod(this.receiver, this.selector, this.arguments) {
139 assert(receiver != null); 139 assert(receiver != null);
140 } 140 }
141 141
142 accept(Visitor visitor) => visitor.visitInvokeMethod(this); 142 accept(ExpressionVisitor visitor) => visitor.visitInvokeMethod(this);
143 } 143 }
144 144
145 /** 145 /**
146 * Non-const call to a factory or generative constructor. 146 * Non-const call to a factory or generative constructor.
147 */ 147 */
148 class InvokeConstructor extends Expression implements Invoke { 148 class InvokeConstructor extends Expression implements Invoke {
149 final GenericType type; 149 final GenericType type;
150 final FunctionElement target; 150 final FunctionElement target;
151 final List<Expression> arguments; 151 final List<Expression> arguments;
152 final Selector selector; 152 final Selector selector;
153 153
154 InvokeConstructor(this.type, this.target, this.selector, this.arguments); 154 InvokeConstructor(this.type, this.target, this.selector, this.arguments);
155 155
156 ClassElement get targetClass => target.enclosingElement; 156 ClassElement get targetClass => target.enclosingElement;
157 157
158 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); 158 accept(ExpressionVisitor visitor) => visitor.visitInvokeConstructor(this);
159 } 159 }
160 160
161 /// Calls [toString] on each argument and concatenates the results. 161 /// Calls [toString] on each argument and concatenates the results.
162 class ConcatenateStrings extends Expression { 162 class ConcatenateStrings extends Expression {
163 final List<Expression> arguments; 163 final List<Expression> arguments;
164 164
165 ConcatenateStrings(this.arguments); 165 ConcatenateStrings(this.arguments);
166 166
167 accept(Visitor visitor) => visitor.visitConcatenateStrings(this); 167 accept(ExpressionVisitor visitor) => visitor.visitConcatenateStrings(this);
168 } 168 }
169 169
170 /** 170 /**
171 * A constant. 171 * A constant.
172 */ 172 */
173 class Constant extends Expression { 173 class Constant extends Expression {
174 dart2js.Constant value; 174 dart2js.Constant value;
175 175
176 Constant(this.value); 176 Constant(this.value);
177 177
178 accept(Visitor visitor) => visitor.visitConstant(this); 178 accept(ExpressionVisitor visitor) => visitor.visitConstant(this);
179 } 179 }
180 180
181 class LiteralList extends Expression { 181 class LiteralList extends Expression {
182 final List<Expression> values; 182 final List<Expression> values;
183 183
184 LiteralList(this.values) ; 184 LiteralList(this.values) ;
185 185
186 accept(Visitor visitor) => visitor.visitLiteralList(this); 186 accept(ExpressionVisitor visitor) => visitor.visitLiteralList(this);
187 } 187 }
188 188
189 class LiteralMap extends Expression { 189 class LiteralMap extends Expression {
190 final List<Expression> keys; 190 final List<Expression> keys;
191 final List<Expression> values; 191 final List<Expression> values;
192 192
193 LiteralMap(this.keys, this.values) ; 193 LiteralMap(this.keys, this.values) ;
194 194
195 accept(Visitor visitor) => visitor.visitLiteralMap(this); 195 accept(ExpressionVisitor visitor) => visitor.visitLiteralMap(this);
196 } 196 }
197 197
198 class InvokeConstConstructor extends Expression implements Invoke { 198 class InvokeConstConstructor extends Expression implements Invoke {
199 final GenericType type; 199 final GenericType type;
200 final FunctionElement target; 200 final FunctionElement target;
201 final List<Expression> arguments; 201 final List<Expression> arguments;
202 final Selector selector; 202 final Selector selector;
203 203
204 ClassElement get targetClass => target.enclosingElement; 204 ClassElement get targetClass => target.enclosingElement;
205 205
206 InvokeConstConstructor(this.type, this.target, this.selector, this.arguments); 206 InvokeConstConstructor(this.type, this.target, this.selector, this.arguments);
207 207
208 accept(Visitor visitor) => visitor.visitInvokeConstConstructor(this); 208 accept(ExpressionVisitor visitor) => visitor.visitInvokeConstConstructor(this) ;
209 } 209 }
210 210
211 /// A conditional expression. 211 /// A conditional expression.
212 class Conditional extends Expression { 212 class Conditional extends Expression {
213 Expression condition; 213 Expression condition;
214 Expression thenExpression; 214 Expression thenExpression;
215 Expression elseExpression; 215 Expression elseExpression;
216 216
217 Conditional(this.condition, this.thenExpression, this.elseExpression); 217 Conditional(this.condition, this.thenExpression, this.elseExpression);
218 218
219 accept(Visitor visitor) => visitor.visitConditional(this); 219 accept(ExpressionVisitor visitor) => visitor.visitConditional(this);
220 } 220 }
221 221
222 /// An && or || expression. The operator is internally represented as a boolean 222 /// An && or || expression. The operator is internally represented as a boolean
223 /// [isAnd] to simplify rewriting of logical operators. 223 /// [isAnd] to simplify rewriting of logical operators.
224 class LogicalOperator extends Expression { 224 class LogicalOperator extends Expression {
225 Expression left; 225 Expression left;
226 bool isAnd; 226 bool isAnd;
227 Expression right; 227 Expression right;
228 228
229 LogicalOperator(this.left, this.right, this.isAnd); 229 LogicalOperator(this.left, this.right, this.isAnd);
230 LogicalOperator.and(this.left, this.right) : isAnd = true; 230 LogicalOperator.and(this.left, this.right) : isAnd = true;
231 LogicalOperator.or(this.left, this.right) : isAnd = false; 231 LogicalOperator.or(this.left, this.right) : isAnd = false;
232 232
233 String get operator => isAnd ? '&&' : '||'; 233 String get operator => isAnd ? '&&' : '||';
234 234
235 accept(Visitor visitor) => visitor.visitLogicalOperator(this); 235 accept(ExpressionVisitor visitor) => visitor.visitLogicalOperator(this);
236 } 236 }
237 237
238 /// Logical negation. 238 /// Logical negation.
239 class Not extends Expression { 239 class Not extends Expression {
240 Expression operand; 240 Expression operand;
241 241
242 Not(this.operand); 242 Not(this.operand);
243 243
244 accept(Visitor visitor) => visitor.visitNot(this); 244 accept(ExpressionVisitor visitor) => visitor.visitNot(this);
245 }
246
247 /// A [LabeledStatement] or [WhileTrue] or [WhileCondition].
248 abstract class JumpTarget extends Statement {
249 Label get label;
250 Statement get body;
245 } 251 }
246 252
247 /** 253 /**
248 * A labeled statement. Breaks to the label within the labeled statement 254 * A labeled statement. Breaks to the label within the labeled statement
249 * target the successor statement. 255 * target the successor statement.
250 */ 256 */
251 class LabeledStatement extends Statement { 257 class LabeledStatement extends JumpTarget {
252 Statement next; 258 Statement next;
253 final Label label; 259 final Label label;
254 Statement body; 260 Statement body;
255 261
256 LabeledStatement(this.label, this.body, this.next) { 262 LabeledStatement(this.label, this.body, this.next) {
257 assert(label.binding == null); 263 assert(label.binding == null);
258 label.binding = this; 264 label.binding = this;
259 } 265 }
260 266
261 accept(Visitor visitor) => visitor.visitLabeledStatement(this); 267 accept(StatementVisitor visitor) => visitor.visitLabeledStatement(this);
268 }
269
270 /// A [WhileTrue] or [WhileCondition] loop.
271 abstract class Loop extends JumpTarget {
272 /// When a [Continue] to a loop is executed, all update expressions are
273 /// evaluated right-to-left before control resumes at the head of the loop.
274 List<Expression> get updates;
275 }
276
277 /**
278 * A labeled while(true) loop.
279 */
280 class WhileTrue extends Loop {
281 final Label label;
282 Statement body;
283 final List<Expression> updates = <Expression>[];
284
285 WhileTrue(this.label, this.body) {
286 assert(label.binding == null);
287 label.binding = this;
288 }
289
290 Statement get next => null;
291 void set next(Statement s) => throw 'UNREACHABLE';
292
293 accept(StatementVisitor visitor) => visitor.visitWhileTrue(this);
294 }
295
296 /**
297 * A while loop with a condition. If the condition is false, control resumes
298 * at the [next] statement.
299 *
300 * It is NOT valid to target this statement with a [Break].
301 * The only way to reach [next] is for the condition to evaluate to false.
302 *
303 * [WhileCondition] statements are introduced in the [LoopRewriter] and is
304 * assumed not to occur before then.
305 */
306 class WhileCondition extends Loop {
307 final Label label;
308 Expression condition;
309 Statement body;
310 Statement next;
311 final List<Expression> updates;
312
313 WhileCondition(this.label, this.condition, this.body,
314 this.next, this.updates) {
315 assert(label.binding == null);
316 label.binding = this;
317 }
318
319 accept(StatementVisitor visitor) => visitor.visitWhileCondition(this);
320 }
321
322
323 /// A [Break] or [Continue] statement.
324 abstract class Jump extends Statement {
325 Label get target;
326 }
327
328 /**
329 * A break from an enclosing [LabeledStatement]. The break targets the
330 * labeled statement's successor statement.
331 */
332 class Break extends Jump {
333 final Label target;
334
335 Statement get next => null;
336 void set next(Statement s) => throw 'UNREACHABLE';
337
338 Break(this.target) {
339 ++target.useCount;
340 }
341
342 accept(StatementVisitor visitor) => visitor.visitBreak(this);
343 }
344
345 /**
346 * A continue to an enclosing [WhileTrue] loop. The continue targets the
347 * loop's body.
348 */
349 class Continue extends Jump {
350 final Label target;
351
352 Statement get next => null;
353 void set next(Statement s) => throw 'UNREACHABLE';
354
355 Continue(this.target) {
356 ++target.useCount;
357 }
358
359 accept(StatementVisitor visitor) => visitor.visitContinue(this);
262 } 360 }
263 361
264 /** 362 /**
265 * An assignments of an [Expression] to a [Variable]. 363 * An assignments of an [Expression] to a [Variable].
266 * 364 *
267 * In contrast to the CPS-based IR, non-primitive expressions can be assigned 365 * In contrast to the CPS-based IR, non-primitive expressions can be assigned
268 * to variables. 366 * to variables.
269 */ 367 */
270 class Assign extends Statement { 368 class Assign extends Statement {
271 Statement next; 369 Statement next;
272 final Variable variable; 370 final Variable variable;
273 Expression definition; 371 Expression definition;
274 final bool hasExactlyOneUse; 372 final bool hasExactlyOneUse;
275 373
276 Assign(this.variable, this.definition, this.next, this.hasExactlyOneUse); 374 Assign(this.variable, this.definition, this.next, this.hasExactlyOneUse);
277 375
278 accept(Visitor visitor) => visitor.visitAssign(this); 376 accept(StatementVisitor visitor) => visitor.visitAssign(this);
279 } 377 }
280 378
379
281 /** 380 /**
282 * A return exit from the function. 381 * A return exit from the function.
283 * 382 *
284 * In contrast to the CPS-based IR, the return value is an arbitrary 383 * In contrast to the CPS-based IR, the return value is an arbitrary
285 * expression. 384 * expression.
286 */ 385 */
287 class Return extends Statement { 386 class Return extends Statement {
288 /// Should not be null. Use [Constant] with [NullConstant] for void returns. 387 /// Should not be null. Use [Constant] with [NullConstant] for void returns.
289 Expression value; 388 Expression value;
290 389
291 Statement get next => null; 390 Statement get next => null;
292 void set next(Statement s) => throw 'UNREACHABLE'; 391 void set next(Statement s) => throw 'UNREACHABLE';
293 392
294 Return(this.value); 393 Return(this.value);
295 394
296 accept(Visitor visitor) => visitor.visitReturn(this); 395 accept(StatementVisitor visitor) => visitor.visitReturn(this);
297 } 396 }
298 397
299 /**
300 * A break from an enclosing [LabeledStatement]. The break targets the
301 * labeled statement's successor statement.
302 */
303 class Break extends Statement {
304 Label _target;
305 398
306 Label get target => _target;
307 void set target(Label newTarget) {
308 ++newTarget.breakCount;
309 --_target.breakCount;
310 _target = newTarget;
311 }
312 399
313 Statement get next => null;
314 void set next(Statement s) => throw 'UNREACHABLE';
315
316 Break(this._target) {
317 ++target.breakCount;
318 }
319
320 accept(Visitor visitor) => visitor.visitBreak(this);
321 }
322
323 /**
324 * A continue to an enclosing [While] loop. The continue targets the
325 * loop's body.
326 */
327 class Continue extends Statement {
328 Label target;
329
330 Statement get next => null;
331 void set next(Statement s) => throw 'UNREACHABLE';
332
333 Continue(this.target);
334
335 accept(Visitor visitor) => visitor.visitContinue(this);
336 }
337 400
338 /** 401 /**
339 * A conditional branch based on the true value of an [Expression]. 402 * A conditional branch based on the true value of an [Expression].
340 */ 403 */
341 class If extends Statement { 404 class If extends Statement {
342 Expression condition; 405 Expression condition;
343 Statement thenStatement; 406 Statement thenStatement;
344 Statement elseStatement; 407 Statement elseStatement;
345 408
346 Statement get next => null; 409 Statement get next => null;
347 void set next(Statement s) => throw 'UNREACHABLE'; 410 void set next(Statement s) => throw 'UNREACHABLE';
348 411
349 If(this.condition, this.thenStatement, this.elseStatement); 412 If(this.condition, this.thenStatement, this.elseStatement);
350 413
351 accept(Visitor visitor) => visitor.visitIf(this); 414 accept(StatementVisitor visitor) => visitor.visitIf(this);
352 }
353
354 /**
355 * A labeled while(true) loop.
356 */
357 class While extends Statement {
358 final Label label;
359 Statement body;
360
361 While(this.label, this.body);
362
363 Statement get next => null;
364 void set next(Statement s) => throw 'UNREACHABLE';
365
366 accept(Visitor visitor) => visitor.visitWhile(this);
367 } 415 }
368 416
369 417
370 class ExpressionStatement extends Statement { 418 class ExpressionStatement extends Statement {
371 Statement next; 419 Statement next;
372 Expression expression; 420 Expression expression;
373 421
374 ExpressionStatement(this.expression, this.next); 422 ExpressionStatement(this.expression, this.next);
375 423
376 accept(Visitor visitor) => visitor.visitExpressionStatement(this); 424 accept(StatementVisitor visitor) => visitor.visitExpressionStatement(this);
377 } 425 }
378 426
379 class FunctionDefinition extends Node { 427 class FunctionDefinition extends Node {
380 final List<Variable> parameters; 428 final List<Variable> parameters;
381 Statement body; 429 Statement body;
382 430
383 FunctionDefinition(this.parameters, this.body); 431 FunctionDefinition(this.parameters, this.body);
384 } 432 }
385 433
386 abstract class Visitor<S, E> { 434 abstract class ExpressionVisitor<E> {
387 E visitExpression(Expression e) => e.accept(this); 435 E visitExpression(Expression e) => e.accept(this);
388 E visitVariable(Variable node); 436 E visitVariable(Variable node);
389 E visitInvokeStatic(InvokeStatic node); 437 E visitInvokeStatic(InvokeStatic node);
390 E visitInvokeMethod(InvokeMethod node); 438 E visitInvokeMethod(InvokeMethod node);
391 E visitInvokeConstructor(InvokeConstructor node); 439 E visitInvokeConstructor(InvokeConstructor node);
392 E visitConcatenateStrings(ConcatenateStrings node); 440 E visitConcatenateStrings(ConcatenateStrings node);
393 E visitConstant(Constant node); 441 E visitConstant(Constant node);
394 E visitConditional(Conditional node); 442 E visitConditional(Conditional node);
395 E visitLogicalOperator(LogicalOperator node); 443 E visitLogicalOperator(LogicalOperator node);
396 E visitNot(Not node); 444 E visitNot(Not node);
397 E visitLiteralList(LiteralList node); 445 E visitLiteralList(LiteralList node);
398 E visitLiteralMap(LiteralMap node); 446 E visitLiteralMap(LiteralMap node);
399 E visitInvokeConstConstructor(InvokeConstConstructor node); 447 E visitInvokeConstConstructor(InvokeConstConstructor node);
448 }
400 449
450 abstract class StatementVisitor<S> {
401 S visitStatement(Statement s) => s.accept(this); 451 S visitStatement(Statement s) => s.accept(this);
402 S visitLabeledStatement(LabeledStatement node); 452 S visitLabeledStatement(LabeledStatement node);
403 S visitAssign(Assign node); 453 S visitAssign(Assign node);
404 S visitReturn(Return node); 454 S visitReturn(Return node);
405 S visitBreak(Break node); 455 S visitBreak(Break node);
406 S visitContinue(Continue node); 456 S visitContinue(Continue node);
407 S visitIf(If node); 457 S visitIf(If node);
408 S visitWhile(While node); 458 S visitWhileTrue(WhileTrue node);
459 S visitWhileCondition(WhileCondition node);
409 S visitExpressionStatement(ExpressionStatement node); 460 S visitExpressionStatement(ExpressionStatement node);
410 } 461 }
411 462
463 abstract class Visitor<S,E> implements ExpressionVisitor<E>,
464 StatementVisitor<S> {
465 E visitExpression(Expression e) => e.accept(this);
466 S visitStatement(Statement s) => s.accept(this);
467 }
468
412 /** 469 /**
413 * Builder translates from CPS-based IR to direct-style Tree. 470 * Builder translates from CPS-based IR to direct-style Tree.
414 * 471 *
415 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced 472 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced
416 * non-exit continuation `Cont(v, body)` is translated into a direct-style call 473 * non-exit continuation `Cont(v, body)` is translated into a direct-style call
417 * whose value is bound in the continuation body: 474 * whose value is bound in the continuation body:
418 * 475 *
419 * `LetVal(v, Invoke(fun, args), body)` 476 * `LetVal(v, Invoke(fun, args), body)`
420 * 477 *
421 * and the continuation definition is eliminated. A similar translation is 478 * and the continuation definition is eliminated. A similar translation is
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 // inline at the invocation site. 686 // inline at the invocation site.
630 // - If there are multiple uses, translate to Break. 687 // - If there are multiple uses, translate to Break.
631 // * Recursive continuations 688 // * Recursive continuations
632 // - There is a single non-recursive invocation. Translate 689 // - There is a single non-recursive invocation. Translate
633 // the continuation body inline as a labeled loop at the 690 // the continuation body inline as a labeled loop at the
634 // invocation site. 691 // invocation site.
635 // - Translate the recursive invocations to Continue. 692 // - Translate the recursive invocations to Continue.
636 if (cont.isRecursive) { 693 if (cont.isRecursive) {
637 return node.isRecursive 694 return node.isRecursive
638 ? new Continue(labels[cont]) 695 ? new Continue(labels[cont])
639 : new While(labels[cont], visit(cont.body)); 696 : new WhileTrue(labels[cont], visit(cont.body));
640 } else { 697 } else {
641 return cont.hasExactlyOneUse 698 return cont.hasExactlyOneUse
642 ? visit(cont.body) 699 ? visit(cont.body)
643 : new Break(labels[cont]); 700 : new Break(labels[cont]);
644 } 701 }
645 }); 702 });
646 } 703 }
647 } 704 }
648 705
649 Statement visitBranch(ir.Branch node) { 706 Statement visitBranch(ir.Branch node) {
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 * v0 = foo(); return v0; 826 * v0 = foo(); return v0;
770 * 827 *
771 * This can lead to propagation of v0. 828 * This can lead to propagation of v0.
772 * 829 *
773 * See [visitBreak] and [visitLabeledStatement]. 830 * See [visitBreak] and [visitLabeledStatement].
774 * 831 *
775 * 832 *
776 * REDIRECT BREAKS: 833 * REDIRECT BREAKS:
777 * Labeled statements whose next is a break become flattened and all breaks 834 * Labeled statements whose next is a break become flattened and all breaks
778 * to their label are redirected. 835 * to their label are redirected.
779 * For example: 836 * For example, where 'jump' is either break or continue:
780 * 837 *
781 * L0: {... break L0 ...}; break L1 838 * L0: {... break L0 ...}; jump L1
782 * ==> 839 * ==>
783 * {... break L1 ...} 840 * {... jump L1 ...}
784 * 841 *
785 * This may trigger a flattening of nested ifs in case the eliminated label 842 * This may trigger a flattening of nested ifs in case the eliminated label
786 * separated two ifs. 843 * separated two ifs.
787 */ 844 */
788 class StatementRewriter extends Visitor<Statement, Expression> { 845 class StatementRewriter extends Visitor<Statement, Expression> {
789 // The binding environment. The rightmost element of the list is the nearest 846 // The binding environment. The rightmost element of the list is the nearest
790 // available enclosing binding. 847 // available enclosing binding.
791 List<Assign> environment; 848 List<Assign> environment;
792 849
793 /// Substitution map for labels. Any break to a label L should be substituted 850 /// Substitution map for labels. Any break to a label L should be substituted
794 /// for a break to L' if L maps to L'. 851 /// for a break to L' if L maps to L'.
795 Map<Label, Label> labelRedirects = <Label, Label>{}; 852 Map<Label, Jump> labelRedirects = <Label, Jump>{};
796 853
797 /// Returns the redirect target of [label] or [label] itself if it should not 854 /// Returns the redirect target of [label] or [label] itself if it should not
798 /// be redirected. 855 /// be redirected.
799 Label redirect(Label label) { 856 Jump redirect(Break jump) {
800 Label newTarget = labelRedirects[label]; 857 Jump newJump = labelRedirects[jump.target];
801 return newTarget != null ? newTarget : label; 858 return newJump != null ? newJump : jump;
802 } 859 }
803 860
804 void rewrite(FunctionDefinition definition) { 861 void rewrite(FunctionDefinition definition) {
805 environment = <Assign>[]; 862 environment = <Assign>[];
806 definition.body = visitStatement(definition.body); 863 definition.body = visitStatement(definition.body);
807 864
808 // TODO(kmillikin): Allow definitions that are not propagated. Here, 865 // TODO(kmillikin): Allow definitions that are not propagated. Here,
809 // this means rebuilding the binding with a recursively unnamed definition, 866 // this means rebuilding the binding with a recursively unnamed definition,
810 // or else introducing a variable definition and an assignment. 867 // or else introducing a variable definition and an assignment.
811 assert(environment.isEmpty); 868 assert(environment.isEmpty);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 } 968 }
912 969
913 Statement visitReturn(Return node) { 970 Statement visitReturn(Return node) {
914 node.value = visitExpression(node.value); 971 node.value = visitExpression(node.value);
915 return node; 972 return node;
916 } 973 }
917 974
918 975
919 Statement visitBreak(Break node) { 976 Statement visitBreak(Break node) {
920 // Redirect through chain of breaks. 977 // Redirect through chain of breaks.
921 // Note that breakCount was accounted for at visitLabeledStatement. 978 // Note that useCount was accounted for at visitLabeledStatement.
922 node.target = redirect(node.target); 979 // Note redirect may return either a Break or Continue statement.
923 if (node.target.breakCount == 1) { 980 node = redirect(node);
924 --node.target.breakCount; 981 if (node is Break && node.target.useCount == 1) {
982 --node.target.useCount;
925 return visitStatement(node.target.binding.next); 983 return visitStatement(node.target.binding.next);
926 } 984 }
927 return node; 985 return node;
928 } 986 }
929 987
930 Statement visitContinue(Continue node) { 988 Statement visitContinue(Continue node) {
931 return node; 989 return node;
932 } 990 }
933 991
934 Statement visitLabeledStatement(LabeledStatement node) { 992 Statement visitLabeledStatement(LabeledStatement node) {
935 if (node.next is Break) { 993 if (node.next is Jump) {
936 // Eliminate label if next is just a break statement 994 // Eliminate label if next is a break or continue statement
937 // Breaks to this label are redirected to the outer label. 995 // Breaks to this label are redirected to the outer label.
938 // Note that breakCount for the two labels is updated proactively here 996 // Note that breakCount for the two labels is updated proactively here
939 // so breaks can reliably tell if they should inline their target. 997 // so breaks can reliably tell if they should inline their target.
940 Break next = node.next; 998 Jump next = node.next;
941 Label newTarget = redirect(next.target); 999 Jump newJump = redirect(next);
942 labelRedirects[node.label] = newTarget; 1000 labelRedirects[node.label] = newJump;
943 newTarget.breakCount += node.label.breakCount; 1001 newJump.target.useCount += node.label.useCount - 1;
944 node.label.breakCount = 0; 1002 node.label.useCount = 0;
945 Statement result = visitStatement(node.body); 1003 Statement result = visitStatement(node.body);
946 labelRedirects.remove(node.label); // Save some space. 1004 labelRedirects.remove(node.label); // Save some space.
947 return result; 1005 return result;
948 } 1006 }
949 1007
950 node.body = visitStatement(node.body); 1008 node.body = visitStatement(node.body);
951 1009
952 if (node.label.breakCount == 0) { 1010 if (node.label.useCount == 0) {
953 // Eliminate the label if next was inlined at a break 1011 // Eliminate the label if next was inlined at a break
954 return node.body; 1012 return node.body;
955 } 1013 }
956 1014
957 node.next = visitStatement(node.next); 1015 node.next = visitStatement(node.next);
958 return node; 1016 return node;
959 } 1017 }
960 1018
961 Statement visitIf(If node) { 1019 Statement visitIf(If node) {
962 node.condition = visitExpression(node.condition); 1020 node.condition = visitExpression(node.condition);
(...skipping 21 matching lines...) Expand all
984 if (reduced.next is Break) { 1042 if (reduced.next is Break) {
985 // In case the break can now be inlined. 1043 // In case the break can now be inlined.
986 reduced = visitStatement(reduced); 1044 reduced = visitStatement(reduced);
987 } 1045 }
988 return reduced; 1046 return reduced;
989 } 1047 }
990 1048
991 return node; 1049 return node;
992 } 1050 }
993 1051
994 Statement visitWhile(While node) { 1052 Statement visitWhileTrue(WhileTrue node) {
995 // Do not propagate assignments into loops. Doing so is not safe for 1053 // Do not propagate assignments into loops. Doing so is not safe for
996 // variables modified in the loop (the initial value will be propagated). 1054 // variables modified in the loop (the initial value will be propagated).
997 List<Assign> savedEnvironment = environment; 1055 List<Assign> savedEnvironment = environment;
998 environment = <Assign>[]; 1056 environment = <Assign>[];
999 node.body = visitStatement(node.body); 1057 node.body = visitStatement(node.body);
1000 assert(environment.isEmpty); 1058 assert(environment.isEmpty);
1001 environment = savedEnvironment; 1059 environment = savedEnvironment;
1002 return node; 1060 return node;
1003 } 1061 }
1004 1062
1063 Statement visitWhileCondition(WhileCondition node) {
1064 // Not introduced yet
1065 throw "Unexpected WhileCondition in StatementRewriter";
1066 }
1067
1005 Expression visitConstant(Constant node) { 1068 Expression visitConstant(Constant node) {
1006 return node; 1069 return node;
1007 } 1070 }
1008 1071
1009 Expression visitLiteralList(LiteralList node) { 1072 Expression visitLiteralList(LiteralList node) {
1010 // Process values right-to-left, the opposite of evaluation order. 1073 // Process values right-to-left, the opposite of evaluation order.
1011 for (int i = node.values.length - 1; i >= 0; --i) { 1074 for (int i = node.values.length - 1; i >= 0; --i) {
1012 node.values[i] = visitExpression(node.values[i]); 1075 node.values[i] = visitExpression(node.values[i]);
1013 } 1076 }
1014 return node; 1077 return node;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 return null; 1144 return null;
1082 } 1145 }
1083 1146
1084 /// Returns a statement equivalent to both [s] and [t], or null if [s] and 1147 /// Returns a statement equivalent to both [s] and [t], or null if [s] and
1085 /// [t] are incompatible. 1148 /// [t] are incompatible.
1086 /// If non-null is returned, the caller MUST discard [s] and [t] and use 1149 /// If non-null is returned, the caller MUST discard [s] and [t] and use
1087 /// the returned statement instead. 1150 /// the returned statement instead.
1088 /// If two breaks are combined, the label's break counter will be decremented. 1151 /// If two breaks are combined, the label's break counter will be decremented.
1089 static Statement combineStatements(Statement s, Statement t) { 1152 static Statement combineStatements(Statement s, Statement t) {
1090 if (s is Break && t is Break && s.target == t.target) { 1153 if (s is Break && t is Break && s.target == t.target) {
1091 --t.target.breakCount; // Two breaks become one. 1154 --t.target.useCount; // Two breaks become one.
1155 return s;
1156 }
1157 if (s is Continue && t is Continue && s.target == t.target) {
1158 --t.target.useCount; // Two continues become one.
1092 return s; 1159 return s;
1093 } 1160 }
1094 if (s is Return && t is Return && equivalentExpressions(s.value, t.value)) { 1161 if (s is Return && t is Return && equivalentExpressions(s.value, t.value)) {
1095 return s; 1162 return s;
1096 } 1163 }
1097 return null; 1164 return null;
1098 } 1165 }
1099 1166
1100 /// True if the two expressions both syntactically and semantically 1167 /// True if the two expressions both syntactically and semantically
1101 /// equivalent. 1168 /// equivalent.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1168 If innerIf = outerThen; 1235 If innerIf = outerThen;
1169 Statement innerThen = getBranch(innerIf, branch2); 1236 Statement innerThen = getBranch(innerIf, branch2);
1170 Statement innerElse = getBranch(innerIf, !branch2); 1237 Statement innerElse = getBranch(innerIf, !branch2);
1171 if (innerElse is Break && innerElse.target == outerElse.target) { 1238 if (innerElse is Break && innerElse.target == outerElse.target) {
1172 // We always put S in the then branch of the result, and adjust the 1239 // We always put S in the then branch of the result, and adjust the
1173 // condition expression if S was actually found in the else branch(es). 1240 // condition expression if S was actually found in the else branch(es).
1174 outerIf.condition = new LogicalOperator.and( 1241 outerIf.condition = new LogicalOperator.and(
1175 makeCondition(outerIf.condition, branch1), 1242 makeCondition(outerIf.condition, branch1),
1176 makeCondition(innerIf.condition, branch2)); 1243 makeCondition(innerIf.condition, branch2));
1177 outerIf.thenStatement = innerThen; 1244 outerIf.thenStatement = innerThen;
1178 --innerElse.target.breakCount; 1245 --innerElse.target.useCount;
1179 1246
1180 // Try to inline the remaining break. Do not propagate assignments. 1247 // Try to inline the remaining break. Do not propagate assignments.
1181 List<Assign> savedEnvironment = environment; 1248 List<Assign> savedEnvironment = environment;
1182 environment = <Assign>[]; 1249 environment = <Assign>[];
1183 outerIf.elseStatement = visitStatement(outerElse); 1250 outerIf.elseStatement = visitStatement(outerElse);
1184 assert(environment.isEmpty); 1251 assert(environment.isEmpty);
1185 environment = savedEnvironment; 1252 environment = savedEnvironment;
1186 1253
1187 return outerIf.elseStatement is If && innerThen is Break; 1254 return outerIf.elseStatement is If && innerThen is Break;
1188 } 1255 }
1189 } 1256 }
1190 return false; 1257 return false;
1191 } 1258 }
1192 1259
1193 Expression makeCondition(Expression e, bool polarity) { 1260 Expression makeCondition(Expression e, bool polarity) {
1194 return polarity ? e : new Not(e); 1261 return polarity ? e : new Not(e);
1195 } 1262 }
1196 1263
1197 Statement getBranch(If node, bool polarity) { 1264 Statement getBranch(If node, bool polarity) {
1198 return polarity ? node.thenStatement : node.elseStatement; 1265 return polarity ? node.thenStatement : node.elseStatement;
1199 } 1266 }
1200 } 1267 }
1201 1268
1269 /// Rewrites [WhileTrue] statements with an [If] body into a [WhileCondition],
1270 /// in situations where only one of the branches contains a [Continue] to the
1271 /// loop. Schematically:
1272 ///
1273 /// L:
1274 /// while (true) {
1275 /// if (E) {
1276 /// S1 (has references to L)
1277 /// } else {
1278 /// S2 (has no references to L)
1279 /// }
1280 /// }
1281 /// ==>
1282 /// L:
1283 /// while (E) {
1284 /// S1
1285 /// };
1286 /// S2
1287 ///
1288 /// A similar transformation is used when S2 occurs in the 'then' position.
1289 ///
1290 /// Note that the above pattern needs no iteration since nested ifs
1291 /// have been collapsed previously in the [StatementRewriter] phase.
1292 class LoopRewriter extends StatementVisitor<Statement> {
1293
1294 Set<Label> usedContinueLabels = new Set<Label>();
1295
1296 void rewrite(FunctionDefinition function) {
1297 function.body = visitStatement(function.body);
1298 }
1299
1300 Statement visitLabeledStatement(LabeledStatement node) {
1301 node.body = visitStatement(node.body);
1302 node.next = visitStatement(node.next);
1303 return node;
1304 }
1305
1306 Statement visitAssign(Assign node) {
1307 node.next = visitStatement(node.next);
1308 return node;
1309 }
1310
1311 Statement visitReturn(Return node) {
1312 return node;
1313 }
1314
1315 Statement visitBreak(Break node) {
1316 return node;
1317 }
1318
1319 Statement visitContinue(Continue node) {
1320 usedContinueLabels.add(node.target);
1321 return node;
1322 }
1323
1324 Statement visitIf(If node) {
1325 node.thenStatement = visitStatement(node.thenStatement);
1326 node.elseStatement = visitStatement(node.elseStatement);
1327 return node;
1328 }
1329
1330 Statement visitWhileTrue(WhileTrue node) {
1331 assert(!usedContinueLabels.contains(node.label));
1332 if (node.body is If) {
1333 If body = node.body;
1334 body.thenStatement = visitStatement(body.thenStatement);
1335 bool thenHasContinue = usedContinueLabels.remove(node.label);
1336 body.elseStatement = visitStatement(body.elseStatement);
1337 bool elseHasContinue = usedContinueLabels.remove(node.label);
1338 if (thenHasContinue && !elseHasContinue) {
1339 node.label.binding = null; // Prepare to rebind the label.
1340 return new WhileCondition(
1341 node.label,
1342 body.condition,
1343 body.thenStatement,
1344 body.elseStatement,
1345 node.updates);
1346 } else if (!thenHasContinue && elseHasContinue) {
1347 node.label.binding = null;
1348 return new WhileCondition(
1349 node.label,
1350 new Not(body.condition),
1351 body.elseStatement,
1352 body.thenStatement,
1353 node.updates);
1354 }
1355 } else {
1356 node.body = visitStatement(node.body);
1357 usedContinueLabels.remove(node.label);
1358 }
1359 return node;
1360 }
1361
1362 Statement visitWhileCondition(WhileCondition node) {
1363 // Note: not reachable but the implementation is trivial
1364 node.body = visitStatement(node.body);
1365 node.next = visitStatement(node.next);
1366 return node;
1367 }
1368
1369 Statement visitExpressionStatement(ExpressionStatement node) {
1370 node.next = visitStatement(node.next);
1371 // for (;;) { ... E; continue* L ... }
1372 // ==>
1373 // for(;;E) { ... continue* L ... }
1374 if (node.next is Continue) {
1375 Continue jump = node.next;
1376 if (jump.target.useCount == 1) {
1377 Loop target = jump.target.binding;
1378 target.updates.add(node.expression);
1379 return jump; // Return the continue statement.
1380 // NOTE: The pattern may reclick in an enclosing expression statement.
1381 }
1382 }
1383 return node;
1384 }
1385
1386 }
1202 1387
1203 1388
1204 /// Rewrites logical expressions to be more compact. 1389 /// Rewrites logical expressions to be more compact.
1205 /// 1390 ///
1206 /// In this class an expression is said to occur in "boolean context" if 1391 /// In this class an expression is said to occur in "boolean context" if
1207 /// its result is immediately applied to boolean conversion. 1392 /// its result is immediately applied to boolean conversion.
1208 /// 1393 ///
1209 /// IF STATEMENTS: 1394 /// IF STATEMENTS:
1210 /// 1395 ///
1211 /// We apply the following two rules to [If] statements (see [visitIf]). 1396 /// We apply the following two rules to [If] statements (see [visitIf]).
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1327 if (!emptyElse && node.condition is Not) { 1512 if (!emptyElse && node.condition is Not) {
1328 node.condition = (node.condition as Not).operand; 1513 node.condition = (node.condition as Not).operand;
1329 Statement tmp = node.thenStatement; 1514 Statement tmp = node.thenStatement;
1330 node.thenStatement = node.elseStatement; 1515 node.thenStatement = node.elseStatement;
1331 node.elseStatement = tmp; 1516 node.elseStatement = tmp;
1332 } 1517 }
1333 1518
1334 return node; 1519 return node;
1335 } 1520 }
1336 1521
1337 Statement visitWhile(While node) { 1522 Statement visitWhileTrue(WhileTrue node) {
1338 node.body = visitStatement(node.body); 1523 node.body = visitStatement(node.body);
1339 return node; 1524 return node;
1340 } 1525 }
1341 1526
1527 Statement visitWhileCondition(WhileCondition node) {
1528 node.condition = makeCondition(node.condition, true, liftNots: false);
1529 node.body = visitStatement(node.body);
1530 node.next = visitStatement(node.next);
1531 return node;
1532 }
1533
1342 Statement visitExpressionStatement(ExpressionStatement node) { 1534 Statement visitExpressionStatement(ExpressionStatement node) {
1343 // TODO(asgerf): in non-checked mode we can remove Not from the expression. 1535 // TODO(asgerf): in non-checked mode we can remove Not from the expression.
1344 node.expression = visitExpression(node.expression); 1536 node.expression = visitExpression(node.expression);
1345 node.next = visitStatement(node.next); 1537 node.next = visitStatement(node.next);
1346 return node; 1538 return node;
1347 } 1539 }
1348 1540
1349 1541
1350 Expression visitVariable(Variable node) { 1542 Expression visitVariable(Variable node) {
1351 return node; 1543 return node;
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 } 1794 }
1603 } 1795 }
1604 1796
1605 /// Destructively updates each entry of [l] with the result of visiting it. 1797 /// Destructively updates each entry of [l] with the result of visiting it.
1606 void _rewriteList(List<Expression> l) { 1798 void _rewriteList(List<Expression> l) {
1607 for (int i = 0; i < l.length; i++) { 1799 for (int i = 0; i < l.length; i++) {
1608 l[i] = visitExpression(l[i]); 1800 l[i] = visitExpression(l[i]);
1609 } 1801 }
1610 } 1802 }
1611 } 1803 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698