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`. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 if (arguments is KernelArguments) { | 46 if (arguments is KernelArguments) { |
47 return arguments._hasExplicitTypeArguments ? arguments.types : null; | 47 return arguments._hasExplicitTypeArguments ? arguments.types : null; |
48 } else { | 48 } else { |
49 // This code path should only be taken in situations where there are no | 49 // This code path should only be taken in situations where there are no |
50 // type arguments at all, e.g. calling a user-definable operator. | 50 // type arguments at all, e.g. calling a user-definable operator. |
51 assert(arguments.types.isEmpty); | 51 assert(arguments.types.isEmpty); |
52 return null; | 52 return null; |
53 } | 53 } |
54 } | 54 } |
55 | 55 |
| 56 bool _isOverloadableArithmeticOperator(String name) { |
| 57 return identical(name, '+') || |
| 58 identical(name, '-') || |
| 59 identical(name, '*') || |
| 60 identical(name, '%'); |
| 61 } |
| 62 |
| 63 bool _isUserDefinableOperator(String name) { |
| 64 return identical(name, '<') || |
| 65 identical(name, '>') || |
| 66 identical(name, '<=') || |
| 67 identical(name, '>=') || |
| 68 identical(name, '==') || |
| 69 identical(name, '-') || |
| 70 identical(name, '+') || |
| 71 identical(name, '/') || |
| 72 identical(name, '~/') || |
| 73 identical(name, '*') || |
| 74 identical(name, '%') || |
| 75 identical(name, '|') || |
| 76 identical(name, '^') || |
| 77 identical(name, '&') || |
| 78 identical(name, '<<') || |
| 79 identical(name, '>>') || |
| 80 identical(name, '[]=') || |
| 81 identical(name, '~'); |
| 82 } |
| 83 |
56 /// Concrete shadow object representing a set of invocation arguments. | 84 /// Concrete shadow object representing a set of invocation arguments. |
57 class KernelArguments extends Arguments { | 85 class KernelArguments extends Arguments { |
58 bool _hasExplicitTypeArguments; | 86 bool _hasExplicitTypeArguments; |
59 | 87 |
60 KernelArguments(List<Expression> positional, | 88 KernelArguments(List<Expression> positional, |
61 {List<DartType> types, List<NamedExpression> named}) | 89 {List<DartType> types, List<NamedExpression> named}) |
62 : _hasExplicitTypeArguments = types != null && types.isNotEmpty, | 90 : _hasExplicitTypeArguments = types != null && types.isNotEmpty, |
63 super(positional, types: types, named: named); | 91 super(positional, types: types, named: named); |
64 | 92 |
65 static void setExplicitArgumentTypes( | 93 static void setExplicitArgumentTypes( |
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 for (var parameter in function.positionalParameters) { | 777 for (var parameter in function.positionalParameters) { |
750 if (parameter.initializer != null) { | 778 if (parameter.initializer != null) { |
751 inferrer.inferExpression(parameter.initializer, parameter.type, false); | 779 inferrer.inferExpression(parameter.initializer, parameter.type, false); |
752 } | 780 } |
753 } | 781 } |
754 for (var parameter in function.namedParameters) { | 782 for (var parameter in function.namedParameters) { |
755 if (parameter.initializer != null) { | 783 if (parameter.initializer != null) { |
756 inferrer.inferExpression(parameter.initializer, parameter.type, false); | 784 inferrer.inferExpression(parameter.initializer, parameter.type, false); |
757 } | 785 } |
758 } | 786 } |
759 var oldClosureContext = inferrer.closureContext; | 787 if (!inferrer.isTopLevel) { |
760 inferrer.closureContext = | 788 var oldClosureContext = inferrer.closureContext; |
761 new ClosureContext(inferrer, function.asyncMarker, function.returnType); | 789 inferrer.closureContext = new ClosureContext( |
762 inferrer.inferStatement(function.body); | 790 inferrer, function.asyncMarker, function.returnType); |
763 inferrer.closureContext = oldClosureContext; | 791 inferrer.inferStatement(function.body); |
| 792 inferrer.closureContext = oldClosureContext; |
| 793 } |
764 inferrer.listener.functionDeclarationExit(this); | 794 inferrer.listener.functionDeclarationExit(this); |
765 } | 795 } |
766 } | 796 } |
767 | 797 |
768 /// Concrete shadow object representing a function expression in kernel form. | 798 /// Concrete shadow object representing a function expression in kernel form. |
769 class KernelFunctionExpression extends FunctionExpression | 799 class KernelFunctionExpression extends FunctionExpression |
770 implements KernelExpression { | 800 implements KernelExpression { |
771 KernelFunctionExpression(FunctionNode function) : super(function); | 801 KernelFunctionExpression(FunctionNode function) : super(function); |
772 | 802 |
773 @override | 803 @override |
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 KernelMethodInvocation(Expression receiver, Name name, Arguments arguments, | 1296 KernelMethodInvocation(Expression receiver, Name name, Arguments arguments, |
1267 {bool isImplicitCall: false, Member interfaceTarget}) | 1297 {bool isImplicitCall: false, Member interfaceTarget}) |
1268 : _isImplicitCall = isImplicitCall, | 1298 : _isImplicitCall = isImplicitCall, |
1269 super(receiver, name, arguments, interfaceTarget); | 1299 super(receiver, name, arguments, interfaceTarget); |
1270 | 1300 |
1271 @override | 1301 @override |
1272 void _collectDependencies(KernelDependencyCollector collector) { | 1302 void _collectDependencies(KernelDependencyCollector collector) { |
1273 // The inference dependencies are the inference dependencies of the | 1303 // The inference dependencies are the inference dependencies of the |
1274 // receiver. | 1304 // receiver. |
1275 collector.collectDependencies(receiver); | 1305 collector.collectDependencies(receiver); |
1276 if (identical(name, '+') || | 1306 if (_isOverloadableArithmeticOperator(name.name)) { |
1277 identical(name, '-') || | |
1278 identical(name, '*') || | |
1279 identical(name, '%')) { | |
1280 collector.collectDependencies(arguments.positional[0]); | 1307 collector.collectDependencies(arguments.positional[0]); |
1281 } | 1308 } |
1282 } | 1309 } |
1283 | 1310 |
1284 @override | 1311 @override |
1285 DartType _inferExpression( | 1312 DartType _inferExpression( |
1286 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { | 1313 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
1287 typeNeeded = inferrer.listener.methodInvocationEnter(this, typeContext) || | 1314 typeNeeded = inferrer.listener.methodInvocationEnter(this, typeContext) || |
1288 typeNeeded; | 1315 typeNeeded; |
1289 // First infer the receiver so we can look up the method that was invoked. | 1316 // First infer the receiver so we can look up the method that was invoked. |
1290 var receiverType = inferrer.inferExpression(receiver, null, true); | 1317 var receiverType = inferrer.inferExpression(receiver, null, true); |
1291 bool isOverloadedArithmeticOperator = false; | 1318 bool isOverloadedArithmeticOperator = false; |
1292 Member interfaceMember = | 1319 Member interfaceMember = |
1293 inferrer.findMethodInvocationMember(receiverType, this); | 1320 inferrer.findMethodInvocationMember(receiverType, this); |
1294 if (interfaceMember is Procedure) { | 1321 if (interfaceMember is Procedure) { |
1295 isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment | 1322 isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment |
1296 .isOverloadedArithmeticOperator(interfaceMember); | 1323 .isOverloadedArithmeticOperator(interfaceMember); |
1297 } | 1324 } |
1298 var calleeType = inferrer.getCalleeFunctionType( | 1325 var calleeType = inferrer.getCalleeFunctionType( |
1299 interfaceMember, receiverType, name, !_isImplicitCall); | 1326 interfaceMember, receiverType, name, !_isImplicitCall); |
| 1327 bool forceArgumentInference = false; |
| 1328 if (inferrer.isDryRun) { |
| 1329 if (_isUserDefinableOperator(name.name)) { |
| 1330 // If this is an overloadable arithmetic operator, then type inference |
| 1331 // might depend on the RHS, so conservatively assume it does. |
| 1332 forceArgumentInference = _isOverloadableArithmeticOperator(name.name); |
| 1333 } else { |
| 1334 // If no type arguments were given, then type inference might depend on |
| 1335 // the arguments (because the called method might be generic), so |
| 1336 // conservatively assume it does. |
| 1337 forceArgumentInference = getExplicitTypeArguments(arguments) == null; |
| 1338 } |
| 1339 } |
1300 var inferredType = inferrer.inferInvocation(typeContext, typeNeeded, | 1340 var inferredType = inferrer.inferInvocation(typeContext, typeNeeded, |
1301 fileOffset, calleeType, calleeType.returnType, arguments, | 1341 fileOffset, calleeType, calleeType.returnType, arguments, |
1302 isOverloadedArithmeticOperator: isOverloadedArithmeticOperator, | 1342 isOverloadedArithmeticOperator: isOverloadedArithmeticOperator, |
1303 receiverType: receiverType); | 1343 receiverType: receiverType, |
| 1344 forceArgumentInference: forceArgumentInference); |
1304 inferrer.listener.methodInvocationExit(this, inferredType); | 1345 inferrer.listener.methodInvocationExit(this, inferredType); |
1305 return inferredType; | 1346 return inferredType; |
1306 } | 1347 } |
1307 } | 1348 } |
1308 | 1349 |
1309 /// Shadow object for [Not]. | 1350 /// Shadow object for [Not]. |
1310 class KernelNot extends Not implements KernelExpression { | 1351 class KernelNot extends Not implements KernelExpression { |
1311 KernelNot(Expression operand) : super(operand); | 1352 KernelNot(Expression operand) : super(operand); |
1312 | 1353 |
1313 @override | 1354 @override |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 typeNeeded; | 1412 typeNeeded; |
1372 // TODO(paulberry): record the appropriate types on let variables and | 1413 // TODO(paulberry): record the appropriate types on let variables and |
1373 // conditional expressions. | 1414 // conditional expressions. |
1374 var receiverType = _inferReceiver(inferrer); | 1415 var receiverType = _inferReceiver(inferrer); |
1375 if (read != null) { | 1416 if (read != null) { |
1376 inferrer.findPropertyGetMember(receiverType, read, silent: true); | 1417 inferrer.findPropertyGetMember(receiverType, read, silent: true); |
1377 } | 1418 } |
1378 Member writeMember; | 1419 Member writeMember; |
1379 if (write != null) { | 1420 if (write != null) { |
1380 writeMember = inferrer.findPropertySetMember(receiverType, write); | 1421 writeMember = inferrer.findPropertySetMember(receiverType, write); |
| 1422 if (inferrer.isTopLevel && |
| 1423 ((writeMember is Procedure && |
| 1424 writeMember.kind == ProcedureKind.Setter) || |
| 1425 writeMember is Field)) { |
| 1426 // References to fields and setters can't be relied upon for top level |
| 1427 // inference. |
| 1428 inferrer.recordNotImmediatelyEvident(fileOffset); |
| 1429 } |
1381 } | 1430 } |
1382 // To replicate analyzer behavior, we base type inference on the write | 1431 // To replicate analyzer behavior, we base type inference on the write |
1383 // member. TODO(paulberry): would it be better to use the read member when | 1432 // member. TODO(paulberry): would it be better to use the read member when |
1384 // doing compound assignment? | 1433 // doing compound assignment? |
1385 var writeContext = writeMember?.setterType; | 1434 var writeContext = writeMember?.setterType; |
1386 var inferredType = _inferRhs(inferrer, writeContext); | 1435 var inferredType = _inferRhs(inferrer, writeContext); |
1387 inferrer.listener.propertyAssignExit(desugared, inferredType); | 1436 inferrer.listener.propertyAssignExit(desugared, inferredType); |
1388 return inferredType; | 1437 return inferredType; |
1389 } | 1438 } |
1390 } | 1439 } |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1547 DartType _inferExpression( | 1596 DartType _inferExpression( |
1548 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { | 1597 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
1549 typeNeeded = inferrer.listener.staticAssignEnter(desugared, typeContext) || | 1598 typeNeeded = inferrer.listener.staticAssignEnter(desugared, typeContext) || |
1550 typeNeeded; | 1599 typeNeeded; |
1551 // TODO(paulberry): record the appropriate types on let variables and | 1600 // TODO(paulberry): record the appropriate types on let variables and |
1552 // conditional expressions. | 1601 // conditional expressions. |
1553 DartType writeContext; | 1602 DartType writeContext; |
1554 var write = this.write; | 1603 var write = this.write; |
1555 if (write is StaticSet) { | 1604 if (write is StaticSet) { |
1556 writeContext = write.target.setterType; | 1605 writeContext = write.target.setterType; |
| 1606 if (inferrer.isDryRun) { |
| 1607 var target = write.target; |
| 1608 if (target is KernelField && target._fieldNode != null) { |
| 1609 inferrer.recordDryRunDependency(target._fieldNode); |
| 1610 } |
| 1611 } |
1557 } | 1612 } |
1558 var inferredType = _inferRhs(inferrer, writeContext); | 1613 var inferredType = _inferRhs(inferrer, writeContext); |
1559 inferrer.listener.staticAssignExit(desugared, inferredType); | 1614 inferrer.listener.staticAssignExit(desugared, inferredType); |
1560 return inferredType; | 1615 return inferredType; |
1561 } | 1616 } |
1562 } | 1617 } |
1563 | 1618 |
1564 /// Concrete shadow object representing a read of a static variable in kernel | 1619 /// Concrete shadow object representing a read of a static variable in kernel |
1565 /// form. | 1620 /// form. |
1566 class KernelStaticGet extends StaticGet implements KernelExpression { | 1621 class KernelStaticGet extends StaticGet implements KernelExpression { |
(...skipping 16 matching lines...) Expand all Loading... |
1583 if (target is KernelField && target._fieldNode != null) { | 1638 if (target is KernelField && target._fieldNode != null) { |
1584 collector.recordDependency(target._fieldNode); | 1639 collector.recordDependency(target._fieldNode); |
1585 } | 1640 } |
1586 } | 1641 } |
1587 | 1642 |
1588 @override | 1643 @override |
1589 DartType _inferExpression( | 1644 DartType _inferExpression( |
1590 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { | 1645 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
1591 typeNeeded = | 1646 typeNeeded = |
1592 inferrer.listener.staticGetEnter(this, typeContext) || typeNeeded; | 1647 inferrer.listener.staticGetEnter(this, typeContext) || typeNeeded; |
| 1648 if (inferrer.isDryRun) { |
| 1649 var target = this.target; |
| 1650 if (target is KernelField && target._fieldNode != null) { |
| 1651 inferrer.recordDryRunDependency(target._fieldNode); |
| 1652 } |
| 1653 } |
1593 var inferredType = typeNeeded ? target.getterType : null; | 1654 var inferredType = typeNeeded ? target.getterType : null; |
1594 inferrer.listener.staticGetExit(this, inferredType); | 1655 inferrer.listener.staticGetExit(this, inferredType); |
1595 return inferredType; | 1656 return inferredType; |
1596 } | 1657 } |
1597 } | 1658 } |
1598 | 1659 |
1599 /// Shadow object for [StaticInvocation]. | 1660 /// Shadow object for [StaticInvocation]. |
1600 class KernelStaticInvocation extends StaticInvocation | 1661 class KernelStaticInvocation extends StaticInvocation |
1601 implements KernelExpression { | 1662 implements KernelExpression { |
1602 KernelStaticInvocation(Procedure target, Arguments arguments, | 1663 KernelStaticInvocation(Procedure target, Arguments arguments, |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1894 : super(engine, uri, listener, topLevel, thisType); | 1955 : super(engine, uri, listener, topLevel, thisType); |
1895 | 1956 |
1896 @override | 1957 @override |
1897 Expression getFieldInitializer(KernelField field) { | 1958 Expression getFieldInitializer(KernelField field) { |
1898 return field.initializer; | 1959 return field.initializer; |
1899 } | 1960 } |
1900 | 1961 |
1901 @override | 1962 @override |
1902 DartType inferExpression( | 1963 DartType inferExpression( |
1903 Expression expression, DartType typeContext, bool typeNeeded) { | 1964 Expression expression, DartType typeContext, bool typeNeeded) { |
| 1965 // When doing top level inference, we skip subexpressions whose type isn't |
| 1966 // needed so that we don't induce bogus dependencies on fields mentioned in |
| 1967 // those subexpressions. |
| 1968 if (!typeNeeded && isTopLevel) return null; |
| 1969 |
1904 if (expression is KernelExpression) { | 1970 if (expression is KernelExpression) { |
1905 // Use polymorphic dispatch on [KernelExpression] to perform whatever kind | 1971 // Use polymorphic dispatch on [KernelExpression] to perform whatever kind |
1906 // of type inference is correct for this kind of statement. | 1972 // of type inference is correct for this kind of statement. |
1907 // TODO(paulberry): experiment to see if dynamic dispatch would be better, | 1973 // TODO(paulberry): experiment to see if dynamic dispatch would be better, |
1908 // so that the type hierarchy will be simpler (which may speed up "is" | 1974 // so that the type hierarchy will be simpler (which may speed up "is" |
1909 // checks). | 1975 // checks). |
1910 return expression._inferExpression(this, typeContext, typeNeeded); | 1976 return expression._inferExpression(this, typeContext, typeNeeded); |
1911 } else { | 1977 } else { |
1912 // Encountered an expression type for which type inference is not yet | 1978 // Encountered an expression type for which type inference is not yet |
1913 // implemented, so just infer dynamic for now. | 1979 // implemented, so just infer dynamic for now. |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2227 } | 2293 } |
2228 | 2294 |
2229 transformChildren(v) { | 2295 transformChildren(v) { |
2230 return internalError("Internal error: Unsupported operation."); | 2296 return internalError("Internal error: Unsupported operation."); |
2231 } | 2297 } |
2232 | 2298 |
2233 visitChildren(v) { | 2299 visitChildren(v) { |
2234 return internalError("Internal error: Unsupported operation."); | 2300 return internalError("Internal error: Unsupported operation."); |
2235 } | 2301 } |
2236 } | 2302 } |
OLD | NEW |