| 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 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; |
| 11 import '../universe/universe.dart'; |
| 10 import '../ir/ir_nodes.dart' as ir; | 12 import '../ir/ir_nodes.dart' as ir; |
| 13 import '../tree/tree.dart' as ast; |
| 14 import '../scanner/scannerlib.dart'; |
| 15 import '../dart_types.dart' show DartType, GenericType; |
| 11 | 16 |
| 12 // The Tree language is the target of translation out of the CPS-based IR. | 17 // The Tree language is the target of translation out of the CPS-based IR. |
| 13 // | 18 // |
| 14 // The translation from CPS to Dart consists of several stages. Among the | 19 // The translation from CPS to Dart consists of several stages. Among the |
| 15 // stages are translation to direct style, translation out of SSA, eliminating | 20 // stages are translation to direct style, translation out of SSA, eliminating |
| 16 // unnecessary names, recognizing high-level control constructs. Combining | 21 // unnecessary names, recognizing high-level control constructs. Combining |
| 17 // these separate concerns is complicated and the constraints of the CPS-based | 22 // these separate concerns is complicated and the constraints of the CPS-based |
| 18 // language do not permit a multi-stage translation. | 23 // language do not permit a multi-stage translation. |
| 19 // | 24 // |
| 20 // For that reason, CPS is translated to the direct-style language Tree. | 25 // For that reason, CPS is translated to the direct-style language Tree. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 final List<Expression> arguments; | 100 final List<Expression> arguments; |
| 96 | 101 |
| 97 InvokeStatic(this.target, this.arguments); | 102 InvokeStatic(this.target, this.arguments); |
| 98 | 103 |
| 99 final bool isPure = false; | 104 final bool isPure = false; |
| 100 | 105 |
| 101 accept(Visitor visitor) => visitor.visitInvokeStatic(this); | 106 accept(Visitor visitor) => visitor.visitInvokeStatic(this); |
| 102 } | 107 } |
| 103 | 108 |
| 104 /** | 109 /** |
| 110 * A call to a method, operator, getter, setter or index getter/setter. |
| 111 * |
| 112 * In contrast to the CPS-based IR, the receiver and arguments can be |
| 113 * arbitrary expressions. |
| 114 */ |
| 115 class InvokeMethod extends Expression { |
| 116 Expression receiver; |
| 117 final Selector selector; |
| 118 final List<Expression> arguments; |
| 119 |
| 120 InvokeMethod(this.receiver, this.selector, this.arguments) { |
| 121 assert(receiver != null); |
| 122 } |
| 123 |
| 124 final bool isPure = false; |
| 125 |
| 126 accept(Visitor visitor) => visitor.visitInvokeMethod(this); |
| 127 } |
| 128 |
| 129 /** |
| 130 * Non-const call to a factory or generative constructor. |
| 131 */ |
| 132 class InvokeConstructor extends Expression { |
| 133 final GenericType type; |
| 134 final FunctionElement target; |
| 135 final List<Expression> arguments; |
| 136 |
| 137 InvokeConstructor(this.type, this.target, this.arguments); |
| 138 |
| 139 ClassElement get targetClass => target.enclosingElement; |
| 140 |
| 141 final bool isPure = false; |
| 142 |
| 143 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); |
| 144 } |
| 145 |
| 146 /** |
| 105 * A constant. | 147 * A constant. |
| 106 */ | 148 */ |
| 107 class Constant extends Expression { | 149 class Constant extends Expression { |
| 108 final dart2js.Constant value; | 150 final dart2js.Constant value; |
| 109 | 151 |
| 110 Constant(this.value); | 152 Constant(this.value); |
| 111 | 153 |
| 112 final bool isPure = true; | 154 final bool isPure = true; |
| 113 | 155 |
| 114 accept(Visitor visitor) => visitor.visitConstant(this); | 156 accept(Visitor visitor) => visitor.visitConstant(this); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 final List<Variable> parameters; | 248 final List<Variable> parameters; |
| 207 Statement body; | 249 Statement body; |
| 208 | 250 |
| 209 FunctionDefinition(this.parameters, this.body); | 251 FunctionDefinition(this.parameters, this.body); |
| 210 } | 252 } |
| 211 | 253 |
| 212 abstract class Visitor<S, E> { | 254 abstract class Visitor<S, E> { |
| 213 E visitExpression(Expression e) => e.accept(this); | 255 E visitExpression(Expression e) => e.accept(this); |
| 214 E visitVariable(Variable node); | 256 E visitVariable(Variable node); |
| 215 E visitInvokeStatic(InvokeStatic node); | 257 E visitInvokeStatic(InvokeStatic node); |
| 258 E visitInvokeMethod(InvokeMethod node); |
| 259 E visitInvokeConstructor(InvokeConstructor node); |
| 216 E visitConstant(Constant node); | 260 E visitConstant(Constant node); |
| 217 | 261 |
| 218 S visitStatement(Statement s) => s.accept(this); | 262 S visitStatement(Statement s) => s.accept(this); |
| 219 S visitLabeledStatement(LabeledStatement node); | 263 S visitLabeledStatement(LabeledStatement node); |
| 220 S visitAssign(Assign node); | 264 S visitAssign(Assign node); |
| 221 S visitReturn(Return node); | 265 S visitReturn(Return node); |
| 222 S visitBreak(Break node); | 266 S visitBreak(Break node); |
| 223 S visitIf(If node); | 267 S visitIf(If node); |
| 224 S visitExpressionStatement(ExpressionStatement node); | 268 S visitExpressionStatement(ExpressionStatement node); |
| 225 } | 269 } |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 if (cont == returnContinuation) { | 408 if (cont == returnContinuation) { |
| 365 return new Return(invoke); | 409 return new Return(invoke); |
| 366 } else { | 410 } else { |
| 367 assert(cont.hasExactlyOneUse); | 411 assert(cont.hasExactlyOneUse); |
| 368 assert(cont.parameters.length == 1); | 412 assert(cont.parameters.length == 1); |
| 369 return buildParameterAssignments(cont.parameters, [invoke], | 413 return buildParameterAssignments(cont.parameters, [invoke], |
| 370 () => visit(cont.body)); | 414 () => visit(cont.body)); |
| 371 } | 415 } |
| 372 } | 416 } |
| 373 | 417 |
| 418 Statement visitInvokeMethod(ir.InvokeMethod node) { |
| 419 Variable receiver = variables[node.receiver.definition]; |
| 420 List<Expression> arguments = translateArguments(node.arguments); |
| 421 Expression invoke = new InvokeMethod(receiver, node.selector, arguments); |
| 422 ir.Continuation cont = node.continuation.definition; |
| 423 if (cont == returnContinuation) { |
| 424 return new Return(invoke); |
| 425 } else { |
| 426 assert(cont.hasExactlyOneUse); |
| 427 assert(cont.parameters.length == 1); |
| 428 return buildParameterAssignments(cont.parameters, [invoke], |
| 429 () => visit(cont.body)); |
| 430 } |
| 431 } |
| 432 |
| 433 Statement visitInvokeConstructor(ir.InvokeConstructor node) { |
| 434 List<Expression> arguments = translateArguments(node.arguments); |
| 435 Expression invoke = |
| 436 new InvokeConstructor(node.type, node.target, arguments); |
| 437 ir.Continuation cont = node.continuation.definition; |
| 438 if (cont == returnContinuation) { |
| 439 return new Return(invoke); |
| 440 } else { |
| 441 assert(cont.hasExactlyOneUse); |
| 442 assert(cont.parameters.length == 1); |
| 443 return buildParameterAssignments(cont.parameters, [invoke], |
| 444 () => visit(cont.body)); |
| 445 } |
| 446 } |
| 447 |
| 374 Statement visitInvokeContinuation(ir.InvokeContinuation node) { | 448 Statement visitInvokeContinuation(ir.InvokeContinuation node) { |
| 375 // Invocations of the return continuation are translated to returns. | 449 // Invocations of the return continuation are translated to returns. |
| 376 // Other continuation invocations are replaced with assignments of the | 450 // Other continuation invocations are replaced with assignments of the |
| 377 // arguments to formal parameter variables, followed by the body if | 451 // arguments to formal parameter variables, followed by the body if |
| 378 // the continuation is singly reference or a break if it is multiply | 452 // the continuation is singly reference or a break if it is multiply |
| 379 // referenced. | 453 // referenced. |
| 380 ir.Continuation cont = node.continuation.definition; | 454 ir.Continuation cont = node.continuation.definition; |
| 381 if (cont == returnContinuation) { | 455 if (cont == returnContinuation) { |
| 382 assert(node.arguments.length == 1); | 456 assert(node.arguments.length == 1); |
| 383 return new Return(variables[node.arguments[0].definition]); | 457 return new Return(variables[node.arguments[0].definition]); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 } | 596 } |
| 523 | 597 |
| 524 Expression visitInvokeStatic(InvokeStatic node) { | 598 Expression visitInvokeStatic(InvokeStatic node) { |
| 525 // Process arguments right-to-left, the opposite of evaluation order. | 599 // Process arguments right-to-left, the opposite of evaluation order. |
| 526 for (int i = node.arguments.length - 1; i >= 0; --i) { | 600 for (int i = node.arguments.length - 1; i >= 0; --i) { |
| 527 node.arguments[i] = visitExpression(node.arguments[i]); | 601 node.arguments[i] = visitExpression(node.arguments[i]); |
| 528 } | 602 } |
| 529 return node; | 603 return node; |
| 530 } | 604 } |
| 531 | 605 |
| 606 Expression visitInvokeMethod(InvokeMethod node) { |
| 607 for (int i = node.arguments.length - 1; i >= 0; --i) { |
| 608 node.arguments[i] = visitExpression(node.arguments[i]); |
| 609 } |
| 610 node.receiver = visitExpression(node.receiver); |
| 611 return node; |
| 612 } |
| 613 |
| 614 Expression visitInvokeConstructor(InvokeConstructor node) { |
| 615 for (int i = node.arguments.length - 1; i >= 0; --i) { |
| 616 node.arguments[i] = visitExpression(node.arguments[i]); |
| 617 } |
| 618 return node; |
| 619 } |
| 620 |
| 532 Statement visitReturn(Return node) { | 621 Statement visitReturn(Return node) { |
| 533 node.value = visitExpression(node.value); | 622 node.value = visitExpression(node.value); |
| 534 return node; | 623 return node; |
| 535 } | 624 } |
| 536 | 625 |
| 537 Statement visitBreak(Break node) { | 626 Statement visitBreak(Break node) { |
| 538 return node; | 627 return node; |
| 539 } | 628 } |
| 540 | 629 |
| 541 Statement visitIf(If node) { | 630 Statement visitIf(If node) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 554 if (!node.expression.isPure) { | 643 if (!node.expression.isPure) { |
| 555 environment.add(null); // insert impurity marker (TODO: refactor) | 644 environment.add(null); // insert impurity marker (TODO: refactor) |
| 556 } | 645 } |
| 557 node.next = visitStatement(node.next); | 646 node.next = visitStatement(node.next); |
| 558 if (!node.expression.isPure) { | 647 if (!node.expression.isPure) { |
| 559 environment.removeLast(); | 648 environment.removeLast(); |
| 560 } | 649 } |
| 561 return node; | 650 return node; |
| 562 } | 651 } |
| 563 } | 652 } |
| OLD | NEW |