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

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

Issue 223783002: Support ExpressionStatement in the dart2dart backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Ensure that a removed 'return' is really a 'return'. Created 6 years, 8 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
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 '../dart_types.dart'; 8 import '../dart_types.dart';
9 import '../util/util.dart'; 9 import '../util/util.dart';
10 import '../elements/elements.dart' show FunctionElement, FunctionSignature; 10 import '../elements/elements.dart' show FunctionElement, FunctionSignature;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 identifier = Emitter.makeIdentifier(name); 58 identifier = Emitter.makeIdentifier(name);
59 return identifier; 59 return identifier;
60 } 60 }
61 61
62 final bool isPure = true; 62 final bool isPure = true;
63 63
64 accept(Visitor visitor) => visitor.visitVariable(this); 64 accept(Visitor visitor) => visitor.visitVariable(this);
65 } 65 }
66 66
67 /** 67 /**
68 * A sequence of expressions.
69 */
70 class Sequence extends Expression {
71 final List<Expression> expressions;
72
73 Sequence(this.expressions);
74
75 bool get isPure => expressions.every((e) => e.isPure);
76
77 accept(Visitor visitor) => visitor.visitSequence(this);
78 }
79
80 /**
68 * A local binding of a [Variable] to an [Expression]. 81 * A local binding of a [Variable] to an [Expression].
69 * 82 *
70 * In contrast to the CPS-based IR, non-primitive expressions can be named 83 * In contrast to the CPS-based IR, non-primitive expressions can be named
71 * with let. 84 * with let.
72 */ 85 */
73 class LetVal extends Expression { 86 class LetVal extends Expression {
74 final Variable variable; 87 final Variable variable;
75 final Expression definition; 88 final Expression definition;
76 final Expression body; 89 final Expression body;
77 90
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 accept(Visitor visitor) => visitor.visitConstant(this); 140 accept(Visitor visitor) => visitor.visitConstant(this);
128 } 141 }
129 142
130 abstract class Visitor<T> { 143 abstract class Visitor<T> {
131 // Abstract classes. 144 // Abstract classes.
132 T visitNode(Node node) => node.accept(this); 145 T visitNode(Node node) => node.accept(this);
133 T visitExpression(Expression node) => visitNode(node); 146 T visitExpression(Expression node) => visitNode(node);
134 147
135 // Concrete classes. 148 // Concrete classes.
136 T visitVariable(Variable node) => visitExpression(node); 149 T visitVariable(Variable node) => visitExpression(node);
150 T visitSequence(Sequence node) => visitExpression(node);
137 T visitLetVal(LetVal node) => visitExpression(node); 151 T visitLetVal(LetVal node) => visitExpression(node);
138 T visitInvokeStatic(InvokeStatic node) => visitExpression(node); 152 T visitInvokeStatic(InvokeStatic node) => visitExpression(node);
139 T visitReturn(Return node) => visitExpression(node); 153 T visitReturn(Return node) => visitExpression(node);
140 T visitConstant(Constant node) => visitExpression(node); 154 T visitConstant(Constant node) => visitExpression(node);
141 } 155 }
142 156
143 /** 157 /**
144 * Builder translates from CPS-based IR to direct-style Tree. 158 * Builder translates from CPS-based IR to direct-style Tree.
145 * 159 *
146 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced 160 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 204
191 Expression visitFunction(ir.Function node) { 205 Expression visitFunction(ir.Function node) {
192 // Functions are simplistically translated to their bodies. For now this 206 // Functions are simplistically translated to their bodies. For now this
193 // is good enough. 207 // is good enough.
194 returnContinuation = node.returnContinuation; 208 returnContinuation = node.returnContinuation;
195 return node.body.accept(this); 209 return node.body.accept(this);
196 } 210 }
197 211
198 Expression visitLetPrim(ir.LetPrim node) { 212 Expression visitLetPrim(ir.LetPrim node) {
199 // LetPrim is translated to LetVal. 213 // LetPrim is translated to LetVal.
200 Variable variable = new Variable();
201 Expression definition = node.primitive.accept(this); 214 Expression definition = node.primitive.accept(this);
202 variables[node.primitive] = variable; 215 if (node.primitive.hasAtLeastOneUse) {
203 return new LetVal(variable, definition, node.body.accept(this)); 216 Variable variable = new Variable();
217 variables[node.primitive] = variable;
218 return new LetVal(variable, definition, node.body.accept(this));
219 } else {
220 return new Sequence([definition, node.body.accept(this)]);
221 }
204 } 222 }
205 223
206 Expression visitLetCont(ir.LetCont node) { 224 Expression visitLetCont(ir.LetCont node) {
207 // TODO(kmillikin): Allow continuations to have multiple uses. This could 225 // TODO(kmillikin): Allow continuations to have multiple uses. This could
208 // arise due to the representation of local control flow or due to 226 // arise due to the representation of local control flow or due to
209 // optimization. 227 // optimization.
210 assert(node.continuation.hasAtMostOneUse); 228 assert(node.continuation.hasAtMostOneUse);
211 return node.body.accept(this); 229 return node.body.accept(this);
212 } 230 }
213 231
214 Expression visitInvokeStatic(ir.InvokeStatic node) { 232 Expression visitInvokeStatic(ir.InvokeStatic node) {
215 // Calls are translated to direct style. 233 // Calls are translated to direct style.
216 List<Expression> arguments = translateArguments(node.arguments); 234 List<Expression> arguments = translateArguments(node.arguments);
217 Expression invoke = new InvokeStatic(node.target, arguments); 235 Expression invoke = new InvokeStatic(node.target, arguments);
218 ir.Continuation cont = node.continuation.definition; 236 ir.Continuation cont = node.continuation.definition;
219 if (cont == returnContinuation) { 237 if (cont == returnContinuation) {
220 return new Return(invoke); 238 return new Return(invoke);
221 } else { 239 } else {
222 assert(cont.hasExactlyOneUse); 240 assert(cont.hasExactlyOneUse);
223 Variable variable = new Variable(); 241 if (cont.parameter.hasAtLeastOneUse) {
224 variables[cont.parameter] = variable; 242 Variable variable = new Variable();
225 return new LetVal(variable, invoke, cont.body.accept(this)); 243 variables[cont.parameter] = variable;
244 return new LetVal(variable, invoke, cont.body.accept(this));
245 } else {
246 return new Sequence([invoke, cont.body.accept(this)]);
247 }
226 } 248 }
227 } 249 }
228 250
229 Expression visitInvokeContinuation(ir.InvokeContinuation node) { 251 Expression visitInvokeContinuation(ir.InvokeContinuation node) {
230 // TODO(kmillikin): Support non-return continuations. These could arise 252 // TODO(kmillikin): Support non-return continuations. These could arise
231 // due to local control flow or due to inlining or other optimization. 253 // due to local control flow or due to inlining or other optimization.
232 assert(node.continuation.definition == returnContinuation); 254 assert(node.continuation.definition == returnContinuation);
233 return new Return(variables[node.argument.definition]); 255 return new Return(variables[node.argument.definition]);
234 } 256 }
235 257
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 } else if (!environment[i].definition.isPure) { 335 } else if (!environment[i].definition.isPure) {
314 // Once the first impure definition is seen, impure definitions should 336 // Once the first impure definition is seen, impure definitions should
315 // no longer be propagated. Continue searching for a pure definition. 337 // no longer be propagated. Continue searching for a pure definition.
316 seenImpure = true; 338 seenImpure = true;
317 } 339 }
318 } 340 }
319 // If the definition could not be propagated, leave the variable use. 341 // If the definition could not be propagated, leave the variable use.
320 return node; 342 return node;
321 } 343 }
322 344
345 Expression visitSequence(Sequence node) {
346 for (int i = 0; i < node.expressions.length; ++i) {
347 node.expressions[i] = node.expressions[i].accept(this);
348 }
349 return node;
350 }
351
323 Expression visitLetVal(LetVal node) { 352 Expression visitLetVal(LetVal node) {
324 environment.add(node); 353 environment.add(node);
325 Expression body = node.body.accept(this); 354 Expression body = node.body.accept(this);
326 355
327 // TODO(kmillikin): Allow definitions that are not propagated. Currently, 356 // TODO(kmillikin): Allow definitions that are not propagated. Currently,
328 // the only bindings are anonymous intermediate values (which only have one 357 // the only bindings are anonymous intermediate values (which only have one
329 // use in the absence of optimizations) and they are not reordered. 358 // use in the absence of optimizations) and they are not reordered.
330 assert(!environment.contains(node)); 359 assert(!environment.contains(node));
331 return body; 360 return body;
332 } 361 }
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 ast.Expression value = (body as ast.Return).expression; 501 ast.Expression value = (body as ast.Return).expression;
473 if (value is ast.LiteralNull) { 502 if (value is ast.LiteralNull) {
474 // '{ return null; }' is '{}'. 503 // '{ return null; }' is '{}'.
475 body = makeBlock([]); 504 body = makeBlock([]);
476 } else { 505 } else {
477 // '{ return e; }' is '=> e;'. 506 // '{ return e; }' is '=> e;'.
478 body = new ast.Return(new SymbolToken(FUNCTION_INFO, -1), 507 body = new ast.Return(new SymbolToken(FUNCTION_INFO, -1),
479 semicolon, 508 semicolon,
480 value); 509 value);
481 } 510 }
511 } else if (body is ast.Block) {
512 // Remove a final 'return null' that ends the body block.
513 Link<ast.Node> nodes = (body as ast.Block).statements.nodes;
514 ast.Node last;
515 for (var n in nodes) {
floitsch 2014/04/04 11:14:27 Why not ast.Node last = nodes.last; or even if (no
516 last = n;
517 }
518 if (last is ast.Return) {
519 List<ast.Node> statements =
520 (body as ast.Block).statements.nodes.toList();
521 statements.removeLast();
522 body = makeBlock(statements);
523 }
482 } 524 }
483 525
484 return new ast.FunctionExpression(name, parameters, body, returnType, 526 return new ast.FunctionExpression(name, parameters, body, returnType,
485 ast.Modifiers.EMPTY, null, null); 527 ast.Modifiers.EMPTY, null, null);
486 } 528 }
487 529
488 /** 530 /**
489 * Translate a list of arguments to an AST NodeList. 531 * Translate a list of arguments to an AST NodeList.
490 */ 532 */
491 ast.NodeList translateArguments(List<Expression> args) { 533 ast.NodeList translateArguments(List<Expression> args) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 new ast.NodeList(openBrace, statements.toLink(), closeBrace)); 569 new ast.NodeList(openBrace, statements.toLink(), closeBrace));
528 } 570 }
529 571
530 ast.Node visitVariable(Variable node) { 572 ast.Node visitVariable(Variable node) {
531 // The scope of variables is the body of their binding, so a name has 573 // The scope of variables is the body of their binding, so a name has
532 // already been generated when we visit a variable. 574 // already been generated when we visit a variable.
533 assert(node.identifier != null); 575 assert(node.identifier != null);
534 return new ast.Send(null, node.identifier); 576 return new ast.Send(null, node.identifier);
535 } 577 }
536 578
579 ast.Node visitSequence(Sequence node) {
580 return node.expressions.map((e) => e.accept(this)).reduce(concatenate);
581 }
582
537 ast.Node visitLetVal(LetVal node) { 583 ast.Node visitLetVal(LetVal node) {
538 // Let bindings translate into assignments. 584 // Let bindings translate into assignments.
539 ast.Identifier identifier = node.variable.assignIdentifier(); 585 ast.Identifier identifier = node.variable.assignIdentifier();
540 variables.add(identifier); 586 variables.add(identifier);
541 587
542 ast.Expression expression = node.definition.accept(this); 588 ast.Expression expression = node.definition.accept(this);
543 ast.Expression assignment = makeAssignment(identifier, expression); 589 ast.Expression assignment = makeAssignment(identifier, expression);
544 590
545 ast.Node rest = node.body.accept(this); 591 ast.Node rest = node.body.accept(this);
546 return concatenate(assignment, rest); 592 return concatenate(assignment, rest);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 } 715 }
670 716
671 ast.Expression visitInterceptor(dart2js.InterceptorConstant constant) { 717 ast.Expression visitInterceptor(dart2js.InterceptorConstant constant) {
672 return unimplemented(); 718 return unimplemented();
673 } 719 }
674 720
675 ast.Expression visitDummy(dart2js.DummyConstant constant) { 721 ast.Expression visitDummy(dart2js.DummyConstant constant) {
676 return unimplemented(); 722 return unimplemented();
677 } 723 }
678 } 724 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698