Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: pkg/analyzer/lib/src/summary/link.dart

Issue 1966783003: First steps toward AST-based type inference involving closures. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 * This library is capable of producing linked summaries from unlinked 6 * This library is capable of producing linked summaries from unlinked
7 * ones (or prelinked ones). It functions by building a miniature 7 * ones (or prelinked ones). It functions by building a miniature
8 * element model to represent the contents of the summaries, and then 8 * element model to represent the contents of the summaries, and then
9 * scanning the element model to gather linked information and adding 9 * scanning the element model to gather linked information and adding
10 * it to the summary data structures. 10 * it to the summary data structures.
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 _storeTypeArguments( 211 _storeTypeArguments(
212 type.typeArguments, result, compilationUnit, typeParameterContext); 212 type.typeArguments, result, compilationUnit, typeParameterContext);
213 return result; 213 return result;
214 } 214 }
215 if (element is FunctionTypeAliasElementForLink) { 215 if (element is FunctionTypeAliasElementForLink) {
216 result.reference = compilationUnit.addReference(element); 216 result.reference = compilationUnit.addReference(element);
217 _storeTypeArguments( 217 _storeTypeArguments(
218 type.typeArguments, result, compilationUnit, typeParameterContext); 218 type.typeArguments, result, compilationUnit, typeParameterContext);
219 return result; 219 return result;
220 } 220 }
221 if (element is FunctionElement) { 221 if (element is FunctionElement && element.enclosingElement == null) {
222 // Element is a FunctionElement but not a TopLevelFunctionElementForLink 222 // Element is a synthetic function element that was generated on the fly
223 // or a MethodElementForLink. This means that it's a synthetic function 223 // to represent a type that has no associated source code location.
224 // element that was generated on the fly to represent a type that has no
225 // associated source code location.
226 assert(element.enclosingElement == null);
227 result.syntheticReturnType = _createLinkedType( 224 result.syntheticReturnType = _createLinkedType(
228 element.returnType, compilationUnit, typeParameterContext); 225 element.returnType, compilationUnit, typeParameterContext);
229 result.syntheticParams = element.parameters 226 result.syntheticParams = element.parameters
230 .map((ParameterElement param) => _serializeSyntheticParam( 227 .map((ParameterElement param) => _serializeSyntheticParam(
231 param, compilationUnit, typeParameterContext)) 228 param, compilationUnit, typeParameterContext))
232 .toList(); 229 .toList();
233 return result; 230 return result;
234 } 231 }
232 if (element is FunctionElement) {
233 // Element is a local function inside another executable.
234 result.reference = compilationUnit.addReference(element);
235 // TODO(paulberry): do I need to store type arguments?
236 return result;
237 }
235 // TODO(paulberry): implement other cases. 238 // TODO(paulberry): implement other cases.
236 throw new UnimplementedError('${element.runtimeType}'); 239 throw new UnimplementedError('${element.runtimeType}');
237 } 240 }
238 // TODO(paulberry): implement other cases. 241 // TODO(paulberry): implement other cases.
239 throw new UnimplementedError('${type.runtimeType}'); 242 throw new UnimplementedError('${type.runtimeType}');
240 } 243 }
241 244
242 /** 245 /**
243 * Create an [UnlinkedParam] representing the given [parameter], which should be 246 * Create an [UnlinkedParam] representing the given [parameter], which should be
244 * a parameter of a synthetic function type (e.g. one produced during type 247 * a parameter of a synthetic function type (e.g. one produced during type
(...skipping 823 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 * If this compilation unit already has a reference in its references table 1071 * If this compilation unit already has a reference in its references table
1069 * matching [dependency], [name], [numTypeParameters], [unitNum], 1072 * matching [dependency], [name], [numTypeParameters], [unitNum],
1070 * [containingReference], and [kind], return its index. Otherwise add a new r eference to 1073 * [containingReference], and [kind], return its index. Otherwise add a new r eference to
1071 * the table and return its index. 1074 * the table and return its index.
1072 */ 1075 */
1073 int addRawReference(String name, 1076 int addRawReference(String name,
1074 {int dependency: 0, 1077 {int dependency: 0,
1075 int numTypeParameters: 0, 1078 int numTypeParameters: 0,
1076 int unitNum: 0, 1079 int unitNum: 0,
1077 int containingReference: 0, 1080 int containingReference: 0,
1081 int localIndex: 0,
1078 ReferenceKind kind: ReferenceKind.classOrEnum}) { 1082 ReferenceKind kind: ReferenceKind.classOrEnum}) {
1079 List<LinkedReferenceBuilder> linkedReferences = _linkedUnit.references; 1083 List<LinkedReferenceBuilder> linkedReferences = _linkedUnit.references;
1080 List<UnlinkedReference> unlinkedReferences = _unlinkedUnit.references; 1084 List<UnlinkedReference> unlinkedReferences = _unlinkedUnit.references;
1081 for (int i = 0; i < linkedReferences.length; i++) { 1085 for (int i = 0; i < linkedReferences.length; i++) {
1082 LinkedReferenceBuilder linkedReference = linkedReferences[i]; 1086 LinkedReferenceBuilder linkedReference = linkedReferences[i];
1083 int candidateContainingReference = i < unlinkedReferences.length 1087 int candidateContainingReference = i < unlinkedReferences.length
1084 ? unlinkedReferences[i].prefixReference 1088 ? unlinkedReferences[i].prefixReference
1085 : linkedReference.containingReference; 1089 : linkedReference.containingReference;
1086 if (candidateContainingReference != 0 && 1090 if (candidateContainingReference != 0 &&
1087 linkedReferences[candidateContainingReference].kind == 1091 linkedReferences[candidateContainingReference].kind ==
1088 ReferenceKind.prefix) { 1092 ReferenceKind.prefix) {
1089 // We don't need to match containing references when they are prefixes, 1093 // We don't need to match containing references when they are prefixes,
1090 // since the relevant information is in linkedReference.dependency. 1094 // since the relevant information is in linkedReference.dependency.
1091 candidateContainingReference = 0; 1095 candidateContainingReference = 0;
1092 } 1096 }
1093 if (linkedReference.dependency == dependency && 1097 if (linkedReference.dependency == dependency &&
1094 (i < unlinkedReferences.length 1098 (i < unlinkedReferences.length
1095 ? unlinkedReferences[i].name 1099 ? unlinkedReferences[i].name
1096 : linkedReference.name) == 1100 : linkedReference.name) ==
1097 name && 1101 name &&
1098 linkedReference.numTypeParameters == numTypeParameters && 1102 linkedReference.numTypeParameters == numTypeParameters &&
1099 linkedReference.unit == unitNum && 1103 linkedReference.unit == unitNum &&
1100 candidateContainingReference == containingReference && 1104 candidateContainingReference == containingReference &&
1101 linkedReference.kind == kind) { 1105 linkedReference.kind == kind &&
1106 linkedReference.localIndex == localIndex) {
1102 return i; 1107 return i;
1103 } 1108 }
1104 } 1109 }
1105 int result = linkedReferences.length; 1110 int result = linkedReferences.length;
1106 linkedReferences.add(new LinkedReferenceBuilder( 1111 linkedReferences.add(new LinkedReferenceBuilder(
1107 dependency: dependency, 1112 dependency: dependency,
1108 name: name, 1113 name: name,
1109 numTypeParameters: numTypeParameters, 1114 numTypeParameters: numTypeParameters,
1110 unit: unitNum, 1115 unit: unitNum,
1111 containingReference: containingReference, 1116 containingReference: containingReference,
1112 kind: kind)); 1117 kind: kind,
1118 localIndex: localIndex));
1113 return result; 1119 return result;
1114 } 1120 }
1115 1121
1116 /** 1122 /**
1117 * If this compilation unit already has a reference in its references table 1123 * If this compilation unit already has a reference in its references table
1118 * to [element], return its index. Otherwise add a new reference to the table 1124 * to [element], return its index. Otherwise add a new reference to the table
1119 * and return its index. 1125 * and return its index.
1120 */ 1126 */
1121 int addReference(Element element) { 1127 int addReference(Element element) {
1122 if (element is ClassElementForLink) { 1128 if (element is ClassElementForLink) {
(...skipping 21 matching lines...) Expand all
1144 break; 1150 break;
1145 default: 1151 default:
1146 // TODO(paulberry): implement other cases as necessary 1152 // TODO(paulberry): implement other cases as necessary
1147 throw new UnimplementedError('${element._unlinkedExecutable.kind}'); 1153 throw new UnimplementedError('${element._unlinkedExecutable.kind}');
1148 } 1154 }
1149 return addRawReference(element.name, 1155 return addRawReference(element.name,
1150 numTypeParameters: element.typeParameters.length, 1156 numTypeParameters: element.typeParameters.length,
1151 containingReference: 1157 containingReference:
1152 enclosingClass != null ? addReference(enclosingClass) : null, 1158 enclosingClass != null ? addReference(enclosingClass) : null,
1153 kind: kind); 1159 kind: kind);
1160 } else if (element is FunctionElementForLink_Local) {
1161 FunctionElementImpl parent = element.enclosingElement;
1162 int localIndex = parent.functions.indexOf(element);
1163 assert(localIndex != -1);
1164 return addRawReference(element.name,
1165 containingReference: addReference(parent),
1166 kind: ReferenceKind.function,
1167 localIndex: localIndex);
1168 } else if (element is FunctionElementForLink_Initializer) {
1169 return addRawReference('',
1170 containingReference: addReference(element.enclosingElement),
1171 kind: ReferenceKind.function);
1172 } else if (element is TopLevelVariableElementForLink) {
1173 return addRawReference(element.name,
1174 kind: ReferenceKind.topLevelPropertyAccessor);
1175 } else if (element is FieldElementForLink_ClassField) {
1176 ClassElementForLink_Class enclosingClass = element.enclosingElement;
1177 // TODO(paulberry): do we need to set numTypeParameters to nonzero if the
1178 // class has type parameters?
1179 return addRawReference(element.name,
1180 containingReference: addReference(enclosingClass),
1181 kind: ReferenceKind.propertyAccessor);
1154 } 1182 }
1155 // TODO(paulberry): implement other cases 1183 // TODO(paulberry): implement other cases
1156 throw new UnimplementedError('${element.runtimeType}'); 1184 throw new UnimplementedError('${element.runtimeType}');
1157 } 1185 }
1158 1186
1159 @override 1187 @override
1160 DartType getLinkedType( 1188 DartType getLinkedType(
1161 int slot, TypeParameterizedElementForLink typeParameterContext) { 1189 int slot, TypeParameterizedElementForLink typeParameterContext) {
1162 // This method should only be called on compilation units that come from 1190 // This method should only be called on compilation units that come from
1163 // dependencies, never on compilation units that are part of the current 1191 // dependencies, never on compilation units that are part of the current
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after
1909 // considered to return `void`. 1937 // considered to return `void`.
1910 return VoidTypeImpl.instance; 1938 return VoidTypeImpl.instance;
1911 } else { 1939 } else {
1912 return DynamicTypeImpl.instance; 1940 return DynamicTypeImpl.instance;
1913 } 1941 }
1914 } 1942 }
1915 } 1943 }
1916 1944
1917 class ExprTypeComputer { 1945 class ExprTypeComputer {
1918 VariableElementForLink variable; 1946 VariableElementForLink variable;
1947 FunctionElementForLink_Initializer initializer;
1919 CompilationUnitElementForLink unit; 1948 CompilationUnitElementForLink unit;
1920 LibraryElementForLink library; 1949 LibraryElementForLink library;
1921 Linker linker; 1950 Linker linker;
1922 TypeProvider typeProvider; 1951 TypeProvider typeProvider;
1923 UnlinkedConst unlinkedConst; 1952 UnlinkedConst unlinkedConst;
1924 1953
1925 final List<DartType> stack = <DartType>[]; 1954 final List<DartType> stack = <DartType>[];
1926 int intPtr = 0; 1955 int intPtr = 0;
1927 int refPtr = 0; 1956 int refPtr = 0;
1928 int strPtr = 0; 1957 int strPtr = 0;
1929 int assignmentOperatorPtr = 0; 1958 int assignmentOperatorPtr = 0;
1930 1959
1931 ExprTypeComputer(VariableElementForLink variableElement) { 1960 ExprTypeComputer(VariableElementForLink variableElement) {
1932 this.variable = variableElement; 1961 this.variable = variableElement;
1962 initializer = variableElement.initializer;
1933 unit = variableElement.compilationUnit; 1963 unit = variableElement.compilationUnit;
1934 library = unit.enclosingElement; 1964 library = unit.enclosingElement;
1935 linker = library._linker; 1965 linker = library._linker;
1936 typeProvider = linker.typeProvider; 1966 typeProvider = linker.typeProvider;
1937 unlinkedConst = variableElement.unlinkedVariable.constExpr; 1967 unlinkedConst = variableElement.unlinkedVariable.constExpr;
1938 } 1968 }
1939 1969
1940 DartType compute() { 1970 DartType compute() {
1941 // Perform RPN evaluation of the constant, using a stack of inferred types. 1971 // Perform RPN evaluation of the constant, using a stack of inferred types.
1942 for (UnlinkedConstOperation operation in unlinkedConst.operations) { 1972 for (UnlinkedConstOperation operation in unlinkedConst.operations) {
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
2089 break; 2119 break;
2090 case UnlinkedConstOperation.typeCheck: 2120 case UnlinkedConstOperation.typeCheck:
2091 stack.removeLast(); 2121 stack.removeLast();
2092 refPtr++; 2122 refPtr++;
2093 stack.add(typeProvider.boolType); 2123 stack.add(typeProvider.boolType);
2094 break; 2124 break;
2095 case UnlinkedConstOperation.throwException: 2125 case UnlinkedConstOperation.throwException:
2096 stack.removeLast(); 2126 stack.removeLast();
2097 stack.add(BottomTypeImpl.instance); 2127 stack.add(BottomTypeImpl.instance);
2098 break; 2128 break;
2129 case UnlinkedConstOperation.pushLocalFunctionReference:
2130 int popCount = _getNextInt();
2131 assert(popCount == 0); // TODO(paulberry): handle the nonzero case.
2132 stack.add(initializer.functions[_getNextInt()].type);
2133 break;
2099 default: 2134 default:
2100 // TODO(paulberry): implement. 2135 // TODO(paulberry): implement.
2101 throw new UnimplementedError('$operation'); 2136 throw new UnimplementedError('$operation');
2102 } 2137 }
2103 } 2138 }
2104 assert(intPtr == unlinkedConst.ints.length); 2139 assert(intPtr == unlinkedConst.ints.length);
2105 assert(refPtr == unlinkedConst.references.length); 2140 assert(refPtr == unlinkedConst.references.length);
2106 assert(strPtr == unlinkedConst.strings.length); 2141 assert(strPtr == unlinkedConst.strings.length);
2107 assert(assignmentOperatorPtr == unlinkedConst.assignmentOperators.length); 2142 assert(assignmentOperatorPtr == unlinkedConst.assignmentOperators.length);
2108 assert(stack.length == 1); 2143 assert(stack.length == 1);
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after
2692 2727
2693 /** 2728 /**
2694 * Element representing the initializer expression of a variable. 2729 * Element representing the initializer expression of a variable.
2695 */ 2730 */
2696 class FunctionElementForLink_Initializer implements FunctionElementImpl { 2731 class FunctionElementForLink_Initializer implements FunctionElementImpl {
2697 /** 2732 /**
2698 * The variable for which this element is the initializer. 2733 * The variable for which this element is the initializer.
2699 */ 2734 */
2700 final VariableElementForLink _variable; 2735 final VariableElementForLink _variable;
2701 2736
2737 List<FunctionElementForLink_Local> _functions;
2738
2702 FunctionElementForLink_Initializer(this._variable); 2739 FunctionElementForLink_Initializer(this._variable);
2703 2740
2704 @override 2741 @override
2742 VariableElementForLink get enclosingElement => _variable;
2743
2744 @override
2745 List<FunctionElementForLink_Local> get functions => _functions ??= _variable
2746 .unlinkedVariable.initializer.localFunctions
2747 .map(
2748 (UnlinkedExecutable ex) => new FunctionElementForLink_Local(this, ex))
2749 .toList();
2750
2751 @override
2705 DartType get returnType { 2752 DartType get returnType {
2706 // If this is a variable whose type needs inferring, infer it. 2753 // If this is a variable whose type needs inferring, infer it.
2707 if (_variable.hasImplicitType) { 2754 if (_variable.hasImplicitType) {
2708 return _variable.inferredType; 2755 return _variable.inferredType;
2709 } else { 2756 } else {
2710 // There's no reason linking should need to access the type of 2757 // There's no reason linking should need to access the type of
2711 // this FunctionElement, since the variable doesn't need its 2758 // this FunctionElement, since the variable doesn't need its
2712 // type inferred. 2759 // type inferred.
2713 assert(false); 2760 assert(false);
2714 // But for robustness, return the dynamic type. 2761 // But for robustness, return the dynamic type.
2715 return DynamicTypeImpl.instance; 2762 return DynamicTypeImpl.instance;
2716 } 2763 }
2717 } 2764 }
2718 2765
2719 @override 2766 @override
2720 void set returnType(DartType newType) { 2767 void set returnType(DartType newType) {
2721 // InstanceMemberInferrer stores the new type both here and on the variable 2768 // InstanceMemberInferrer stores the new type both here and on the variable
2722 // element. We don't need to record both values, so we ignore it here. 2769 // element. We don't need to record both values, so we ignore it here.
2723 } 2770 }
2724 2771
2725 @override 2772 @override
2726 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); 2773 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
2727 } 2774 }
2728 2775
2729 /** 2776 /**
2777 * Element representing a local function (possibly a closure) inside another
2778 * executable.
2779 */
2780 class FunctionElementForLink_Local implements FunctionElementImpl {
2781 /**
2782 * The unlinked representation of the local function in the summary.
2783 */
2784 final UnlinkedExecutable _executable;
2785
2786 @override
2787 final FunctionElementImpl enclosingElement;
2788
2789 DartType _type;
2790
2791 FunctionElementForLink_Local(this.enclosingElement, this._executable);
2792
2793 @override
2794 String get name => _executable.name;
2795
2796 @override
2797 DartType get type => _type ??= new FunctionTypeImpl(this);
2798
2799 @override
2800 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
2801 }
2802
2803 /**
2730 * Element representing a typedef resynthesized from a summary during linking. 2804 * Element representing a typedef resynthesized from a summary during linking.
2731 */ 2805 */
2732 class FunctionTypeAliasElementForLink extends Object 2806 class FunctionTypeAliasElementForLink extends Object
2733 with TypeParameterizedElementForLink, ParameterParentElementForLink 2807 with TypeParameterizedElementForLink, ParameterParentElementForLink
2734 implements 2808 implements
2735 FunctionTypeAliasElement, 2809 FunctionTypeAliasElement,
2736 ReferenceableElementForLink, 2810 ReferenceableElementForLink,
2737 ElementImpl { 2811 ElementImpl {
2738 @override 2812 @override
2739 final CompilationUnitElementForLink enclosingElement; 2813 final CompilationUnitElementForLink enclosingElement;
(...skipping 2011 matching lines...) Expand 10 before | Expand all | Expand 10 after
4751 * there are no type parameters in scope. 4825 * there are no type parameters in scope.
4752 */ 4826 */
4753 TypeParameterizedElementForLink get _typeParameterContext; 4827 TypeParameterizedElementForLink get _typeParameterContext;
4754 4828
4755 @override 4829 @override
4756 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); 4830 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
4757 4831
4758 @override 4832 @override
4759 String toString() => '$enclosingElement.$name'; 4833 String toString() => '$enclosingElement.$name';
4760 } 4834 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698