OLD | NEW |
---|---|
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 /// ----------------------------------------------------------------------- | 5 /// ----------------------------------------------------------------------- |
6 /// ERROR HANDLING | 6 /// ERROR HANDLING |
7 /// ----------------------------------------------------------------------- | 7 /// ----------------------------------------------------------------------- |
8 /// | 8 /// |
9 /// As a rule of thumb, errors that can be detected statically are handled by | 9 /// As a rule of thumb, errors that can be detected statically are handled by |
10 /// the frontend, typically by translating the erroneous code into a 'throw' or | 10 /// the frontend, typically by translating the erroneous code into a 'throw' or |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
49 /// has to update parent pointers manually. | 49 /// has to update parent pointers manually. |
50 /// | 50 /// |
51 library kernel.ast; | 51 library kernel.ast; |
52 | 52 |
53 import 'visitor.dart'; | 53 import 'visitor.dart'; |
54 export 'visitor.dart'; | 54 export 'visitor.dart'; |
55 | 55 |
56 import 'type_propagation/type_propagation.dart'; | 56 import 'type_propagation/type_propagation.dart'; |
57 export 'type_propagation/type_propagation.dart'; | 57 export 'type_propagation/type_propagation.dart'; |
58 | 58 |
59 import 'canonical_name.dart' show CanonicalName; | |
60 export 'canonical_name.dart' show CanonicalName; | |
61 | |
59 import 'transformations/flags.dart'; | 62 import 'transformations/flags.dart'; |
60 import 'text/ast_to_text.dart'; | 63 import 'text/ast_to_text.dart'; |
61 import 'type_algebra.dart'; | 64 import 'type_algebra.dart'; |
62 import 'type_environment.dart'; | 65 import 'type_environment.dart'; |
63 | 66 |
64 /// Any type of node in the IR. | 67 /// Any type of node in the IR. |
65 abstract class Node { | 68 abstract class Node { |
66 const Node(); | 69 const Node(); |
67 | 70 |
68 accept(Visitor v); | 71 accept(Visitor v); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
126 parent = null; | 129 parent = null; |
127 } | 130 } |
128 | 131 |
129 /// Removes this node from the [List] it is currently stored in, or assigns | 132 /// Removes this node from the [List] it is currently stored in, or assigns |
130 /// `null` to the field on the parent currently pointing to the node. | 133 /// `null` to the field on the parent currently pointing to the node. |
131 /// | 134 /// |
132 /// Has no effect if the node is orphaned or if the parent pointer is stale. | 135 /// Has no effect if the node is orphaned or if the parent pointer is stale. |
133 void remove() { | 136 void remove() { |
134 parent?.replaceChild(this, null); | 137 parent?.replaceChild(this, null); |
135 parent = null; | 138 parent = null; |
136 } | 139 } |
kustermann
2017/02/01 13:00:54
Do the replaceWith/replaceChild/remove/parent= met
asgerf
2017/02/02 12:30:27
No.
| |
137 | 140 |
138 Program get enclosingProgram => parent?.enclosingProgram; | 141 Program get enclosingProgram => parent?.enclosingProgram; |
139 | 142 |
140 /// Returns the best known source location of the given AST node, or `null` if | 143 /// Returns the best known source location of the given AST node, or `null` if |
141 /// the node is orphaned. | 144 /// the node is orphaned. |
142 /// | 145 /// |
143 /// This getter is intended for diagnostics and debugging, and should be | 146 /// This getter is intended for diagnostics and debugging, and should be |
144 /// avoided in production code. | 147 /// avoided in production code. |
145 Location get location { | 148 Location get location { |
146 if (fileOffset == noOffset) return parent?.location; | 149 if (fileOffset == noOffset) return parent?.location; |
147 return _getLocationInEnclosingFile(fileOffset); | 150 return _getLocationInEnclosingFile(fileOffset); |
148 } | 151 } |
149 | 152 |
150 Location _getLocationInEnclosingFile(int offset) { | 153 Location _getLocationInEnclosingFile(int offset) { |
151 return parent?._getLocationInEnclosingFile(offset); | 154 return parent?._getLocationInEnclosingFile(offset); |
152 } | 155 } |
153 } | 156 } |
154 | 157 |
158 /// An AST node that has an associated [CanonicalName], allowing it to be | |
159 /// referenced by name. Libraries, classes, and members are linked nodes. | |
160 /// | |
161 /// When created, a linked node has no associated canonical name, and must be | |
162 /// linked to such a name before it can be referenced. A canonical name is | |
163 /// typically assigned by either: | |
164 /// - Adding it to the a class or library using `addMember` or `addClass`. | |
165 /// - Explicitly assigning a name using [CanonicalName.linkTo]. | |
166 abstract class LinkedNode extends TreeNode { | |
167 CanonicalName canonicalName; | |
168 } | |
169 | |
155 // ------------------------------------------------------------------------ | 170 // ------------------------------------------------------------------------ |
156 // LIBRARIES and CLASSES | 171 // LIBRARIES and CLASSES |
157 // ------------------------------------------------------------------------ | 172 // ------------------------------------------------------------------------ |
158 | 173 |
159 class Library extends TreeNode implements Comparable<Library> { | 174 class Library extends LinkedNode implements Comparable<Library> { |
160 /// An import path to this library. | 175 /// An import path to this library. |
161 /// | 176 /// |
162 /// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme. | 177 /// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme. |
163 /// | 178 /// |
164 /// If the URI has the `app` scheme, it is relative to the application root. | 179 /// If the URI has the `app` scheme, it is relative to the application root. |
165 Uri importUri; | 180 Uri importUri; |
166 | 181 |
167 /// The uri of the source file this library was loaded from. | 182 /// The uri of the source file this library was loaded from. |
168 String fileUri; | 183 String fileUri; |
169 | 184 |
(...skipping 28 matching lines...) Expand all Loading... | |
198 } | 213 } |
199 | 214 |
200 /// Returns the top-level fields and procedures defined in this library. | 215 /// Returns the top-level fields and procedures defined in this library. |
201 /// | 216 /// |
202 /// This getter is for convenience, not efficiency. Consider manually | 217 /// This getter is for convenience, not efficiency. Consider manually |
203 /// iterating the members to speed up code in production. | 218 /// iterating the members to speed up code in production. |
204 Iterable<Member> get members => | 219 Iterable<Member> get members => |
205 <Iterable<Member>>[fields, procedures].expand((x) => x); | 220 <Iterable<Member>>[fields, procedures].expand((x) => x); |
206 | 221 |
207 void addMember(Member member) { | 222 void addMember(Member member) { |
223 if (member.canonicalName == null) { | |
224 getCanonicalNameOfLibrary(this).getChildFromMember(member).linkTo(member); | |
ahe
2017/01/30 17:16:16
Would it make sense to move this to "set parent"?
asgerf
2017/02/02 12:30:27
I don't see why. Set parent is the low-level acces
| |
225 } | |
208 member.parent = this; | 226 member.parent = this; |
209 if (member is Procedure) { | 227 if (member is Procedure) { |
210 procedures.add(member); | 228 procedures.add(member); |
211 } else if (member is Field) { | 229 } else if (member is Field) { |
212 fields.add(member); | 230 fields.add(member); |
213 } else { | 231 } else { |
214 throw new ArgumentError(member); | 232 throw new ArgumentError(member); |
215 } | 233 } |
216 } | 234 } |
217 | 235 |
218 void addClass(Class class_) { | 236 void addClass(Class class_) { |
237 if (class_.canonicalName == null) { | |
238 getCanonicalNameOfLibrary(this).getChild(class_.name).linkTo(class_); | |
239 } | |
219 class_.parent = this; | 240 class_.parent = this; |
220 classes.add(class_); | 241 classes.add(class_); |
221 } | 242 } |
222 | 243 |
223 accept(TreeVisitor v) => v.visitLibrary(this); | 244 accept(TreeVisitor v) => v.visitLibrary(this); |
224 | 245 |
225 visitChildren(Visitor v) { | 246 visitChildren(Visitor v) { |
226 visitList(classes, v); | 247 visitList(classes, v); |
227 visitList(procedures, v); | 248 visitList(procedures, v); |
228 visitList(fields, v); | 249 visitList(fields, v); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
282 /// not necessarily at [Body] level. | 303 /// not necessarily at [Body] level. |
283 Body, | 304 Body, |
284 } | 305 } |
285 | 306 |
286 /// Declaration of a regular class or a mixin application. | 307 /// Declaration of a regular class or a mixin application. |
287 /// | 308 /// |
288 /// Mixin applications may not contain fields or procedures, as they implicitly | 309 /// Mixin applications may not contain fields or procedures, as they implicitly |
289 /// use those from its mixed-in type. However, the IR does not enforce this | 310 /// use those from its mixed-in type. However, the IR does not enforce this |
290 /// rule directly, as doing so can obstruct transformations. It is possible to | 311 /// rule directly, as doing so can obstruct transformations. It is possible to |
291 /// transform a mixin application to become a regular class, and vice versa. | 312 /// transform a mixin application to become a regular class, and vice versa. |
292 class Class extends TreeNode { | 313 class Class extends LinkedNode { |
293 /// The degree to which the contents of the class have been loaded. | 314 /// The degree to which the contents of the class have been loaded. |
294 ClassLevel level = ClassLevel.Body; | 315 ClassLevel level = ClassLevel.Body; |
295 | 316 |
296 /// List of metadata annotations on the class. | 317 /// List of metadata annotations on the class. |
297 /// | 318 /// |
298 /// This defaults to an immutable empty list. Use [addAnnotation] to add | 319 /// This defaults to an immutable empty list. Use [addAnnotation] to add |
299 /// annotations if needed. | 320 /// annotations if needed. |
300 List<Expression> annotations = const <Expression>[]; | 321 List<Expression> annotations = const <Expression>[]; |
301 | 322 |
302 /// Name of the class. | 323 /// Name of the class. |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 ].expand((x) => x); | 411 ].expand((x) => x); |
391 | 412 |
392 /// The library containing this class. | 413 /// The library containing this class. |
393 Library get enclosingLibrary => parent; | 414 Library get enclosingLibrary => parent; |
394 | 415 |
395 /// Adds a member to this class. | 416 /// Adds a member to this class. |
396 /// | 417 /// |
397 /// Throws an error if attempting to add a field or procedure to a mixin | 418 /// Throws an error if attempting to add a field or procedure to a mixin |
398 /// application. | 419 /// application. |
399 void addMember(Member member) { | 420 void addMember(Member member) { |
421 if (member.canonicalName == null) { | |
422 getCanonicalNameOfClass(this).getChildFromMember(member).linkTo(member); | |
423 } | |
kustermann
2017/02/01 13:00:54
Should we do some verification in the else branch,
asgerf
2017/02/02 12:30:27
The assertion is equivalent to always doing linkTo
| |
400 member.parent = this; | 424 member.parent = this; |
401 if (member is Constructor) { | 425 if (member is Constructor) { |
402 constructors.add(member); | 426 constructors.add(member); |
403 } else if (member is Procedure) { | 427 } else if (member is Procedure) { |
404 procedures.add(member); | 428 procedures.add(member); |
405 } else if (member is Field) { | 429 } else if (member is Field) { |
406 fields.add(member); | 430 fields.add(member); |
407 } else { | 431 } else { |
408 throw new ArgumentError(member); | 432 throw new ArgumentError(member); |
409 } | 433 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
483 | 507 |
484 Location _getLocationInEnclosingFile(int offset) { | 508 Location _getLocationInEnclosingFile(int offset) { |
485 return enclosingProgram.getLocation(fileUri, offset); | 509 return enclosingProgram.getLocation(fileUri, offset); |
486 } | 510 } |
487 } | 511 } |
488 | 512 |
489 // ------------------------------------------------------------------------ | 513 // ------------------------------------------------------------------------ |
490 // MEMBERS | 514 // MEMBERS |
491 // ------------------------------------------------------------------------ | 515 // ------------------------------------------------------------------------ |
492 | 516 |
493 /// A indirect reference to a member, which can be updated to point at another | 517 abstract class Member extends LinkedNode { |
494 /// member at a later time. | |
495 class _MemberAccessor { | |
496 Member target; | |
497 _MemberAccessor(this.target); | |
498 } | |
499 | |
500 abstract class Member extends TreeNode { | |
501 /// End offset in the source file it comes from. Valid values are from 0 and | 518 /// End offset in the source file it comes from. Valid values are from 0 and |
502 /// up, or -1 ([TreeNode.noOffset]) if the file end offset is not available | 519 /// up, or -1 ([TreeNode.noOffset]) if the file end offset is not available |
503 /// (this is the default if none is specifically set). | 520 /// (this is the default if none is specifically set). |
504 int fileEndOffset = TreeNode.noOffset; | 521 int fileEndOffset = TreeNode.noOffset; |
505 | 522 |
506 /// List of metadata annotations on the member. | 523 /// List of metadata annotations on the member. |
507 /// | 524 /// |
508 /// This defaults to an immutable empty list. Use [addAnnotation] to add | 525 /// This defaults to an immutable empty list. Use [addAnnotation] to add |
509 /// annotations if needed. | 526 /// annotations if needed. |
510 List<Expression> annotations = const <Expression>[]; | 527 List<Expression> annotations = const <Expression>[]; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
578 annotations.add(node); | 595 annotations.add(node); |
579 node.parent = this; | 596 node.parent = this; |
580 } | 597 } |
581 | 598 |
582 DartType get getterType; | 599 DartType get getterType; |
583 DartType get setterType; | 600 DartType get setterType; |
584 | 601 |
585 bool get containsSuperCalls { | 602 bool get containsSuperCalls { |
586 return transformerFlags & TransformerFlag.superCalls != 0; | 603 return transformerFlags & TransformerFlag.superCalls != 0; |
587 } | 604 } |
588 | |
589 _MemberAccessor get _getterInterface; | |
590 _MemberAccessor get _setterInterface; | |
591 } | 605 } |
592 | 606 |
593 /// A field declaration. | 607 /// A field declaration. |
594 /// | 608 /// |
595 /// The implied getter and setter for the field are not represented explicitly, | 609 /// The implied getter and setter for the field are not represented explicitly, |
596 /// but can be made explicit if needed. | 610 /// but can be made explicit if needed. |
597 class Field extends Member { | 611 class Field extends Member { |
598 _MemberAccessor _getterInterface, _setterInterface; | |
599 | |
600 DartType type; // Not null. Defaults to DynamicType. | 612 DartType type; // Not null. Defaults to DynamicType. |
601 InferredValue inferredValue; // May be null. | 613 InferredValue inferredValue; // May be null. |
602 int flags = 0; | 614 int flags = 0; |
603 Expression initializer; // May be null. | 615 Expression initializer; // May be null. |
604 | 616 |
605 /// The uri of the source file this field was loaded from. | 617 /// The uri of the source file this field was loaded from. |
606 String fileUri; | 618 String fileUri; |
607 | 619 |
608 Field(Name name, | 620 Field(Name name, |
609 {this.type: const DynamicType(), | 621 {this.type: const DynamicType(), |
610 this.inferredValue, | 622 this.inferredValue, |
611 this.initializer, | 623 this.initializer, |
612 bool isFinal: false, | 624 bool isFinal: false, |
613 bool isConst: false, | 625 bool isConst: false, |
614 bool isStatic: false, | 626 bool isStatic: false, |
615 bool hasImplicitGetter, | 627 bool hasImplicitGetter, |
616 bool hasImplicitSetter, | 628 bool hasImplicitSetter, |
617 int transformerFlags: 0, | 629 int transformerFlags: 0, |
618 this.fileUri}) | 630 this.fileUri}) |
619 : super(name) { | 631 : super(name) { |
620 _getterInterface = new _MemberAccessor(this); | |
621 _setterInterface = new _MemberAccessor(this); | |
622 assert(type != null); | 632 assert(type != null); |
623 initializer?.parent = this; | 633 initializer?.parent = this; |
624 this.isFinal = isFinal; | 634 this.isFinal = isFinal; |
625 this.isConst = isConst; | 635 this.isConst = isConst; |
626 this.isStatic = isStatic; | 636 this.isStatic = isStatic; |
627 this.hasImplicitGetter = hasImplicitGetter ?? !isStatic; | 637 this.hasImplicitGetter = hasImplicitGetter ?? !isStatic; |
628 this.hasImplicitSetter = hasImplicitSetter ?? (!isStatic && !isFinal); | 638 this.hasImplicitSetter = hasImplicitSetter ?? (!isStatic && !isFinal); |
629 this.transformerFlags = transformerFlags; | 639 this.transformerFlags = transformerFlags; |
630 } | 640 } |
631 | 641 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
711 transformList(annotations, v, this); | 721 transformList(annotations, v, this); |
712 if (initializer != null) { | 722 if (initializer != null) { |
713 initializer = initializer.accept(v); | 723 initializer = initializer.accept(v); |
714 initializer?.parent = this; | 724 initializer?.parent = this; |
715 } | 725 } |
716 } | 726 } |
717 | 727 |
718 DartType get getterType => type; | 728 DartType get getterType => type; |
719 DartType get setterType => isMutable ? type : const BottomType(); | 729 DartType get setterType => isMutable ? type : const BottomType(); |
720 | 730 |
721 /// Makes all [PropertyGet]s that have this field as its interface target | |
722 /// use [getter] as its interface target instead. | |
723 /// | |
724 /// That can be used to introduce an explicit getter for a field instead of | |
725 /// its implicit getter. | |
726 /// | |
727 /// This method only updates the stored interface target -- the caller must | |
728 /// ensure that [getter] actually becomes the target for dispatches that | |
729 /// would previously hit the implicit field getter. | |
730 /// | |
731 /// [DirectPropertyGet]s are not affected, and will continue to access the | |
732 /// field directly. [PropertyGet] nodes created after the call will not be | |
733 /// affected until the method is called again. | |
734 /// | |
735 /// Existing [ClassHierarchy] instances are not affected by this call. | |
736 void replaceGetterInterfaceWith(Procedure getter) { | |
737 _getterInterface.target = getter; | |
738 _getterInterface = new _MemberAccessor(this); | |
739 } | |
740 | |
741 /// Makes all [PropertySet]s that have this field as its interface target | |
742 /// use [setter] as its interface target instead. | |
743 /// | |
744 /// That can be used to introduce an explicit setter for a field instead of | |
745 /// its implicit setter. | |
746 /// | |
747 /// This method only updates the stored interface target -- the caller must | |
748 /// ensure that [setter] actually becomes the target for dispatches that | |
749 /// would previously hit the implicit field setter. | |
750 /// | |
751 /// [DirectPropertySet] and [FieldInitializer]s are not affected, and will | |
752 /// continue to access the field directly. [PropertySet] nodes created after | |
753 /// the call will not be affected until the method is called again. | |
754 /// | |
755 /// Existing [ClassHierarchy] instances are not affected by this call. | |
756 void replaceSetterInterfaceWith(Procedure setter) { | |
757 _setterInterface.target = setter; | |
758 _setterInterface = new _MemberAccessor(this); | |
759 } | |
760 | |
761 Location _getLocationInEnclosingFile(int offset) { | 731 Location _getLocationInEnclosingFile(int offset) { |
762 return enclosingProgram.getLocation(fileUri, offset); | 732 return enclosingProgram.getLocation(fileUri, offset); |
763 } | 733 } |
764 } | 734 } |
765 | 735 |
766 /// A generative constructor, possibly redirecting. | 736 /// A generative constructor, possibly redirecting. |
767 /// | 737 /// |
768 /// Note that factory constructors are treated as [Procedure]s. | 738 /// Note that factory constructors are treated as [Procedure]s. |
769 /// | 739 /// |
770 /// Constructors do not take type parameters. Type arguments from a constructor | 740 /// Constructors do not take type parameters. Type arguments from a constructor |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
825 transformList(annotations, v, this); | 795 transformList(annotations, v, this); |
826 if (function != null) { | 796 if (function != null) { |
827 function = function.accept(v); | 797 function = function.accept(v); |
828 function?.parent = this; | 798 function?.parent = this; |
829 } | 799 } |
830 transformList(initializers, v, this); | 800 transformList(initializers, v, this); |
831 } | 801 } |
832 | 802 |
833 DartType get getterType => const BottomType(); | 803 DartType get getterType => const BottomType(); |
834 DartType get setterType => const BottomType(); | 804 DartType get setterType => const BottomType(); |
835 | |
836 _MemberAccessor get _getterInterface { | |
837 throw 'Constructors cannot be used as getters'; | |
838 } | |
839 | |
840 _MemberAccessor get _setterInterface { | |
841 throw 'Constructors cannot be used as setters'; | |
842 } | |
843 } | 805 } |
844 | 806 |
845 /// A method, getter, setter, index-getter, index-setter, operator overloader, | 807 /// A method, getter, setter, index-getter, index-setter, operator overloader, |
846 /// or factory. | 808 /// or factory. |
847 /// | 809 /// |
848 /// Procedures can have the static, abstract, and/or external modifier, although | 810 /// Procedures can have the static, abstract, and/or external modifier, although |
849 /// only the static and external modifiers may be used together. | 811 /// only the static and external modifiers may be used together. |
850 /// | 812 /// |
851 /// For non-static procedures the name is required for dynamic dispatch. | 813 /// For non-static procedures the name is required for dynamic dispatch. |
852 /// For external procedures the name is required for identifying the external | 814 /// For external procedures the name is required for identifying the external |
853 /// implementation. | 815 /// implementation. |
854 /// | 816 /// |
855 /// For methods, getters, and setters the name is just as it was declared. | 817 /// For methods, getters, and setters the name is just as it was declared. |
856 /// For setters this does not include a trailing `=`. | 818 /// For setters this does not include a trailing `=`. |
857 /// For index-getters/setters, this is `[]` and `[]=`. | 819 /// For index-getters/setters, this is `[]` and `[]=`. |
858 /// For operators, this is the token for the operator, e.g. `+` or `==`, | 820 /// For operators, this is the token for the operator, e.g. `+` or `==`, |
859 /// except for the unary minus operator, whose name is `unary-`. | 821 /// except for the unary minus operator, whose name is `unary-`. |
860 class Procedure extends Member { | 822 class Procedure extends Member { |
861 _MemberAccessor _reference; | |
862 ProcedureKind kind; | 823 ProcedureKind kind; |
863 int flags = 0; | 824 int flags = 0; |
864 FunctionNode function; // Body is null if and only if abstract or external. | 825 FunctionNode function; // Body is null if and only if abstract or external. |
865 | 826 |
866 /// The uri of the source file this procedure was loaded from. | 827 /// The uri of the source file this procedure was loaded from. |
867 String fileUri; | 828 String fileUri; |
868 | 829 |
869 Procedure(Name name, this.kind, this.function, | 830 Procedure(Name name, this.kind, this.function, |
870 {bool isAbstract: false, | 831 {bool isAbstract: false, |
871 bool isStatic: false, | 832 bool isStatic: false, |
872 bool isExternal: false, | 833 bool isExternal: false, |
873 bool isConst: false, | 834 bool isConst: false, |
874 int transformerFlags: 0, | 835 int transformerFlags: 0, |
875 this.fileUri}) | 836 this.fileUri}) |
876 : super(name) { | 837 : super(name) { |
877 _reference = new _MemberAccessor(this); | |
878 function?.parent = this; | 838 function?.parent = this; |
879 this.isAbstract = isAbstract; | 839 this.isAbstract = isAbstract; |
880 this.isStatic = isStatic; | 840 this.isStatic = isStatic; |
881 this.isExternal = isExternal; | 841 this.isExternal = isExternal; |
882 this.isConst = isConst; | 842 this.isConst = isConst; |
883 this.transformerFlags = transformerFlags; | 843 this.transformerFlags = transformerFlags; |
884 } | 844 } |
885 | 845 |
886 static const int FlagStatic = 1 << 0; // Must match serialized bit positions. | 846 static const int FlagStatic = 1 << 0; // Must match serialized bit positions. |
887 static const int FlagAbstract = 1 << 1; | 847 static const int FlagAbstract = 1 << 1; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
940 DartType get getterType { | 900 DartType get getterType { |
941 return isGetter ? function.returnType : function.functionType; | 901 return isGetter ? function.returnType : function.functionType; |
942 } | 902 } |
943 | 903 |
944 DartType get setterType { | 904 DartType get setterType { |
945 return isSetter | 905 return isSetter |
946 ? function.positionalParameters[0].type | 906 ? function.positionalParameters[0].type |
947 : const BottomType(); | 907 : const BottomType(); |
948 } | 908 } |
949 | 909 |
950 _MemberAccessor get _getterInterface => _reference; | |
951 _MemberAccessor get _setterInterface => _reference; | |
952 | |
953 Location _getLocationInEnclosingFile(int offset) { | 910 Location _getLocationInEnclosingFile(int offset) { |
954 return enclosingProgram.getLocation(fileUri, offset); | 911 return enclosingProgram.getLocation(fileUri, offset); |
955 } | 912 } |
956 } | 913 } |
957 | 914 |
958 enum ProcedureKind { | 915 enum ProcedureKind { |
959 Method, | 916 Method, |
960 Getter, | 917 Getter, |
961 Setter, | 918 Setter, |
962 Operator, | 919 Operator, |
(...skipping 25 matching lines...) Expand all Loading... | |
988 /// A field assignment `field = value` occurring in the initializer list of | 945 /// A field assignment `field = value` occurring in the initializer list of |
989 /// a constructor. | 946 /// a constructor. |
990 /// | 947 /// |
991 /// This node has nothing to do with declaration-site field initializers; those | 948 /// This node has nothing to do with declaration-site field initializers; those |
992 /// are [Expression]s stored in [Field.initializer]. | 949 /// are [Expression]s stored in [Field.initializer]. |
993 // | 950 // |
994 // TODO: The frontend should check that all final fields are initialized | 951 // TODO: The frontend should check that all final fields are initialized |
995 // exactly once, and that no fields are assigned twice in the initializer list. | 952 // exactly once, and that no fields are assigned twice in the initializer list. |
996 class FieldInitializer extends Initializer { | 953 class FieldInitializer extends Initializer { |
997 /// Reference to the field being initialized. Not null. | 954 /// Reference to the field being initialized. Not null. |
998 Field field; | 955 CanonicalName fieldName; |
999 Expression value; | 956 Expression value; |
1000 | 957 |
1001 FieldInitializer(this.field, this.value) { | 958 FieldInitializer(Field field, Expression value) |
959 : this.byName(getCanonicalNameOfMember(field), value); | |
960 | |
961 FieldInitializer.byName(this.fieldName, this.value) { | |
1002 value?.parent = this; | 962 value?.parent = this; |
1003 } | 963 } |
1004 | 964 |
965 Field get field => fieldName?.definition as Field; | |
kustermann
2017/02/01 13:00:54
Could you use fieldName?.asField here?
Or is this
asgerf
2017/02/02 12:30:27
Yep, it was supposed to say fieldName?.asField.
| |
966 | |
967 void set field(Field field) { | |
968 fieldName = getCanonicalNameOfMember(field); | |
969 } | |
970 | |
1005 accept(InitializerVisitor v) => v.visitFieldInitializer(this); | 971 accept(InitializerVisitor v) => v.visitFieldInitializer(this); |
1006 | 972 |
1007 visitChildren(Visitor v) { | 973 visitChildren(Visitor v) { |
1008 field?.acceptReference(v); | 974 field?.acceptReference(v); |
1009 value?.accept(v); | 975 value?.accept(v); |
1010 } | 976 } |
1011 | 977 |
1012 transformChildren(Transformer v) { | 978 transformChildren(Transformer v) { |
1013 if (value != null) { | 979 if (value != null) { |
1014 value = value.accept(v); | 980 value = value.accept(v); |
1015 value?.parent = this; | 981 value?.parent = this; |
1016 } | 982 } |
1017 } | 983 } |
1018 } | 984 } |
1019 | 985 |
1020 /// A super call `super(x,y)` occurring in the initializer list of a | 986 /// A super call `super(x,y)` occurring in the initializer list of a |
1021 /// constructor. | 987 /// constructor. |
1022 /// | 988 /// |
1023 /// There are no type arguments on this call. | 989 /// There are no type arguments on this call. |
1024 // | 990 // |
1025 // TODO: The frontend should check that there is no more than one super call. | 991 // TODO: The frontend should check that there is no more than one super call. |
1026 // | 992 // |
1027 // DESIGN TODO: Consider if the frontend should insert type arguments derived | 993 // DESIGN TODO: Consider if the frontend should insert type arguments derived |
1028 // from the extends clause. | 994 // from the extends clause. |
1029 class SuperInitializer extends Initializer { | 995 class SuperInitializer extends Initializer { |
1030 /// Reference to the constructor being invoked in the super class. Not null. | 996 /// Reference to the constructor being invoked in the super class. Not null. |
1031 Constructor target; | 997 CanonicalName targetName; |
1032 Arguments arguments; | 998 Arguments arguments; |
1033 | 999 |
1034 SuperInitializer(this.target, this.arguments) { | 1000 SuperInitializer(Constructor target, Arguments arguments) |
1001 : this.byName(getCanonicalNameOfMember(target), arguments); | |
1002 | |
1003 SuperInitializer.byName(this.targetName, this.arguments) { | |
1035 arguments?.parent = this; | 1004 arguments?.parent = this; |
1036 } | 1005 } |
1037 | 1006 |
1007 Constructor get target => targetName?.definition as Constructor; | |
kustermann
2017/02/01 13:00:54
ditto
asgerf
2017/02/02 12:30:27
Done.
| |
1008 | |
1009 void set target(Constructor target) { | |
1010 targetName = getCanonicalNameOfMember(target); | |
1011 } | |
1012 | |
1038 accept(InitializerVisitor v) => v.visitSuperInitializer(this); | 1013 accept(InitializerVisitor v) => v.visitSuperInitializer(this); |
1039 | 1014 |
1040 visitChildren(Visitor v) { | 1015 visitChildren(Visitor v) { |
1041 target?.acceptReference(v); | 1016 target?.acceptReference(v); |
1042 arguments?.accept(v); | 1017 arguments?.accept(v); |
1043 } | 1018 } |
1044 | 1019 |
1045 transformChildren(Transformer v) { | 1020 transformChildren(Transformer v) { |
1046 if (arguments != null) { | 1021 if (arguments != null) { |
1047 arguments = arguments.accept(v); | 1022 arguments = arguments.accept(v); |
1048 arguments?.parent = this; | 1023 arguments?.parent = this; |
1049 } | 1024 } |
1050 } | 1025 } |
1051 } | 1026 } |
1052 | 1027 |
1053 /// A redirecting call `this(x,y)` occurring in the initializer list of | 1028 /// A redirecting call `this(x,y)` occurring in the initializer list of |
1054 /// a constructor. | 1029 /// a constructor. |
1055 // | 1030 // |
1056 // TODO: The frontend should check that this is the only initializer and if the | 1031 // TODO: The frontend should check that this is the only initializer and if the |
1057 // constructor has a body or if there is a cycle in the initializer calls. | 1032 // constructor has a body or if there is a cycle in the initializer calls. |
1058 class RedirectingInitializer extends Initializer { | 1033 class RedirectingInitializer extends Initializer { |
1059 /// Reference to the constructor being invoked in the same class. Not null. | 1034 /// Reference to the constructor being invoked in the same class. Not null. |
1060 Constructor target; | 1035 CanonicalName targetName; |
1061 Arguments arguments; | 1036 Arguments arguments; |
1062 | 1037 |
1063 RedirectingInitializer(this.target, this.arguments) { | 1038 RedirectingInitializer(Constructor target, Arguments arguments) |
1039 : this.byName(getCanonicalNameOfMember(target), arguments); | |
1040 | |
1041 RedirectingInitializer.byName(this.targetName, this.arguments) { | |
1064 arguments?.parent = this; | 1042 arguments?.parent = this; |
1065 } | 1043 } |
1066 | 1044 |
1045 Constructor get target => targetName?.definition as Constructor; | |
kustermann
2017/02/01 13:00:54
ditto
asgerf
2017/02/02 12:30:27
Done.
| |
1046 | |
1047 void set target(Constructor target) { | |
1048 targetName = getCanonicalNameOfMember(target); | |
1049 } | |
1050 | |
1067 accept(InitializerVisitor v) => v.visitRedirectingInitializer(this); | 1051 accept(InitializerVisitor v) => v.visitRedirectingInitializer(this); |
1068 | 1052 |
1069 visitChildren(Visitor v) { | 1053 visitChildren(Visitor v) { |
1070 target?.acceptReference(v); | 1054 target?.acceptReference(v); |
1071 arguments?.accept(v); | 1055 arguments?.accept(v); |
1072 } | 1056 } |
1073 | 1057 |
1074 transformChildren(Transformer v) { | 1058 transformChildren(Transformer v) { |
1075 if (arguments != null) { | 1059 if (arguments != null) { |
1076 arguments = arguments.accept(v); | 1060 arguments = arguments.accept(v); |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1349 } | 1333 } |
1350 } | 1334 } |
1351 | 1335 |
1352 /// Expression of form `x.field`. | 1336 /// Expression of form `x.field`. |
1353 /// | 1337 /// |
1354 /// This may invoke a getter, read a field, or tear off a method. | 1338 /// This may invoke a getter, read a field, or tear off a method. |
1355 class PropertyGet extends Expression { | 1339 class PropertyGet extends Expression { |
1356 Expression receiver; | 1340 Expression receiver; |
1357 Name name; | 1341 Name name; |
1358 | 1342 |
1359 _MemberAccessor _interfaceTargetReference; | 1343 CanonicalName interfaceTargetName; |
1360 | 1344 |
1361 PropertyGet(this.receiver, this.name, [Member interfaceTarget]) { | 1345 PropertyGet(Expression receiver, Name name, [Member interfaceTarget]) |
1346 : this.byName(receiver, name, getCanonicalNameOfMember(interfaceTarget)); | |
1347 | |
1348 PropertyGet.byName(this.receiver, this.name, this.interfaceTargetName) { | |
1362 receiver?.parent = this; | 1349 receiver?.parent = this; |
1363 this.interfaceTarget = interfaceTarget; | |
1364 } | 1350 } |
1365 | 1351 |
1366 Member get interfaceTarget => _interfaceTargetReference?.target; | 1352 Member get interfaceTarget => interfaceTargetName?.asMember; |
1367 | 1353 |
1368 void set interfaceTarget(Member newTarget) { | 1354 void set interfaceTarget(Member member) { |
1369 _interfaceTargetReference = newTarget?._getterInterface; | 1355 interfaceTargetName = getCanonicalNameOfMember(member); |
1370 } | 1356 } |
1371 | 1357 |
1372 DartType getStaticType(TypeEnvironment types) { | 1358 DartType getStaticType(TypeEnvironment types) { |
1373 var interfaceTarget = this.interfaceTarget; | 1359 var interfaceTarget = this.interfaceTarget; |
1374 if (interfaceTarget != null) { | 1360 if (interfaceTarget != null) { |
1375 Class superclass = interfaceTarget.enclosingClass; | 1361 Class superclass = interfaceTarget.enclosingClass; |
1376 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types); | 1362 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types); |
1377 return Substitution | 1363 return Substitution |
1378 .fromInterfaceType(receiverType) | 1364 .fromInterfaceType(receiverType) |
1379 .substituteType(interfaceTarget.getterType); | 1365 .substituteType(interfaceTarget.getterType); |
(...skipping 26 matching lines...) Expand all Loading... | |
1406 /// Expression of form `x.field = value`. | 1392 /// Expression of form `x.field = value`. |
1407 /// | 1393 /// |
1408 /// This may invoke a setter or assign a field. | 1394 /// This may invoke a setter or assign a field. |
1409 /// | 1395 /// |
1410 /// Evaluates to the value of [value]. | 1396 /// Evaluates to the value of [value]. |
1411 class PropertySet extends Expression { | 1397 class PropertySet extends Expression { |
1412 Expression receiver; | 1398 Expression receiver; |
1413 Name name; | 1399 Name name; |
1414 Expression value; | 1400 Expression value; |
1415 | 1401 |
1416 _MemberAccessor _interfaceTargetReference; | 1402 CanonicalName interfaceTargetName; |
1417 | 1403 |
1418 PropertySet(this.receiver, this.name, this.value, [Member interfaceTarget]) { | 1404 PropertySet(Expression receiver, Name name, Expression value, |
1405 [Member interfaceTarget]) | |
1406 : this.byName( | |
1407 receiver, name, value, getCanonicalNameOfMember(interfaceTarget)); | |
1408 | |
1409 PropertySet.byName( | |
1410 this.receiver, this.name, this.value, this.interfaceTargetName) { | |
1419 receiver?.parent = this; | 1411 receiver?.parent = this; |
1420 value?.parent = this; | 1412 value?.parent = this; |
1421 this.interfaceTarget = interfaceTarget; | |
1422 } | 1413 } |
1423 | 1414 |
1424 Member get interfaceTarget => _interfaceTargetReference?.target; | 1415 Member get interfaceTarget => interfaceTargetName?.asMember; |
1425 | 1416 |
1426 void set interfaceTarget(Member newTarget) { | 1417 void set interfaceTarget(Member member) { |
1427 _interfaceTargetReference = newTarget?._setterInterface; | 1418 interfaceTargetName = getCanonicalNameOfMember(member); |
1428 } | 1419 } |
1429 | 1420 |
1430 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); | 1421 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); |
1431 | 1422 |
1432 accept(ExpressionVisitor v) => v.visitPropertySet(this); | 1423 accept(ExpressionVisitor v) => v.visitPropertySet(this); |
1433 | 1424 |
1434 visitChildren(Visitor v) { | 1425 visitChildren(Visitor v) { |
1435 receiver?.accept(v); | 1426 receiver?.accept(v); |
1436 name?.accept(v); | 1427 name?.accept(v); |
1437 value?.accept(v); | 1428 value?.accept(v); |
1438 } | 1429 } |
1439 | 1430 |
1440 transformChildren(Transformer v) { | 1431 transformChildren(Transformer v) { |
1441 if (receiver != null) { | 1432 if (receiver != null) { |
1442 receiver = receiver.accept(v); | 1433 receiver = receiver.accept(v); |
1443 receiver?.parent = this; | 1434 receiver?.parent = this; |
1444 } | 1435 } |
1445 if (value != null) { | 1436 if (value != null) { |
1446 value = value.accept(v); | 1437 value = value.accept(v); |
1447 value?.parent = this; | 1438 value?.parent = this; |
1448 } | 1439 } |
1449 } | 1440 } |
1450 } | 1441 } |
1451 | 1442 |
1452 /// Directly read a field, call a getter, or tear off a method. | 1443 /// Directly read a field, call a getter, or tear off a method. |
1453 class DirectPropertyGet extends Expression { | 1444 class DirectPropertyGet extends Expression { |
1454 Expression receiver; | 1445 Expression receiver; |
1455 Member target; | 1446 CanonicalName targetName; |
1456 | 1447 |
1457 DirectPropertyGet(this.receiver, this.target) { | 1448 DirectPropertyGet(Expression receiver, Member target) |
1449 : this.byName(receiver, getCanonicalNameOfMember(target)); | |
1450 | |
1451 DirectPropertyGet.byName(this.receiver, this.targetName) { | |
1458 receiver?.parent = this; | 1452 receiver?.parent = this; |
1459 } | 1453 } |
1460 | 1454 |
1455 Member get target => targetName?.asMember; | |
1456 | |
1457 void set target(Member target) { | |
1458 targetName = getCanonicalNameOfMember(target); | |
1459 } | |
1460 | |
1461 visitChildren(Visitor v) { | 1461 visitChildren(Visitor v) { |
1462 receiver?.accept(v); | 1462 receiver?.accept(v); |
1463 target?.acceptReference(v); | 1463 target?.acceptReference(v); |
1464 } | 1464 } |
1465 | 1465 |
1466 transformChildren(Transformer v) { | 1466 transformChildren(Transformer v) { |
1467 if (receiver != null) { | 1467 if (receiver != null) { |
1468 receiver = receiver.accept(v); | 1468 receiver = receiver.accept(v); |
1469 receiver?.parent = this; | 1469 receiver?.parent = this; |
1470 } | 1470 } |
1471 } | 1471 } |
1472 | 1472 |
1473 accept(ExpressionVisitor v) => v.visitDirectPropertyGet(this); | 1473 accept(ExpressionVisitor v) => v.visitDirectPropertyGet(this); |
1474 | 1474 |
1475 DartType getStaticType(TypeEnvironment types) { | 1475 DartType getStaticType(TypeEnvironment types) { |
1476 Class superclass = target.enclosingClass; | 1476 Class superclass = target.enclosingClass; |
1477 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types); | 1477 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types); |
1478 return Substitution | 1478 return Substitution |
1479 .fromInterfaceType(receiverType) | 1479 .fromInterfaceType(receiverType) |
1480 .substituteType(target.getterType); | 1480 .substituteType(target.getterType); |
1481 } | 1481 } |
1482 } | 1482 } |
1483 | 1483 |
1484 /// Directly assign a field, or call a setter. | 1484 /// Directly assign a field, or call a setter. |
1485 /// | 1485 /// |
1486 /// Evaluates to the value of [value]. | 1486 /// Evaluates to the value of [value]. |
1487 class DirectPropertySet extends Expression { | 1487 class DirectPropertySet extends Expression { |
1488 Expression receiver; | 1488 Expression receiver; |
1489 Member target; | 1489 CanonicalName targetName; |
1490 Expression value; | 1490 Expression value; |
1491 | 1491 |
1492 DirectPropertySet(this.receiver, this.target, this.value) { | 1492 DirectPropertySet(Expression receiver, Member target, Expression value) |
1493 : this.byName(receiver, getCanonicalNameOfMember(target), value); | |
1494 | |
1495 DirectPropertySet.byName(this.receiver, this.targetName, this.value) { | |
1493 receiver?.parent = this; | 1496 receiver?.parent = this; |
1494 value?.parent = this; | 1497 value?.parent = this; |
1495 } | 1498 } |
1496 | 1499 |
1500 Member get target => targetName?.asMember; | |
1501 | |
1502 void set target(Member target) { | |
1503 targetName = getCanonicalNameOfMember(target); | |
1504 } | |
1505 | |
1497 visitChildren(Visitor v) { | 1506 visitChildren(Visitor v) { |
1498 receiver?.accept(v); | 1507 receiver?.accept(v); |
1499 target?.acceptReference(v); | 1508 target?.acceptReference(v); |
1500 value?.accept(v); | 1509 value?.accept(v); |
1501 } | 1510 } |
1502 | 1511 |
1503 transformChildren(Transformer v) { | 1512 transformChildren(Transformer v) { |
1504 if (receiver != null) { | 1513 if (receiver != null) { |
1505 receiver = receiver.accept(v); | 1514 receiver = receiver.accept(v); |
1506 receiver?.parent = this; | 1515 receiver?.parent = this; |
1507 } | 1516 } |
1508 if (value != null) { | 1517 if (value != null) { |
1509 value = value.accept(v); | 1518 value = value.accept(v); |
1510 value?.parent = this; | 1519 value?.parent = this; |
1511 } | 1520 } |
1512 } | 1521 } |
1513 | 1522 |
1514 accept(ExpressionVisitor v) => v.visitDirectPropertySet(this); | 1523 accept(ExpressionVisitor v) => v.visitDirectPropertySet(this); |
1515 | 1524 |
1516 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); | 1525 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); |
1517 } | 1526 } |
1518 | 1527 |
1519 /// Directly call an instance method, bypassing ordinary dispatch. | 1528 /// Directly call an instance method, bypassing ordinary dispatch. |
1520 class DirectMethodInvocation extends Expression { | 1529 class DirectMethodInvocation extends Expression { |
1521 Expression receiver; | 1530 Expression receiver; |
1522 Procedure target; | 1531 CanonicalName targetName; |
1523 Arguments arguments; | 1532 Arguments arguments; |
1524 | 1533 |
1525 DirectMethodInvocation(this.receiver, this.target, this.arguments) { | 1534 DirectMethodInvocation( |
1535 Expression receiver, Procedure target, Arguments arguments) | |
1536 : this.byName(receiver, getCanonicalNameOfMember(target), arguments); | |
1537 | |
1538 DirectMethodInvocation.byName( | |
1539 this.receiver, this.targetName, this.arguments) { | |
1526 receiver?.parent = this; | 1540 receiver?.parent = this; |
1527 arguments?.parent = this; | 1541 arguments?.parent = this; |
1528 } | 1542 } |
1529 | 1543 |
1544 Procedure get target => targetName?.asProcedure; | |
1545 | |
1546 void set target(Procedure target) { | |
1547 targetName = getCanonicalNameOfMember(target); | |
1548 } | |
1549 | |
1530 visitChildren(Visitor v) { | 1550 visitChildren(Visitor v) { |
1531 receiver?.accept(v); | 1551 receiver?.accept(v); |
1532 target?.acceptReference(v); | 1552 target?.acceptReference(v); |
1533 arguments?.accept(v); | 1553 arguments?.accept(v); |
1534 } | 1554 } |
1535 | 1555 |
1536 transformChildren(Transformer v) { | 1556 transformChildren(Transformer v) { |
1537 if (receiver != null) { | 1557 if (receiver != null) { |
1538 receiver = receiver.accept(v); | 1558 receiver = receiver.accept(v); |
1539 receiver?.parent = this; | 1559 receiver?.parent = this; |
(...skipping 20 matching lines...) Expand all Loading... | |
1560 .fromPairs(target.function.typeParameters, arguments.types) | 1580 .fromPairs(target.function.typeParameters, arguments.types) |
1561 .substituteType(returnType); | 1581 .substituteType(returnType); |
1562 } | 1582 } |
1563 } | 1583 } |
1564 | 1584 |
1565 /// Expression of form `super.field`. | 1585 /// Expression of form `super.field`. |
1566 /// | 1586 /// |
1567 /// This may invoke a getter, read a field, or tear off a method. | 1587 /// This may invoke a getter, read a field, or tear off a method. |
1568 class SuperPropertyGet extends Expression { | 1588 class SuperPropertyGet extends Expression { |
1569 Name name; | 1589 Name name; |
1570 _MemberAccessor _interfaceTargetReference; | 1590 CanonicalName interfaceTargetName; |
1571 | 1591 |
1572 SuperPropertyGet(this.name, [Member interfaceTarget]) { | 1592 SuperPropertyGet(Name name, [Member interfaceTarget]) |
1573 _interfaceTargetReference = interfaceTarget?._getterInterface; | 1593 : this.byName(name, getCanonicalNameOfMember(interfaceTarget)); |
1574 } | |
1575 | 1594 |
1576 Member get interfaceTarget => _interfaceTargetReference?.target; | 1595 SuperPropertyGet.byName(this.name, this.interfaceTargetName); |
1577 | 1596 |
1578 void set interfaceTarget(Member newTarget) { | 1597 Member get interfaceTarget => interfaceTargetName?.asMember; |
1579 _interfaceTargetReference = newTarget?._getterInterface; | 1598 |
1599 void set interfaceTarget(Member member) { | |
1600 interfaceTargetName = getCanonicalNameOfMember(member); | |
1580 } | 1601 } |
1581 | 1602 |
1582 DartType getStaticType(TypeEnvironment types) { | 1603 DartType getStaticType(TypeEnvironment types) { |
1583 Class declaringClass = interfaceTarget.enclosingClass; | 1604 Class declaringClass = interfaceTarget.enclosingClass; |
1584 if (declaringClass.typeParameters.isEmpty) { | 1605 if (declaringClass.typeParameters.isEmpty) { |
1585 return interfaceTarget.getterType; | 1606 return interfaceTarget.getterType; |
1586 } | 1607 } |
1587 var receiver = | 1608 var receiver = |
1588 types.hierarchy.getTypeAsInstanceOf(types.thisType, declaringClass); | 1609 types.hierarchy.getTypeAsInstanceOf(types.thisType, declaringClass); |
1589 return Substitution | 1610 return Substitution |
(...skipping 11 matching lines...) Expand all Loading... | |
1601 } | 1622 } |
1602 | 1623 |
1603 /// Expression of form `super.field = value`. | 1624 /// Expression of form `super.field = value`. |
1604 /// | 1625 /// |
1605 /// This may invoke a setter or assign a field. | 1626 /// This may invoke a setter or assign a field. |
1606 /// | 1627 /// |
1607 /// Evaluates to the value of [value]. | 1628 /// Evaluates to the value of [value]. |
1608 class SuperPropertySet extends Expression { | 1629 class SuperPropertySet extends Expression { |
1609 Name name; | 1630 Name name; |
1610 Expression value; | 1631 Expression value; |
1611 _MemberAccessor _interfaceTargetReference; | 1632 CanonicalName interfaceTargetName; |
1612 | 1633 |
1613 SuperPropertySet(this.name, this.value, [Member interfaceTarget]) { | 1634 SuperPropertySet(Name name, Expression value, Member interfaceTarget) |
1635 : this.byName(name, value, getCanonicalNameOfMember(interfaceTarget)); | |
1636 | |
1637 SuperPropertySet.byName(this.name, this.value, this.interfaceTargetName) { | |
1614 value?.parent = this; | 1638 value?.parent = this; |
1615 _interfaceTargetReference = interfaceTarget?._setterInterface; | |
1616 } | 1639 } |
1617 | 1640 |
1618 Member get interfaceTarget => _interfaceTargetReference?.target; | 1641 Member get interfaceTarget => interfaceTargetName?.asMember; |
1619 | 1642 |
1620 void set interfaceTarget(Member newTarget) { | 1643 void set interfaceTarget(Member member) { |
1621 _interfaceTargetReference = newTarget?._setterInterface; | 1644 interfaceTargetName = getCanonicalNameOfMember(member); |
1622 } | 1645 } |
1623 | 1646 |
1624 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); | 1647 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); |
1625 | 1648 |
1626 accept(ExpressionVisitor v) => v.visitSuperPropertySet(this); | 1649 accept(ExpressionVisitor v) => v.visitSuperPropertySet(this); |
1627 | 1650 |
1628 visitChildren(Visitor v) { | 1651 visitChildren(Visitor v) { |
1629 name?.accept(v); | 1652 name?.accept(v); |
1630 value?.accept(v); | 1653 value?.accept(v); |
1631 } | 1654 } |
1632 | 1655 |
1633 transformChildren(Transformer v) { | 1656 transformChildren(Transformer v) { |
1634 if (value != null) { | 1657 if (value != null) { |
1635 value = value.accept(v); | 1658 value = value.accept(v); |
1636 value?.parent = this; | 1659 value?.parent = this; |
1637 } | 1660 } |
1638 } | 1661 } |
1639 } | 1662 } |
1640 | 1663 |
1641 /// Read a static field, call a static getter, or tear off a static method. | 1664 /// Read a static field, call a static getter, or tear off a static method. |
1642 class StaticGet extends Expression { | 1665 class StaticGet extends Expression { |
1643 /// A static field, getter, or method (for tear-off). | 1666 /// A static field, getter, or method (for tear-off). |
1644 Member target; | 1667 CanonicalName targetName; |
1645 | 1668 |
1646 StaticGet(this.target); | 1669 StaticGet(Member target) : this.byName(getCanonicalNameOfMember(target)); |
1670 | |
1671 StaticGet.byName(this.targetName); | |
1672 | |
1673 Member get target => targetName?.asMember; | |
1674 | |
1675 void set target(Member target) { | |
1676 targetName = getCanonicalNameOfMember(target); | |
1677 } | |
1647 | 1678 |
1648 DartType getStaticType(TypeEnvironment types) => target.getterType; | 1679 DartType getStaticType(TypeEnvironment types) => target.getterType; |
1649 | 1680 |
1650 accept(ExpressionVisitor v) => v.visitStaticGet(this); | 1681 accept(ExpressionVisitor v) => v.visitStaticGet(this); |
1651 | 1682 |
1652 visitChildren(Visitor v) { | 1683 visitChildren(Visitor v) { |
1653 target?.acceptReference(v); | 1684 target?.acceptReference(v); |
1654 } | 1685 } |
1655 | 1686 |
1656 transformChildren(Transformer v) {} | 1687 transformChildren(Transformer v) {} |
1657 } | 1688 } |
1658 | 1689 |
1659 /// Assign a static field or call a static setter. | 1690 /// Assign a static field or call a static setter. |
1660 /// | 1691 /// |
1661 /// Evaluates to the value of [value]. | 1692 /// Evaluates to the value of [value]. |
1662 class StaticSet extends Expression { | 1693 class StaticSet extends Expression { |
1663 /// A mutable static field or a static setter. | 1694 /// A mutable static field or a static setter. |
1664 Member target; | 1695 CanonicalName targetName; |
1665 Expression value; | 1696 Expression value; |
1666 | 1697 |
1667 StaticSet(this.target, this.value) { | 1698 StaticSet(Member target, Expression value) |
1699 : this.byName(getCanonicalNameOfMember(target), value); | |
1700 | |
1701 StaticSet.byName(this.targetName, this.value) { | |
1668 value?.parent = this; | 1702 value?.parent = this; |
1669 } | 1703 } |
1670 | 1704 |
1705 Member get target => targetName?.asMember; | |
1706 | |
1707 void set target(Member target) { | |
1708 targetName = getCanonicalNameOfMember(target); | |
1709 } | |
1710 | |
1671 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); | 1711 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); |
1672 | 1712 |
1673 accept(ExpressionVisitor v) => v.visitStaticSet(this); | 1713 accept(ExpressionVisitor v) => v.visitStaticSet(this); |
1674 | 1714 |
1675 visitChildren(Visitor v) { | 1715 visitChildren(Visitor v) { |
1676 target?.acceptReference(v); | 1716 target?.acceptReference(v); |
1677 value?.accept(v); | 1717 value?.accept(v); |
1678 } | 1718 } |
1679 | 1719 |
1680 transformChildren(Transformer v) { | 1720 transformChildren(Transformer v) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1754 /// May be `null` if the target is a synthetic static member without a name. | 1794 /// May be `null` if the target is a synthetic static member without a name. |
1755 Name get name; | 1795 Name get name; |
1756 } | 1796 } |
1757 | 1797 |
1758 /// Expression of form `x.foo(y)`. | 1798 /// Expression of form `x.foo(y)`. |
1759 class MethodInvocation extends InvocationExpression { | 1799 class MethodInvocation extends InvocationExpression { |
1760 Expression receiver; | 1800 Expression receiver; |
1761 Name name; | 1801 Name name; |
1762 Arguments arguments; | 1802 Arguments arguments; |
1763 | 1803 |
1764 Procedure interfaceTarget; | 1804 CanonicalName interfaceTargetName; |
1765 | 1805 |
1766 MethodInvocation(this.receiver, this.name, this.arguments, | 1806 MethodInvocation(Expression receiver, Name name, Arguments arguments, |
1767 [this.interfaceTarget]) { | 1807 [Procedure interfaceTarget]) |
1808 : this.byName(receiver, name, arguments, | |
1809 getCanonicalNameOfMember(interfaceTarget)); | |
1810 | |
1811 MethodInvocation.byName( | |
1812 this.receiver, this.name, this.arguments, this.interfaceTargetName) { | |
1768 receiver?.parent = this; | 1813 receiver?.parent = this; |
1769 arguments?.parent = this; | 1814 arguments?.parent = this; |
1770 } | 1815 } |
1771 | 1816 |
1817 Procedure get interfaceTarget => interfaceTargetName?.asProcedure; | |
1818 | |
1819 void set interfaceTarget(Member target) { | |
1820 interfaceTargetName = getCanonicalNameOfMember(target); | |
1821 } | |
1822 | |
1772 DartType getStaticType(TypeEnvironment types) { | 1823 DartType getStaticType(TypeEnvironment types) { |
1773 if (interfaceTarget != null) { | 1824 if (interfaceTarget != null) { |
1774 if (types.isOverloadedArithmeticOperator(interfaceTarget)) { | 1825 if (types.isOverloadedArithmeticOperator(interfaceTarget)) { |
1775 return types.getTypeOfOverloadedArithmetic( | 1826 return types.getTypeOfOverloadedArithmetic( |
1776 receiver.getStaticType(types), | 1827 receiver.getStaticType(types), |
1777 arguments.positional[0].getStaticType(types)); | 1828 arguments.positional[0].getStaticType(types)); |
1778 } | 1829 } |
1779 Class superclass = interfaceTarget.enclosingClass; | 1830 Class superclass = interfaceTarget.enclosingClass; |
1780 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types); | 1831 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types); |
1781 var returnType = Substitution | 1832 var returnType = Substitution |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1823 } | 1874 } |
1824 } | 1875 } |
1825 | 1876 |
1826 /// Expression of form `super.foo(x)`. | 1877 /// Expression of form `super.foo(x)`. |
1827 /// | 1878 /// |
1828 /// The provided arguments might not match the parameters of the target. | 1879 /// The provided arguments might not match the parameters of the target. |
1829 class SuperMethodInvocation extends InvocationExpression { | 1880 class SuperMethodInvocation extends InvocationExpression { |
1830 Name name; | 1881 Name name; |
1831 Arguments arguments; | 1882 Arguments arguments; |
1832 | 1883 |
1833 Member interfaceTarget; | 1884 CanonicalName interfaceTargetName; |
1834 | 1885 |
1835 SuperMethodInvocation(this.name, this.arguments, this.interfaceTarget) { | 1886 SuperMethodInvocation(Name name, Arguments arguments, |
1887 [Procedure interfaceTarget]) | |
1888 : this.byName(name, arguments, getCanonicalNameOfMember(interfaceTarget)); | |
1889 | |
1890 SuperMethodInvocation.byName( | |
1891 this.name, this.arguments, this.interfaceTargetName) { | |
1836 arguments?.parent = this; | 1892 arguments?.parent = this; |
1837 } | 1893 } |
1838 | 1894 |
1895 Procedure get interfaceTarget => interfaceTargetName?.asProcedure; | |
1896 | |
1897 void set interfaceTarget(Procedure target) { | |
1898 interfaceTargetName = getCanonicalNameOfMember(target); | |
1899 } | |
1900 | |
1839 DartType getStaticType(TypeEnvironment types) { | 1901 DartType getStaticType(TypeEnvironment types) { |
1840 if (interfaceTarget == null) return const DynamicType(); | 1902 if (interfaceTarget == null) return const DynamicType(); |
1841 Class superclass = interfaceTarget.enclosingClass; | 1903 Class superclass = interfaceTarget.enclosingClass; |
1842 var receiverType = | 1904 var receiverType = |
1843 types.hierarchy.getTypeAsInstanceOf(types.thisType, superclass); | 1905 types.hierarchy.getTypeAsInstanceOf(types.thisType, superclass); |
1844 var returnType = Substitution | 1906 var returnType = Substitution |
1845 .fromInterfaceType(receiverType) | 1907 .fromInterfaceType(receiverType) |
1846 .substituteType(interfaceTarget.function.returnType); | 1908 .substituteType(interfaceTarget.function.returnType); |
1847 return Substitution | 1909 return Substitution |
1848 .fromPairs(interfaceTarget.function.typeParameters, arguments.types) | 1910 .fromPairs(interfaceTarget.function.typeParameters, arguments.types) |
(...skipping 13 matching lines...) Expand all Loading... | |
1862 arguments?.parent = this; | 1924 arguments?.parent = this; |
1863 } | 1925 } |
1864 } | 1926 } |
1865 } | 1927 } |
1866 | 1928 |
1867 /// Expression of form `foo(x)`, or `const foo(x)` if the target is an | 1929 /// Expression of form `foo(x)`, or `const foo(x)` if the target is an |
1868 /// external constant factory. | 1930 /// external constant factory. |
1869 /// | 1931 /// |
1870 /// The provided arguments might not match the parameters of the target. | 1932 /// The provided arguments might not match the parameters of the target. |
1871 class StaticInvocation extends InvocationExpression { | 1933 class StaticInvocation extends InvocationExpression { |
1872 Procedure target; | 1934 CanonicalName targetName; |
1873 Arguments arguments; | 1935 Arguments arguments; |
1874 | 1936 |
1875 /// True if this is a constant call to an external constant factory. | 1937 /// True if this is a constant call to an external constant factory. |
1876 bool isConst; | 1938 bool isConst; |
1877 | 1939 |
1878 Name get name => target?.name; | 1940 Name get name => target?.name; |
1879 | 1941 |
1880 StaticInvocation(this.target, this.arguments, {this.isConst: false}) { | 1942 StaticInvocation(Procedure target, Arguments arguments, {bool isConst: false}) |
1943 : this.byName(getCanonicalNameOfMember(target), arguments, | |
1944 isConst: isConst); | |
1945 | |
1946 StaticInvocation.byName(this.targetName, this.arguments, | |
1947 {this.isConst: false}) { | |
1881 arguments?.parent = this; | 1948 arguments?.parent = this; |
1882 } | 1949 } |
1883 | 1950 |
1951 Procedure get target => targetName?.asProcedure; | |
1952 | |
1953 void set target(Procedure target) { | |
1954 targetName = getCanonicalNameOfMember(target); | |
1955 } | |
1956 | |
1884 DartType getStaticType(TypeEnvironment types) { | 1957 DartType getStaticType(TypeEnvironment types) { |
1885 return Substitution | 1958 return Substitution |
1886 .fromPairs(target.function.typeParameters, arguments.types) | 1959 .fromPairs(target.function.typeParameters, arguments.types) |
1887 .substituteType(target.function.returnType); | 1960 .substituteType(target.function.returnType); |
1888 } | 1961 } |
1889 | 1962 |
1890 accept(ExpressionVisitor v) => v.visitStaticInvocation(this); | 1963 accept(ExpressionVisitor v) => v.visitStaticInvocation(this); |
1891 | 1964 |
1892 visitChildren(Visitor v) { | 1965 visitChildren(Visitor v) { |
1893 target?.acceptReference(v); | 1966 target?.acceptReference(v); |
1894 arguments?.accept(v); | 1967 arguments?.accept(v); |
1895 } | 1968 } |
1896 | 1969 |
1897 transformChildren(Transformer v) { | 1970 transformChildren(Transformer v) { |
1898 if (arguments != null) { | 1971 if (arguments != null) { |
1899 arguments = arguments.accept(v); | 1972 arguments = arguments.accept(v); |
1900 arguments?.parent = this; | 1973 arguments?.parent = this; |
1901 } | 1974 } |
1902 } | 1975 } |
1903 } | 1976 } |
1904 | 1977 |
1905 /// Expression of form `new Foo(x)` or `const Foo(x)`. | 1978 /// Expression of form `new Foo(x)` or `const Foo(x)`. |
1906 /// | 1979 /// |
1907 /// The provided arguments might not match the parameters of the target. | 1980 /// The provided arguments might not match the parameters of the target. |
1908 // | 1981 // |
1909 // DESIGN TODO: Should we pass type arguments in a separate field | 1982 // DESIGN TODO: Should we pass type arguments in a separate field |
1910 // `classTypeArguments`? They are quite different from type arguments to | 1983 // `classTypeArguments`? They are quite different from type arguments to |
1911 // generic functions. | 1984 // generic functions. |
1912 class ConstructorInvocation extends InvocationExpression { | 1985 class ConstructorInvocation extends InvocationExpression { |
1913 Constructor target; | 1986 CanonicalName targetName; |
1914 Arguments arguments; | 1987 Arguments arguments; |
1915 bool isConst; | 1988 bool isConst; |
1916 | 1989 |
1917 Name get name => target?.name; | 1990 Name get name => target?.name; |
1918 | 1991 |
1919 ConstructorInvocation(this.target, this.arguments, {this.isConst: false}) { | 1992 ConstructorInvocation(Constructor target, Arguments arguments, |
1993 {bool isConst: false}) | |
1994 : this.byName(getCanonicalNameOfMember(target), arguments, | |
1995 isConst: isConst); | |
1996 | |
1997 ConstructorInvocation.byName(this.targetName, this.arguments, | |
1998 {this.isConst: false}) { | |
1920 arguments?.parent = this; | 1999 arguments?.parent = this; |
1921 } | 2000 } |
1922 | 2001 |
2002 Constructor get target => targetName?.asConstructor; | |
2003 | |
2004 void set target(Constructor target) { | |
2005 targetName = getCanonicalNameOfMember(target); | |
2006 } | |
2007 | |
1923 DartType getStaticType(TypeEnvironment types) { | 2008 DartType getStaticType(TypeEnvironment types) { |
1924 return arguments.types.isEmpty | 2009 return arguments.types.isEmpty |
1925 ? target.enclosingClass.rawType | 2010 ? target.enclosingClass.rawType |
1926 : new InterfaceType(target.enclosingClass, arguments.types); | 2011 : new InterfaceType(target.enclosingClass, arguments.types); |
1927 } | 2012 } |
1928 | 2013 |
1929 accept(ExpressionVisitor v) => v.visitConstructorInvocation(this); | 2014 accept(ExpressionVisitor v) => v.visitConstructorInvocation(this); |
1930 | 2015 |
1931 visitChildren(Visitor v) { | 2016 visitChildren(Visitor v) { |
1932 target?.acceptReference(v); | 2017 target?.acceptReference(v); |
(...skipping 1181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3114 /// statically resolved references are represented in nameless form. | 3199 /// statically resolved references are represented in nameless form. |
3115 /// | 3200 /// |
3116 /// [Name]s are immutable and compare based on structural equality, and they | 3201 /// [Name]s are immutable and compare based on structural equality, and they |
3117 /// are not AST nodes. | 3202 /// are not AST nodes. |
3118 /// | 3203 /// |
3119 /// The [toString] method returns a human-readable string that includes the | 3204 /// The [toString] method returns a human-readable string that includes the |
3120 /// library name for private names; uniqueness is not guaranteed. | 3205 /// library name for private names; uniqueness is not guaranteed. |
3121 abstract class Name implements Node { | 3206 abstract class Name implements Node { |
3122 final int hashCode; | 3207 final int hashCode; |
3123 final String name; | 3208 final String name; |
3209 CanonicalName get libraryName; | |
3124 Library get library; | 3210 Library get library; |
3125 bool get isPrivate; | 3211 bool get isPrivate; |
3126 | 3212 |
3127 Name._internal(this.hashCode, this.name); | 3213 Name._internal(this.hashCode, this.name); |
3128 | 3214 |
3129 factory Name(String name, [Library library]) { | 3215 factory Name(String name, [Library library]) => |
3216 new Name.byReference(name, library?.canonicalName); | |
3217 | |
3218 factory Name.byReference(String name, CanonicalName library) { | |
kustermann
2017/02/01 13:00:54
library -> libraryName
asgerf
2017/02/02 12:30:27
Done.
| |
3130 /// Use separate subclasses for the public and private case to save memory | 3219 /// Use separate subclasses for the public and private case to save memory |
3131 /// for public names. | 3220 /// for public names. |
3132 if (name.startsWith('_')) { | 3221 if (name.startsWith('_')) { |
3133 assert(library != null); | 3222 assert(library != null); |
3134 return new _PrivateName(name, library); | 3223 return new _PrivateName(name, library); |
3135 } else { | 3224 } else { |
3136 return new _PublicName(name); | 3225 return new _PublicName(name); |
3137 } | 3226 } |
3138 } | 3227 } |
3139 | 3228 |
3140 bool operator ==(other) { | 3229 bool operator ==(other) { |
3141 return other is Name && name == other.name && library == other.library; | 3230 return other is Name && name == other.name && library == other.library; |
3142 } | 3231 } |
3143 | 3232 |
3144 accept(Visitor v) => v.visitName(this); | 3233 accept(Visitor v) => v.visitName(this); |
3145 | 3234 |
3146 visitChildren(Visitor v) { | 3235 visitChildren(Visitor v) { |
3147 // DESIGN TODO: Should we visit the library as a library reference? | 3236 // DESIGN TODO: Should we visit the library as a library reference? |
3148 } | 3237 } |
3149 } | 3238 } |
3150 | 3239 |
3151 class _PrivateName extends Name { | 3240 class _PrivateName extends Name { |
3152 final Library library; | 3241 final CanonicalName libraryName; |
3153 bool get isPrivate => true; | 3242 bool get isPrivate => true; |
3154 | 3243 |
3155 _PrivateName(String name, Library library) | 3244 _PrivateName(String name, CanonicalName libraryName) |
3156 : this.library = library, | 3245 : this.libraryName = libraryName, |
3157 super._internal(_computeHashCode(name, library), name); | 3246 super._internal(_computeHashCode(name, libraryName), name); |
3158 | 3247 |
3159 String toString() => library != null ? '$library::$name' : name; | 3248 String toString() => library != null ? '$library::$name' : name; |
3160 | 3249 |
3161 static int _computeHashCode(String name, Library library) { | 3250 Library get library => libraryName.asLibrary; |
3162 return 131 * name.hashCode + 17 * library.hashCode; | 3251 |
3252 static int _computeHashCode(String name, CanonicalName libraryName) { | |
3253 return 131 * name.hashCode + 17 * libraryName.hashCode; | |
3163 } | 3254 } |
3164 } | 3255 } |
3165 | 3256 |
3166 class _PublicName extends Name { | 3257 class _PublicName extends Name { |
3258 CanonicalName get libraryName => null; | |
3167 Library get library => null; | 3259 Library get library => null; |
3168 bool get isPrivate => false; | 3260 bool get isPrivate => false; |
3169 | 3261 |
3170 _PublicName(String name) : super._internal(name.hashCode, name); | 3262 _PublicName(String name) : super._internal(name.hashCode, name); |
3171 | 3263 |
3172 String toString() => name; | 3264 String toString() => name; |
3173 } | 3265 } |
3174 | 3266 |
3175 // ------------------------------------------------------------------------ | 3267 // ------------------------------------------------------------------------ |
3176 // TYPES | 3268 // TYPES |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3236 | 3328 |
3237 const BottomType(); | 3329 const BottomType(); |
3238 | 3330 |
3239 accept(DartTypeVisitor v) => v.visitBottomType(this); | 3331 accept(DartTypeVisitor v) => v.visitBottomType(this); |
3240 visitChildren(Visitor v) {} | 3332 visitChildren(Visitor v) {} |
3241 | 3333 |
3242 bool operator ==(Object other) => other is BottomType; | 3334 bool operator ==(Object other) => other is BottomType; |
3243 } | 3335 } |
3244 | 3336 |
3245 class InterfaceType extends DartType { | 3337 class InterfaceType extends DartType { |
3246 final Class classNode; | 3338 final CanonicalName className; |
3247 final List<DartType> typeArguments; | 3339 final List<DartType> typeArguments; |
3248 | 3340 |
3249 /// The [typeArguments] list must not be modified after this call. If the | 3341 /// The [typeArguments] list must not be modified after this call. If the |
3250 /// list is omitted, 'dynamic' type arguments are filled in. | 3342 /// list is omitted, 'dynamic' type arguments are filled in. |
3251 InterfaceType(Class classNode, [List<DartType> typeArguments]) | 3343 InterfaceType(Class classNode, [List<DartType> typeArguments]) |
3252 : this.classNode = classNode, | 3344 : this.byName(getCanonicalNameOfClass(classNode), |
3253 this.typeArguments = typeArguments ?? _defaultTypeArguments(classNode); | 3345 typeArguments ?? _defaultTypeArguments(classNode)); |
3346 | |
3347 InterfaceType.byName(this.className, this.typeArguments); | |
3348 | |
3349 Class get classNode => className.asClass; | |
3254 | 3350 |
3255 static List<DartType> _defaultTypeArguments(Class classNode) { | 3351 static List<DartType> _defaultTypeArguments(Class classNode) { |
3256 if (classNode.typeParameters.length == 0) { | 3352 if (classNode.typeParameters.length == 0) { |
3257 // Avoid allocating a list in this very common case. | 3353 // Avoid allocating a list in this very common case. |
3258 return const <DartType>[]; | 3354 return const <DartType>[]; |
3259 } else { | 3355 } else { |
3260 return new List<DartType>.filled( | 3356 return new List<DartType>.filled( |
3261 classNode.typeParameters.length, const DynamicType()); | 3357 classNode.typeParameters.length, const DynamicType()); |
3262 } | 3358 } |
3263 } | 3359 } |
3264 | 3360 |
3265 accept(DartTypeVisitor v) => v.visitInterfaceType(this); | 3361 accept(DartTypeVisitor v) => v.visitInterfaceType(this); |
3266 | 3362 |
3267 visitChildren(Visitor v) { | 3363 visitChildren(Visitor v) { |
3268 classNode.acceptReference(v); | 3364 classNode.acceptReference(v); |
3269 visitList(typeArguments, v); | 3365 visitList(typeArguments, v); |
3270 } | 3366 } |
3271 | 3367 |
3272 bool operator ==(Object other) { | 3368 bool operator ==(Object other) { |
3273 if (identical(this, other)) return true; | 3369 if (identical(this, other)) return true; |
3274 if (other is InterfaceType) { | 3370 if (other is InterfaceType) { |
3275 if (classNode != other.classNode) return false; | 3371 if (className != other.className) return false; |
3276 if (typeArguments.length != other.typeArguments.length) return false; | 3372 if (typeArguments.length != other.typeArguments.length) return false; |
3277 for (int i = 0; i < typeArguments.length; ++i) { | 3373 for (int i = 0; i < typeArguments.length; ++i) { |
3278 if (typeArguments[i] != other.typeArguments[i]) return false; | 3374 if (typeArguments[i] != other.typeArguments[i]) return false; |
3279 } | 3375 } |
3280 return true; | 3376 return true; |
3281 } else { | 3377 } else { |
3282 return false; | 3378 return false; |
3283 } | 3379 } |
3284 } | 3380 } |
3285 | 3381 |
3286 int get hashCode { | 3382 int get hashCode { |
3287 int hash = 0x3fffffff & classNode.hashCode; | 3383 int hash = 0x3fffffff & className.hashCode; |
3288 for (int i = 0; i < typeArguments.length; ++i) { | 3384 for (int i = 0; i < typeArguments.length; ++i) { |
3289 hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode)); | 3385 hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode)); |
3290 } | 3386 } |
3291 return hash; | 3387 return hash; |
3292 } | 3388 } |
3293 } | 3389 } |
3294 | 3390 |
3295 /// A possibly generic function type. | 3391 /// A possibly generic function type. |
3296 class FunctionType extends DartType { | 3392 class FunctionType extends DartType { |
3297 final List<TypeParameter> typeParameters; | 3393 final List<TypeParameter> typeParameters; |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3465 transformChildren(Transformer v) { | 3561 transformChildren(Transformer v) { |
3466 bound = v.visitDartType(bound); | 3562 bound = v.visitDartType(bound); |
3467 } | 3563 } |
3468 | 3564 |
3469 /// Returns a possibly synthesized name for this type parameter, consistent | 3565 /// Returns a possibly synthesized name for this type parameter, consistent |
3470 /// with the names used across all [toString] calls. | 3566 /// with the names used across all [toString] calls. |
3471 String toString() => debugQualifiedTypeParameterName(this); | 3567 String toString() => debugQualifiedTypeParameterName(this); |
3472 } | 3568 } |
3473 | 3569 |
3474 class Supertype extends Node { | 3570 class Supertype extends Node { |
3475 final Class classNode; | 3571 final CanonicalName className; |
3476 final List<DartType> typeArguments; | 3572 final List<DartType> typeArguments; |
3477 | 3573 |
3478 Supertype(this.classNode, this.typeArguments); | 3574 Supertype(Class classNode, List<DartType> typeArguments) |
3575 : this.byName(getCanonicalNameOfClass(classNode), typeArguments); | |
3576 | |
3577 Supertype.byName(this.className, this.typeArguments); | |
3578 | |
3579 Class get classNode => className.asClass; | |
3479 | 3580 |
3480 accept(Visitor v) => v.visitSupertype(this); | 3581 accept(Visitor v) => v.visitSupertype(this); |
3481 | 3582 |
3482 visitChildren(Visitor v) { | 3583 visitChildren(Visitor v) { |
3483 classNode.acceptReference(v); | 3584 classNode.acceptReference(v); |
3484 visitList(typeArguments, v); | 3585 visitList(typeArguments, v); |
3485 } | 3586 } |
3486 | 3587 |
3487 InterfaceType get asInterfaceType { | 3588 InterfaceType get asInterfaceType { |
3488 return new InterfaceType(classNode, typeArguments); | 3589 return new InterfaceType(classNode, typeArguments); |
3489 } | 3590 } |
3490 | 3591 |
3491 bool operator ==(Object other) { | 3592 bool operator ==(Object other) { |
3492 if (identical(this, other)) return true; | 3593 if (identical(this, other)) return true; |
3493 if (other is Supertype) { | 3594 if (other is Supertype) { |
3494 if (classNode != other.classNode) return false; | 3595 if (className != other.className) return false; |
3495 if (typeArguments.length != other.typeArguments.length) return false; | 3596 if (typeArguments.length != other.typeArguments.length) return false; |
3496 for (int i = 0; i < typeArguments.length; ++i) { | 3597 for (int i = 0; i < typeArguments.length; ++i) { |
3497 if (typeArguments[i] != other.typeArguments[i]) return false; | 3598 if (typeArguments[i] != other.typeArguments[i]) return false; |
3498 } | 3599 } |
3499 return true; | 3600 return true; |
3500 } else { | 3601 } else { |
3501 return false; | 3602 return false; |
3502 } | 3603 } |
3503 } | 3604 } |
3504 | 3605 |
3505 int get hashCode { | 3606 int get hashCode { |
3506 int hash = 0x3fffffff & classNode.hashCode; | 3607 int hash = 0x3fffffff & className.hashCode; |
3507 for (int i = 0; i < typeArguments.length; ++i) { | 3608 for (int i = 0; i < typeArguments.length; ++i) { |
3508 hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode)); | 3609 hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode)); |
3509 } | 3610 } |
3510 return hash; | 3611 return hash; |
3511 } | 3612 } |
3512 } | 3613 } |
3513 | 3614 |
3514 // ------------------------------------------------------------------------ | 3615 // ------------------------------------------------------------------------ |
3515 // PROGRAM | 3616 // PROGRAM |
3516 // ------------------------------------------------------------------------ | 3617 // ------------------------------------------------------------------------ |
3517 | 3618 |
3518 /// A way to bundle up all the libraries in a program. | 3619 /// A way to bundle up all the libraries in a program. |
3519 class Program extends TreeNode { | 3620 class Program extends TreeNode { |
3621 final CanonicalName root = new CanonicalName.root(); | |
3622 | |
3520 final List<Library> libraries; | 3623 final List<Library> libraries; |
3521 | 3624 |
3522 /// Map from a source file uri to a line-starts table and source code. | 3625 /// Map from a source file uri to a line-starts table and source code. |
3523 /// Given a source file uri and a offset in that file one can translate | 3626 /// Given a source file uri and a offset in that file one can translate |
3524 /// it to a line:column position in that file. | 3627 /// it to a line:column position in that file. |
3525 final Map<String, Source> uriToSource; | 3628 final Map<String, Source> uriToSource; |
3526 | 3629 |
3527 /// Reference to the main method in one of the libraries. | 3630 /// Reference to the main method in one of the libraries. |
3528 Procedure mainMethod; | 3631 CanonicalName mainMethodName; |
3529 | 3632 |
3530 Program([List<Library> libraries, Map<String, Source> uriToSource]) | 3633 Program([List<Library> libraries, Map<String, Source> uriToSource]) |
3531 : libraries = libraries ?? <Library>[], | 3634 : libraries = libraries ?? <Library>[], |
3532 uriToSource = uriToSource ?? <String, Source>{} { | 3635 uriToSource = uriToSource ?? <String, Source>{} { |
3533 setParents(libraries, this); | 3636 setParents(this.libraries, this); |
3637 } | |
3638 | |
3639 Procedure get mainMethod => mainMethodName?.asProcedure; | |
3640 | |
3641 void set mainMethod(Procedure main) { | |
3642 mainMethodName = getCanonicalNameOfMember(main); | |
3534 } | 3643 } |
3535 | 3644 |
3536 accept(TreeVisitor v) => v.visitProgram(this); | 3645 accept(TreeVisitor v) => v.visitProgram(this); |
3537 | 3646 |
3538 visitChildren(Visitor v) { | 3647 visitChildren(Visitor v) { |
3539 visitList(libraries, v); | 3648 visitList(libraries, v); |
3540 mainMethod?.acceptReference(v); | 3649 mainMethod?.acceptReference(v); |
3541 } | 3650 } |
3542 | 3651 |
3543 transformChildren(Transformer v) { | 3652 transformChildren(Transformer v) { |
(...skipping 14 matching lines...) Expand all Loading... | |
3558 } else { | 3667 } else { |
3559 high = mid - 1; | 3668 high = mid - 1; |
3560 } | 3669 } |
3561 } | 3670 } |
3562 int lineIndex = low; | 3671 int lineIndex = low; |
3563 int lineStart = lines[lineIndex]; | 3672 int lineStart = lines[lineIndex]; |
3564 int lineNumber = 1 + lineIndex; | 3673 int lineNumber = 1 + lineIndex; |
3565 int columnNumber = 1 + offset - lineStart; | 3674 int columnNumber = 1 + offset - lineStart; |
3566 return new Location(file, lineNumber, columnNumber); | 3675 return new Location(file, lineNumber, columnNumber); |
3567 } | 3676 } |
3677 | |
3678 Library getLibraryReference(Uri uri) { | |
3679 assert(uri.hasScheme); | |
3680 var canonicalName = root.getChildFromUri(uri); | |
3681 Library library; | |
3682 if (canonicalName.definition == null) { | |
3683 library = new Library(uri, isExternal: true); | |
3684 canonicalName.linkTo(library); | |
3685 libraries.add(library..parent = this); | |
3686 } else { | |
3687 library = canonicalName.definition; | |
3688 } | |
3689 return library; | |
3690 } | |
3568 } | 3691 } |
3569 | 3692 |
3570 /// A tuple with file, line, and column number, for displaying human-readable | 3693 /// A tuple with file, line, and column number, for displaying human-readable |
3571 /// locations. | 3694 /// locations. |
3572 class Location { | 3695 class Location { |
3573 final String file; | 3696 final String file; |
3574 final int line; // 1-based. | 3697 final int line; // 1-based. |
3575 final int column; // 1-based. | 3698 final int column; // 1-based. |
3576 | 3699 |
3577 Location(this.file, this.line, this.column); | 3700 Location(this.file, this.line, this.column); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3666 } | 3789 } |
3667 } | 3790 } |
3668 } | 3791 } |
3669 | 3792 |
3670 class Source { | 3793 class Source { |
3671 final List<int> lineStarts; | 3794 final List<int> lineStarts; |
3672 final String source; | 3795 final String source; |
3673 | 3796 |
3674 Source(this.lineStarts, this.source); | 3797 Source(this.lineStarts, this.source); |
3675 } | 3798 } |
3799 | |
3800 /// Returns the canonical name of [member], or throws an exception if the | |
3801 /// member has not been assigned a canonical name yet. | |
3802 /// | |
3803 /// Returns `null` if the member is `null`. | |
3804 CanonicalName getCanonicalNameOfMember(Member member) { | |
3805 if (member == null) { | |
3806 return null; | |
3807 } | |
3808 var name = member.canonicalName; | |
3809 if (name == null) { | |
3810 throw '$member has no canonical name. ' | |
3811 'It must be added to a class or library before it can be referenced.'; | |
3812 } | |
3813 return name; | |
3814 } | |
3815 | |
3816 /// Returns the canonical name of [class_], or throws an exception if the | |
3817 /// class has not been assigned a canonical name yet. | |
3818 /// | |
3819 /// Returns `null` if the class is `null`. | |
3820 CanonicalName getCanonicalNameOfClass(Class class_) { | |
3821 if (class_ == null) { | |
3822 return null; | |
3823 } | |
3824 var name = class_.canonicalName; | |
3825 if (name == null) { | |
3826 throw '$class_ has no canonical name. ' | |
3827 'It must be added to a library before it can be referenced.'; | |
3828 } | |
3829 return name; | |
3830 } | |
3831 | |
3832 CanonicalName getCanonicalNameOfLibrary(Library library) { | |
kustermann
2017/02/01 13:00:54
for consistency you can add the comment here as we
asgerf
2017/02/02 12:30:27
Done.
| |
3833 if (library == null) { | |
3834 return null; | |
3835 } | |
3836 var name = library.canonicalName; | |
3837 if (name == null) { | |
3838 throw '$library has no canonical name. ' | |
3839 'It must be added to a program before it can be referenced.'; | |
3840 } | |
3841 return name; | |
3842 } | |
OLD | NEW |