| 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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /// This file declares a "shadow hierarchy" of concrete classes which extend | 5 /// This file declares a "shadow hierarchy" of concrete classes which extend |
| 6 /// the kernel class hierarchy, adding methods and fields needed by the | 6 /// the kernel class hierarchy, adding methods and fields needed by the |
| 7 /// BodyBuilder. | 7 /// BodyBuilder. |
| 8 /// | 8 /// |
| 9 /// Instances of these classes may be created using the factory methods in | 9 /// Instances of these classes may be created using the factory methods in |
| 10 /// `ast_factory.dart`. | 10 /// `ast_factory.dart`. |
| 11 /// | 11 /// |
| 12 /// Note that these classes represent the Dart language prior to desugaring. | 12 /// Note that these classes represent the Dart language prior to desugaring. |
| 13 /// When a single Dart construct desugars to a tree containing multiple kernel | 13 /// When a single Dart construct desugars to a tree containing multiple kernel |
| 14 /// AST nodes, the shadow class extends the kernel object at the top of the | 14 /// AST nodes, the shadow class extends the kernel object at the top of the |
| 15 /// desugared tree. | 15 /// desugared tree. |
| 16 /// | 16 /// |
| 17 /// This means that in some cases multiple shadow classes may extend the same | 17 /// This means that in some cases multiple shadow classes may extend the same |
| 18 /// kernel class, because multiple constructs in Dart may desugar to a tree | 18 /// kernel class, because multiple constructs in Dart may desugar to a tree |
| 19 /// with the same kind of root node. | 19 /// with the same kind of root node. |
| 20 import 'package:front_end/src/base/instrumentation.dart'; | 20 import 'package:front_end/src/base/instrumentation.dart'; |
| 21 import 'package:front_end/src/fasta/type_inference/dependency_collector.dart'; | 21 import 'package:front_end/src/fasta/type_inference/dependency_collector.dart'; |
| 22 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart'; | 22 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart'; |
| 23 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
; | 23 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
; |
| 24 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'; | 24 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'; |
| 25 import 'package:front_end/src/fasta/type_inference/type_promotion.dart'; | 25 import 'package:front_end/src/fasta/type_inference/type_promotion.dart'; |
| 26 import 'package:front_end/src/fasta/type_inference/type_schema.dart'; | 26 import 'package:front_end/src/fasta/type_inference/type_schema.dart'; |
| 27 import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart'
; | 27 import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart'
; |
| 28 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart'
; | |
| 29 import 'package:kernel/ast.dart' | 28 import 'package:kernel/ast.dart' |
| 30 hide InvalidExpression, InvalidInitializer, InvalidStatement; | 29 hide InvalidExpression, InvalidInitializer, InvalidStatement; |
| 31 import 'package:kernel/frontend/accessors.dart'; | 30 import 'package:kernel/frontend/accessors.dart'; |
| 32 import 'package:kernel/type_algebra.dart'; | |
| 33 import 'package:kernel/type_environment.dart'; | 31 import 'package:kernel/type_environment.dart'; |
| 34 | 32 |
| 35 import '../errors.dart' show internalError; | 33 import '../errors.dart' show internalError; |
| 36 | 34 |
| 37 /// Computes the return type of a (possibly factory) constructor. | 35 /// Computes the return type of a (possibly factory) constructor. |
| 38 InterfaceType computeConstructorReturnType(Member constructor) { | 36 InterfaceType computeConstructorReturnType(Member constructor) { |
| 39 if (constructor is Constructor) { | 37 if (constructor is Constructor) { |
| 40 return constructor.enclosingClass.thisType; | 38 return constructor.enclosingClass.thisType; |
| 41 } else { | 39 } else { |
| 42 return constructor.function.returnType; | 40 return constructor.function.returnType; |
| (...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 } | 706 } |
| 709 inferrer.inferStatement(body); | 707 inferrer.inferStatement(body); |
| 710 inferrer.listener.forInStatementExit(this); | 708 inferrer.listener.forInStatementExit(this); |
| 711 } | 709 } |
| 712 } | 710 } |
| 713 | 711 |
| 714 /// Concrete shadow object representing a local function declaration in kernel | 712 /// Concrete shadow object representing a local function declaration in kernel |
| 715 /// form. | 713 /// form. |
| 716 class KernelFunctionDeclaration extends FunctionDeclaration | 714 class KernelFunctionDeclaration extends FunctionDeclaration |
| 717 implements KernelStatement { | 715 implements KernelStatement { |
| 716 bool _hasImplicitReturnType = false; |
| 717 |
| 718 KernelFunctionDeclaration(VariableDeclaration variable, FunctionNode function) | 718 KernelFunctionDeclaration(VariableDeclaration variable, FunctionNode function) |
| 719 : super(variable, function); | 719 : super(variable, function); |
| 720 | 720 |
| 721 @override | 721 @override |
| 722 void _inferStatement(KernelTypeInferrer inferrer) { | 722 void _inferStatement(KernelTypeInferrer inferrer) { |
| 723 inferrer.listener.functionDeclarationEnter(this); | 723 inferrer.listener.functionDeclarationEnter(this); |
| 724 for (var parameter in function.positionalParameters) { | 724 inferrer.inferLocalFunction(function, null, false, fileOffset, |
| 725 if (parameter.initializer != null) { | 725 _hasImplicitReturnType ? null : function.returnType, true); |
| 726 inferrer.inferExpression(parameter.initializer, parameter.type, false); | 726 variable.type = function.functionType; |
| 727 } | |
| 728 } | |
| 729 for (var parameter in function.namedParameters) { | |
| 730 if (parameter.initializer != null) { | |
| 731 inferrer.inferExpression(parameter.initializer, parameter.type, false); | |
| 732 } | |
| 733 } | |
| 734 if (!inferrer.isTopLevel) { | |
| 735 var oldClosureContext = inferrer.closureContext; | |
| 736 inferrer.closureContext = new ClosureContext( | |
| 737 inferrer, function.asyncMarker, function.returnType); | |
| 738 inferrer.inferStatement(function.body); | |
| 739 inferrer.closureContext = oldClosureContext; | |
| 740 } | |
| 741 inferrer.listener.functionDeclarationExit(this); | 727 inferrer.listener.functionDeclarationExit(this); |
| 742 } | 728 } |
| 729 |
| 730 static void setHasImplicitReturnType( |
| 731 KernelFunctionDeclaration declaration, bool hasImplicitReturnType) { |
| 732 declaration._hasImplicitReturnType = hasImplicitReturnType; |
| 733 } |
| 743 } | 734 } |
| 744 | 735 |
| 745 /// Concrete shadow object representing a function expression in kernel form. | 736 /// Concrete shadow object representing a function expression in kernel form. |
| 746 class KernelFunctionExpression extends FunctionExpression | 737 class KernelFunctionExpression extends FunctionExpression |
| 747 implements KernelExpression { | 738 implements KernelExpression { |
| 748 KernelFunctionExpression(FunctionNode function) : super(function); | 739 KernelFunctionExpression(FunctionNode function) : super(function); |
| 749 | 740 |
| 750 @override | 741 @override |
| 751 void _collectDependencies(KernelDependencyCollector collector) { | 742 void _collectDependencies(KernelDependencyCollector collector) { |
| 752 for (KernelVariableDeclaration parameter in function.positionalParameters) { | 743 for (KernelVariableDeclaration parameter in function.positionalParameters) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 767 } else { | 758 } else { |
| 768 collector.recordNotImmediatelyEvident(fileOffset); | 759 collector.recordNotImmediatelyEvident(fileOffset); |
| 769 } | 760 } |
| 770 } | 761 } |
| 771 | 762 |
| 772 @override | 763 @override |
| 773 DartType _inferExpression( | 764 DartType _inferExpression( |
| 774 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { | 765 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
| 775 typeNeeded = inferrer.listener.functionExpressionEnter(this, typeContext) || | 766 typeNeeded = inferrer.listener.functionExpressionEnter(this, typeContext) || |
| 776 typeNeeded; | 767 typeNeeded; |
| 777 | 768 var inferredType = inferrer.inferLocalFunction( |
| 778 if (!inferrer.isTopLevel) { | 769 function, typeContext, typeNeeded, fileOffset, null, false); |
| 779 for (var parameter in function.positionalParameters) { | |
| 780 if (parameter.initializer != null) { | |
| 781 inferrer.inferExpression( | |
| 782 parameter.initializer, parameter.type, false); | |
| 783 } | |
| 784 } | |
| 785 for (var parameter in function.namedParameters) { | |
| 786 if (parameter.initializer != null) { | |
| 787 inferrer.inferExpression( | |
| 788 parameter.initializer, parameter.type, false); | |
| 789 } | |
| 790 } | |
| 791 } | |
| 792 | |
| 793 // Let `<T0, ..., Tn>` be the set of type parameters of the closure (with | |
| 794 // `n`=0 if there are no type parameters). | |
| 795 List<TypeParameter> typeParameters = function.typeParameters; | |
| 796 | |
| 797 // Let `(P0 x0, ..., Pm xm)` be the set of formal parameters of the closure | |
| 798 // (including required, positional optional, and named optional parameters). | |
| 799 // If any type `Pi` is missing, denote it as `_`. | |
| 800 List<VariableDeclaration> formals = function.positionalParameters.toList() | |
| 801 ..addAll(function.namedParameters); | |
| 802 | |
| 803 // Let `B` denote the closure body. If `B` is an expression function body | |
| 804 // (`=> e`), treat it as equivalent to a block function body containing a | |
| 805 // single `return` statement (`{ return e; }`). | |
| 806 | |
| 807 // Attempt to match `K` as a function type compatible with the closure (that | |
| 808 // is, one having n type parameters and a compatible set of formal | |
| 809 // parameters). If there is a successful match, let `<S0, ..., Sn>` be the | |
| 810 // set of matched type parameters and `(Q0, ..., Qm)` be the set of matched | |
| 811 // formal parameter types, and let `N` be the return type. | |
| 812 Substitution substitution; | |
| 813 List<DartType> formalTypesFromContext = | |
| 814 new List<DartType>.filled(formals.length, null); | |
| 815 DartType returnContext; | |
| 816 if (inferrer.strongMode && typeContext is FunctionType) { | |
| 817 for (int i = 0; i < formals.length; i++) { | |
| 818 if (i < function.positionalParameters.length) { | |
| 819 formalTypesFromContext[i] = | |
| 820 getPositionalParameterType(typeContext, i); | |
| 821 } else { | |
| 822 formalTypesFromContext[i] = | |
| 823 getNamedParameterType(typeContext, formals[i].name); | |
| 824 } | |
| 825 } | |
| 826 returnContext = typeContext.returnType; | |
| 827 | |
| 828 // Let `[T/S]` denote the type substitution where each `Si` is replaced wi
th | |
| 829 // the corresponding `Ti`. | |
| 830 var substitutionMap = <TypeParameter, DartType>{}; | |
| 831 for (int i = 0; i < typeContext.typeParameters.length; i++) { | |
| 832 substitutionMap[typeContext.typeParameters[i]] = | |
| 833 i < typeParameters.length | |
| 834 ? new TypeParameterType(typeParameters[i]) | |
| 835 : const DynamicType(); | |
| 836 } | |
| 837 substitution = Substitution.fromMap(substitutionMap); | |
| 838 } else { | |
| 839 // If the match is not successful because `K` is `_`, let all `Si`, all | |
| 840 // `Qi`, and `N` all be `_`. | |
| 841 | |
| 842 // If the match is not successful for any other reason, this will result i
n | |
| 843 // a type error, so the implementation is free to choose the best error | |
| 844 // recovery path. | |
| 845 substitution = Substitution.empty; | |
| 846 } | |
| 847 | |
| 848 // Define `Ri` as follows: if `Pi` is not `_`, let `Ri` be `Pi`. | |
| 849 // Otherwise, if `Qi` is not `_`, let `Ri` be the greatest closure of | |
| 850 // `Qi[T/S]` with respect to `?`. Otherwise, let `Ri` be `dynamic`. | |
| 851 for (int i = 0; i < formals.length; i++) { | |
| 852 KernelVariableDeclaration formal = formals[i]; | |
| 853 if (KernelVariableDeclaration.isImplicitlyTyped(formal)) { | |
| 854 DartType inferredType; | |
| 855 if (formalTypesFromContext[i] != null) { | |
| 856 inferredType = greatestClosure(inferrer.coreTypes, | |
| 857 substitution.substituteType(formalTypesFromContext[i])); | |
| 858 } else { | |
| 859 inferredType = const DynamicType(); | |
| 860 } | |
| 861 inferrer.instrumentation?.record( | |
| 862 Uri.parse(inferrer.uri), | |
| 863 formal.fileOffset, | |
| 864 'type', | |
| 865 new InstrumentationValueForType(inferredType)); | |
| 866 formal.type = inferredType; | |
| 867 } | |
| 868 } | |
| 869 | |
| 870 // Let `N'` be `N[T/S]`. The [ClosureContext] constructor will adjust | |
| 871 // accordingly if the closure is declared with `async`, `async*`, or | |
| 872 // `sync*`. | |
| 873 if (returnContext != null) { | |
| 874 returnContext = substitution.substituteType(returnContext); | |
| 875 } | |
| 876 | |
| 877 // Apply type inference to `B` in return context `N’`, with any references | |
| 878 // to `xi` in `B` having type `Pi`. This produces `B’`. | |
| 879 bool isExpressionFunction = function.body is ReturnStatement; | |
| 880 bool needToSetReturnType = isExpressionFunction || inferrer.strongMode; | |
| 881 ClosureContext oldClosureContext = inferrer.closureContext; | |
| 882 ClosureContext closureContext = | |
| 883 new ClosureContext(inferrer, function.asyncMarker, returnContext); | |
| 884 inferrer.closureContext = closureContext; | |
| 885 inferrer.inferStatement(function.body); | |
| 886 | |
| 887 // If the closure is declared with `async*` or `sync*`, let `M` be the least | |
| 888 // upper bound of the types of the `yield` expressions in `B’`, or `void` if | |
| 889 // `B’` contains no `yield` expressions. Otherwise, let `M` be the least | |
| 890 // upper bound of the types of the `return` expressions in `B’`, or `void` | |
| 891 // if `B’` contains no `return` expressions. | |
| 892 DartType inferredReturnType; | |
| 893 if (needToSetReturnType || typeNeeded) { | |
| 894 inferredReturnType = | |
| 895 closureContext.inferReturnType(inferrer, isExpressionFunction); | |
| 896 } | |
| 897 | |
| 898 // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B` with | |
| 899 // type `<T0, ..., Tn>(R0, ..., Rn) -> M’` (with some of the `Ri` and `xi` | |
| 900 // denoted as optional or named parameters, if appropriate). | |
| 901 if (needToSetReturnType) { | |
| 902 inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset, | |
| 903 'returnType', new InstrumentationValueForType(inferredReturnType)); | |
| 904 function.returnType = inferredReturnType; | |
| 905 } | |
| 906 inferrer.closureContext = oldClosureContext; | |
| 907 var inferredType = typeNeeded ? function.functionType : null; | |
| 908 inferrer.listener.functionExpressionExit(this, inferredType); | 770 inferrer.listener.functionExpressionExit(this, inferredType); |
| 909 return inferredType; | 771 return inferredType; |
| 910 } | 772 } |
| 911 } | 773 } |
| 912 | 774 |
| 913 /// Concrete shadow object representing an if-null expression. | 775 /// Concrete shadow object representing an if-null expression. |
| 914 /// | 776 /// |
| 915 /// An if-null expression of the form `a ?? b` is represented as the kernel | 777 /// An if-null expression of the form `a ?? b` is represented as the kernel |
| 916 /// expression: | 778 /// expression: |
| 917 /// | 779 /// |
| (...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2354 } | 2216 } |
| 2355 | 2217 |
| 2356 transformChildren(v) { | 2218 transformChildren(v) { |
| 2357 return internalError("Internal error: Unsupported operation."); | 2219 return internalError("Internal error: Unsupported operation."); |
| 2358 } | 2220 } |
| 2359 | 2221 |
| 2360 visitChildren(v) { | 2222 visitChildren(v) { |
| 2361 return internalError("Internal error: Unsupported operation."); | 2223 return internalError("Internal error: Unsupported operation."); |
| 2362 } | 2224 } |
| 2363 } | 2225 } |
| OLD | NEW |