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 |