Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: pkg/kernel/lib/ast.dart

Issue 2665723002: Implement canonical name scheme in kernel. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698