OLD | NEW |
---|---|
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// ----------------------------------------------------------------------- | 5 /// ----------------------------------------------------------------------- |
6 /// ERROR HANDLING | 6 /// ERROR HANDLING |
7 /// ----------------------------------------------------------------------- | 7 /// ----------------------------------------------------------------------- |
8 /// | 8 /// |
9 /// As a rule of thumb, errors that can be detected statically are handled by | 9 /// As a rule of thumb, errors that can be detected statically are handled by |
10 /// the frontend, typically by translating the erroneous code into a 'throw' or | 10 /// the frontend, typically by translating the erroneous code into a 'throw' or |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
49 /// has to update parent pointers manually. | 49 /// has to update parent pointers manually. |
50 /// | 50 /// |
51 library kernel.ast; | 51 library kernel.ast; |
52 | 52 |
53 import 'visitor.dart'; | 53 import 'visitor.dart'; |
54 export 'visitor.dart'; | 54 export 'visitor.dart'; |
55 | 55 |
56 import 'type_propagation/type_propagation.dart'; | 56 import 'type_propagation/type_propagation.dart'; |
57 export 'type_propagation/type_propagation.dart'; | 57 export 'type_propagation/type_propagation.dart'; |
58 | 58 |
59 import 'canonical_name.dart' show CanonicalName; | |
60 export 'canonical_name.dart' show CanonicalName; | |
61 | |
59 import 'transformations/flags.dart'; | 62 import 'transformations/flags.dart'; |
60 import 'text/ast_to_text.dart'; | 63 import 'text/ast_to_text.dart'; |
61 import 'type_algebra.dart'; | 64 import 'type_algebra.dart'; |
62 import 'type_environment.dart'; | 65 import 'type_environment.dart'; |
63 | 66 |
64 /// Any type of node in the IR. | 67 /// Any type of node in the IR. |
65 abstract class Node { | 68 abstract class Node { |
66 const Node(); | 69 const Node(); |
67 | 70 |
68 accept(Visitor v); | 71 accept(Visitor v); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |