| 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 |