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

Side by Side Diff: pkg/analyzer/lib/src/summary/summarize_ast.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 library serialization.summarize_ast; 5 library serialization.summarize_ast;
6 6
7 import 'package:analyzer/dart/ast/ast.dart'; 7 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/ast/token.dart'; 8 import 'package:analyzer/dart/ast/token.dart';
9 import 'package:analyzer/dart/ast/visitor.dart'; 9 import 'package:analyzer/dart/ast/visitor.dart';
10 import 'package:analyzer/dart/element/type.dart' show DartType; 10 import 'package:analyzer/dart/element/type.dart' show DartType;
(...skipping 11 matching lines...) Expand all
22 } 22 }
23 23
24 /** 24 /**
25 * Instances of this class keep track of intermediate state during 25 * Instances of this class keep track of intermediate state during
26 * serialization of a single constant [Expression]. 26 * serialization of a single constant [Expression].
27 */ 27 */
28 class _ConstExprSerializer extends AbstractConstExprSerializer { 28 class _ConstExprSerializer extends AbstractConstExprSerializer {
29 final _SummarizeAstVisitor visitor; 29 final _SummarizeAstVisitor visitor;
30 30
31 /** 31 /**
32 * If the expression being serialized can contain closures, map whose
33 * keys are the offsets of local function nodes representing those closures,
34 * and whose values are indices of those local functions relative to their
35 * siblings.
36 */
37 final Map<int, int> localClosureIndexMap;
38
39 /**
32 * If a constructor initializer expression is being serialized, the names of 40 * If a constructor initializer expression is being serialized, the names of
33 * the constructor parameters. Otherwise `null`. 41 * the constructor parameters. Otherwise `null`.
34 */ 42 */
35 final Set<String> constructorParameterNames; 43 final Set<String> constructorParameterNames;
36 44
37 _ConstExprSerializer(this.visitor, this.constructorParameterNames); 45 _ConstExprSerializer(
46 this.visitor, this.localClosureIndexMap, this.constructorParameterNames);
38 47
39 @override 48 @override
40 bool isConstructorParameterName(String name) { 49 bool isConstructorParameterName(String name) {
41 return constructorParameterNames?.contains(name) ?? false; 50 return constructorParameterNames?.contains(name) ?? false;
42 } 51 }
43 52
44 @override 53 @override
45 void serializeAnnotation(Annotation annotation) { 54 void serializeAnnotation(Annotation annotation) {
46 if (annotation.arguments == null) { 55 if (annotation.arguments == null) {
47 assert(annotation.constructorName == null); 56 assert(annotation.constructorName == null);
(...skipping 19 matching lines...) Expand all
67 if (name == null) { 76 if (name == null) {
68 return typeBuilder; 77 return typeBuilder;
69 } else { 78 } else {
70 int nameRef = 79 int nameRef =
71 visitor.serializeReference(typeBuilder.reference, name.name); 80 visitor.serializeReference(typeBuilder.reference, name.name);
72 return new EntityRefBuilder( 81 return new EntityRefBuilder(
73 reference: nameRef, typeArguments: typeBuilder.typeArguments); 82 reference: nameRef, typeArguments: typeBuilder.typeArguments);
74 } 83 }
75 } 84 }
76 85
86 @override
87 List<int> serializeFunctionExpression(FunctionExpression functionExpression) {
88 int localIndex;
89 if (localClosureIndexMap == null) {
90 return null;
91 } else {
92 localIndex = localClosureIndexMap[functionExpression.offset];
93 assert(localIndex != null);
94 return <int>[0, localIndex];
95 }
96 }
97
77 EntityRefBuilder serializeIdentifier(Identifier identifier) { 98 EntityRefBuilder serializeIdentifier(Identifier identifier) {
78 EntityRefBuilder b = new EntityRefBuilder(); 99 EntityRefBuilder b = new EntityRefBuilder();
79 if (identifier is SimpleIdentifier) { 100 if (identifier is SimpleIdentifier) {
80 int index = visitor.serializeSimpleReference(identifier.name, 101 int index = visitor.serializeSimpleReference(identifier.name,
81 allowTypeParameter: true); 102 allowTypeParameter: true);
82 if (index < 0) { 103 if (index < 0) {
83 b.paramReference = -index; 104 b.paramReference = -index;
84 } else { 105 } else {
85 b.reference = index; 106 b.reference = index;
86 } 107 }
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 * The number of slot ids which have been assigned to this compilation unit. 331 * The number of slot ids which have been assigned to this compilation unit.
311 */ 332 */
312 int numSlots = 0; 333 int numSlots = 0;
313 334
314 /** 335 /**
315 * The [Block] that is being visited now, or `null` for non-local contexts. 336 * The [Block] that is being visited now, or `null` for non-local contexts.
316 */ 337 */
317 Block enclosingBlock = null; 338 Block enclosingBlock = null;
318 339
319 /** 340 /**
341 * If an expression is being serialized which can contain closures, map whose
342 * keys are the offsets of local function nodes representing those closures,
343 * and whose values are indices of those local functions relative to their
344 * siblings.
345 */
346 Map<int, int> _localClosureIndexMap;
347
348 /**
320 * Create a slot id for storing a propagated or inferred type or const cycle 349 * Create a slot id for storing a propagated or inferred type or const cycle
321 * info. 350 * info.
322 */ 351 */
323 int assignSlot() => ++numSlots; 352 int assignSlot() => ++numSlots;
324 353
325 /** 354 /**
326 * Build a [_Scope] object containing the names defined within the body of a 355 * Build a [_Scope] object containing the names defined within the body of a
327 * class declaration. 356 * class declaration.
328 */ 357 */
329 _Scope buildClassMemberScope( 358 _Scope buildClassMemberScope(
(...skipping 22 matching lines...) Expand all
352 /** 381 /**
353 * Serialize the given list of [annotations]. If there are no annotations, 382 * Serialize the given list of [annotations]. If there are no annotations,
354 * the empty list is returned. 383 * the empty list is returned.
355 */ 384 */
356 List<UnlinkedConstBuilder> serializeAnnotations( 385 List<UnlinkedConstBuilder> serializeAnnotations(
357 NodeList<Annotation> annotations) { 386 NodeList<Annotation> annotations) {
358 if (annotations == null || annotations.isEmpty) { 387 if (annotations == null || annotations.isEmpty) {
359 return const <UnlinkedConstBuilder>[]; 388 return const <UnlinkedConstBuilder>[];
360 } 389 }
361 return annotations.map((Annotation a) { 390 return annotations.map((Annotation a) {
362 _ConstExprSerializer serializer = new _ConstExprSerializer(this, null); 391 var localClosureIndexMap = null; // TODO(paulberry): fix.
scheglov 2016/05/10 21:47:03 Do we want to have types for these variables?
Paul Berry 2016/05/10 22:04:15 Good point. Fixed.
392 _ConstExprSerializer serializer =
393 new _ConstExprSerializer(this, localClosureIndexMap, null);
363 serializer.serializeAnnotation(a); 394 serializer.serializeAnnotation(a);
364 return serializer.toBuilder(); 395 return serializer.toBuilder();
365 }).toList(); 396 }).toList();
366 } 397 }
367 398
368 /** 399 /**
369 * Serialize a [ClassDeclaration] or [ClassTypeAlias] into an [UnlinkedClass] 400 * Serialize a [ClassDeclaration] or [ClassTypeAlias] into an [UnlinkedClass]
370 * and store the result in [classes]. 401 * and store the result in [classes].
371 */ 402 */
372 void serializeClass( 403 void serializeClass(
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 b.references = unlinkedReferences; 511 b.references = unlinkedReferences;
481 b.typedefs = typedefs; 512 b.typedefs = typedefs;
482 b.variables = variables; 513 b.variables = variables;
483 b.publicNamespace = computePublicNamespace(compilationUnit); 514 b.publicNamespace = computePublicNamespace(compilationUnit);
484 return b; 515 return b;
485 } 516 }
486 517
487 /** 518 /**
488 * Serialize the given [expression], creating an [UnlinkedConstBuilder]. 519 * Serialize the given [expression], creating an [UnlinkedConstBuilder].
489 */ 520 */
490 UnlinkedConstBuilder serializeConstExpr(Expression expression, 521 UnlinkedConstBuilder serializeConstExpr(
522 Map<int, int> localClosureIndexMap, Expression expression,
491 [Set<String> constructorParameterNames]) { 523 [Set<String> constructorParameterNames]) {
492 _ConstExprSerializer serializer = 524 _ConstExprSerializer serializer = new _ConstExprSerializer(
493 new _ConstExprSerializer(this, constructorParameterNames); 525 this, localClosureIndexMap, constructorParameterNames);
494 serializer.serialize(expression); 526 serializer.serialize(expression);
495 return serializer.toBuilder(); 527 return serializer.toBuilder();
496 } 528 }
497 529
498 /** 530 /**
499 * Serialize the given [declaredIdentifier] into [UnlinkedVariable], and 531 * Serialize the given [declaredIdentifier] into [UnlinkedVariable], and
500 * store it in [variables]. 532 * store it in [variables].
501 */ 533 */
502 void serializeDeclaredIdentifier( 534 void serializeDeclaredIdentifier(
503 AstNode scopeNode, 535 AstNode scopeNode,
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder(); 875 UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
844 b.isFinal = variables.isFinal; 876 b.isFinal = variables.isFinal;
845 b.isConst = variables.isConst; 877 b.isConst = variables.isConst;
846 b.isStatic = isDeclaredStatic; 878 b.isStatic = isDeclaredStatic;
847 b.name = variable.name.name; 879 b.name = variable.name.name;
848 b.nameOffset = variable.name.offset; 880 b.nameOffset = variable.name.offset;
849 b.type = serializeTypeName(variables.type); 881 b.type = serializeTypeName(variables.type);
850 b.documentationComment = serializeDocumentation(documentationComment); 882 b.documentationComment = serializeDocumentation(documentationComment);
851 b.annotations = serializeAnnotations(annotations); 883 b.annotations = serializeAnnotations(annotations);
852 b.codeRange = serializeCodeRange(variables.parent); 884 b.codeRange = serializeCodeRange(variables.parent);
885 Map<int, int> localClosureIndexMap = _withLocalClosureIndexMap(() {
886 b.initializer = serializeInitializerFunction(variable.initializer);
887 });
853 if (variable.isConst || 888 if (variable.isConst ||
854 variable.isFinal && isField && !isDeclaredStatic || 889 variable.isFinal && isField && !isDeclaredStatic ||
855 variables.type == null) { 890 variables.type == null) {
856 Expression initializer = variable.initializer; 891 Expression initializer = variable.initializer;
857 if (initializer != null) { 892 if (initializer != null) {
858 b.constExpr = serializeConstExpr(initializer); 893 b.constExpr = serializeConstExpr(localClosureIndexMap, initializer);
859 } 894 }
860 } 895 }
861 if (variable.initializer != null && 896 if (variable.initializer != null &&
862 (variables.isFinal || variables.isConst)) { 897 (variables.isFinal || variables.isConst)) {
863 b.propagatedTypeSlot = assignSlot(); 898 b.propagatedTypeSlot = assignSlot();
864 } 899 }
865 bool isSemanticallyStatic = !isField || isDeclaredStatic; 900 bool isSemanticallyStatic = !isField || isDeclaredStatic;
866 if (variables.type == null && 901 if (variables.type == null &&
867 (variable.initializer != null || !isSemanticallyStatic)) { 902 (variable.initializer != null || !isSemanticallyStatic)) {
868 b.inferredTypeSlot = assignSlot(); 903 b.inferredTypeSlot = assignSlot();
869 } 904 }
870 b.visibleOffset = scopeNode?.offset; 905 b.visibleOffset = scopeNode?.offset;
871 b.visibleLength = scopeNode?.length; 906 b.visibleLength = scopeNode?.length;
872 b.initializer = serializeInitializerFunction(variable.initializer);
873 this.variables.add(b); 907 this.variables.add(b);
874 } 908 }
875 } 909 }
876 910
877 @override 911 @override
878 void visitBlock(Block node) { 912 void visitBlock(Block node) {
879 Block oldBlock = enclosingBlock; 913 Block oldBlock = enclosingBlock;
880 enclosingBlock = node; 914 enclosingBlock = node;
881 super.visitBlock(node); 915 super.visitBlock(node);
882 enclosingBlock = oldBlock; 916 enclosingBlock = oldBlock;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 } 980 }
947 b.parameters = node.parameters.parameters 981 b.parameters = node.parameters.parameters
948 .map((FormalParameter p) => p.accept(this)) 982 .map((FormalParameter p) => p.accept(this))
949 .toList(); 983 .toList();
950 b.kind = UnlinkedExecutableKind.constructor; 984 b.kind = UnlinkedExecutableKind.constructor;
951 if (node.factoryKeyword != null) { 985 if (node.factoryKeyword != null) {
952 b.isFactory = true; 986 b.isFactory = true;
953 if (node.redirectedConstructor != null) { 987 if (node.redirectedConstructor != null) {
954 b.isRedirectedConstructor = true; 988 b.isRedirectedConstructor = true;
955 TypeName typeName = node.redirectedConstructor.type; 989 TypeName typeName = node.redirectedConstructor.type;
956 b.redirectedConstructor = new _ConstExprSerializer(this, null) 990 var localClosureIndexMap = null; // TODO(paulberry): fix.
957 .serializeConstructorRef(null, typeName.name, 991 b.redirectedConstructor =
958 typeName.typeArguments, node.redirectedConstructor.name); 992 new _ConstExprSerializer(this, localClosureIndexMap, null)
993 .serializeConstructorRef(null, typeName.name,
994 typeName.typeArguments, node.redirectedConstructor.name);
959 } 995 }
960 } else { 996 } else {
961 for (ConstructorInitializer initializer in node.initializers) { 997 for (ConstructorInitializer initializer in node.initializers) {
962 if (initializer is RedirectingConstructorInvocation) { 998 if (initializer is RedirectingConstructorInvocation) {
963 b.isRedirectedConstructor = true; 999 b.isRedirectedConstructor = true;
964 b.redirectedConstructorName = initializer.constructorName?.name; 1000 b.redirectedConstructorName = initializer.constructorName?.name;
965 } 1001 }
966 } 1002 }
967 } 1003 }
968 if (node.constKeyword != null) { 1004 if (node.constKeyword != null) {
969 b.isConst = true; 1005 b.isConst = true;
970 b.constCycleSlot = assignSlot(); 1006 b.constCycleSlot = assignSlot();
971 } 1007 }
972 b.isExternal = node.externalKeyword != null; 1008 b.isExternal = node.externalKeyword != null;
973 b.documentationComment = serializeDocumentation(node.documentationComment); 1009 b.documentationComment = serializeDocumentation(node.documentationComment);
974 b.annotations = serializeAnnotations(node.metadata); 1010 b.annotations = serializeAnnotations(node.metadata);
975 b.codeRange = serializeCodeRange(node); 1011 b.codeRange = serializeCodeRange(node);
976 if (node.constKeyword != null) { 1012 if (node.constKeyword != null) {
977 Set<String> constructorParameterNames = 1013 Set<String> constructorParameterNames =
978 node.parameters.parameters.map((p) => p.identifier.name).toSet(); 1014 node.parameters.parameters.map((p) => p.identifier.name).toSet();
1015 var localClosureIndexMap = null; // TODO(paulberry): fix.
979 b.constantInitializers = node.initializers 1016 b.constantInitializers = node.initializers
980 .map((ConstructorInitializer initializer) => 1017 .map((ConstructorInitializer initializer) =>
981 serializeConstructorInitializer(initializer, (Expression expr) { 1018 serializeConstructorInitializer(initializer, (Expression expr) {
982 return serializeConstExpr(expr, constructorParameterNames); 1019 return serializeConstExpr(
1020 localClosureIndexMap, expr, constructorParameterNames);
983 })) 1021 }))
984 .toList(); 1022 .toList();
985 } 1023 }
986 serializeFunctionBody(b, node.body); 1024 serializeFunctionBody(b, node.body);
987 executables.add(b); 1025 executables.add(b);
988 } 1026 }
989 1027
990 @override 1028 @override
991 UnlinkedParamBuilder visitDefaultFormalParameter( 1029 UnlinkedParamBuilder visitDefaultFormalParameter(
992 DefaultFormalParameter node) { 1030 DefaultFormalParameter node) {
993 UnlinkedParamBuilder b = node.parameter.accept(this); 1031 UnlinkedParamBuilder b = node.parameter.accept(this);
994 if (node.defaultValue != null) { 1032 if (node.defaultValue != null) {
995 b.defaultValue = serializeConstExpr(node.defaultValue); 1033 var localClosureIndexMap = null; // TODO(paulberry): fix.
1034 b.defaultValue =
1035 serializeConstExpr(localClosureIndexMap, node.defaultValue);
996 b.defaultValueCode = node.defaultValue.toSource(); 1036 b.defaultValueCode = node.defaultValue.toSource();
997 } 1037 }
998 b.initializer = serializeInitializerFunction(node.defaultValue); 1038 b.initializer = serializeInitializerFunction(node.defaultValue);
999 b.codeRange = serializeCodeRange(node); 1039 b.codeRange = serializeCodeRange(node);
1000 return b; 1040 return b;
1001 } 1041 }
1002 1042
1003 @override 1043 @override
1004 void visitEnumDeclaration(EnumDeclaration node) { 1044 void visitEnumDeclaration(EnumDeclaration node) {
1005 UnlinkedEnumBuilder b = new UnlinkedEnumBuilder(); 1045 UnlinkedEnumBuilder b = new UnlinkedEnumBuilder();
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1088 false, 1128 false,
1089 node.documentationComment, 1129 node.documentationComment,
1090 node.metadata, 1130 node.metadata,
1091 node.functionExpression.typeParameters, 1131 node.functionExpression.typeParameters,
1092 node.externalKeyword != null)); 1132 node.externalKeyword != null));
1093 } 1133 }
1094 1134
1095 @override 1135 @override
1096 void visitFunctionExpression(FunctionExpression node) { 1136 void visitFunctionExpression(FunctionExpression node) {
1097 if (node.parent is! FunctionDeclaration) { 1137 if (node.parent is! FunctionDeclaration) {
1138 if (_localClosureIndexMap != null) {
1139 _localClosureIndexMap[node.offset] = executables.length;
1140 }
1098 executables.add(serializeExecutable( 1141 executables.add(serializeExecutable(
1099 node, 1142 node,
1100 null, 1143 null,
1101 node.offset, 1144 node.offset,
1102 false, 1145 false,
1103 false, 1146 false,
1104 null, 1147 null,
1105 node.parameters, 1148 node.parameters,
1106 node.body, 1149 node.body,
1107 false, 1150 false,
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 return b; 1293 return b;
1251 } 1294 }
1252 1295
1253 @override 1296 @override
1254 void visitVariableDeclarationStatement(VariableDeclarationStatement node) { 1297 void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
1255 serializeVariables( 1298 serializeVariables(
1256 enclosingBlock, node.variables, false, null, null, false); 1299 enclosingBlock, node.variables, false, null, null, false);
1257 } 1300 }
1258 1301
1259 /** 1302 /**
1303 * Execute [callback], gathering any local closures in
1304 * [_localClosureIndexMap], and return the resulting map.
1305 *
1306 * Properly handles cases where one closure is nested within another.
1307 */
1308 Map<int, int> _withLocalClosureIndexMap(void callback()) {
1309 Map<int, int> prevLocalClosureIndexMap = _localClosureIndexMap;
1310 _localClosureIndexMap = <int, int>{};
1311 callback();
1312 Map<int, int> localClosureIndexMap = _localClosureIndexMap;
1313 _localClosureIndexMap = prevLocalClosureIndexMap;
1314 return localClosureIndexMap;
1315 }
1316
1317 /**
1260 * Helper method to determine if a given [typeName] refers to `dynamic`. 1318 * Helper method to determine if a given [typeName] refers to `dynamic`.
1261 */ 1319 */
1262 static bool isDynamic(TypeName typeName) { 1320 static bool isDynamic(TypeName typeName) {
1263 Identifier name = typeName.name; 1321 Identifier name = typeName.name;
1264 return name is SimpleIdentifier && name.name == 'dynamic'; 1322 return name is SimpleIdentifier && name.name == 'dynamic';
1265 } 1323 }
1266 } 1324 }
1267 1325
1268 /** 1326 /**
1269 * A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s. 1327 * A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s.
1270 */ 1328 */
1271 class _TypeParameterScope extends _Scope { 1329 class _TypeParameterScope extends _Scope {
1272 /** 1330 /**
1273 * Get the number of [_ScopedTypeParameter]s defined in this 1331 * Get the number of [_ScopedTypeParameter]s defined in this
1274 * [_TypeParameterScope]. 1332 * [_TypeParameterScope].
1275 */ 1333 */
1276 int get length => _definedNames.length; 1334 int get length => _definedNames.length;
1277 } 1335 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/summary/resynthesize.dart ('k') | pkg/analyzer/lib/src/summary/summarize_const_expr.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698