OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 import 'package:front_end/src/base/instrumentation.dart'; | 5 import 'package:front_end/src/base/instrumentation.dart'; |
6 import 'package:front_end/src/fasta/errors.dart' show internalError; | 6 import 'package:front_end/src/fasta/errors.dart' show internalError; |
7 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; | 7 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; |
8 import 'package:front_end/src/fasta/names.dart' show callName; | 8 import 'package:front_end/src/fasta/names.dart' show callName; |
9 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart'; | 9 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart'; |
10 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
; | 10 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 final ClassHierarchy classHierarchy; | 216 final ClassHierarchy classHierarchy; |
217 | 217 |
218 final Instrumentation instrumentation; | 218 final Instrumentation instrumentation; |
219 | 219 |
220 final TypeSchemaEnvironment typeSchemaEnvironment; | 220 final TypeSchemaEnvironment typeSchemaEnvironment; |
221 | 221 |
222 final TypeInferenceListener listener; | 222 final TypeInferenceListener listener; |
223 | 223 |
224 final InterfaceType thisType; | 224 final InterfaceType thisType; |
225 | 225 |
226 /// The [FieldNode] whose initializer will be type inferred using this | 226 /// The [AccessorNode] whose type will be type inferred using this |
227 /// [TypeInferrerImpl], or `null` if this [TypeInferrerImpl] will be used to | 227 /// [TypeInferrerImpl], or `null` if this [TypeInferrerImpl] will be used to |
228 /// infer types outside the scope of a field initializer. | 228 /// infer types outside the scope of top level type inference. |
229 final FieldNode fieldNode; | 229 final AccessorNode accessorNode; |
230 | 230 |
231 /// Context information for the current closure, or `null` if we are not | 231 /// Context information for the current closure, or `null` if we are not |
232 /// inside a closure. | 232 /// inside a closure. |
233 ClosureContext closureContext; | 233 ClosureContext closureContext; |
234 | 234 |
235 /// When performing top level inference, this boolean is set to `false` if we | 235 /// When performing top level inference, this boolean is set to `false` if we |
236 /// discover that the type of the object is not immediately evident. | 236 /// discover that the type of the object is not immediately evident. |
237 /// | 237 /// |
238 /// Not used when performing local inference. | 238 /// Not used when performing local inference. |
239 bool isImmediatelyEvident = true; | 239 bool isImmediatelyEvident = true; |
240 | 240 |
241 List<FieldNode> _dryRunDependencies; | 241 List<AccessorNode> _dryRunDependencies; |
242 | 242 |
243 TypeInferrerImpl(this.engine, this.uri, this.listener, bool topLevel, | 243 TypeInferrerImpl(this.engine, this.uri, this.listener, bool topLevel, |
244 this.thisType, this.fieldNode) | 244 this.thisType, this.accessorNode) |
245 : coreTypes = engine.coreTypes, | 245 : coreTypes = engine.coreTypes, |
246 strongMode = engine.strongMode, | 246 strongMode = engine.strongMode, |
247 classHierarchy = engine.classHierarchy, | 247 classHierarchy = engine.classHierarchy, |
248 instrumentation = topLevel ? null : engine.instrumentation, | 248 instrumentation = topLevel ? null : engine.instrumentation, |
249 typeSchemaEnvironment = engine.typeSchemaEnvironment, | 249 typeSchemaEnvironment = engine.typeSchemaEnvironment, |
250 isTopLevel = topLevel; | 250 isTopLevel = topLevel; |
251 | 251 |
252 /// Indicates whether we are currently doing a "dry run" in order to collect | 252 /// Indicates whether we are currently doing a "dry run" in order to collect |
253 /// type inference dependencies. | 253 /// type inference dependencies. |
254 bool get isDryRun => _dryRunDependencies != null; | 254 bool get isDryRun => _dryRunDependencies != null; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 propertySet.interfaceTarget = interfaceMember; | 344 propertySet.interfaceTarget = interfaceMember; |
345 return interfaceMember; | 345 return interfaceMember; |
346 } else { | 346 } else { |
347 throw internalError( | 347 throw internalError( |
348 'Unexpected propertySet type: ${propertySet.runtimeType}'); | 348 'Unexpected propertySet type: ${propertySet.runtimeType}'); |
349 } | 349 } |
350 } | 350 } |
351 | 351 |
352 /// Ends a dry run started by [startDryRun] and returns the collected | 352 /// Ends a dry run started by [startDryRun] and returns the collected |
353 /// dependencies. | 353 /// dependencies. |
354 List<FieldNode> finishDryRun() { | 354 List<AccessorNode> finishDryRun() { |
355 var dryRunDependencies = _dryRunDependencies; | 355 var dryRunDependencies = _dryRunDependencies; |
356 _dryRunDependencies = null; | 356 _dryRunDependencies = null; |
357 return dryRunDependencies; | 357 return dryRunDependencies; |
358 } | 358 } |
359 | 359 |
360 FunctionType getCalleeFunctionType(Member interfaceMember, | 360 FunctionType getCalleeFunctionType(Member interfaceMember, |
361 DartType receiverType, Name methodName, bool followCall) { | 361 DartType receiverType, Name methodName, bool followCall) { |
362 var type = getCalleeType(interfaceMember, receiverType, methodName); | 362 var type = getCalleeType(interfaceMember, receiverType, methodName); |
363 if (type is FunctionType) { | 363 if (type is FunctionType) { |
364 return type; | 364 return type; |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 // First infer the receiver so we can look up the getter that was invoked. | 641 // First infer the receiver so we can look up the getter that was invoked. |
642 var receiverType = inferExpression(receiver, null, true); | 642 var receiverType = inferExpression(receiver, null, true); |
643 Member interfaceMember = | 643 Member interfaceMember = |
644 findInterfaceMember(receiverType, desugaredGet.name, fileOffset); | 644 findInterfaceMember(receiverType, desugaredGet.name, fileOffset); |
645 if (isTopLevel && | 645 if (isTopLevel && |
646 ((interfaceMember is Procedure && | 646 ((interfaceMember is Procedure && |
647 interfaceMember.kind == ProcedureKind.Getter) || | 647 interfaceMember.kind == ProcedureKind.Getter) || |
648 interfaceMember is Field)) { | 648 interfaceMember is Field)) { |
649 if (TypeInferenceEngineImpl.fullTopLevelInference) { | 649 if (TypeInferenceEngineImpl.fullTopLevelInference) { |
650 if (interfaceMember is KernelField) { | 650 if (interfaceMember is KernelField) { |
651 var fieldNode = KernelMember.getFieldNode(interfaceMember); | 651 var accessorNode = KernelMember.getAccessorNode(interfaceMember); |
652 if (fieldNode != null) { | 652 if (accessorNode != null) { |
653 engine.inferFieldFused(fieldNode, this.fieldNode); | 653 engine.inferAccessorFused(accessorNode, this.accessorNode); |
654 } | 654 } |
655 } | 655 } |
656 } else { | 656 } else { |
657 // References to fields and getters can't be relied upon for top level | 657 // References to fields and getters can't be relied upon for top level |
658 // inference. | 658 // inference. |
659 recordNotImmediatelyEvident(fileOffset); | 659 recordNotImmediatelyEvident(fileOffset); |
660 } | 660 } |
661 } | 661 } |
662 desugaredGet.interfaceTarget = interfaceMember; | 662 desugaredGet.interfaceTarget = interfaceMember; |
663 var inferredType = | 663 var inferredType = |
(...skipping 19 matching lines...) Expand all Loading... |
683 } | 683 } |
684 return returnType; | 684 return returnType; |
685 } | 685 } |
686 | 686 |
687 /// Performs type inference on the given [statement]. | 687 /// Performs type inference on the given [statement]. |
688 /// | 688 /// |
689 /// Derived classes should override this method with logic that dispatches on | 689 /// Derived classes should override this method with logic that dispatches on |
690 /// the statement type and calls the appropriate specialized "infer" method. | 690 /// the statement type and calls the appropriate specialized "infer" method. |
691 void inferStatement(Statement statement); | 691 void inferStatement(Statement statement); |
692 | 692 |
693 /// Records that the field represented by [fieldNode] is a dependency of the | 693 /// Records that the accessor represented by [accessorNode] is a dependency of |
694 /// static field for which we are currently doing a dry run of type inference. | 694 /// the accessor for which we are currently doing a dry run of type inference. |
695 /// | 695 /// |
696 /// May only be called if a dry run is in progress. | 696 /// May only be called if a dry run is in progress. |
697 void recordDryRunDependency(FieldNode fieldNode) { | 697 void recordDryRunDependency(AccessorNode accessorNode) { |
698 listener.recordDependency(fieldNode); | 698 listener.recordDependency(accessorNode); |
699 _dryRunDependencies.add(fieldNode); | 699 _dryRunDependencies.add(accessorNode); |
700 } | 700 } |
701 | 701 |
702 void recordNotImmediatelyEvident(int fileOffset) { | 702 void recordNotImmediatelyEvident(int fileOffset) { |
703 assert(isTopLevel); | 703 assert(isTopLevel); |
704 isImmediatelyEvident = false; | 704 isImmediatelyEvident = false; |
705 // TODO(paulberry): report an error. | 705 // TODO(paulberry): report an error. |
706 } | 706 } |
707 | 707 |
708 /// Begins a dry run of type inference, in which the goal is to collect the | 708 /// Begins a dry run of type inference, in which the goal is to collect the |
709 /// dependencies of a given field. | 709 /// dependencies of a given accessor. |
710 void startDryRun() { | 710 void startDryRun() { |
711 assert(_dryRunDependencies == null); | 711 assert(_dryRunDependencies == null); |
712 _dryRunDependencies = <FieldNode>[]; | 712 _dryRunDependencies = <AccessorNode>[]; |
713 } | 713 } |
714 | 714 |
715 DartType wrapFutureOrType(DartType type) { | 715 DartType wrapFutureOrType(DartType type) { |
716 if (type is InterfaceType && | 716 if (type is InterfaceType && |
717 identical(type.classNode, coreTypes.futureOrClass)) { | 717 identical(type.classNode, coreTypes.futureOrClass)) { |
718 return type; | 718 return type; |
719 } | 719 } |
720 // TODO(paulberry): If [type] is a subtype of `Future`, should we just | 720 // TODO(paulberry): If [type] is a subtype of `Future`, should we just |
721 // return it unmodified? | 721 // return it unmodified? |
722 return new InterfaceType( | 722 return new InterfaceType( |
(...skipping 17 matching lines...) Expand all Loading... |
740 void _forEachArgument( | 740 void _forEachArgument( |
741 Arguments arguments, void callback(String name, Expression expression)) { | 741 Arguments arguments, void callback(String name, Expression expression)) { |
742 for (var expression in arguments.positional) { | 742 for (var expression in arguments.positional) { |
743 callback(null, expression); | 743 callback(null, expression); |
744 } | 744 } |
745 for (var namedExpression in arguments.named) { | 745 for (var namedExpression in arguments.named) { |
746 callback(namedExpression.name, namedExpression.value); | 746 callback(namedExpression.name, namedExpression.value); |
747 } | 747 } |
748 } | 748 } |
749 } | 749 } |
OLD | NEW |