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 | |
84 /// Concrete shadow object representing a set of invocation arguments. | 56 /// Concrete shadow object representing a set of invocation arguments. |
85 class KernelArguments extends Arguments { | 57 class KernelArguments extends Arguments { |
86 bool _hasExplicitTypeArguments; | 58 bool _hasExplicitTypeArguments; |
87 | 59 |
88 KernelArguments(List<Expression> positional, | 60 KernelArguments(List<Expression> positional, |
89 {List<DartType> types, List<NamedExpression> named}) | 61 {List<DartType> types, List<NamedExpression> named}) |
90 : _hasExplicitTypeArguments = types != null && types.isNotEmpty, | 62 : _hasExplicitTypeArguments = types != null && types.isNotEmpty, |
91 super(positional, types: types, named: named); | 63 super(positional, types: types, named: named); |
92 | 64 |
93 static void setExplicitArgumentTypes( | 65 static void setExplicitArgumentTypes( |
(...skipping 1258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 KernelMethodInvocation(Expression receiver, Name name, Arguments arguments, | 1324 KernelMethodInvocation(Expression receiver, Name name, Arguments arguments, |
1353 {bool isImplicitCall: false, Member interfaceTarget}) | 1325 {bool isImplicitCall: false, Member interfaceTarget}) |
1354 : _isImplicitCall = isImplicitCall, | 1326 : _isImplicitCall = isImplicitCall, |
1355 super(receiver, name, arguments, interfaceTarget); | 1327 super(receiver, name, arguments, interfaceTarget); |
1356 | 1328 |
1357 @override | 1329 @override |
1358 void _collectDependencies(KernelDependencyCollector collector) { | 1330 void _collectDependencies(KernelDependencyCollector collector) { |
1359 // The inference dependencies are the inference dependencies of the | 1331 // The inference dependencies are the inference dependencies of the |
1360 // receiver. | 1332 // receiver. |
1361 collector.collectDependencies(receiver); | 1333 collector.collectDependencies(receiver); |
1362 if (_isOverloadableArithmeticOperator(name.name)) { | 1334 if (isOverloadableArithmeticOperator(name.name)) { |
1363 collector.collectDependencies(arguments.positional[0]); | 1335 collector.collectDependencies(arguments.positional[0]); |
1364 } | 1336 } |
1365 } | 1337 } |
1366 | 1338 |
1367 @override | 1339 @override |
1368 DartType _inferExpression( | 1340 DartType _inferExpression( |
1369 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { | 1341 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
1370 typeNeeded = inferrer.listener.methodInvocationEnter(this, typeContext) || | 1342 return inferrer.inferMethodInvocation(this, receiver, fileOffset, this, |
1371 typeNeeded; | 1343 _isImplicitCall, typeContext, typeNeeded); |
1372 // First infer the receiver so we can look up the method that was invoked. | |
1373 var receiverType = inferrer.inferExpression(receiver, null, true); | |
1374 bool isOverloadedArithmeticOperator = false; | |
1375 Member interfaceMember = | |
1376 inferrer.findMethodInvocationMember(receiverType, this); | |
1377 if (interfaceMember is Procedure) { | |
1378 isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment | |
1379 .isOverloadedArithmeticOperatorAndType(interfaceMember, receiverType); | |
1380 } | |
1381 var calleeType = inferrer.getCalleeFunctionType( | |
1382 interfaceMember, receiverType, name, !_isImplicitCall); | |
1383 bool forceArgumentInference = false; | |
1384 if (inferrer.isDryRun) { | |
1385 if (_isUserDefinableOperator(name.name)) { | |
1386 // If this is an overloadable arithmetic operator, then type inference | |
1387 // might depend on the RHS, so conservatively assume it does. | |
1388 forceArgumentInference = _isOverloadableArithmeticOperator(name.name); | |
1389 } else { | |
1390 // If no type arguments were given, then type inference might depend on | |
1391 // the arguments (because the called method might be generic), so | |
1392 // conservatively assume it does. | |
1393 forceArgumentInference = getExplicitTypeArguments(arguments) == null; | |
1394 } | |
1395 } | |
1396 var inferredType = inferrer.inferInvocation(typeContext, typeNeeded, | |
1397 fileOffset, calleeType, calleeType.returnType, arguments, | |
1398 isOverloadedArithmeticOperator: isOverloadedArithmeticOperator, | |
1399 receiverType: receiverType, | |
1400 forceArgumentInference: forceArgumentInference); | |
1401 inferrer.listener.methodInvocationExit(this, inferredType); | |
1402 return inferredType; | |
1403 } | 1344 } |
1404 } | 1345 } |
1405 | 1346 |
1406 /// Shadow object for [Not]. | 1347 /// Shadow object for [Not]. |
1407 class KernelNot extends Not implements KernelExpression { | 1348 class KernelNot extends Not implements KernelExpression { |
1408 KernelNot(Expression operand) : super(operand); | 1349 KernelNot(Expression operand) : super(operand); |
1409 | 1350 |
1410 @override | 1351 @override |
1411 void _collectDependencies(KernelDependencyCollector collector) { | 1352 void _collectDependencies(KernelDependencyCollector collector) { |
1412 collector.collectDependencies(operand); | 1353 collector.collectDependencies(operand); |
1413 } | 1354 } |
1414 | 1355 |
1415 @override | 1356 @override |
1416 DartType _inferExpression( | 1357 DartType _inferExpression( |
1417 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { | 1358 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
1418 typeNeeded = inferrer.listener.notEnter(this, typeContext) || typeNeeded; | 1359 typeNeeded = inferrer.listener.notEnter(this, typeContext) || typeNeeded; |
1419 // First infer the receiver so we can look up the method that was invoked. | 1360 // First infer the receiver so we can look up the method that was invoked. |
1420 var boolType = inferrer.coreTypes.boolClass.rawType; | 1361 var boolType = inferrer.coreTypes.boolClass.rawType; |
1421 inferrer.inferExpression(operand, boolType, false); | 1362 inferrer.inferExpression(operand, boolType, false); |
1422 DartType inferredType = typeNeeded ? boolType : null; | 1363 DartType inferredType = typeNeeded ? boolType : null; |
1423 inferrer.listener.notExit(this, inferredType); | 1364 inferrer.listener.notExit(this, inferredType); |
1424 return inferredType; | 1365 return inferredType; |
1425 } | 1366 } |
1426 } | 1367 } |
1427 | 1368 |
| 1369 /// Concrete shadow object representing a null-aware method invocation. |
| 1370 /// |
| 1371 /// A null-aware method invocation of the form `a?.b(...)` is represented as the |
| 1372 /// expression: |
| 1373 /// |
| 1374 /// let v = a in v == null ? null : v.b(...) |
| 1375 class KernelNullAwareMethodInvocation extends Let implements KernelExpression { |
| 1376 KernelNullAwareMethodInvocation(VariableDeclaration variable, Expression body) |
| 1377 : super(variable, body); |
| 1378 |
| 1379 @override |
| 1380 ConditionalExpression get body => super.body; |
| 1381 |
| 1382 MethodInvocation get _desugaredInvocation => body.otherwise; |
| 1383 |
| 1384 @override |
| 1385 void _collectDependencies(KernelDependencyCollector collector) { |
| 1386 // Null aware expressions are not immediately evident. |
| 1387 collector.recordNotImmediatelyEvident(fileOffset); |
| 1388 } |
| 1389 |
| 1390 @override |
| 1391 DartType _inferExpression( |
| 1392 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
| 1393 var inferredType = inferrer.inferMethodInvocation( |
| 1394 this, |
| 1395 variable.initializer, |
| 1396 fileOffset, |
| 1397 _desugaredInvocation, |
| 1398 false, |
| 1399 typeContext, |
| 1400 true, |
| 1401 receiverVariable: variable); |
| 1402 body.staticType = inferredType; |
| 1403 return inferredType; |
| 1404 } |
| 1405 } |
| 1406 |
1428 /// Concrete shadow object representing a null-aware read from a property. | 1407 /// Concrete shadow object representing a null-aware read from a property. |
1429 /// | 1408 /// |
1430 /// A null-aware property get of the form `a?.b` is represented as the kernel | 1409 /// A null-aware property get of the form `a?.b` is represented as the kernel |
1431 /// expression: | 1410 /// expression: |
1432 /// | 1411 /// |
1433 /// let v = a in v == null ? null : v.b | 1412 /// let v = a in v == null ? null : v.b |
1434 class KernelNullAwarePropertyGet extends Let implements KernelExpression { | 1413 class KernelNullAwarePropertyGet extends Let implements KernelExpression { |
1435 KernelNullAwarePropertyGet( | 1414 KernelNullAwarePropertyGet( |
1436 VariableDeclaration variable, ConditionalExpression body) | 1415 VariableDeclaration variable, ConditionalExpression body) |
1437 : super(variable, body); | 1416 : super(variable, body); |
(...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2286 } | 2265 } |
2287 | 2266 |
2288 transformChildren(v) { | 2267 transformChildren(v) { |
2289 return internalError("Internal error: Unsupported operation."); | 2268 return internalError("Internal error: Unsupported operation."); |
2290 } | 2269 } |
2291 | 2270 |
2292 visitChildren(v) { | 2271 visitChildren(v) { |
2293 return internalError("Internal error: Unsupported operation."); | 2272 return internalError("Internal error: Unsupported operation."); |
2294 } | 2273 } |
2295 } | 2274 } |
OLD | NEW |