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

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

Issue 2665723002: Implement canonical name scheme in kernel. (Closed)
Patch Set: Remove unintended change in fasta 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 can be referenced by other nodes.
159 ///
160 /// There is a single [box] belonging to this node, providing a level of
161 /// indirection that is needed during serialization.
162 abstract class LinkedNode extends TreeNode {
Kevin Millikin (Google) 2017/02/22 09:09:30 Suggestion: LinkedNode ==> NamedNode, LinkedNodeBo
asgerf 2017/02/22 10:06:54 Done.
163 final LinkedNodeBox box;
164
165 LinkedNode(LinkedNodeBox box)
166 : this.box = box ?? new LinkedNodeBox() {
167 this.box.node = this;
168 }
169
170 CanonicalName get canonicalName => box?.canonicalName;
171 }
172
173 /// Indirection between a reference and its definition.
174 class LinkedNodeBox {
175 CanonicalName canonicalName;
176 LinkedNode node;
177
178 Library get asLibrary {
179 if (node == null) throw 'The box is empty. A library was expected';
180 return node as Library;
181 }
182
183 Class get asClass {
184 if (node == null) throw 'The box is empty. A class was expected';
185 return node as Class;
186 }
187
188 Member get asMember {
189 if (node == null) throw 'The box is empty. A member was expected';
190 return node as Member;
191 }
192
193 Field get asField {
194 if (node == null) throw 'The box is empty. A field was expected';
195 return node as Field;
196 }
197
198 Constructor get asConstructor {
199 if (node == null) throw 'The box is empty. A constructor was expected';
200 return node as Constructor;
201 }
202
203 Procedure get asProcedure {
204 if (node == null) throw 'The box is empty. A procedure was expected';
205 return node as Procedure;
206 }
207 }
208
155 // ------------------------------------------------------------------------ 209 // ------------------------------------------------------------------------
156 // LIBRARIES and CLASSES 210 // LIBRARIES and CLASSES
157 // ------------------------------------------------------------------------ 211 // ------------------------------------------------------------------------
158 212
159 class Library extends TreeNode implements Comparable<Library> { 213 class Library extends LinkedNode implements Comparable<Library> {
160 /// An import path to this library. 214 /// An import path to this library.
161 /// 215 ///
162 /// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme. 216 /// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme.
163 /// 217 ///
164 /// If the URI has the `app` scheme, it is relative to the application root. 218 /// If the URI has the `app` scheme, it is relative to the application root.
165 Uri importUri; 219 Uri importUri;
166 220
167 /// The uri of the source file this library was loaded from. 221 /// The uri of the source file this library was loaded from.
168 String fileUri; 222 String fileUri;
169 223
(...skipping 14 matching lines...) Expand all
184 final List<Procedure> procedures; 238 final List<Procedure> procedures;
185 final List<Field> fields; 239 final List<Field> fields;
186 240
187 Library(this.importUri, 241 Library(this.importUri,
188 {this.name, 242 {this.name,
189 this.isExternal: false, 243 this.isExternal: false,
190 List<DeferredImport> imports, 244 List<DeferredImport> imports,
191 List<Class> classes, 245 List<Class> classes,
192 List<Procedure> procedures, 246 List<Procedure> procedures,
193 List<Field> fields, 247 List<Field> fields,
194 this.fileUri}) 248 this.fileUri,
249 LinkedNodeBox box})
195 : this.deferredImports = imports ?? <DeferredImport>[], 250 : this.deferredImports = imports ?? <DeferredImport>[],
196 this.classes = classes ?? <Class>[], 251 this.classes = classes ?? <Class>[],
197 this.procedures = procedures ?? <Procedure>[], 252 this.procedures = procedures ?? <Procedure>[],
198 this.fields = fields ?? <Field>[] { 253 this.fields = fields ?? <Field>[],
254 super(box) {
199 setParents(this.classes, this); 255 setParents(this.classes, this);
200 setParents(this.procedures, this); 256 setParents(this.procedures, this);
201 setParents(this.fields, this); 257 setParents(this.fields, this);
202 } 258 }
203 259
204 /// Returns the top-level fields and procedures defined in this library. 260 /// Returns the top-level fields and procedures defined in this library.
205 /// 261 ///
206 /// This getter is for convenience, not efficiency. Consider manually 262 /// This getter is for convenience, not efficiency. Consider manually
207 /// iterating the members to speed up code in production. 263 /// iterating the members to speed up code in production.
208 Iterable<Member> get members => 264 Iterable<Member> get members =>
209 <Iterable<Member>>[fields, procedures].expand((x) => x); 265 <Iterable<Member>>[fields, procedures].expand((x) => x);
210 266
211 void addMember(Member member) { 267 void addMember(Member member) {
212 member.parent = this; 268 member.parent = this;
213 if (member is Procedure) { 269 if (member is Procedure) {
214 procedures.add(member); 270 procedures.add(member);
215 } else if (member is Field) { 271 } else if (member is Field) {
216 fields.add(member); 272 fields.add(member);
217 } else { 273 } else {
218 throw new ArgumentError(member); 274 throw new ArgumentError(member);
219 } 275 }
220 } 276 }
221 277
222 void addClass(Class class_) { 278 void addClass(Class class_) {
223 class_.parent = this; 279 class_.parent = this;
224 classes.add(class_); 280 classes.add(class_);
225 } 281 }
226 282
283 void computeCanonicalNames() {
284 assert(canonicalName != null);
285 for (var field in fields) {
286 canonicalName.getChildFromMember(field).bindTo(field.box);
287 }
288 for (var member in procedures) {
289 canonicalName.getChildFromMember(member).bindTo(member.box);
290 }
291 for (var class_ in classes) {
292 canonicalName.getChild(class_.name).bindTo(class_.box);
293 class_.computeCanonicalNames();
294 }
295 }
296
227 accept(TreeVisitor v) => v.visitLibrary(this); 297 accept(TreeVisitor v) => v.visitLibrary(this);
228 298
229 visitChildren(Visitor v) { 299 visitChildren(Visitor v) {
230 visitList(classes, v); 300 visitList(classes, v);
231 visitList(procedures, v); 301 visitList(procedures, v);
232 visitList(fields, v); 302 visitList(fields, v);
233 } 303 }
234 304
235 transformChildren(Transformer v) { 305 transformChildren(Transformer v) {
236 transformList(classes, v, this); 306 transformList(classes, v, this);
(...skipping 10 matching lines...) Expand all
247 /// the names across all [toString] calls. 317 /// the names across all [toString] calls.
248 String toString() => debugLibraryName(this); 318 String toString() => debugLibraryName(this);
249 319
250 Location _getLocationInEnclosingFile(int offset) { 320 Location _getLocationInEnclosingFile(int offset) {
251 return enclosingProgram.getLocation(fileUri, offset); 321 return enclosingProgram.getLocation(fileUri, offset);
252 } 322 }
253 } 323 }
254 324
255 /// An import of form: `import <url> deferred as <name>;`. 325 /// An import of form: `import <url> deferred as <name>;`.
256 class DeferredImport extends TreeNode { 326 class DeferredImport extends TreeNode {
257 Library importedLibrary; 327 LinkedNodeBox importedLibraryBox;
258 String name; 328 String name;
259 329
260 DeferredImport(this.importedLibrary, this.name); 330 DeferredImport(Library importedLibrary, String name)
331 : this.byBox(importedLibrary.box, name);
332
333 DeferredImport.byBox(this.importedLibraryBox, this.name);
261 334
262 Library get enclosingLibrary => parent; 335 Library get enclosingLibrary => parent;
336 Library get importedLibrary => importedLibraryBox.node;
263 337
264 accept(TreeVisitor v) => v.visitDeferredImport(this); 338 accept(TreeVisitor v) => v.visitDeferredImport(this);
265 339
266 visitChildren(Visitor v) {} 340 visitChildren(Visitor v) {}
267 341
268 transformChildren(Transformer v) {} 342 transformChildren(Transformer v) {}
269 } 343 }
270 344
271 /// The degree to which the contents of a class have been loaded into memory. 345 /// The degree to which the contents of a class have been loaded into memory.
272 /// 346 ///
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 /// not necessarily at [Body] level. 388 /// not necessarily at [Body] level.
315 Body, 389 Body,
316 } 390 }
317 391
318 /// Declaration of a regular class or a mixin application. 392 /// Declaration of a regular class or a mixin application.
319 /// 393 ///
320 /// Mixin applications may not contain fields or procedures, as they implicitly 394 /// Mixin applications may not contain fields or procedures, as they implicitly
321 /// use those from its mixed-in type. However, the IR does not enforce this 395 /// use those from its mixed-in type. However, the IR does not enforce this
322 /// rule directly, as doing so can obstruct transformations. It is possible to 396 /// rule directly, as doing so can obstruct transformations. It is possible to
323 /// transform a mixin application to become a regular class, and vice versa. 397 /// transform a mixin application to become a regular class, and vice versa.
324 class Class extends TreeNode { 398 class Class extends LinkedNode {
325 /// The degree to which the contents of the class have been loaded. 399 /// The degree to which the contents of the class have been loaded.
326 ClassLevel level = ClassLevel.Body; 400 ClassLevel level = ClassLevel.Body;
327 401
328 /// List of metadata annotations on the class. 402 /// List of metadata annotations on the class.
329 /// 403 ///
330 /// This defaults to an immutable empty list. Use [addAnnotation] to add 404 /// This defaults to an immutable empty list. Use [addAnnotation] to add
331 /// annotations if needed. 405 /// annotations if needed.
332 List<Expression> annotations = const <Expression>[]; 406 List<Expression> annotations = const <Expression>[];
333 407
334 /// Name of the class. 408 /// Name of the class.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 Class( 445 Class(
372 {this.name, 446 {this.name,
373 this.isAbstract: false, 447 this.isAbstract: false,
374 this.supertype, 448 this.supertype,
375 this.mixedInType, 449 this.mixedInType,
376 List<TypeParameter> typeParameters, 450 List<TypeParameter> typeParameters,
377 List<Supertype> implementedTypes, 451 List<Supertype> implementedTypes,
378 List<Constructor> constructors, 452 List<Constructor> constructors,
379 List<Procedure> procedures, 453 List<Procedure> procedures,
380 List<Field> fields, 454 List<Field> fields,
381 this.fileUri}) 455 this.fileUri,
456 LinkedNodeBox box})
382 : this.typeParameters = typeParameters ?? <TypeParameter>[], 457 : this.typeParameters = typeParameters ?? <TypeParameter>[],
383 this.implementedTypes = implementedTypes ?? <Supertype>[], 458 this.implementedTypes = implementedTypes ?? <Supertype>[],
384 this.fields = fields ?? <Field>[], 459 this.fields = fields ?? <Field>[],
385 this.constructors = constructors ?? <Constructor>[], 460 this.constructors = constructors ?? <Constructor>[],
386 this.procedures = procedures ?? <Procedure>[] { 461 this.procedures = procedures ?? <Procedure>[],
462 super(box) {
387 setParents(this.typeParameters, this); 463 setParents(this.typeParameters, this);
388 setParents(this.constructors, this); 464 setParents(this.constructors, this);
389 setParents(this.procedures, this); 465 setParents(this.procedures, this);
390 setParents(this.fields, this); 466 setParents(this.fields, this);
391 } 467 }
392 468
469 void computeCanonicalNames() {
470 assert(canonicalName != null);
471 for (var member in fields) {
472 canonicalName.getChildFromMember(member).bindTo(member.box);
473 }
474 for (var member in procedures) {
475 canonicalName.getChildFromMember(member).bindTo(member.box);
476 }
477 for (var member in constructors) {
478 canonicalName.getChildFromMember(member).bindTo(member.box);
479 }
480 }
481
393 /// The immediate super class, or `null` if this is the root class. 482 /// The immediate super class, or `null` if this is the root class.
394 Class get superclass => supertype?.classNode; 483 Class get superclass => supertype?.classNode;
395 484
396 /// The mixed-in class if this is a mixin application, otherwise `null`. 485 /// The mixed-in class if this is a mixin application, otherwise `null`.
397 /// 486 ///
398 /// Note that this may itself be a mixin application. Use [mixin] to get the 487 /// Note that this may itself be a mixin application. Use [mixin] to get the
399 /// class that has the fields and procedures. 488 /// class that has the fields and procedures.
400 Class get mixedInClass => mixedInType?.classNode; 489 Class get mixedInClass => mixedInType?.classNode;
401 490
402 /// The class that declares the field and procedures of this class. 491 /// The class that declares the field and procedures of this class.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 604
516 Location _getLocationInEnclosingFile(int offset) { 605 Location _getLocationInEnclosingFile(int offset) {
517 return enclosingProgram.getLocation(fileUri, offset); 606 return enclosingProgram.getLocation(fileUri, offset);
518 } 607 }
519 } 608 }
520 609
521 // ------------------------------------------------------------------------ 610 // ------------------------------------------------------------------------
522 // MEMBERS 611 // MEMBERS
523 // ------------------------------------------------------------------------ 612 // ------------------------------------------------------------------------
524 613
525 /// A indirect reference to a member, which can be updated to point at another 614 abstract class Member extends LinkedNode {
526 /// member at a later time.
527 class _MemberAccessor {
528 Member target;
529 _MemberAccessor(this.target);
530 }
531
532 abstract class Member extends TreeNode {
533 /// End offset in the source file it comes from. Valid values are from 0 and 615 /// End offset in the source file it comes from. Valid values are from 0 and
534 /// up, or -1 ([TreeNode.noOffset]) if the file end offset is not available 616 /// up, or -1 ([TreeNode.noOffset]) if the file end offset is not available
535 /// (this is the default if none is specifically set). 617 /// (this is the default if none is specifically set).
536 int fileEndOffset = TreeNode.noOffset; 618 int fileEndOffset = TreeNode.noOffset;
537 619
538 /// List of metadata annotations on the member. 620 /// List of metadata annotations on the member.
539 /// 621 ///
540 /// This defaults to an immutable empty list. Use [addAnnotation] to add 622 /// This defaults to an immutable empty list. Use [addAnnotation] to add
541 /// annotations if needed. 623 /// annotations if needed.
542 List<Expression> annotations = const <Expression>[]; 624 List<Expression> annotations = const <Expression>[];
543 Name name; 625 Name name;
544 626
545 /// Flags summarizing the kinds of AST nodes contained in this member, for 627 /// Flags summarizing the kinds of AST nodes contained in this member, for
546 /// speeding up transformations that only affect certain types of nodes. 628 /// speeding up transformations that only affect certain types of nodes.
547 /// 629 ///
548 /// See [TransformerFlag] for the meaning of each bit. 630 /// See [TransformerFlag] for the meaning of each bit.
549 /// 631 ///
550 /// These should not be used for any purpose other than skipping certain 632 /// These should not be used for any purpose other than skipping certain
551 /// members if it can be determined that no work is needed in there. 633 /// members if it can be determined that no work is needed in there.
552 /// 634 ///
553 /// It is valid for these flags to be false positives in rare cases, so 635 /// It is valid for these flags to be false positives in rare cases, so
554 /// transformers must tolerate the case where a flag is spuriously set. 636 /// transformers must tolerate the case where a flag is spuriously set.
555 /// 637 ///
556 /// This value is not serialized; it is populated by the frontend and the 638 /// This value is not serialized; it is populated by the frontend and the
557 /// deserializer. 639 /// deserializer.
558 // 640 //
559 // TODO(asgerf): It might be worthwhile to put this on classes as well. 641 // TODO(asgerf): It might be worthwhile to put this on classes as well.
560 int transformerFlags = 0; 642 int transformerFlags = 0;
561 643
562 Member(this.name); 644 Member(this.name, LinkedNodeBox box) : super(box);
563 645
564 Class get enclosingClass => parent is Class ? parent : null; 646 Class get enclosingClass => parent is Class ? parent : null;
565 Library get enclosingLibrary => parent is Class ? parent.parent : parent; 647 Library get enclosingLibrary => parent is Class ? parent.parent : parent;
566 648
567 accept(MemberVisitor v); 649 accept(MemberVisitor v);
568 acceptReference(MemberReferenceVisitor v); 650 acceptReference(MemberReferenceVisitor v);
569 651
570 /// If true, the member is part of an external library, that is, it is defined 652 /// If true, the member is part of an external library, that is, it is defined
571 /// in another build unit. Such members have no body or initializer present 653 /// in another build unit. Such members have no body or initializer present
572 /// in the IR. 654 /// in the IR.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 annotations.add(node); 692 annotations.add(node);
611 node.parent = this; 693 node.parent = this;
612 } 694 }
613 695
614 DartType get getterType; 696 DartType get getterType;
615 DartType get setterType; 697 DartType get setterType;
616 698
617 bool get containsSuperCalls { 699 bool get containsSuperCalls {
618 return transformerFlags & TransformerFlag.superCalls != 0; 700 return transformerFlags & TransformerFlag.superCalls != 0;
619 } 701 }
620
621 _MemberAccessor get _getterInterface;
622 _MemberAccessor get _setterInterface;
623 } 702 }
624 703
625 /// A field declaration. 704 /// A field declaration.
626 /// 705 ///
627 /// The implied getter and setter for the field are not represented explicitly, 706 /// The implied getter and setter for the field are not represented explicitly,
628 /// but can be made explicit if needed. 707 /// but can be made explicit if needed.
629 class Field extends Member { 708 class Field extends Member {
630 _MemberAccessor _getterInterface, _setterInterface;
631
632 DartType type; // Not null. Defaults to DynamicType. 709 DartType type; // Not null. Defaults to DynamicType.
633 InferredValue inferredValue; // May be null. 710 InferredValue inferredValue; // May be null.
634 int flags = 0; 711 int flags = 0;
635 Expression initializer; // May be null. 712 Expression initializer; // May be null.
636 713
637 /// The uri of the source file this field was loaded from. 714 /// The uri of the source file this field was loaded from.
638 String fileUri; 715 String fileUri;
639 716
640 Field(Name name, 717 Field(Name name,
641 {this.type: const DynamicType(), 718 {this.type: const DynamicType(),
642 this.inferredValue, 719 this.inferredValue,
643 this.initializer, 720 this.initializer,
644 bool isFinal: false, 721 bool isFinal: false,
645 bool isConst: false, 722 bool isConst: false,
646 bool isStatic: false, 723 bool isStatic: false,
647 bool hasImplicitGetter, 724 bool hasImplicitGetter,
648 bool hasImplicitSetter, 725 bool hasImplicitSetter,
649 int transformerFlags: 0, 726 int transformerFlags: 0,
650 this.fileUri}) 727 this.fileUri,
651 : super(name) { 728 LinkedNodeBox box})
652 _getterInterface = new _MemberAccessor(this); 729 : super(name, box) {
653 _setterInterface = new _MemberAccessor(this);
654 assert(type != null); 730 assert(type != null);
655 initializer?.parent = this; 731 initializer?.parent = this;
656 this.isFinal = isFinal; 732 this.isFinal = isFinal;
657 this.isConst = isConst; 733 this.isConst = isConst;
658 this.isStatic = isStatic; 734 this.isStatic = isStatic;
659 this.hasImplicitGetter = hasImplicitGetter ?? !isStatic; 735 this.hasImplicitGetter = hasImplicitGetter ?? !isStatic;
660 this.hasImplicitSetter = hasImplicitSetter ?? (!isStatic && !isFinal); 736 this.hasImplicitSetter = hasImplicitSetter ?? (!isStatic && !isFinal);
661 this.transformerFlags = transformerFlags; 737 this.transformerFlags = transformerFlags;
662 } 738 }
663 739
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 transformList(annotations, v, this); 819 transformList(annotations, v, this);
744 if (initializer != null) { 820 if (initializer != null) {
745 initializer = initializer.accept(v); 821 initializer = initializer.accept(v);
746 initializer?.parent = this; 822 initializer?.parent = this;
747 } 823 }
748 } 824 }
749 825
750 DartType get getterType => type; 826 DartType get getterType => type;
751 DartType get setterType => isMutable ? type : const BottomType(); 827 DartType get setterType => isMutable ? type : const BottomType();
752 828
753 /// Makes all [PropertyGet]s that have this field as its interface target
754 /// use [getter] as its interface target instead.
755 ///
756 /// That can be used to introduce an explicit getter for a field instead of
757 /// its implicit getter.
758 ///
759 /// This method only updates the stored interface target -- the caller must
760 /// ensure that [getter] actually becomes the target for dispatches that
761 /// would previously hit the implicit field getter.
762 ///
763 /// [DirectPropertyGet]s are not affected, and will continue to access the
764 /// field directly. [PropertyGet] nodes created after the call will not be
765 /// affected until the method is called again.
766 ///
767 /// Existing [ClassHierarchy] instances are not affected by this call.
768 void replaceGetterInterfaceWith(Procedure getter) {
769 _getterInterface.target = getter;
770 _getterInterface = new _MemberAccessor(this);
771 }
772
773 /// Makes all [PropertySet]s that have this field as its interface target
774 /// use [setter] as its interface target instead.
775 ///
776 /// That can be used to introduce an explicit setter for a field instead of
777 /// its implicit setter.
778 ///
779 /// This method only updates the stored interface target -- the caller must
780 /// ensure that [setter] actually becomes the target for dispatches that
781 /// would previously hit the implicit field setter.
782 ///
783 /// [DirectPropertySet] and [FieldInitializer]s are not affected, and will
784 /// continue to access the field directly. [PropertySet] nodes created after
785 /// the call will not be affected until the method is called again.
786 ///
787 /// Existing [ClassHierarchy] instances are not affected by this call.
788 void replaceSetterInterfaceWith(Procedure setter) {
789 _setterInterface.target = setter;
790 _setterInterface = new _MemberAccessor(this);
791 }
792
793 Location _getLocationInEnclosingFile(int offset) { 829 Location _getLocationInEnclosingFile(int offset) {
794 return enclosingProgram.getLocation(fileUri, offset); 830 return enclosingProgram.getLocation(fileUri, offset);
795 } 831 }
796 } 832 }
797 833
798 /// A generative constructor, possibly redirecting. 834 /// A generative constructor, possibly redirecting.
799 /// 835 ///
800 /// Note that factory constructors are treated as [Procedure]s. 836 /// Note that factory constructors are treated as [Procedure]s.
801 /// 837 ///
802 /// Constructors do not take type parameters. Type arguments from a constructor 838 /// Constructors do not take type parameters. Type arguments from a constructor
803 /// invocation should be matched with the type parameters declared in the class. 839 /// invocation should be matched with the type parameters declared in the class.
804 /// 840 ///
805 /// For unnamed constructors, the name is an empty string (in a [Name]). 841 /// For unnamed constructors, the name is an empty string (in a [Name]).
806 class Constructor extends Member { 842 class Constructor extends Member {
807 int flags = 0; 843 int flags = 0;
808 FunctionNode function; 844 FunctionNode function;
809 List<Initializer> initializers; 845 List<Initializer> initializers;
810 846
811 Constructor(this.function, 847 Constructor(this.function,
812 {Name name, 848 {Name name,
813 bool isConst: false, 849 bool isConst: false,
814 bool isExternal: false, 850 bool isExternal: false,
815 List<Initializer> initializers, 851 List<Initializer> initializers,
816 int transformerFlags: 0}) 852 int transformerFlags: 0,
853 LinkedNodeBox box})
817 : this.initializers = initializers ?? <Initializer>[], 854 : this.initializers = initializers ?? <Initializer>[],
818 super(name) { 855 super(name, box) {
819 function?.parent = this; 856 function?.parent = this;
820 setParents(this.initializers, this); 857 setParents(this.initializers, this);
821 this.isConst = isConst; 858 this.isConst = isConst;
822 this.isExternal = isExternal; 859 this.isExternal = isExternal;
823 this.transformerFlags = transformerFlags; 860 this.transformerFlags = transformerFlags;
824 } 861 }
825 862
826 static const int FlagConst = 1 << 0; // Must match serialized bit positions. 863 static const int FlagConst = 1 << 0; // Must match serialized bit positions.
827 static const int FlagExternal = 1 << 1; 864 static const int FlagExternal = 1 << 1;
828 865
(...skipping 28 matching lines...) Expand all
857 transformList(annotations, v, this); 894 transformList(annotations, v, this);
858 if (function != null) { 895 if (function != null) {
859 function = function.accept(v); 896 function = function.accept(v);
860 function?.parent = this; 897 function?.parent = this;
861 } 898 }
862 transformList(initializers, v, this); 899 transformList(initializers, v, this);
863 } 900 }
864 901
865 DartType get getterType => const BottomType(); 902 DartType get getterType => const BottomType();
866 DartType get setterType => const BottomType(); 903 DartType get setterType => const BottomType();
867
868 _MemberAccessor get _getterInterface {
869 throw 'Constructors cannot be used as getters';
870 }
871
872 _MemberAccessor get _setterInterface {
873 throw 'Constructors cannot be used as setters';
874 }
875 } 904 }
876 905
877 /// A method, getter, setter, index-getter, index-setter, operator overloader, 906 /// A method, getter, setter, index-getter, index-setter, operator overloader,
878 /// or factory. 907 /// or factory.
879 /// 908 ///
880 /// Procedures can have the static, abstract, and/or external modifier, although 909 /// Procedures can have the static, abstract, and/or external modifier, although
881 /// only the static and external modifiers may be used together. 910 /// only the static and external modifiers may be used together.
882 /// 911 ///
883 /// For non-static procedures the name is required for dynamic dispatch. 912 /// For non-static procedures the name is required for dynamic dispatch.
884 /// For external procedures the name is required for identifying the external 913 /// For external procedures the name is required for identifying the external
885 /// implementation. 914 /// implementation.
886 /// 915 ///
887 /// For methods, getters, and setters the name is just as it was declared. 916 /// For methods, getters, and setters the name is just as it was declared.
888 /// For setters this does not include a trailing `=`. 917 /// For setters this does not include a trailing `=`.
889 /// For index-getters/setters, this is `[]` and `[]=`. 918 /// For index-getters/setters, this is `[]` and `[]=`.
890 /// For operators, this is the token for the operator, e.g. `+` or `==`, 919 /// For operators, this is the token for the operator, e.g. `+` or `==`,
891 /// except for the unary minus operator, whose name is `unary-`. 920 /// except for the unary minus operator, whose name is `unary-`.
892 class Procedure extends Member { 921 class Procedure extends Member {
893 _MemberAccessor _reference;
894 ProcedureKind kind; 922 ProcedureKind kind;
895 int flags = 0; 923 int flags = 0;
896 FunctionNode function; // Body is null if and only if abstract or external. 924 FunctionNode function; // Body is null if and only if abstract or external.
897 925
898 /// The uri of the source file this procedure was loaded from. 926 /// The uri of the source file this procedure was loaded from.
899 String fileUri; 927 String fileUri;
900 928
901 Procedure(Name name, this.kind, this.function, 929 Procedure(Name name, this.kind, this.function,
902 {bool isAbstract: false, 930 {bool isAbstract: false,
903 bool isStatic: false, 931 bool isStatic: false,
904 bool isExternal: false, 932 bool isExternal: false,
905 bool isConst: false, 933 bool isConst: false,
906 int transformerFlags: 0, 934 int transformerFlags: 0,
907 this.fileUri}) 935 this.fileUri,
908 : super(name) { 936 LinkedNodeBox box})
909 _reference = new _MemberAccessor(this); 937 : super(name, box) {
910 function?.parent = this; 938 function?.parent = this;
911 this.isAbstract = isAbstract; 939 this.isAbstract = isAbstract;
912 this.isStatic = isStatic; 940 this.isStatic = isStatic;
913 this.isExternal = isExternal; 941 this.isExternal = isExternal;
914 this.isConst = isConst; 942 this.isConst = isConst;
915 this.transformerFlags = transformerFlags; 943 this.transformerFlags = transformerFlags;
916 } 944 }
917 945
918 static const int FlagStatic = 1 << 0; // Must match serialized bit positions. 946 static const int FlagStatic = 1 << 0; // Must match serialized bit positions.
919 static const int FlagAbstract = 1 << 1; 947 static const int FlagAbstract = 1 << 1;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 DartType get getterType { 1000 DartType get getterType {
973 return isGetter ? function.returnType : function.functionType; 1001 return isGetter ? function.returnType : function.functionType;
974 } 1002 }
975 1003
976 DartType get setterType { 1004 DartType get setterType {
977 return isSetter 1005 return isSetter
978 ? function.positionalParameters[0].type 1006 ? function.positionalParameters[0].type
979 : const BottomType(); 1007 : const BottomType();
980 } 1008 }
981 1009
982 _MemberAccessor get _getterInterface => _reference;
983 _MemberAccessor get _setterInterface => _reference;
984
985 Location _getLocationInEnclosingFile(int offset) { 1010 Location _getLocationInEnclosingFile(int offset) {
986 return enclosingProgram.getLocation(fileUri, offset); 1011 return enclosingProgram.getLocation(fileUri, offset);
987 } 1012 }
988 } 1013 }
989 1014
990 enum ProcedureKind { 1015 enum ProcedureKind {
991 Method, 1016 Method,
992 Getter, 1017 Getter,
993 Setter, 1018 Setter,
994 Operator, 1019 Operator,
(...skipping 25 matching lines...) Expand all
1020 /// A field assignment `field = value` occurring in the initializer list of 1045 /// A field assignment `field = value` occurring in the initializer list of
1021 /// a constructor. 1046 /// a constructor.
1022 /// 1047 ///
1023 /// This node has nothing to do with declaration-site field initializers; those 1048 /// This node has nothing to do with declaration-site field initializers; those
1024 /// are [Expression]s stored in [Field.initializer]. 1049 /// are [Expression]s stored in [Field.initializer].
1025 // 1050 //
1026 // TODO: The frontend should check that all final fields are initialized 1051 // TODO: The frontend should check that all final fields are initialized
1027 // exactly once, and that no fields are assigned twice in the initializer list. 1052 // exactly once, and that no fields are assigned twice in the initializer list.
1028 class FieldInitializer extends Initializer { 1053 class FieldInitializer extends Initializer {
1029 /// Reference to the field being initialized. Not null. 1054 /// Reference to the field being initialized. Not null.
1030 Field field; 1055 LinkedNodeBox fieldBox;
1031 Expression value; 1056 Expression value;
1032 1057
1033 FieldInitializer(this.field, this.value) { 1058 FieldInitializer(Field field, Expression value)
1059 : this.byBox(field?.box, value);
1060
1061 FieldInitializer.byBox(this.fieldBox, this.value) {
1034 value?.parent = this; 1062 value?.parent = this;
1035 } 1063 }
1036 1064
1065 Field get field => fieldBox?.node;
1066
1067 void set field(Field field) {
1068 fieldBox = field?.box;
1069 }
1070
1037 accept(InitializerVisitor v) => v.visitFieldInitializer(this); 1071 accept(InitializerVisitor v) => v.visitFieldInitializer(this);
1038 1072
1039 visitChildren(Visitor v) { 1073 visitChildren(Visitor v) {
1040 field?.acceptReference(v); 1074 field?.acceptReference(v);
1041 value?.accept(v); 1075 value?.accept(v);
1042 } 1076 }
1043 1077
1044 transformChildren(Transformer v) { 1078 transformChildren(Transformer v) {
1045 if (value != null) { 1079 if (value != null) {
1046 value = value.accept(v); 1080 value = value.accept(v);
1047 value?.parent = this; 1081 value?.parent = this;
1048 } 1082 }
1049 } 1083 }
1050 } 1084 }
1051 1085
1052 /// A super call `super(x,y)` occurring in the initializer list of a 1086 /// A super call `super(x,y)` occurring in the initializer list of a
1053 /// constructor. 1087 /// constructor.
1054 /// 1088 ///
1055 /// There are no type arguments on this call. 1089 /// There are no type arguments on this call.
1056 // 1090 //
1057 // TODO: The frontend should check that there is no more than one super call. 1091 // TODO: The frontend should check that there is no more than one super call.
1058 // 1092 //
1059 // DESIGN TODO: Consider if the frontend should insert type arguments derived 1093 // DESIGN TODO: Consider if the frontend should insert type arguments derived
1060 // from the extends clause. 1094 // from the extends clause.
1061 class SuperInitializer extends Initializer { 1095 class SuperInitializer extends Initializer {
1062 /// Reference to the constructor being invoked in the super class. Not null. 1096 /// Reference to the constructor being invoked in the super class. Not null.
1063 Constructor target; 1097 LinkedNodeBox targetBox;
1064 Arguments arguments; 1098 Arguments arguments;
1065 1099
1066 SuperInitializer(this.target, this.arguments) { 1100 SuperInitializer(Constructor target, Arguments arguments)
1101 : this.byBox(getBoxOfMember(target), arguments);
1102
1103 SuperInitializer.byBox(this.targetBox, this.arguments) {
1067 arguments?.parent = this; 1104 arguments?.parent = this;
1068 } 1105 }
1069 1106
1107 Constructor get target => targetBox?.asConstructor;
1108
1109 void set target(Constructor target) {
1110 targetBox = getBoxOfMember(target);
1111 }
1112
1070 accept(InitializerVisitor v) => v.visitSuperInitializer(this); 1113 accept(InitializerVisitor v) => v.visitSuperInitializer(this);
1071 1114
1072 visitChildren(Visitor v) { 1115 visitChildren(Visitor v) {
1073 target?.acceptReference(v); 1116 target?.acceptReference(v);
1074 arguments?.accept(v); 1117 arguments?.accept(v);
1075 } 1118 }
1076 1119
1077 transformChildren(Transformer v) { 1120 transformChildren(Transformer v) {
1078 if (arguments != null) { 1121 if (arguments != null) {
1079 arguments = arguments.accept(v); 1122 arguments = arguments.accept(v);
1080 arguments?.parent = this; 1123 arguments?.parent = this;
1081 } 1124 }
1082 } 1125 }
1083 } 1126 }
1084 1127
1085 /// A redirecting call `this(x,y)` occurring in the initializer list of 1128 /// A redirecting call `this(x,y)` occurring in the initializer list of
1086 /// a constructor. 1129 /// a constructor.
1087 // 1130 //
1088 // TODO: The frontend should check that this is the only initializer and if the 1131 // TODO: The frontend should check that this is the only initializer and if the
1089 // constructor has a body or if there is a cycle in the initializer calls. 1132 // constructor has a body or if there is a cycle in the initializer calls.
1090 class RedirectingInitializer extends Initializer { 1133 class RedirectingInitializer extends Initializer {
1091 /// Reference to the constructor being invoked in the same class. Not null. 1134 /// Reference to the constructor being invoked in the same class. Not null.
1092 Constructor target; 1135 LinkedNodeBox targetBox;
1093 Arguments arguments; 1136 Arguments arguments;
1094 1137
1095 RedirectingInitializer(this.target, this.arguments) { 1138 RedirectingInitializer(Constructor target, Arguments arguments)
1139 : this.byBox(getBoxOfMember(target), arguments);
1140
1141 RedirectingInitializer.byBox(this.targetBox, this.arguments) {
1096 arguments?.parent = this; 1142 arguments?.parent = this;
1097 } 1143 }
1098 1144
1145 Constructor get target => targetBox?.asConstructor;
1146
1147 void set target(Constructor target) {
1148 targetBox = getBoxOfMember(target);
1149 }
1150
1099 accept(InitializerVisitor v) => v.visitRedirectingInitializer(this); 1151 accept(InitializerVisitor v) => v.visitRedirectingInitializer(this);
1100 1152
1101 visitChildren(Visitor v) { 1153 visitChildren(Visitor v) {
1102 target?.acceptReference(v); 1154 target?.acceptReference(v);
1103 arguments?.accept(v); 1155 arguments?.accept(v);
1104 } 1156 }
1105 1157
1106 transformChildren(Transformer v) { 1158 transformChildren(Transformer v) {
1107 if (arguments != null) { 1159 if (arguments != null) {
1108 arguments = arguments.accept(v); 1160 arguments = arguments.accept(v);
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
1381 } 1433 }
1382 } 1434 }
1383 1435
1384 /// Expression of form `x.field`. 1436 /// Expression of form `x.field`.
1385 /// 1437 ///
1386 /// This may invoke a getter, read a field, or tear off a method. 1438 /// This may invoke a getter, read a field, or tear off a method.
1387 class PropertyGet extends Expression { 1439 class PropertyGet extends Expression {
1388 Expression receiver; 1440 Expression receiver;
1389 Name name; 1441 Name name;
1390 1442
1391 _MemberAccessor _interfaceTargetReference; 1443 LinkedNodeBox interfaceTargetBox;
1392 1444
1393 PropertyGet(this.receiver, this.name, [Member interfaceTarget]) { 1445 PropertyGet(Expression receiver, Name name, [Member interfaceTarget])
1446 : this.byBox(receiver, name, getBoxOfMember(interfaceTarget));
1447
1448 PropertyGet.byBox(this.receiver, this.name, this.interfaceTargetBox) {
1394 receiver?.parent = this; 1449 receiver?.parent = this;
1395 this.interfaceTarget = interfaceTarget;
1396 } 1450 }
1397 1451
1398 Member get interfaceTarget => _interfaceTargetReference?.target; 1452 Member get interfaceTarget => interfaceTargetBox?.asMember;
1399 1453
1400 void set interfaceTarget(Member newTarget) { 1454 void set interfaceTarget(Member member) {
1401 _interfaceTargetReference = newTarget?._getterInterface; 1455 interfaceTargetBox = getBoxOfMember(member);
1402 } 1456 }
1403 1457
1404 DartType getStaticType(TypeEnvironment types) { 1458 DartType getStaticType(TypeEnvironment types) {
1405 var interfaceTarget = this.interfaceTarget; 1459 var interfaceTarget = this.interfaceTarget;
1406 if (interfaceTarget != null) { 1460 if (interfaceTarget != null) {
1407 Class superclass = interfaceTarget.enclosingClass; 1461 Class superclass = interfaceTarget.enclosingClass;
1408 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types); 1462 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types);
1409 return Substitution 1463 return Substitution
1410 .fromInterfaceType(receiverType) 1464 .fromInterfaceType(receiverType)
1411 .substituteType(interfaceTarget.getterType); 1465 .substituteType(interfaceTarget.getterType);
(...skipping 26 matching lines...) Expand all
1438 /// Expression of form `x.field = value`. 1492 /// Expression of form `x.field = value`.
1439 /// 1493 ///
1440 /// This may invoke a setter or assign a field. 1494 /// This may invoke a setter or assign a field.
1441 /// 1495 ///
1442 /// Evaluates to the value of [value]. 1496 /// Evaluates to the value of [value].
1443 class PropertySet extends Expression { 1497 class PropertySet extends Expression {
1444 Expression receiver; 1498 Expression receiver;
1445 Name name; 1499 Name name;
1446 Expression value; 1500 Expression value;
1447 1501
1448 _MemberAccessor _interfaceTargetReference; 1502 LinkedNodeBox interfaceTargetBox;
1449 1503
1450 PropertySet(this.receiver, this.name, this.value, [Member interfaceTarget]) { 1504 PropertySet(Expression receiver, Name name, Expression value,
1505 [Member interfaceTarget])
1506 : this.byBox(
1507 receiver, name, value, getBoxOfMember(interfaceTarget));
1508
1509 PropertySet.byBox(
1510 this.receiver, this.name, this.value, this.interfaceTargetBox) {
1451 receiver?.parent = this; 1511 receiver?.parent = this;
1452 value?.parent = this; 1512 value?.parent = this;
1453 this.interfaceTarget = interfaceTarget;
1454 } 1513 }
1455 1514
1456 Member get interfaceTarget => _interfaceTargetReference?.target; 1515 Member get interfaceTarget => interfaceTargetBox?.asMember;
1457 1516
1458 void set interfaceTarget(Member newTarget) { 1517 void set interfaceTarget(Member member) {
1459 _interfaceTargetReference = newTarget?._setterInterface; 1518 interfaceTargetBox = getBoxOfMember(member);
1460 } 1519 }
1461 1520
1462 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); 1521 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
1463 1522
1464 accept(ExpressionVisitor v) => v.visitPropertySet(this); 1523 accept(ExpressionVisitor v) => v.visitPropertySet(this);
1465 1524
1466 visitChildren(Visitor v) { 1525 visitChildren(Visitor v) {
1467 receiver?.accept(v); 1526 receiver?.accept(v);
1468 name?.accept(v); 1527 name?.accept(v);
1469 value?.accept(v); 1528 value?.accept(v);
1470 } 1529 }
1471 1530
1472 transformChildren(Transformer v) { 1531 transformChildren(Transformer v) {
1473 if (receiver != null) { 1532 if (receiver != null) {
1474 receiver = receiver.accept(v); 1533 receiver = receiver.accept(v);
1475 receiver?.parent = this; 1534 receiver?.parent = this;
1476 } 1535 }
1477 if (value != null) { 1536 if (value != null) {
1478 value = value.accept(v); 1537 value = value.accept(v);
1479 value?.parent = this; 1538 value?.parent = this;
1480 } 1539 }
1481 } 1540 }
1482 } 1541 }
1483 1542
1484 /// Directly read a field, call a getter, or tear off a method. 1543 /// Directly read a field, call a getter, or tear off a method.
1485 class DirectPropertyGet extends Expression { 1544 class DirectPropertyGet extends Expression {
1486 Expression receiver; 1545 Expression receiver;
1487 Member target; 1546 LinkedNodeBox targetBox;
1488 1547
1489 DirectPropertyGet(this.receiver, this.target) { 1548 DirectPropertyGet(Expression receiver, Member target)
1549 : this.byBox(receiver, getBoxOfMember(target));
1550
1551 DirectPropertyGet.byBox(this.receiver, this.targetBox) {
1490 receiver?.parent = this; 1552 receiver?.parent = this;
1491 } 1553 }
1492 1554
1555 Member get target => targetBox?.asMember;
1556
1557 void set target(Member target) {
1558 targetBox = getBoxOfMember(target);
1559 }
1560
1493 visitChildren(Visitor v) { 1561 visitChildren(Visitor v) {
1494 receiver?.accept(v); 1562 receiver?.accept(v);
1495 target?.acceptReference(v); 1563 target?.acceptReference(v);
1496 } 1564 }
1497 1565
1498 transformChildren(Transformer v) { 1566 transformChildren(Transformer v) {
1499 if (receiver != null) { 1567 if (receiver != null) {
1500 receiver = receiver.accept(v); 1568 receiver = receiver.accept(v);
1501 receiver?.parent = this; 1569 receiver?.parent = this;
1502 } 1570 }
1503 } 1571 }
1504 1572
1505 accept(ExpressionVisitor v) => v.visitDirectPropertyGet(this); 1573 accept(ExpressionVisitor v) => v.visitDirectPropertyGet(this);
1506 1574
1507 DartType getStaticType(TypeEnvironment types) { 1575 DartType getStaticType(TypeEnvironment types) {
1508 Class superclass = target.enclosingClass; 1576 Class superclass = target.enclosingClass;
1509 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types); 1577 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types);
1510 return Substitution 1578 return Substitution
1511 .fromInterfaceType(receiverType) 1579 .fromInterfaceType(receiverType)
1512 .substituteType(target.getterType); 1580 .substituteType(target.getterType);
1513 } 1581 }
1514 } 1582 }
1515 1583
1516 /// Directly assign a field, or call a setter. 1584 /// Directly assign a field, or call a setter.
1517 /// 1585 ///
1518 /// Evaluates to the value of [value]. 1586 /// Evaluates to the value of [value].
1519 class DirectPropertySet extends Expression { 1587 class DirectPropertySet extends Expression {
1520 Expression receiver; 1588 Expression receiver;
1521 Member target; 1589 LinkedNodeBox targetBox;
1522 Expression value; 1590 Expression value;
1523 1591
1524 DirectPropertySet(this.receiver, this.target, this.value) { 1592 DirectPropertySet(Expression receiver, Member target, Expression value)
1593 : this.byBox(receiver, getBoxOfMember(target), value);
1594
1595 DirectPropertySet.byBox(this.receiver, this.targetBox, this.value) {
1525 receiver?.parent = this; 1596 receiver?.parent = this;
1526 value?.parent = this; 1597 value?.parent = this;
1527 } 1598 }
1528 1599
1600 Member get target => targetBox?.asMember;
1601
1602 void set target(Member target) {
1603 targetBox = getBoxOfMember(target);
1604 }
1605
1529 visitChildren(Visitor v) { 1606 visitChildren(Visitor v) {
1530 receiver?.accept(v); 1607 receiver?.accept(v);
1531 target?.acceptReference(v); 1608 target?.acceptReference(v);
1532 value?.accept(v); 1609 value?.accept(v);
1533 } 1610 }
1534 1611
1535 transformChildren(Transformer v) { 1612 transformChildren(Transformer v) {
1536 if (receiver != null) { 1613 if (receiver != null) {
1537 receiver = receiver.accept(v); 1614 receiver = receiver.accept(v);
1538 receiver?.parent = this; 1615 receiver?.parent = this;
1539 } 1616 }
1540 if (value != null) { 1617 if (value != null) {
1541 value = value.accept(v); 1618 value = value.accept(v);
1542 value?.parent = this; 1619 value?.parent = this;
1543 } 1620 }
1544 } 1621 }
1545 1622
1546 accept(ExpressionVisitor v) => v.visitDirectPropertySet(this); 1623 accept(ExpressionVisitor v) => v.visitDirectPropertySet(this);
1547 1624
1548 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); 1625 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
1549 } 1626 }
1550 1627
1551 /// Directly call an instance method, bypassing ordinary dispatch. 1628 /// Directly call an instance method, bypassing ordinary dispatch.
1552 class DirectMethodInvocation extends InvocationExpression { 1629 class DirectMethodInvocation extends InvocationExpression {
1553 Expression receiver; 1630 Expression receiver;
1554 Procedure target; 1631 LinkedNodeBox targetBox;
1555 Arguments arguments; 1632 Arguments arguments;
1556 1633
1557 DirectMethodInvocation(this.receiver, this.target, this.arguments) { 1634 DirectMethodInvocation(
1635 Expression receiver, Procedure target, Arguments arguments)
1636 : this.byBox(receiver, getBoxOfMember(target), arguments);
1637
1638 DirectMethodInvocation.byBox(
1639 this.receiver, this.targetBox, this.arguments) {
1558 receiver?.parent = this; 1640 receiver?.parent = this;
1559 arguments?.parent = this; 1641 arguments?.parent = this;
1560 } 1642 }
1561 1643
1644 Procedure get target => targetBox?.asProcedure;
1645
1646 void set target(Procedure target) {
1647 targetBox = getBoxOfMember(target);
1648 }
1649
1562 Name get name => target?.name; 1650 Name get name => target?.name;
1563 1651
1564 visitChildren(Visitor v) { 1652 visitChildren(Visitor v) {
1565 receiver?.accept(v); 1653 receiver?.accept(v);
1566 target?.acceptReference(v); 1654 target?.acceptReference(v);
1567 arguments?.accept(v); 1655 arguments?.accept(v);
1568 } 1656 }
1569 1657
1570 transformChildren(Transformer v) { 1658 transformChildren(Transformer v) {
1571 if (receiver != null) { 1659 if (receiver != null) {
(...skipping 22 matching lines...) Expand all
1594 .fromPairs(target.function.typeParameters, arguments.types) 1682 .fromPairs(target.function.typeParameters, arguments.types)
1595 .substituteType(returnType); 1683 .substituteType(returnType);
1596 } 1684 }
1597 } 1685 }
1598 1686
1599 /// Expression of form `super.field`. 1687 /// Expression of form `super.field`.
1600 /// 1688 ///
1601 /// This may invoke a getter, read a field, or tear off a method. 1689 /// This may invoke a getter, read a field, or tear off a method.
1602 class SuperPropertyGet extends Expression { 1690 class SuperPropertyGet extends Expression {
1603 Name name; 1691 Name name;
1604 _MemberAccessor _interfaceTargetReference; 1692 LinkedNodeBox interfaceTargetBox;
1605 1693
1606 SuperPropertyGet(this.name, [Member interfaceTarget]) { 1694 SuperPropertyGet(Name name, [Member interfaceTarget])
1607 _interfaceTargetReference = interfaceTarget?._getterInterface; 1695 : this.byBox(name, getBoxOfMember(interfaceTarget));
1608 }
1609 1696
1610 Member get interfaceTarget => _interfaceTargetReference?.target; 1697 SuperPropertyGet.byBox(this.name, this.interfaceTargetBox);
1611 1698
1612 void set interfaceTarget(Member newTarget) { 1699 Member get interfaceTarget => interfaceTargetBox?.asMember;
1613 _interfaceTargetReference = newTarget?._getterInterface; 1700
1701 void set interfaceTarget(Member member) {
1702 interfaceTargetBox = getBoxOfMember(member);
1614 } 1703 }
1615 1704
1616 DartType getStaticType(TypeEnvironment types) { 1705 DartType getStaticType(TypeEnvironment types) {
1617 Class declaringClass = interfaceTarget.enclosingClass; 1706 Class declaringClass = interfaceTarget.enclosingClass;
1618 if (declaringClass.typeParameters.isEmpty) { 1707 if (declaringClass.typeParameters.isEmpty) {
1619 return interfaceTarget.getterType; 1708 return interfaceTarget.getterType;
1620 } 1709 }
1621 var receiver = 1710 var receiver =
1622 types.hierarchy.getTypeAsInstanceOf(types.thisType, declaringClass); 1711 types.hierarchy.getTypeAsInstanceOf(types.thisType, declaringClass);
1623 return Substitution 1712 return Substitution
(...skipping 11 matching lines...) Expand all
1635 } 1724 }
1636 1725
1637 /// Expression of form `super.field = value`. 1726 /// Expression of form `super.field = value`.
1638 /// 1727 ///
1639 /// This may invoke a setter or assign a field. 1728 /// This may invoke a setter or assign a field.
1640 /// 1729 ///
1641 /// Evaluates to the value of [value]. 1730 /// Evaluates to the value of [value].
1642 class SuperPropertySet extends Expression { 1731 class SuperPropertySet extends Expression {
1643 Name name; 1732 Name name;
1644 Expression value; 1733 Expression value;
1645 _MemberAccessor _interfaceTargetReference; 1734 LinkedNodeBox interfaceTargetBox;
1646 1735
1647 SuperPropertySet(this.name, this.value, [Member interfaceTarget]) { 1736 SuperPropertySet(Name name, Expression value, Member interfaceTarget)
1737 : this.byBox(name, value, getBoxOfMember(interfaceTarget));
1738
1739 SuperPropertySet.byBox(this.name, this.value, this.interfaceTargetBox) {
1648 value?.parent = this; 1740 value?.parent = this;
1649 _interfaceTargetReference = interfaceTarget?._setterInterface;
1650 } 1741 }
1651 1742
1652 Member get interfaceTarget => _interfaceTargetReference?.target; 1743 Member get interfaceTarget => interfaceTargetBox?.asMember;
1653 1744
1654 void set interfaceTarget(Member newTarget) { 1745 void set interfaceTarget(Member member) {
1655 _interfaceTargetReference = newTarget?._setterInterface; 1746 interfaceTargetBox = getBoxOfMember(member);
1656 } 1747 }
1657 1748
1658 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); 1749 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
1659 1750
1660 accept(ExpressionVisitor v) => v.visitSuperPropertySet(this); 1751 accept(ExpressionVisitor v) => v.visitSuperPropertySet(this);
1661 1752
1662 visitChildren(Visitor v) { 1753 visitChildren(Visitor v) {
1663 name?.accept(v); 1754 name?.accept(v);
1664 value?.accept(v); 1755 value?.accept(v);
1665 } 1756 }
1666 1757
1667 transformChildren(Transformer v) { 1758 transformChildren(Transformer v) {
1668 if (value != null) { 1759 if (value != null) {
1669 value = value.accept(v); 1760 value = value.accept(v);
1670 value?.parent = this; 1761 value?.parent = this;
1671 } 1762 }
1672 } 1763 }
1673 } 1764 }
1674 1765
1675 /// Read a static field, call a static getter, or tear off a static method. 1766 /// Read a static field, call a static getter, or tear off a static method.
1676 class StaticGet extends Expression { 1767 class StaticGet extends Expression {
1677 /// A static field, getter, or method (for tear-off). 1768 /// A static field, getter, or method (for tear-off).
1678 Member target; 1769 LinkedNodeBox targetBox;
1679 1770
1680 StaticGet(this.target); 1771 StaticGet(Member target) : this.byBox(getBoxOfMember(target));
1772
1773 StaticGet.byBox(this.targetBox);
1774
1775 Member get target => targetBox?.asMember;
1776
1777 void set target(Member target) {
1778 targetBox = getBoxOfMember(target);
1779 }
1681 1780
1682 DartType getStaticType(TypeEnvironment types) => target.getterType; 1781 DartType getStaticType(TypeEnvironment types) => target.getterType;
1683 1782
1684 accept(ExpressionVisitor v) => v.visitStaticGet(this); 1783 accept(ExpressionVisitor v) => v.visitStaticGet(this);
1685 1784
1686 visitChildren(Visitor v) { 1785 visitChildren(Visitor v) {
1687 target?.acceptReference(v); 1786 target?.acceptReference(v);
1688 } 1787 }
1689 1788
1690 transformChildren(Transformer v) {} 1789 transformChildren(Transformer v) {}
1691 } 1790 }
1692 1791
1693 /// Assign a static field or call a static setter. 1792 /// Assign a static field or call a static setter.
1694 /// 1793 ///
1695 /// Evaluates to the value of [value]. 1794 /// Evaluates to the value of [value].
1696 class StaticSet extends Expression { 1795 class StaticSet extends Expression {
1697 /// A mutable static field or a static setter. 1796 /// A mutable static field or a static setter.
1698 Member target; 1797 LinkedNodeBox targetBox;
1699 Expression value; 1798 Expression value;
1700 1799
1701 StaticSet(this.target, this.value) { 1800 StaticSet(Member target, Expression value)
1801 : this.byBox(getBoxOfMember(target), value);
1802
1803 StaticSet.byBox(this.targetBox, this.value) {
1702 value?.parent = this; 1804 value?.parent = this;
1703 } 1805 }
1704 1806
1807 Member get target => targetBox?.asMember;
1808
1809 void set target(Member target) {
1810 targetBox = getBoxOfMember(target);
1811 }
1812
1705 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types); 1813 DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
1706 1814
1707 accept(ExpressionVisitor v) => v.visitStaticSet(this); 1815 accept(ExpressionVisitor v) => v.visitStaticSet(this);
1708 1816
1709 visitChildren(Visitor v) { 1817 visitChildren(Visitor v) {
1710 target?.acceptReference(v); 1818 target?.acceptReference(v);
1711 value?.accept(v); 1819 value?.accept(v);
1712 } 1820 }
1713 1821
1714 transformChildren(Transformer v) { 1822 transformChildren(Transformer v) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1788 /// May be `null` if the target is a synthetic static member without a name. 1896 /// May be `null` if the target is a synthetic static member without a name.
1789 Name get name; 1897 Name get name;
1790 } 1898 }
1791 1899
1792 /// Expression of form `x.foo(y)`. 1900 /// Expression of form `x.foo(y)`.
1793 class MethodInvocation extends InvocationExpression { 1901 class MethodInvocation extends InvocationExpression {
1794 Expression receiver; 1902 Expression receiver;
1795 Name name; 1903 Name name;
1796 Arguments arguments; 1904 Arguments arguments;
1797 1905
1798 Procedure interfaceTarget; 1906 LinkedNodeBox interfaceTargetBox;
1799 1907
1800 MethodInvocation(this.receiver, this.name, this.arguments, 1908 MethodInvocation(Expression receiver, Name name, Arguments arguments,
1801 [this.interfaceTarget]) { 1909 [Procedure interfaceTarget])
1910 : this.byBox(receiver, name, arguments,
1911 getBoxOfMember(interfaceTarget));
1912
1913 MethodInvocation.byBox(
1914 this.receiver, this.name, this.arguments, this.interfaceTargetBox) {
1802 receiver?.parent = this; 1915 receiver?.parent = this;
1803 arguments?.parent = this; 1916 arguments?.parent = this;
1804 } 1917 }
1805 1918
1919 Procedure get interfaceTarget => interfaceTargetBox?.asProcedure;
1920
1921 void set interfaceTarget(Member target) {
1922 interfaceTargetBox = getBoxOfMember(target);
1923 }
1924
1806 DartType getStaticType(TypeEnvironment types) { 1925 DartType getStaticType(TypeEnvironment types) {
1807 if (interfaceTarget != null) { 1926 if (interfaceTarget != null) {
1808 if (types.isOverloadedArithmeticOperator(interfaceTarget)) { 1927 if (types.isOverloadedArithmeticOperator(interfaceTarget)) {
1809 return types.getTypeOfOverloadedArithmetic( 1928 return types.getTypeOfOverloadedArithmetic(
1810 receiver.getStaticType(types), 1929 receiver.getStaticType(types),
1811 arguments.positional[0].getStaticType(types)); 1930 arguments.positional[0].getStaticType(types));
1812 } 1931 }
1813 Class superclass = interfaceTarget.enclosingClass; 1932 Class superclass = interfaceTarget.enclosingClass;
1814 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types); 1933 var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types);
1815 var returnType = Substitution 1934 var returnType = Substitution
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1857 } 1976 }
1858 } 1977 }
1859 1978
1860 /// Expression of form `super.foo(x)`. 1979 /// Expression of form `super.foo(x)`.
1861 /// 1980 ///
1862 /// The provided arguments might not match the parameters of the target. 1981 /// The provided arguments might not match the parameters of the target.
1863 class SuperMethodInvocation extends InvocationExpression { 1982 class SuperMethodInvocation extends InvocationExpression {
1864 Name name; 1983 Name name;
1865 Arguments arguments; 1984 Arguments arguments;
1866 1985
1867 Procedure interfaceTarget; 1986 LinkedNodeBox interfaceTargetBox;
1868 1987
1869 SuperMethodInvocation(this.name, this.arguments, this.interfaceTarget) { 1988 SuperMethodInvocation(Name name, Arguments arguments,
1989 [Procedure interfaceTarget])
1990 : this.byBox(name, arguments, getBoxOfMember(interfaceTarget));
1991
1992 SuperMethodInvocation.byBox(
1993 this.name, this.arguments, this.interfaceTargetBox) {
1870 arguments?.parent = this; 1994 arguments?.parent = this;
1871 } 1995 }
1872 1996
1997 Procedure get interfaceTarget => interfaceTargetBox?.asProcedure;
1998
1999 void set interfaceTarget(Procedure target) {
2000 interfaceTargetBox = getBoxOfMember(target);
2001 }
2002
1873 DartType getStaticType(TypeEnvironment types) { 2003 DartType getStaticType(TypeEnvironment types) {
1874 if (interfaceTarget == null) return const DynamicType(); 2004 if (interfaceTarget == null) return const DynamicType();
1875 Class superclass = interfaceTarget.enclosingClass; 2005 Class superclass = interfaceTarget.enclosingClass;
1876 var receiverType = 2006 var receiverType =
1877 types.hierarchy.getTypeAsInstanceOf(types.thisType, superclass); 2007 types.hierarchy.getTypeAsInstanceOf(types.thisType, superclass);
1878 var returnType = Substitution 2008 var returnType = Substitution
1879 .fromInterfaceType(receiverType) 2009 .fromInterfaceType(receiverType)
1880 .substituteType(interfaceTarget.function.returnType); 2010 .substituteType(interfaceTarget.function.returnType);
1881 return Substitution 2011 return Substitution
1882 .fromPairs(interfaceTarget.function.typeParameters, arguments.types) 2012 .fromPairs(interfaceTarget.function.typeParameters, arguments.types)
(...skipping 13 matching lines...) Expand all
1896 arguments?.parent = this; 2026 arguments?.parent = this;
1897 } 2027 }
1898 } 2028 }
1899 } 2029 }
1900 2030
1901 /// Expression of form `foo(x)`, or `const foo(x)` if the target is an 2031 /// Expression of form `foo(x)`, or `const foo(x)` if the target is an
1902 /// external constant factory. 2032 /// external constant factory.
1903 /// 2033 ///
1904 /// The provided arguments might not match the parameters of the target. 2034 /// The provided arguments might not match the parameters of the target.
1905 class StaticInvocation extends InvocationExpression { 2035 class StaticInvocation extends InvocationExpression {
1906 Procedure target; 2036 LinkedNodeBox targetBox;
1907 Arguments arguments; 2037 Arguments arguments;
1908 2038
1909 /// True if this is a constant call to an external constant factory. 2039 /// True if this is a constant call to an external constant factory.
1910 bool isConst; 2040 bool isConst;
1911 2041
1912 Name get name => target?.name; 2042 Name get name => target?.name;
1913 2043
1914 StaticInvocation(this.target, this.arguments, {this.isConst: false}) { 2044 StaticInvocation(Procedure target, Arguments arguments, {bool isConst: false})
2045 : this.byBox(getBoxOfMember(target), arguments,
2046 isConst: isConst);
2047
2048 StaticInvocation.byBox(this.targetBox, this.arguments,
2049 {this.isConst: false}) {
1915 arguments?.parent = this; 2050 arguments?.parent = this;
1916 } 2051 }
1917 2052
2053 Procedure get target => targetBox?.asProcedure;
2054
2055 void set target(Procedure target) {
2056 targetBox = getBoxOfMember(target);
2057 }
2058
1918 DartType getStaticType(TypeEnvironment types) { 2059 DartType getStaticType(TypeEnvironment types) {
1919 return Substitution 2060 return Substitution
1920 .fromPairs(target.function.typeParameters, arguments.types) 2061 .fromPairs(target.function.typeParameters, arguments.types)
1921 .substituteType(target.function.returnType); 2062 .substituteType(target.function.returnType);
1922 } 2063 }
1923 2064
1924 accept(ExpressionVisitor v) => v.visitStaticInvocation(this); 2065 accept(ExpressionVisitor v) => v.visitStaticInvocation(this);
1925 2066
1926 visitChildren(Visitor v) { 2067 visitChildren(Visitor v) {
1927 target?.acceptReference(v); 2068 target?.acceptReference(v);
1928 arguments?.accept(v); 2069 arguments?.accept(v);
1929 } 2070 }
1930 2071
1931 transformChildren(Transformer v) { 2072 transformChildren(Transformer v) {
1932 if (arguments != null) { 2073 if (arguments != null) {
1933 arguments = arguments.accept(v); 2074 arguments = arguments.accept(v);
1934 arguments?.parent = this; 2075 arguments?.parent = this;
1935 } 2076 }
1936 } 2077 }
1937 } 2078 }
1938 2079
1939 /// Expression of form `new Foo(x)` or `const Foo(x)`. 2080 /// Expression of form `new Foo(x)` or `const Foo(x)`.
1940 /// 2081 ///
1941 /// The provided arguments might not match the parameters of the target. 2082 /// The provided arguments might not match the parameters of the target.
1942 // 2083 //
1943 // DESIGN TODO: Should we pass type arguments in a separate field 2084 // DESIGN TODO: Should we pass type arguments in a separate field
1944 // `classTypeArguments`? They are quite different from type arguments to 2085 // `classTypeArguments`? They are quite different from type arguments to
1945 // generic functions. 2086 // generic functions.
1946 class ConstructorInvocation extends InvocationExpression { 2087 class ConstructorInvocation extends InvocationExpression {
1947 Constructor target; 2088 LinkedNodeBox targetBox;
1948 Arguments arguments; 2089 Arguments arguments;
1949 bool isConst; 2090 bool isConst;
1950 2091
1951 Name get name => target?.name; 2092 Name get name => target?.name;
1952 2093
1953 ConstructorInvocation(this.target, this.arguments, {this.isConst: false}) { 2094 ConstructorInvocation(Constructor target, Arguments arguments,
2095 {bool isConst: false})
2096 : this.byBox(getBoxOfMember(target), arguments,
2097 isConst: isConst);
2098
2099 ConstructorInvocation.byBox(this.targetBox, this.arguments,
2100 {this.isConst: false}) {
1954 arguments?.parent = this; 2101 arguments?.parent = this;
1955 } 2102 }
1956 2103
2104 Constructor get target => targetBox?.asConstructor;
2105
2106 void set target(Constructor target) {
2107 targetBox = getBoxOfMember(target);
2108 }
2109
1957 DartType getStaticType(TypeEnvironment types) { 2110 DartType getStaticType(TypeEnvironment types) {
1958 return arguments.types.isEmpty 2111 return arguments.types.isEmpty
1959 ? target.enclosingClass.rawType 2112 ? target.enclosingClass.rawType
1960 : new InterfaceType(target.enclosingClass, arguments.types); 2113 : new InterfaceType(target.enclosingClass, arguments.types);
1961 } 2114 }
1962 2115
1963 accept(ExpressionVisitor v) => v.visitConstructorInvocation(this); 2116 accept(ExpressionVisitor v) => v.visitConstructorInvocation(this);
1964 2117
1965 visitChildren(Visitor v) { 2118 visitChildren(Visitor v) {
1966 target?.acceptReference(v); 2119 target?.acceptReference(v);
(...skipping 1226 matching lines...) Expand 10 before | Expand all | Expand 10 after
3193 /// statically resolved references are represented in nameless form. 3346 /// statically resolved references are represented in nameless form.
3194 /// 3347 ///
3195 /// [Name]s are immutable and compare based on structural equality, and they 3348 /// [Name]s are immutable and compare based on structural equality, and they
3196 /// are not AST nodes. 3349 /// are not AST nodes.
3197 /// 3350 ///
3198 /// The [toString] method returns a human-readable string that includes the 3351 /// The [toString] method returns a human-readable string that includes the
3199 /// library name for private names; uniqueness is not guaranteed. 3352 /// library name for private names; uniqueness is not guaranteed.
3200 abstract class Name implements Node { 3353 abstract class Name implements Node {
3201 final int hashCode; 3354 final int hashCode;
3202 final String name; 3355 final String name;
3356 LinkedNodeBox get libraryName;
3203 Library get library; 3357 Library get library;
3204 bool get isPrivate; 3358 bool get isPrivate;
3205 3359
3206 Name._internal(this.hashCode, this.name); 3360 Name._internal(this.hashCode, this.name);
3207 3361
3208 factory Name(String name, [Library library]) { 3362 factory Name(String name, [Library library]) =>
3363 new Name.byReference(name, library?.box);
3364
3365 factory Name.byReference(String name, LinkedNodeBox libraryName) {
3209 /// Use separate subclasses for the public and private case to save memory 3366 /// Use separate subclasses for the public and private case to save memory
3210 /// for public names. 3367 /// for public names.
3211 if (name.startsWith('_')) { 3368 if (name.startsWith('_')) {
3212 assert(library != null); 3369 assert(libraryName != null);
3213 return new _PrivateName(name, library); 3370 return new _PrivateName(name, libraryName);
3214 } else { 3371 } else {
3215 return new _PublicName(name); 3372 return new _PublicName(name);
3216 } 3373 }
3217 } 3374 }
3218 3375
3219 bool operator ==(other) { 3376 bool operator ==(other) {
3220 return other is Name && name == other.name && library == other.library; 3377 return other is Name && name == other.name && library == other.library;
3221 } 3378 }
3222 3379
3223 accept(Visitor v) => v.visitName(this); 3380 accept(Visitor v) => v.visitName(this);
3224 3381
3225 visitChildren(Visitor v) { 3382 visitChildren(Visitor v) {
3226 // DESIGN TODO: Should we visit the library as a library reference? 3383 // DESIGN TODO: Should we visit the library as a library reference?
3227 } 3384 }
3228 } 3385 }
3229 3386
3230 class _PrivateName extends Name { 3387 class _PrivateName extends Name {
3231 final Library library; 3388 final LinkedNodeBox libraryName;
3232 bool get isPrivate => true; 3389 bool get isPrivate => true;
3233 3390
3234 _PrivateName(String name, Library library) 3391 _PrivateName(String name, LinkedNodeBox libraryName)
3235 : this.library = library, 3392 : this.libraryName = libraryName,
3236 super._internal(_computeHashCode(name, library), name); 3393 super._internal(_computeHashCode(name, libraryName), name);
3237 3394
3238 String toString() => library != null ? '$library::$name' : name; 3395 String toString() => library != null ? '$library::$name' : name;
3239 3396
3240 static int _computeHashCode(String name, Library library) { 3397 Library get library => libraryName.asLibrary;
3241 return 131 * name.hashCode + 17 * library.hashCode; 3398
3399 static int _computeHashCode(String name, LinkedNodeBox libraryName) {
3400 return 131 * name.hashCode + 17 * libraryName.hashCode;
3242 } 3401 }
3243 } 3402 }
3244 3403
3245 class _PublicName extends Name { 3404 class _PublicName extends Name {
3405 LinkedNodeBox get libraryName => null;
3246 Library get library => null; 3406 Library get library => null;
3247 bool get isPrivate => false; 3407 bool get isPrivate => false;
3248 3408
3249 _PublicName(String name) : super._internal(name.hashCode, name); 3409 _PublicName(String name) : super._internal(name.hashCode, name);
3250 3410
3251 String toString() => name; 3411 String toString() => name;
3252 } 3412 }
3253 3413
3254 // ------------------------------------------------------------------------ 3414 // ------------------------------------------------------------------------
3255 // TYPES 3415 // TYPES
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3315 3475
3316 const BottomType(); 3476 const BottomType();
3317 3477
3318 accept(DartTypeVisitor v) => v.visitBottomType(this); 3478 accept(DartTypeVisitor v) => v.visitBottomType(this);
3319 visitChildren(Visitor v) {} 3479 visitChildren(Visitor v) {}
3320 3480
3321 bool operator ==(Object other) => other is BottomType; 3481 bool operator ==(Object other) => other is BottomType;
3322 } 3482 }
3323 3483
3324 class InterfaceType extends DartType { 3484 class InterfaceType extends DartType {
3325 final Class classNode; 3485 final LinkedNodeBox className;
3326 final List<DartType> typeArguments; 3486 final List<DartType> typeArguments;
3327 3487
3328 /// The [typeArguments] list must not be modified after this call. If the 3488 /// The [typeArguments] list must not be modified after this call. If the
3329 /// list is omitted, 'dynamic' type arguments are filled in. 3489 /// list is omitted, 'dynamic' type arguments are filled in.
3330 InterfaceType(Class classNode, [List<DartType> typeArguments]) 3490 InterfaceType(Class classNode, [List<DartType> typeArguments])
3331 : this.classNode = classNode, 3491 : this.byBox(getBoxOfClass(classNode),
3332 this.typeArguments = typeArguments ?? _defaultTypeArguments(classNode); 3492 typeArguments ?? _defaultTypeArguments(classNode));
3493
3494 InterfaceType.byBox(this.className, this.typeArguments);
3495
3496 Class get classNode => className.asClass;
3333 3497
3334 static List<DartType> _defaultTypeArguments(Class classNode) { 3498 static List<DartType> _defaultTypeArguments(Class classNode) {
3335 if (classNode.typeParameters.length == 0) { 3499 if (classNode.typeParameters.length == 0) {
3336 // Avoid allocating a list in this very common case. 3500 // Avoid allocating a list in this very common case.
3337 return const <DartType>[]; 3501 return const <DartType>[];
3338 } else { 3502 } else {
3339 return new List<DartType>.filled( 3503 return new List<DartType>.filled(
3340 classNode.typeParameters.length, const DynamicType()); 3504 classNode.typeParameters.length, const DynamicType());
3341 } 3505 }
3342 } 3506 }
3343 3507
3344 accept(DartTypeVisitor v) => v.visitInterfaceType(this); 3508 accept(DartTypeVisitor v) => v.visitInterfaceType(this);
3345 3509
3346 visitChildren(Visitor v) { 3510 visitChildren(Visitor v) {
3347 classNode.acceptReference(v); 3511 classNode.acceptReference(v);
3348 visitList(typeArguments, v); 3512 visitList(typeArguments, v);
3349 } 3513 }
3350 3514
3351 bool operator ==(Object other) { 3515 bool operator ==(Object other) {
3352 if (identical(this, other)) return true; 3516 if (identical(this, other)) return true;
3353 if (other is InterfaceType) { 3517 if (other is InterfaceType) {
3354 if (classNode != other.classNode) return false; 3518 if (className != other.className) return false;
3355 if (typeArguments.length != other.typeArguments.length) return false; 3519 if (typeArguments.length != other.typeArguments.length) return false;
3356 for (int i = 0; i < typeArguments.length; ++i) { 3520 for (int i = 0; i < typeArguments.length; ++i) {
3357 if (typeArguments[i] != other.typeArguments[i]) return false; 3521 if (typeArguments[i] != other.typeArguments[i]) return false;
3358 } 3522 }
3359 return true; 3523 return true;
3360 } else { 3524 } else {
3361 return false; 3525 return false;
3362 } 3526 }
3363 } 3527 }
3364 3528
3365 int get hashCode { 3529 int get hashCode {
3366 int hash = 0x3fffffff & classNode.hashCode; 3530 int hash = 0x3fffffff & className.hashCode;
3367 for (int i = 0; i < typeArguments.length; ++i) { 3531 for (int i = 0; i < typeArguments.length; ++i) {
3368 hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode)); 3532 hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
3369 } 3533 }
3370 return hash; 3534 return hash;
3371 } 3535 }
3372 } 3536 }
3373 3537
3374 /// A possibly generic function type. 3538 /// A possibly generic function type.
3375 class FunctionType extends DartType { 3539 class FunctionType extends DartType {
3376 final List<TypeParameter> typeParameters; 3540 final List<TypeParameter> typeParameters;
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
3544 transformChildren(Transformer v) { 3708 transformChildren(Transformer v) {
3545 bound = v.visitDartType(bound); 3709 bound = v.visitDartType(bound);
3546 } 3710 }
3547 3711
3548 /// Returns a possibly synthesized name for this type parameter, consistent 3712 /// Returns a possibly synthesized name for this type parameter, consistent
3549 /// with the names used across all [toString] calls. 3713 /// with the names used across all [toString] calls.
3550 String toString() => debugQualifiedTypeParameterName(this); 3714 String toString() => debugQualifiedTypeParameterName(this);
3551 } 3715 }
3552 3716
3553 class Supertype extends Node { 3717 class Supertype extends Node {
3554 final Class classNode; 3718 final LinkedNodeBox className;
3555 final List<DartType> typeArguments; 3719 final List<DartType> typeArguments;
3556 3720
3557 Supertype(this.classNode, this.typeArguments); 3721 Supertype(Class classNode, List<DartType> typeArguments)
3722 : this.byBox(getBoxOfClass(classNode), typeArguments);
3723
3724 Supertype.byBox(this.className, this.typeArguments);
3725
3726 Class get classNode => className.asClass;
3558 3727
3559 accept(Visitor v) => v.visitSupertype(this); 3728 accept(Visitor v) => v.visitSupertype(this);
3560 3729
3561 visitChildren(Visitor v) { 3730 visitChildren(Visitor v) {
3562 classNode.acceptReference(v); 3731 classNode.acceptReference(v);
3563 visitList(typeArguments, v); 3732 visitList(typeArguments, v);
3564 } 3733 }
3565 3734
3566 InterfaceType get asInterfaceType { 3735 InterfaceType get asInterfaceType {
3567 return new InterfaceType(classNode, typeArguments); 3736 return new InterfaceType(classNode, typeArguments);
3568 } 3737 }
3569 3738
3570 bool operator ==(Object other) { 3739 bool operator ==(Object other) {
3571 if (identical(this, other)) return true; 3740 if (identical(this, other)) return true;
3572 if (other is Supertype) { 3741 if (other is Supertype) {
3573 if (classNode != other.classNode) return false; 3742 if (className != other.className) return false;
3574 if (typeArguments.length != other.typeArguments.length) return false; 3743 if (typeArguments.length != other.typeArguments.length) return false;
3575 for (int i = 0; i < typeArguments.length; ++i) { 3744 for (int i = 0; i < typeArguments.length; ++i) {
3576 if (typeArguments[i] != other.typeArguments[i]) return false; 3745 if (typeArguments[i] != other.typeArguments[i]) return false;
3577 } 3746 }
3578 return true; 3747 return true;
3579 } else { 3748 } else {
3580 return false; 3749 return false;
3581 } 3750 }
3582 } 3751 }
3583 3752
3584 int get hashCode { 3753 int get hashCode {
3585 int hash = 0x3fffffff & classNode.hashCode; 3754 int hash = 0x3fffffff & className.hashCode;
3586 for (int i = 0; i < typeArguments.length; ++i) { 3755 for (int i = 0; i < typeArguments.length; ++i) {
3587 hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode)); 3756 hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
3588 } 3757 }
3589 return hash; 3758 return hash;
3590 } 3759 }
3591 } 3760 }
3592 3761
3593 // ------------------------------------------------------------------------ 3762 // ------------------------------------------------------------------------
3594 // PROGRAM 3763 // PROGRAM
3595 // ------------------------------------------------------------------------ 3764 // ------------------------------------------------------------------------
3596 3765
3597 /// A way to bundle up all the libraries in a program. 3766 /// A way to bundle up all the libraries in a program.
3598 class Program extends TreeNode { 3767 class Program extends TreeNode {
3768 final CanonicalName root = new CanonicalName.root();
3769
3599 final List<Library> libraries; 3770 final List<Library> libraries;
3600 3771
3601 /// Map from a source file uri to a line-starts table and source code. 3772 /// Map from a source file uri to a line-starts table and source code.
3602 /// Given a source file uri and a offset in that file one can translate 3773 /// Given a source file uri and a offset in that file one can translate
3603 /// it to a line:column position in that file. 3774 /// it to a line:column position in that file.
3604 final Map<String, Source> uriToSource; 3775 final Map<String, Source> uriToSource;
3605 3776
3606 /// Reference to the main method in one of the libraries. 3777 /// Reference to the main method in one of the libraries.
3607 Procedure mainMethod; 3778 LinkedNodeBox mainMethodName;
3608 3779
3609 Program([List<Library> libraries, Map<String, Source> uriToSource]) 3780 Program([List<Library> libraries, Map<String, Source> uriToSource])
3610 : libraries = libraries ?? <Library>[], 3781 : libraries = libraries ?? <Library>[],
3611 uriToSource = uriToSource ?? <String, Source>{} { 3782 uriToSource = uriToSource ?? <String, Source>{} {
3612 setParents(libraries, this); 3783 setParents(this.libraries, this);
3784 }
3785
3786 void computeCanonicalNames() {
3787 for (var library in libraries) {
3788 root.getChildFromUri(library.importUri).bindTo(library.box);
3789 library.computeCanonicalNames();
3790 }
3791 }
3792
3793 void unbindCanonicalNames() {
3794 root.unbindAll();
3795 }
3796
3797 Procedure get mainMethod => mainMethodName?.asProcedure;
3798
3799 void set mainMethod(Procedure main) {
3800 mainMethodName = getBoxOfMember(main);
3613 } 3801 }
3614 3802
3615 accept(TreeVisitor v) => v.visitProgram(this); 3803 accept(TreeVisitor v) => v.visitProgram(this);
3616 3804
3617 visitChildren(Visitor v) { 3805 visitChildren(Visitor v) {
3618 visitList(libraries, v); 3806 visitList(libraries, v);
3619 mainMethod?.acceptReference(v); 3807 mainMethod?.acceptReference(v);
3620 } 3808 }
3621 3809
3622 transformChildren(Transformer v) { 3810 transformChildren(Transformer v) {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
3745 } 3933 }
3746 } 3934 }
3747 } 3935 }
3748 3936
3749 class Source { 3937 class Source {
3750 final List<int> lineStarts; 3938 final List<int> lineStarts;
3751 final String source; 3939 final String source;
3752 3940
3753 Source(this.lineStarts, this.source); 3941 Source(this.lineStarts, this.source);
3754 } 3942 }
3943
3944 /// Returns the canonical name of [member], or throws an exception if the
3945 /// member has not been assigned a canonical name yet.
3946 ///
3947 /// Returns `null` if the member is `null`.
3948 LinkedNodeBox getBoxOfMember(Member member) {
3949 return member?.box;
3950 }
3951
3952 /// Returns the canonical name of [class_], or throws an exception if the
3953 /// class has not been assigned a canonical name yet.
3954 ///
3955 /// Returns `null` if the class is `null`.
3956 LinkedNodeBox getBoxOfClass(Class class_) {
3957 return class_?.box;
3958 }
3959
3960 /// Returns the canonical name of [library], or throws an exception if the
3961 /// library has not been assigned a canonical name yet.
3962 ///
3963 /// Returns `null` if the library is `null`.
3964 LinkedNodeBox getBoxOfLibrary(Library library) {
3965 return library?.box;
3966 }
3967
3968 /// Returns the canonical name of [member], or throws an exception if the
3969 /// member has not been assigned a canonical name yet.
3970 ///
3971 /// Returns `null` if the member is `null`.
3972 CanonicalName getCanonicalNameOfMember(Member member) {
3973 if (member == null) return null;
3974 if (member.canonicalName == null) {
3975 throw '$member has no canonical name';
3976 }
3977 return member.canonicalName;
3978 }
3979
3980 /// Returns the canonical name of [class_], or throws an exception if the
3981 /// class has not been assigned a canonical name yet.
3982 ///
3983 /// Returns `null` if the class is `null`.
3984 CanonicalName getCanonicalNameOfClass(Class class_) {
3985 if (class_ == null) return null;
3986 if (class_.canonicalName == null) {
3987 throw '$class_ has no canonical name';
3988 }
3989 return class_.canonicalName;
3990 }
3991
3992 /// Returns the canonical name of [library], or throws an exception if the
3993 /// library has not been assigned a canonical name yet.
3994 ///
3995 /// Returns `null` if the library is `null`.
3996 CanonicalName getCanonicalNameOfLibrary(Library library) {
3997 if (library == null) return null;
3998 if (library.canonicalName == null) {
3999 throw '$library has no canonical name';
4000 }
4001 return library.canonicalName;
4002 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698