Chromium Code Reviews| 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] automatically update the reference count | |
| 97 * for their variables, but when transforming the tree, the transformer is | |
| 98 * responsible for updating reference counts. | |
| 88 */ | 99 */ |
| 89 class Variable extends Expression { | 100 class Variable extends Node { |
|
Kevin Millikin (Google)
2015/02/26 12:43:18
Is there any reason to make this a subclass of Nod
asgerf
2015/02/27 12:05:19
Currently tree_ir.Node is just used for stuff like
| |
| 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] |
| 103 int writeCount = 0; | 115 int writeCount = 0; |
| 104 | 116 |
| 105 Variable(this.host, this.element) { | 117 Variable(this.host, this.element) { |
| 106 assert(host != null); | 118 assert(host != null); |
| 107 } | 119 } |
| 120 } | |
| 108 | 121 |
| 109 accept(ExpressionVisitor visitor) => visitor.visitVariable(this); | 122 /// Read the value of a variable. |
| 110 accept1(ExpressionVisitor1 visitor, arg) => visitor.visitVariable(this, arg); | 123 class VariableUse extends Expression { |
| 124 Variable variable; | |
| 125 | |
| 126 /// Creates a use of [variable] and updates its `readCount`. | |
| 127 VariableUse(this.variable) { | |
| 128 variable.readCount++; | |
| 129 } | |
| 130 | |
| 131 accept(ExpressionVisitor visitor) => visitor.visitVariableUse(this); | |
| 132 accept1(ExpressionVisitor1 visitor, arg) { | |
| 133 return visitor.visitVariableUse(this, arg); | |
| 134 } | |
| 111 } | 135 } |
| 112 | 136 |
| 113 /** | 137 /** |
| 114 * Common interface for invocations with arguments. | 138 * Common interface for invocations with arguments. |
| 115 */ | 139 */ |
| 116 abstract class Invoke { | 140 abstract class Invoke { |
| 117 List<Expression> get arguments; | 141 List<Expression> get arguments; |
| 118 Selector get selector; | 142 Selector get selector; |
| 119 } | 143 } |
| 120 | 144 |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 491 Statement next; | 515 Statement next; |
| 492 Variable variable; | 516 Variable variable; |
| 493 Expression definition; | 517 Expression definition; |
| 494 | 518 |
| 495 /// If true, this assignes to a fresh variable scoped to the [next] | 519 /// If true, this assignes to a fresh variable scoped to the [next] |
| 496 /// statement. | 520 /// statement. |
| 497 /// | 521 /// |
| 498 /// Variable declarations themselves are hoisted to function level. | 522 /// Variable declarations themselves are hoisted to function level. |
| 499 bool isDeclaration; | 523 bool isDeclaration; |
| 500 | 524 |
| 525 /// Creates an assignment to [variable] and updates its `writeCount`. | |
| 501 Assign(this.variable, this.definition, this.next, | 526 Assign(this.variable, this.definition, this.next, |
| 502 { this.isDeclaration: false }) { | 527 { this.isDeclaration: false }) { |
| 503 variable.writeCount++; | 528 variable.writeCount++; |
| 504 } | 529 } |
| 505 | 530 |
| 506 bool get hasExactlyOneUse => variable.readCount == 1; | 531 bool get hasExactlyOneUse => variable.readCount == 1; |
| 507 | 532 |
| 508 accept(StatementVisitor visitor) => visitor.visitAssign(this); | 533 accept(StatementVisitor visitor) => visitor.visitAssign(this); |
| 509 accept1(StatementVisitor1 visitor, arg) => visitor.visitAssign(this, arg); | 534 accept1(StatementVisitor1 visitor, arg) => visitor.visitAssign(this, arg); |
| 510 } | 535 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 595 bool get hasInitializer => body != null; | 620 bool get hasInitializer => body != null; |
| 596 } | 621 } |
| 597 | 622 |
| 598 class FunctionDefinition extends Node implements ExecutableDefinition { | 623 class FunctionDefinition extends Node implements ExecutableDefinition { |
| 599 final FunctionElement element; | 624 final FunctionElement element; |
| 600 final List<Variable> parameters; | 625 final List<Variable> parameters; |
| 601 Statement body; | 626 Statement body; |
| 602 final List<ConstDeclaration> localConstants; | 627 final List<ConstDeclaration> localConstants; |
| 603 final List<ConstantExpression> defaultParameterValues; | 628 final List<ConstantExpression> defaultParameterValues; |
| 604 | 629 |
| 630 /// Creates a function definition and updates `writeCount` for [parameters]. | |
| 605 FunctionDefinition(this.element, this.parameters, this.body, | 631 FunctionDefinition(this.element, this.parameters, this.body, |
| 606 this.localConstants, this.defaultParameterValues); | 632 this.localConstants, this.defaultParameterValues) { |
| 633 for (Variable param in parameters) { | |
| 634 param.writeCount++; // Being a parameter counts as a write. | |
| 635 } | |
| 636 } | |
| 607 | 637 |
| 608 /// Returns `true` if this function is abstract. | 638 /// Returns `true` if this function is abstract. |
| 609 /// | 639 /// |
| 610 /// If `true` [body] is `null` and [localConstants] is empty. | 640 /// If `true` [body] is `null` and [localConstants] is empty. |
| 611 bool get isAbstract => body == null; | 641 bool get isAbstract => body == null; |
| 612 applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); | 642 applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); |
| 613 } | 643 } |
| 614 | 644 |
| 615 abstract class Initializer implements Expression, DartSpecificNode {} | 645 abstract class Initializer implements Expression, DartSpecificNode {} |
| 616 | 646 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 693 Statement next; | 723 Statement next; |
| 694 | 724 |
| 695 SetField(this.object, this.field, this.value, this.next); | 725 SetField(this.object, this.field, this.value, this.next); |
| 696 | 726 |
| 697 accept(StatementVisitor visitor) => visitor.visitSetField(this); | 727 accept(StatementVisitor visitor) => visitor.visitSetField(this); |
| 698 accept1(StatementVisitor1 visitor, arg) => visitor.visitSetField(this, arg); | 728 accept1(StatementVisitor1 visitor, arg) => visitor.visitSetField(this, arg); |
| 699 } | 729 } |
| 700 | 730 |
| 701 abstract class ExpressionVisitor<E> { | 731 abstract class ExpressionVisitor<E> { |
| 702 E visitExpression(Expression e) => e.accept(this); | 732 E visitExpression(Expression e) => e.accept(this); |
| 703 E visitVariable(Variable node); | 733 E visitVariableUse(VariableUse node); |
| 704 E visitInvokeStatic(InvokeStatic node); | 734 E visitInvokeStatic(InvokeStatic node); |
| 705 E visitInvokeMethod(InvokeMethod node); | 735 E visitInvokeMethod(InvokeMethod node); |
| 706 E visitInvokeMethodDirectly(InvokeMethodDirectly node); | 736 E visitInvokeMethodDirectly(InvokeMethodDirectly node); |
| 707 E visitInvokeConstructor(InvokeConstructor node); | 737 E visitInvokeConstructor(InvokeConstructor node); |
| 708 E visitConcatenateStrings(ConcatenateStrings node); | 738 E visitConcatenateStrings(ConcatenateStrings node); |
| 709 E visitConstant(Constant node); | 739 E visitConstant(Constant node); |
| 710 E visitThis(This node); | 740 E visitThis(This node); |
| 711 E visitReifyTypeVar(ReifyTypeVar node); | 741 E visitReifyTypeVar(ReifyTypeVar node); |
| 712 E visitConditional(Conditional node); | 742 E visitConditional(Conditional node); |
| 713 E visitLogicalOperator(LogicalOperator node); | 743 E visitLogicalOperator(LogicalOperator node); |
| 714 E visitNot(Not node); | 744 E visitNot(Not node); |
| 715 E visitLiteralList(LiteralList node); | 745 E visitLiteralList(LiteralList node); |
| 716 E visitLiteralMap(LiteralMap node); | 746 E visitLiteralMap(LiteralMap node); |
| 717 E visitTypeOperator(TypeOperator node); | 747 E visitTypeOperator(TypeOperator node); |
| 718 E visitFunctionExpression(FunctionExpression node); | 748 E visitFunctionExpression(FunctionExpression node); |
| 719 E visitFieldInitializer(FieldInitializer node); | 749 E visitFieldInitializer(FieldInitializer node); |
| 720 E visitSuperInitializer(SuperInitializer node); | 750 E visitSuperInitializer(SuperInitializer node); |
| 721 E visitGetField(GetField node); | 751 E visitGetField(GetField node); |
| 722 E visitCreateBox(CreateBox node); | 752 E visitCreateBox(CreateBox node); |
| 723 E visitCreateInstance(CreateInstance node); | 753 E visitCreateInstance(CreateInstance node); |
| 724 } | 754 } |
| 725 | 755 |
| 726 abstract class ExpressionVisitor1<E, A> { | 756 abstract class ExpressionVisitor1<E, A> { |
| 727 E visitExpression(Expression e, A arg) => e.accept1(this, arg); | 757 E visitExpression(Expression e, A arg) => e.accept1(this, arg); |
| 728 E visitVariable(Variable node, A arg); | 758 E visitVariableUse(VariableUse node, A arg); |
| 729 E visitInvokeStatic(InvokeStatic node, A arg); | 759 E visitInvokeStatic(InvokeStatic node, A arg); |
| 730 E visitInvokeMethod(InvokeMethod node, A arg); | 760 E visitInvokeMethod(InvokeMethod node, A arg); |
| 731 E visitInvokeMethodDirectly(InvokeMethodDirectly node, A arg); | 761 E visitInvokeMethodDirectly(InvokeMethodDirectly node, A arg); |
| 732 E visitInvokeConstructor(InvokeConstructor node, A arg); | 762 E visitInvokeConstructor(InvokeConstructor node, A arg); |
| 733 E visitConcatenateStrings(ConcatenateStrings node, A arg); | 763 E visitConcatenateStrings(ConcatenateStrings node, A arg); |
| 734 E visitConstant(Constant node, A arg); | 764 E visitConstant(Constant node, A arg); |
| 735 E visitThis(This node, A arg); | 765 E visitThis(This node, A arg); |
| 736 E visitReifyTypeVar(ReifyTypeVar node, A arg); | 766 E visitReifyTypeVar(ReifyTypeVar node, A arg); |
| 737 E visitConditional(Conditional node, A arg); | 767 E visitConditional(Conditional node, A arg); |
| 738 E visitLogicalOperator(LogicalOperator node, A arg); | 768 E visitLogicalOperator(LogicalOperator node, A arg); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 785 } | 815 } |
| 786 | 816 |
| 787 abstract class Visitor1<S, E, A> implements ExpressionVisitor1<E, A>, | 817 abstract class Visitor1<S, E, A> implements ExpressionVisitor1<E, A>, |
| 788 StatementVisitor1<S, A> { | 818 StatementVisitor1<S, A> { |
| 789 E visitExpression(Expression e, A arg) => e.accept1(this, arg); | 819 E visitExpression(Expression e, A arg) => e.accept1(this, arg); |
| 790 S visitStatement(Statement s, A arg) => s.accept1(this, arg); | 820 S visitStatement(Statement s, A arg) => s.accept1(this, arg); |
| 791 } | 821 } |
| 792 | 822 |
| 793 class RecursiveVisitor extends Visitor { | 823 class RecursiveVisitor extends Visitor { |
| 794 visitFunctionDefinition(FunctionDefinition node) { | 824 visitFunctionDefinition(FunctionDefinition node) { |
| 825 node.parameters.forEach(visitVariable); | |
| 795 visitStatement(node.body); | 826 visitStatement(node.body); |
| 796 } | 827 } |
| 797 | 828 |
| 798 visitVariable(Variable node) {} | 829 visitVariable(Variable node) {} |
| 799 | 830 |
| 831 visitVariableUse(VariableUse node) { | |
| 832 visitVariable(node.variable); | |
| 833 } | |
| 834 | |
| 800 visitInvokeStatic(InvokeStatic node) { | 835 visitInvokeStatic(InvokeStatic node) { |
| 801 node.arguments.forEach(visitExpression); | 836 node.arguments.forEach(visitExpression); |
| 802 } | 837 } |
| 803 | 838 |
| 804 visitInvokeMethod(InvokeMethod node) { | 839 visitInvokeMethod(InvokeMethod node) { |
| 805 visitExpression(node.receiver); | 840 visitExpression(node.receiver); |
| 806 node.arguments.forEach(visitExpression); | 841 node.arguments.forEach(visitExpression); |
| 807 } | 842 } |
| 808 | 843 |
| 809 visitInvokeMethodDirectly(InvokeMethodDirectly node) { | 844 visitInvokeMethodDirectly(InvokeMethodDirectly node) { |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 922 visitStatement(node.next); | 957 visitStatement(node.next); |
| 923 } | 958 } |
| 924 | 959 |
| 925 visitCreateBox(CreateBox node) { | 960 visitCreateBox(CreateBox node) { |
| 926 } | 961 } |
| 927 | 962 |
| 928 visitCreateInstance(CreateInstance node) { | 963 visitCreateInstance(CreateInstance node) { |
| 929 node.arguments.forEach(visitExpression); | 964 node.arguments.forEach(visitExpression); |
| 930 } | 965 } |
| 931 } | 966 } |
| OLD | NEW |