| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 // IrNodes are kept in a separate library to have precise control over their | 5 // IrNodes are kept in a separate library to have precise control over their |
| 6 // dependencies on other parts of the system. | 6 // dependencies on other parts of the system. |
| 7 library dart2js.ir_nodes; | 7 library dart2js.ir_nodes; |
| 8 | 8 |
| 9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
| 10 import '../constants/values.dart' as values show ConstantValue; | 10 import '../constants/values.dart' as values show ConstantValue; |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 | 202 |
| 203 /// Represents a node with a child node, which can be accessed through the | 203 /// Represents a node with a child node, which can be accessed through the |
| 204 /// `body` member. A typical usage is when removing a node from the CPS graph: | 204 /// `body` member. A typical usage is when removing a node from the CPS graph: |
| 205 /// | 205 /// |
| 206 /// Node child = node.body; | 206 /// Node child = node.body; |
| 207 /// InteriorNode parent = node.parent; | 207 /// InteriorNode parent = node.parent; |
| 208 /// | 208 /// |
| 209 /// child.parent = parent; | 209 /// child.parent = parent; |
| 210 /// parent.body = child; | 210 /// parent.body = child; |
| 211 abstract class InteriorNode extends Node { | 211 abstract class InteriorNode extends Node { |
| 212 Expression body; | 212 Expression get body; |
| 213 void set body(Expression body); |
| 213 } | 214 } |
| 214 | 215 |
| 215 /// Invoke a static function or static field getter/setter. | 216 /// Invoke a static function or static field getter/setter. |
| 216 class InvokeStatic extends Expression implements Invoke { | 217 class InvokeStatic extends Expression implements Invoke { |
| 217 /// [FunctionElement] or [FieldElement]. | 218 /// [FunctionElement] or [FieldElement]. |
| 218 final Entity target; | 219 final Entity target; |
| 219 | 220 |
| 220 /** | 221 /** |
| 221 * The selector encodes how the function is invoked: number of positional | 222 * The selector encodes how the function is invoked: number of positional |
| 222 * arguments, names used in named arguments. This information is required | 223 * arguments, names used in named arguments. This information is required |
| (...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 | 720 |
| 720 bool get isReturnContinuation => body == null; | 721 bool get isReturnContinuation => body == null; |
| 721 | 722 |
| 722 Continuation(this.parameters, {this.isRecursive: false}); | 723 Continuation(this.parameters, {this.isRecursive: false}); |
| 723 | 724 |
| 724 Continuation.retrn() : parameters = <Parameter>[new Parameter(null)]; | 725 Continuation.retrn() : parameters = <Parameter>[new Parameter(null)]; |
| 725 | 726 |
| 726 accept(Visitor visitor) => visitor.visitContinuation(this); | 727 accept(Visitor visitor) => visitor.visitContinuation(this); |
| 727 } | 728 } |
| 728 | 729 |
| 729 abstract class ExecutableDefinition implements Node { | 730 abstract class RootNode extends Node { |
| 730 RunnableBody get body; | |
| 731 Element get element; | 731 Element get element; |
| 732 | 732 |
| 733 applyPass(Pass pass); | 733 /// True if there is no body for this root node. |
| 734 /// |
| 735 /// In some parts of the compiler, empty root nodes are used as placeholders |
| 736 /// for abstract methods, external constructors, fields without initializers, |
| 737 /// etc. |
| 738 bool get isEmpty; |
| 739 |
| 740 /// List of parameters, or an empty list if this is a field. |
| 741 /// For fields, this list is immutable. |
| 742 List<Definition> get parameters; |
| 734 } | 743 } |
| 735 | 744 |
| 736 // This is basically a function definition with an empty parameter list and a | 745 // This is basically a function definition with an empty parameter list and a |
| 737 // field element instead of a function element and no const declarations, and | 746 // field element instead of a function element and no const declarations, and |
| 738 // never a getter or setter, though that's less important. | 747 // never a getter or setter, though that's less important. |
| 739 class FieldDefinition extends Node implements ExecutableDefinition { | 748 class FieldDefinition extends RootNode implements DartSpecificNode { |
| 740 final FieldElement element; | 749 final FieldElement element; |
| 741 RunnableBody body; | 750 List<Definition> get parameters => const <Definition>[]; |
| 751 final Body body; |
| 742 | 752 |
| 743 FieldDefinition(this.element, this.body); | 753 FieldDefinition(this.element, this.body); |
| 744 | 754 |
| 745 FieldDefinition.withoutInitializer(this.element) | 755 FieldDefinition.withoutInitializer(this.element) |
| 746 : this.body = null; | 756 : this.body = null; |
| 747 | 757 |
| 748 accept(Visitor visitor) => visitor.visitFieldDefinition(this); | 758 accept(Visitor visitor) => visitor.visitFieldDefinition(this); |
| 749 applyPass(Pass pass) => pass.rewriteFieldDefinition(this); | |
| 750 | 759 |
| 751 /// `true` if this field has no initializer. | 760 bool get isEmpty => body == null; |
| 752 /// | |
| 753 /// If `true` [body] is `null`. | |
| 754 /// | |
| 755 /// This is different from a initializer that is `null`. Consider this class: | |
| 756 /// | |
| 757 /// class Class { | |
| 758 /// final field; | |
| 759 /// Class.a(this.field); | |
| 760 /// Class.b() : this.field = null; | |
| 761 /// Class.c(); | |
| 762 /// } | |
| 763 /// | |
| 764 /// If `field` had an initializer, possibly `null`, constructors `Class.a` and | |
| 765 /// `Class.b` would be invalid, and since `field` has no initializer | |
| 766 /// constructor `Class.c` is invalid. We therefore need to distinguish the two | |
| 767 /// cases. | |
| 768 bool get hasInitializer => body != null; | |
| 769 } | 761 } |
| 770 | 762 |
| 771 /// Identifies a mutable variable. | 763 /// Identifies a mutable variable. |
| 772 class MutableVariable extends Definition { | 764 class MutableVariable extends Definition { |
| 773 /// Body of source code that declares this mutable variable. | 765 /// Body of source code that declares this mutable variable. |
| 774 ExecutableElement host; | 766 ExecutableElement host; |
| 775 Entity hint; | 767 Entity hint; |
| 776 | 768 |
| 777 MutableVariable(this.host, this.hint); | 769 MutableVariable(this.host, this.hint); |
| 778 | 770 |
| 779 accept(Visitor v) => v.visitMutableVariable(this); | 771 accept(Visitor v) => v.visitMutableVariable(this); |
| 780 } | 772 } |
| 781 | 773 |
| 782 class RunnableBody extends InteriorNode { | 774 class Body extends InteriorNode { |
| 783 Expression body; | 775 Expression body; |
| 784 final Continuation returnContinuation; | 776 final Continuation returnContinuation; |
| 785 RunnableBody(this.body, this.returnContinuation); | 777 Body(this.body, this.returnContinuation); |
| 786 accept(Visitor visitor) => visitor.visitRunnableBody(this); | 778 accept(Visitor visitor) => visitor.visitBody(this); |
| 787 } | 779 } |
| 788 | 780 |
| 789 /// A function definition, consisting of parameters and a body. The parameters | 781 /// A function definition, consisting of parameters and a body. The parameters |
| 790 /// include a distinguished continuation parameter (held by the body). | 782 /// include a distinguished continuation parameter (held by the body). |
| 791 class FunctionDefinition extends Node | 783 class FunctionDefinition extends RootNode { |
| 792 implements ExecutableDefinition { | |
| 793 final FunctionElement element; | 784 final FunctionElement element; |
| 794 final Parameter thisParameter; | 785 final Parameter thisParameter; |
| 795 /// Mixed list of [Parameter]s and [MutableVariable]s. | 786 /// Mixed list of [Parameter]s and [MutableVariable]s. |
| 796 final List<Definition> parameters; | 787 final List<Definition> parameters; |
| 797 final RunnableBody body; | 788 final Body body; |
| 798 final List<ConstDeclaration> localConstants; | 789 final List<ConstDeclaration> localConstants; |
| 799 | 790 |
| 800 /// Values for optional parameters. | 791 /// Values for optional parameters. |
| 801 final List<ConstantExpression> defaultParameterValues; | 792 final List<ConstantExpression> defaultParameterValues; |
| 802 | 793 |
| 803 FunctionDefinition(this.element, | 794 FunctionDefinition(this.element, |
| 804 this.thisParameter, | 795 this.thisParameter, |
| 805 this.parameters, | 796 this.parameters, |
| 806 this.body, | 797 this.body, |
| 807 this.localConstants, | 798 this.localConstants, |
| 808 this.defaultParameterValues); | 799 this.defaultParameterValues); |
| 809 | 800 |
| 810 FunctionDefinition.abstract(this.element, | 801 FunctionDefinition.abstract(this.element, |
| 811 this.thisParameter, | |
| 812 this.parameters, | 802 this.parameters, |
| 813 this.defaultParameterValues) | 803 this.defaultParameterValues) |
| 814 : body = null, | 804 : body = null, |
| 805 thisParameter = null, |
| 815 localConstants = const <ConstDeclaration>[]; | 806 localConstants = const <ConstDeclaration>[]; |
| 816 | 807 |
| 817 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); | 808 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); |
| 818 applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); | |
| 819 | 809 |
| 820 /// Returns `true` if this function is abstract or external. | 810 bool get isEmpty => body == null; |
| 821 /// | |
| 822 /// If `true`, [body] is `null` and [localConstants] is empty. | |
| 823 bool get isAbstract => body == null; | |
| 824 } | 811 } |
| 825 | 812 |
| 826 abstract class Initializer extends Node implements DartSpecificNode {} | 813 abstract class Initializer extends Node implements DartSpecificNode {} |
| 827 | 814 |
| 828 class FieldInitializer extends Initializer { | 815 class FieldInitializer extends Initializer { |
| 829 final FieldElement element; | 816 final FieldElement element; |
| 830 final RunnableBody body; | 817 final Body body; |
| 831 | 818 |
| 832 FieldInitializer(this.element, this.body); | 819 FieldInitializer(this.element, this.body); |
| 833 accept(Visitor visitor) => visitor.visitFieldInitializer(this); | 820 accept(Visitor visitor) => visitor.visitFieldInitializer(this); |
| 834 } | 821 } |
| 835 | 822 |
| 836 class SuperInitializer extends Initializer { | 823 class SuperInitializer extends Initializer { |
| 837 final ConstructorElement target; | 824 final ConstructorElement target; |
| 838 final List<RunnableBody> arguments; | 825 final List<Body> arguments; |
| 839 final Selector selector; | 826 final Selector selector; |
| 840 SuperInitializer(this.target, this.arguments, this.selector); | 827 SuperInitializer(this.target, this.arguments, this.selector); |
| 841 accept(Visitor visitor) => visitor.visitSuperInitializer(this); | 828 accept(Visitor visitor) => visitor.visitSuperInitializer(this); |
| 842 } | 829 } |
| 843 | 830 |
| 844 class ConstructorDefinition extends FunctionDefinition { | 831 class ConstructorDefinition extends RootNode implements DartSpecificNode { |
| 832 final ConstructorElement element; |
| 833 final Parameter thisParameter; |
| 834 /// Mixed list of [Parameter]s and [MutableVariable]s. |
| 835 final List<Definition> parameters; |
| 836 final Body body; |
| 837 final List<ConstDeclaration> localConstants; |
| 845 final List<Initializer> initializers; | 838 final List<Initializer> initializers; |
| 846 | 839 |
| 847 ConstructorDefinition(ConstructorElement element, | 840 /// Values for optional parameters. |
| 848 Definition thisParameter, // only Dart | 841 final List<ConstantExpression> defaultParameterValues; |
| 849 List<Definition> parameters, | 842 |
| 850 RunnableBody body, | 843 ConstructorDefinition(this.element, |
| 844 this.thisParameter, |
| 845 this.parameters, |
| 846 this.body, |
| 851 this.initializers, | 847 this.initializers, |
| 852 List<ConstDeclaration> localConstants, | 848 this.localConstants, |
| 853 List<ConstantExpression> defaultParameterValues) | 849 this.defaultParameterValues); |
| 854 : super(element, thisParameter, parameters, body, localConstants, | |
| 855 defaultParameterValues); | |
| 856 | 850 |
| 857 // 'Abstract' here means "has no body" and is used to represent external | 851 // 'Abstract' here means "has no body" and is used to represent external |
| 858 // constructors. | 852 // constructors. |
| 859 ConstructorDefinition.abstract( | 853 ConstructorDefinition.abstract( |
| 860 ConstructorElement element, | 854 this.element, |
| 861 List<Definition> parameters, | 855 this.parameters, |
| 862 List<ConstantExpression> defaultParameterValues) | 856 this.defaultParameterValues) |
| 863 : initializers = null, | 857 : body = null, |
| 864 super.abstract(element, null, parameters, defaultParameterValues); | 858 initializers = null, |
| 859 thisParameter = null, |
| 860 localConstants = const <ConstDeclaration>[]; |
| 865 | 861 |
| 866 accept(Visitor visitor) => visitor.visitConstructorDefinition(this); | 862 accept(Visitor visitor) => visitor.visitConstructorDefinition(this); |
| 867 applyPass(Pass pass) => pass.rewriteConstructorDefinition(this); | 863 |
| 864 bool get isEmpty => body == null; |
| 868 } | 865 } |
| 869 | 866 |
| 870 /// Converts the internal representation of a type to a Dart object of type | 867 /// Converts the internal representation of a type to a Dart object of type |
| 871 /// [Type]. | 868 /// [Type]. |
| 872 class ReifyRuntimeType extends Primitive implements JsSpecificNode { | 869 class ReifyRuntimeType extends Primitive implements JsSpecificNode { |
| 873 /// Reference to the internal representation of a type (as produced, for | 870 /// Reference to the internal representation of a type (as produced, for |
| 874 /// example, by [ReadTypeVariable]). | 871 /// example, by [ReadTypeVariable]). |
| 875 final Reference<Primitive> value; | 872 final Reference<Primitive> value; |
| 876 ReifyRuntimeType(Primitive value) | 873 ReifyRuntimeType(Primitive value) |
| 877 : this.value = new Reference<Primitive>(value); | 874 : this.value = new Reference<Primitive>(value); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 924 | 921 |
| 925 abstract class Visitor<T> { | 922 abstract class Visitor<T> { |
| 926 const Visitor(); | 923 const Visitor(); |
| 927 | 924 |
| 928 T visit(Node node); | 925 T visit(Node node); |
| 929 | 926 |
| 930 // Concrete classes. | 927 // Concrete classes. |
| 931 T visitFieldDefinition(FieldDefinition node); | 928 T visitFieldDefinition(FieldDefinition node); |
| 932 T visitFunctionDefinition(FunctionDefinition node); | 929 T visitFunctionDefinition(FunctionDefinition node); |
| 933 T visitConstructorDefinition(ConstructorDefinition node); | 930 T visitConstructorDefinition(ConstructorDefinition node); |
| 934 T visitRunnableBody(RunnableBody node); | 931 T visitBody(Body node); |
| 935 | 932 |
| 936 // Initializers | 933 // Initializers |
| 937 T visitFieldInitializer(FieldInitializer node); | 934 T visitFieldInitializer(FieldInitializer node); |
| 938 T visitSuperInitializer(SuperInitializer node); | 935 T visitSuperInitializer(SuperInitializer node); |
| 939 | 936 |
| 940 // Expressions. | 937 // Expressions. |
| 941 T visitLetPrim(LetPrim node); | 938 T visitLetPrim(LetPrim node); |
| 942 T visitLetCont(LetCont node); | 939 T visitLetCont(LetCont node); |
| 943 T visitLetHandler(LetHandler node); | 940 T visitLetHandler(LetHandler node); |
| 944 T visitLetMutable(LetMutable node); | 941 T visitLetMutable(LetMutable node); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 | 982 |
| 986 /// Recursively visits the entire CPS term, and calls abstract `process*` | 983 /// Recursively visits the entire CPS term, and calls abstract `process*` |
| 987 /// (i.e. `processLetPrim`) functions in pre-order. | 984 /// (i.e. `processLetPrim`) functions in pre-order. |
| 988 class RecursiveVisitor implements Visitor { | 985 class RecursiveVisitor implements Visitor { |
| 989 const RecursiveVisitor(); | 986 const RecursiveVisitor(); |
| 990 | 987 |
| 991 visit(Node node) => node.accept(this); | 988 visit(Node node) => node.accept(this); |
| 992 | 989 |
| 993 processReference(Reference ref) {} | 990 processReference(Reference ref) {} |
| 994 | 991 |
| 995 processRunnableBody(RunnableBody node) {} | 992 processBody(Body node) {} |
| 996 visitRunnableBody(RunnableBody node) { | 993 visitBody(Body node) { |
| 997 processRunnableBody(node); | 994 processBody(node); |
| 998 visit(node.returnContinuation); | 995 visit(node.returnContinuation); |
| 999 visit(node.body); | 996 visit(node.body); |
| 1000 } | 997 } |
| 1001 | 998 |
| 1002 processFieldDefinition(FieldDefinition node) {} | 999 processFieldDefinition(FieldDefinition node) {} |
| 1003 visitFieldDefinition(FieldDefinition node) { | 1000 visitFieldDefinition(FieldDefinition node) { |
| 1004 processFieldDefinition(node); | 1001 processFieldDefinition(node); |
| 1005 if (node.hasInitializer) { | 1002 if (node.body != null) { |
| 1006 visit(node.body); | 1003 visit(node.body); |
| 1007 } | 1004 } |
| 1008 } | 1005 } |
| 1009 | 1006 |
| 1010 processFunctionDefinition(FunctionDefinition node) {} | 1007 processFunctionDefinition(FunctionDefinition node) {} |
| 1011 visitFunctionDefinition(FunctionDefinition node) { | 1008 visitFunctionDefinition(FunctionDefinition node) { |
| 1012 processFunctionDefinition(node); | 1009 processFunctionDefinition(node); |
| 1013 if (node.thisParameter != null) visit(node.thisParameter); | 1010 if (node.thisParameter != null) visit(node.thisParameter); |
| 1014 node.parameters.forEach(visit); | 1011 node.parameters.forEach(visit); |
| 1015 if (!node.isAbstract) { | 1012 if (node.body != null) { |
| 1016 visit(node.body); | 1013 visit(node.body); |
| 1017 } | 1014 } |
| 1018 } | 1015 } |
| 1019 | 1016 |
| 1020 processConstructorDefinition(ConstructorDefinition node) {} | 1017 processConstructorDefinition(ConstructorDefinition node) {} |
| 1021 visitConstructorDefinition(ConstructorDefinition node) { | 1018 visitConstructorDefinition(ConstructorDefinition node) { |
| 1022 processConstructorDefinition(node); | 1019 processConstructorDefinition(node); |
| 1023 if (node.thisParameter != null) visit(node.thisParameter); | 1020 if (node.thisParameter != null) visit(node.thisParameter); |
| 1024 node.parameters.forEach(visit); | 1021 node.parameters.forEach(visit); |
| 1025 if (!node.isAbstract) { | 1022 if (node.initializers != null) { |
| 1026 node.initializers.forEach(visit); | 1023 node.initializers.forEach(visit); |
| 1024 } |
| 1025 if (node.body != null) { |
| 1027 visit(node.body); | 1026 visit(node.body); |
| 1028 } | 1027 } |
| 1029 } | 1028 } |
| 1030 | 1029 |
| 1031 processFieldInitializer(FieldInitializer node) {} | 1030 processFieldInitializer(FieldInitializer node) {} |
| 1032 visitFieldInitializer(FieldInitializer node) { | 1031 visitFieldInitializer(FieldInitializer node) { |
| 1033 processFieldInitializer(node); | 1032 processFieldInitializer(node); |
| 1034 visit(node.body); | 1033 visit(node.body); |
| 1035 } | 1034 } |
| 1036 | 1035 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 processReference(node.target); | 1255 processReference(node.target); |
| 1257 } | 1256 } |
| 1258 | 1257 |
| 1259 processTypeExpression(TypeExpression node) {} | 1258 processTypeExpression(TypeExpression node) {} |
| 1260 @override | 1259 @override |
| 1261 visitTypeExpression(TypeExpression node) { | 1260 visitTypeExpression(TypeExpression node) { |
| 1262 processTypeExpression(node); | 1261 processTypeExpression(node); |
| 1263 node.arguments.forEach(processReference); | 1262 node.arguments.forEach(processReference); |
| 1264 } | 1263 } |
| 1265 } | 1264 } |
| OLD | NEW |