| 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 |