| 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 tree_ir_nodes; | 5 library tree_ir_nodes; |
| 6 | 6 |
| 7 import '../constants/expressions.dart'; | 7 import '../constants/expressions.dart'; |
| 8 import '../constants/values.dart' as values; | 8 import '../constants/values.dart' as values; |
| 9 import '../dart_types.dart' show DartType, GenericType; | 9 import '../dart_types.dart' show DartType, GenericType; |
| 10 import '../elements/elements.dart'; | 10 import '../elements/elements.dart'; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 /// Number of [Break] or [Continue] statements that target this label. | 77 /// Number of [Break] or [Continue] statements that target this label. |
| 78 /// The [Break] constructor will increment this automatically, but the | 78 /// The [Break] constructor will increment this automatically, but the |
| 79 /// counter must be decremented by hand when a [Break] becomes orphaned. | 79 /// counter must be decremented by hand when a [Break] becomes orphaned. |
| 80 int useCount = 0; | 80 int useCount = 0; |
| 81 | 81 |
| 82 /// The [LabeledStatement] or [WhileTrue] binding this label. | 82 /// The [LabeledStatement] or [WhileTrue] binding this label. |
| 83 JumpTarget binding; | 83 JumpTarget binding; |
| 84 } | 84 } |
| 85 | 85 |
| 86 /** | 86 /** |
| 87 * Variables are [Expression]s. | 87 * A local variable in the tree IR. |
| 88 * |
| 89 * All tree IR variables are mutable, and may in Dart-mode be referenced inside |
| 90 * nested functions. |
| 91 * |
| 92 * To use a variable as an expression, reference it from a [VariableUse], with |
| 93 * one [VariableUse] per expression. |
| 94 * |
| 95 * [Variable]s are reference counted. The node constructors [VariableUse], |
| 96 * [Assign], [FunctionDefinition], and [Try] automatically update the reference |
| 97 * count for their variables, but when transforming the tree, the transformer |
| 98 * is responsible for updating reference counts. |
| 88 */ | 99 */ |
| 89 class Variable extends Expression { | 100 class Variable extends Node { |
| 90 /// Function that declares this variable. | 101 /// Function that declares this variable. |
| 91 ExecutableElement host; | 102 ExecutableElement host; |
| 92 | 103 |
| 93 /// [Entity] used for synthesizing a name for the variable. | 104 /// [Entity] used for synthesizing a name for the variable. |
| 94 /// Different variables may have the same entity. May be null. | 105 /// Different variables may have the same entity. May be null. |
| 95 Entity element; | 106 Entity element; |
| 96 | 107 |
| 108 /// Number of places where this variable occurs in a [VariableUse]. |
| 97 int readCount = 0; | 109 int readCount = 0; |
| 98 | 110 |
| 99 /// Number of places where this variable occurs as: | 111 /// Number of places where this variable occurs as: |
| 100 /// - left-hand of an [Assign] | 112 /// - left-hand of an [Assign] |
| 101 /// - left-hand of a [FunctionDeclaration] | 113 /// - left-hand of a [FunctionDeclaration] |
| 102 /// - parameter in a [FunctionDefinition] | 114 /// - parameter in a [FunctionDefinition] |
| 115 /// - catch parameter in a [Try] |
| 103 int writeCount = 0; | 116 int writeCount = 0; |
| 104 | 117 |
| 105 Variable(this.host, this.element) { | 118 Variable(this.host, this.element) { |
| 106 assert(host != null); | 119 assert(host != null); |
| 107 } | 120 } |
| 121 } |
| 108 | 122 |
| 109 accept(ExpressionVisitor visitor) => visitor.visitVariable(this); | 123 /// Read the value of a variable. |
| 110 accept1(ExpressionVisitor1 visitor, arg) => visitor.visitVariable(this, arg); | 124 class VariableUse extends Expression { |
| 125 Variable variable; |
| 126 |
| 127 /// Creates a use of [variable] and updates its `readCount`. |
| 128 VariableUse(this.variable) { |
| 129 variable.readCount++; |
| 130 } |
| 131 |
| 132 accept(ExpressionVisitor visitor) => visitor.visitVariableUse(this); |
| 133 accept1(ExpressionVisitor1 visitor, arg) { |
| 134 return visitor.visitVariableUse(this, arg); |
| 135 } |
| 111 } | 136 } |
| 112 | 137 |
| 113 /** | 138 /** |
| 114 * Common interface for invocations with arguments. | 139 * Common interface for invocations with arguments. |
| 115 */ | 140 */ |
| 116 abstract class Invoke { | 141 abstract class Invoke { |
| 117 List<Expression> get arguments; | 142 List<Expression> get arguments; |
| 118 Selector get selector; | 143 Selector get selector; |
| 119 } | 144 } |
| 120 | 145 |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 Statement next; | 516 Statement next; |
| 492 Variable variable; | 517 Variable variable; |
| 493 Expression definition; | 518 Expression definition; |
| 494 | 519 |
| 495 /// If true, this assignes to a fresh variable scoped to the [next] | 520 /// If true, this assignes to a fresh variable scoped to the [next] |
| 496 /// statement. | 521 /// statement. |
| 497 /// | 522 /// |
| 498 /// Variable declarations themselves are hoisted to function level. | 523 /// Variable declarations themselves are hoisted to function level. |
| 499 bool isDeclaration; | 524 bool isDeclaration; |
| 500 | 525 |
| 526 /// Creates an assignment to [variable] and updates its `writeCount`. |
| 501 Assign(this.variable, this.definition, this.next, | 527 Assign(this.variable, this.definition, this.next, |
| 502 { this.isDeclaration: false }) { | 528 { this.isDeclaration: false }) { |
| 503 variable.writeCount++; | 529 variable.writeCount++; |
| 504 } | 530 } |
| 505 | 531 |
| 506 bool get hasExactlyOneUse => variable.readCount == 1; | 532 bool get hasExactlyOneUse => variable.readCount == 1; |
| 507 | 533 |
| 508 accept(StatementVisitor visitor) => visitor.visitAssign(this); | 534 accept(StatementVisitor visitor) => visitor.visitAssign(this); |
| 509 accept1(StatementVisitor1 visitor, arg) => visitor.visitAssign(this, arg); | 535 accept1(StatementVisitor1 visitor, arg) => visitor.visitAssign(this, arg); |
| 510 } | 536 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 // LabeledStatement and EmptyStatement, the statement class names are not | 590 // LabeledStatement and EmptyStatement, the statement class names are not |
| 565 // suffixed with 'Statement'. | 591 // suffixed with 'Statement'. |
| 566 class Try extends Statement { | 592 class Try extends Statement { |
| 567 Statement tryBody; | 593 Statement tryBody; |
| 568 List<Variable> catchParameters; | 594 List<Variable> catchParameters; |
| 569 Statement catchBody; | 595 Statement catchBody; |
| 570 | 596 |
| 571 Statement get next => null; | 597 Statement get next => null; |
| 572 void set next(Statement s) => throw 'UNREACHABLE'; | 598 void set next(Statement s) => throw 'UNREACHABLE'; |
| 573 | 599 |
| 574 Try(this.tryBody, this.catchParameters, this.catchBody); | 600 Try(this.tryBody, this.catchParameters, this.catchBody) { |
| 601 for (Variable variable in catchParameters) { |
| 602 variable.writeCount++; // Being a catch parameter counts as a write. |
| 603 } |
| 604 } |
| 575 | 605 |
| 576 accept(StatementVisitor visitor) => visitor.visitTry(this); | 606 accept(StatementVisitor visitor) => visitor.visitTry(this); |
| 577 accept1(StatementVisitor1 visitor, arg) { | 607 accept1(StatementVisitor1 visitor, arg) { |
| 578 return visitor.visitTry(this, arg); | 608 return visitor.visitTry(this, arg); |
| 579 } | 609 } |
| 580 } | 610 } |
| 581 | 611 |
| 582 abstract class ExecutableDefinition { | 612 abstract class ExecutableDefinition { |
| 583 ExecutableElement get element; | 613 ExecutableElement get element; |
| 584 Statement body; | 614 Statement body; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 614 bool get hasInitializer => body != null; | 644 bool get hasInitializer => body != null; |
| 615 } | 645 } |
| 616 | 646 |
| 617 class FunctionDefinition extends Node implements ExecutableDefinition { | 647 class FunctionDefinition extends Node implements ExecutableDefinition { |
| 618 final FunctionElement element; | 648 final FunctionElement element; |
| 619 final List<Variable> parameters; | 649 final List<Variable> parameters; |
| 620 Statement body; | 650 Statement body; |
| 621 final List<ConstDeclaration> localConstants; | 651 final List<ConstDeclaration> localConstants; |
| 622 final List<ConstantExpression> defaultParameterValues; | 652 final List<ConstantExpression> defaultParameterValues; |
| 623 | 653 |
| 654 /// Creates a function definition and updates `writeCount` for [parameters]. |
| 624 FunctionDefinition(this.element, this.parameters, this.body, | 655 FunctionDefinition(this.element, this.parameters, this.body, |
| 625 this.localConstants, this.defaultParameterValues); | 656 this.localConstants, this.defaultParameterValues) { |
| 657 for (Variable param in parameters) { |
| 658 param.writeCount++; // Being a parameter counts as a write. |
| 659 } |
| 660 } |
| 626 | 661 |
| 627 /// Returns `true` if this function is abstract. | 662 /// Returns `true` if this function is abstract. |
| 628 /// | 663 /// |
| 629 /// If `true` [body] is `null` and [localConstants] is empty. | 664 /// If `true` [body] is `null` and [localConstants] is empty. |
| 630 bool get isAbstract => body == null; | 665 bool get isAbstract => body == null; |
| 631 applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); | 666 applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); |
| 632 } | 667 } |
| 633 | 668 |
| 634 abstract class Initializer implements Expression, DartSpecificNode {} | 669 abstract class Initializer implements Expression, DartSpecificNode {} |
| 635 | 670 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 Statement next; | 747 Statement next; |
| 713 | 748 |
| 714 SetField(this.object, this.field, this.value, this.next); | 749 SetField(this.object, this.field, this.value, this.next); |
| 715 | 750 |
| 716 accept(StatementVisitor visitor) => visitor.visitSetField(this); | 751 accept(StatementVisitor visitor) => visitor.visitSetField(this); |
| 717 accept1(StatementVisitor1 visitor, arg) => visitor.visitSetField(this, arg); | 752 accept1(StatementVisitor1 visitor, arg) => visitor.visitSetField(this, arg); |
| 718 } | 753 } |
| 719 | 754 |
| 720 abstract class ExpressionVisitor<E> { | 755 abstract class ExpressionVisitor<E> { |
| 721 E visitExpression(Expression e) => e.accept(this); | 756 E visitExpression(Expression e) => e.accept(this); |
| 722 E visitVariable(Variable node); | 757 E visitVariableUse(VariableUse node); |
| 723 E visitInvokeStatic(InvokeStatic node); | 758 E visitInvokeStatic(InvokeStatic node); |
| 724 E visitInvokeMethod(InvokeMethod node); | 759 E visitInvokeMethod(InvokeMethod node); |
| 725 E visitInvokeMethodDirectly(InvokeMethodDirectly node); | 760 E visitInvokeMethodDirectly(InvokeMethodDirectly node); |
| 726 E visitInvokeConstructor(InvokeConstructor node); | 761 E visitInvokeConstructor(InvokeConstructor node); |
| 727 E visitConcatenateStrings(ConcatenateStrings node); | 762 E visitConcatenateStrings(ConcatenateStrings node); |
| 728 E visitConstant(Constant node); | 763 E visitConstant(Constant node); |
| 729 E visitThis(This node); | 764 E visitThis(This node); |
| 730 E visitReifyTypeVar(ReifyTypeVar node); | 765 E visitReifyTypeVar(ReifyTypeVar node); |
| 731 E visitConditional(Conditional node); | 766 E visitConditional(Conditional node); |
| 732 E visitLogicalOperator(LogicalOperator node); | 767 E visitLogicalOperator(LogicalOperator node); |
| 733 E visitNot(Not node); | 768 E visitNot(Not node); |
| 734 E visitLiteralList(LiteralList node); | 769 E visitLiteralList(LiteralList node); |
| 735 E visitLiteralMap(LiteralMap node); | 770 E visitLiteralMap(LiteralMap node); |
| 736 E visitTypeOperator(TypeOperator node); | 771 E visitTypeOperator(TypeOperator node); |
| 737 E visitFunctionExpression(FunctionExpression node); | 772 E visitFunctionExpression(FunctionExpression node); |
| 738 E visitFieldInitializer(FieldInitializer node); | 773 E visitFieldInitializer(FieldInitializer node); |
| 739 E visitSuperInitializer(SuperInitializer node); | 774 E visitSuperInitializer(SuperInitializer node); |
| 740 E visitGetField(GetField node); | 775 E visitGetField(GetField node); |
| 741 E visitCreateBox(CreateBox node); | 776 E visitCreateBox(CreateBox node); |
| 742 E visitCreateInstance(CreateInstance node); | 777 E visitCreateInstance(CreateInstance node); |
| 743 } | 778 } |
| 744 | 779 |
| 745 abstract class ExpressionVisitor1<E, A> { | 780 abstract class ExpressionVisitor1<E, A> { |
| 746 E visitExpression(Expression e, A arg) => e.accept1(this, arg); | 781 E visitExpression(Expression e, A arg) => e.accept1(this, arg); |
| 747 E visitVariable(Variable node, A arg); | 782 E visitVariableUse(VariableUse node, A arg); |
| 748 E visitInvokeStatic(InvokeStatic node, A arg); | 783 E visitInvokeStatic(InvokeStatic node, A arg); |
| 749 E visitInvokeMethod(InvokeMethod node, A arg); | 784 E visitInvokeMethod(InvokeMethod node, A arg); |
| 750 E visitInvokeMethodDirectly(InvokeMethodDirectly node, A arg); | 785 E visitInvokeMethodDirectly(InvokeMethodDirectly node, A arg); |
| 751 E visitInvokeConstructor(InvokeConstructor node, A arg); | 786 E visitInvokeConstructor(InvokeConstructor node, A arg); |
| 752 E visitConcatenateStrings(ConcatenateStrings node, A arg); | 787 E visitConcatenateStrings(ConcatenateStrings node, A arg); |
| 753 E visitConstant(Constant node, A arg); | 788 E visitConstant(Constant node, A arg); |
| 754 E visitThis(This node, A arg); | 789 E visitThis(This node, A arg); |
| 755 E visitReifyTypeVar(ReifyTypeVar node, A arg); | 790 E visitReifyTypeVar(ReifyTypeVar node, A arg); |
| 756 E visitConditional(Conditional node, A arg); | 791 E visitConditional(Conditional node, A arg); |
| 757 E visitLogicalOperator(LogicalOperator node, A arg); | 792 E visitLogicalOperator(LogicalOperator node, A arg); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 806 } | 841 } |
| 807 | 842 |
| 808 abstract class Visitor1<S, E, A> implements ExpressionVisitor1<E, A>, | 843 abstract class Visitor1<S, E, A> implements ExpressionVisitor1<E, A>, |
| 809 StatementVisitor1<S, A> { | 844 StatementVisitor1<S, A> { |
| 810 E visitExpression(Expression e, A arg) => e.accept1(this, arg); | 845 E visitExpression(Expression e, A arg) => e.accept1(this, arg); |
| 811 S visitStatement(Statement s, A arg) => s.accept1(this, arg); | 846 S visitStatement(Statement s, A arg) => s.accept1(this, arg); |
| 812 } | 847 } |
| 813 | 848 |
| 814 class RecursiveVisitor extends Visitor { | 849 class RecursiveVisitor extends Visitor { |
| 815 visitFunctionDefinition(FunctionDefinition node) { | 850 visitFunctionDefinition(FunctionDefinition node) { |
| 851 node.parameters.forEach(visitVariable); |
| 816 visitStatement(node.body); | 852 visitStatement(node.body); |
| 817 } | 853 } |
| 818 | 854 |
| 819 visitVariable(Variable node) {} | 855 visitVariable(Variable node) {} |
| 820 | 856 |
| 857 visitVariableUse(VariableUse node) { |
| 858 visitVariable(node.variable); |
| 859 } |
| 860 |
| 821 visitInvokeStatic(InvokeStatic node) { | 861 visitInvokeStatic(InvokeStatic node) { |
| 822 node.arguments.forEach(visitExpression); | 862 node.arguments.forEach(visitExpression); |
| 823 } | 863 } |
| 824 | 864 |
| 825 visitInvokeMethod(InvokeMethod node) { | 865 visitInvokeMethod(InvokeMethod node) { |
| 826 visitExpression(node.receiver); | 866 visitExpression(node.receiver); |
| 827 node.arguments.forEach(visitExpression); | 867 node.arguments.forEach(visitExpression); |
| 828 } | 868 } |
| 829 | 869 |
| 830 visitInvokeMethodDirectly(InvokeMethodDirectly node) { | 870 visitInvokeMethodDirectly(InvokeMethodDirectly node) { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 visitStatement(node.next); | 988 visitStatement(node.next); |
| 949 } | 989 } |
| 950 | 990 |
| 951 visitCreateBox(CreateBox node) { | 991 visitCreateBox(CreateBox node) { |
| 952 } | 992 } |
| 953 | 993 |
| 954 visitCreateInstance(CreateInstance node) { | 994 visitCreateInstance(CreateInstance node) { |
| 955 node.arguments.forEach(visitExpression); | 995 node.arguments.forEach(visitExpression); |
| 956 } | 996 } |
| 957 } | 997 } |
| OLD | NEW |