| 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 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 /// form. | 339 /// form. |
| 340 class KernelFunctionDeclaration extends FunctionDeclaration | 340 class KernelFunctionDeclaration extends FunctionDeclaration |
| 341 implements KernelStatement { | 341 implements KernelStatement { |
| 342 KernelFunctionDeclaration(VariableDeclaration variable, FunctionNode function) | 342 KernelFunctionDeclaration(VariableDeclaration variable, FunctionNode function) |
| 343 : super(variable, function); | 343 : super(variable, function); |
| 344 | 344 |
| 345 @override | 345 @override |
| 346 void _inferStatement(KernelTypeInferrer inferrer) { | 346 void _inferStatement(KernelTypeInferrer inferrer) { |
| 347 inferrer.listener.functionDeclarationEnter(this); | 347 inferrer.listener.functionDeclarationEnter(this); |
| 348 var oldClosureContext = inferrer.closureContext; | 348 var oldClosureContext = inferrer.closureContext; |
| 349 inferrer.closureContext = null; | 349 inferrer.closureContext = |
| 350 new ClosureContext(inferrer, function.asyncMarker, function.returnType); |
| 350 inferrer.inferStatement(function.body); | 351 inferrer.inferStatement(function.body); |
| 351 inferrer.closureContext = oldClosureContext; | 352 inferrer.closureContext = oldClosureContext; |
| 352 inferrer.listener.functionDeclarationExit(this); | 353 inferrer.listener.functionDeclarationExit(this); |
| 353 } | 354 } |
| 354 } | 355 } |
| 355 | 356 |
| 356 /// Concrete shadow object representing a function expression in kernel form. | 357 /// Concrete shadow object representing a function expression in kernel form. |
| 357 class KernelFunctionExpression extends FunctionExpression | 358 class KernelFunctionExpression extends FunctionExpression |
| 358 implements KernelExpression { | 359 implements KernelExpression { |
| 359 KernelFunctionExpression(FunctionNode function) : super(function); | 360 KernelFunctionExpression(FunctionNode function) : super(function); |
| 360 | 361 |
| 361 @override | 362 @override |
| 362 DartType _inferExpression( | 363 DartType _inferExpression( |
| 363 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { | 364 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { |
| 364 var asyncMarker = function.asyncMarker; | |
| 365 bool isAsync = asyncMarker == AsyncMarker.Async || | |
| 366 asyncMarker == AsyncMarker.AsyncStar; | |
| 367 bool isGenerator = asyncMarker == AsyncMarker.SyncStar || | |
| 368 asyncMarker == AsyncMarker.AsyncStar; | |
| 369 typeNeeded = inferrer.listener.functionExpressionEnter(this, typeContext) || | 365 typeNeeded = inferrer.listener.functionExpressionEnter(this, typeContext) || |
| 370 typeNeeded; | 366 typeNeeded; |
| 371 // TODO(paulberry): do we also need to visit default parameter values? | 367 // TODO(paulberry): do we also need to visit default parameter values? |
| 372 | 368 |
| 373 // Let `<T0, ..., Tn>` be the set of type parameters of the closure (with | 369 // Let `<T0, ..., Tn>` be the set of type parameters of the closure (with |
| 374 // `n`=0 if there are no type parameters). | 370 // `n`=0 if there are no type parameters). |
| 375 List<TypeParameter> typeParameters = function.typeParameters; | 371 List<TypeParameter> typeParameters = function.typeParameters; |
| 376 | 372 |
| 377 // Let `(P0 x0, ..., Pm xm)` be the set of formal parameters of the closure | 373 // Let `(P0 x0, ..., Pm xm)` be the set of formal parameters of the closure |
| 378 // (including required, positional optional, and named optional parameters). | 374 // (including required, positional optional, and named optional parameters). |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 inferrer.instrumentation?.record( | 433 inferrer.instrumentation?.record( |
| 438 Uri.parse(inferrer.uri), | 434 Uri.parse(inferrer.uri), |
| 439 formal.fileOffset, | 435 formal.fileOffset, |
| 440 'type', | 436 'type', |
| 441 new InstrumentationValueForType(inferredType)); | 437 new InstrumentationValueForType(inferredType)); |
| 442 formal.type = inferredType; | 438 formal.type = inferredType; |
| 443 } | 439 } |
| 444 } | 440 } |
| 445 } | 441 } |
| 446 | 442 |
| 447 // Let `N’` be `N[T/S]`, adjusted accordingly if the closure is declared | 443 // Let `N'` be `N[T/S]`. The [ClosureContext] constructor will adjust |
| 448 // with `async`, `async*`, or `sync*`. | 444 // accordingly if the closure is declared with `async`, `async*`, or |
| 445 // `sync*`. |
| 449 if (returnContext != null) { | 446 if (returnContext != null) { |
| 450 returnContext = substitution.substituteType(returnContext); | 447 returnContext = substitution.substituteType(returnContext); |
| 451 } | 448 } |
| 452 if (isGenerator) { | |
| 453 if (isAsync) { | |
| 454 returnContext = inferrer.getTypeArgumentOf( | |
| 455 returnContext, inferrer.coreTypes.streamClass); | |
| 456 } else { | |
| 457 returnContext = inferrer.getTypeArgumentOf( | |
| 458 returnContext, inferrer.coreTypes.iterableClass); | |
| 459 } | |
| 460 } else if (isAsync) { | |
| 461 // TODO(paulberry): do we have to handle FutureOr<> here? | |
| 462 returnContext = inferrer.getTypeArgumentOf( | |
| 463 returnContext, inferrer.coreTypes.futureClass); | |
| 464 } | |
| 465 | 449 |
| 466 // Apply type inference to `B` in return context `N’`, with any references | 450 // Apply type inference to `B` in return context `N’`, with any references |
| 467 // to `xi` in `B` having type `Pi`. This produces `B’`. | 451 // to `xi` in `B` having type `Pi`. This produces `B’`. |
| 468 bool isExpressionFunction = function.body is ReturnStatement; | 452 bool isExpressionFunction = function.body is ReturnStatement; |
| 469 bool needToSetReturnType = isExpressionFunction || inferrer.strongMode; | 453 bool needToSetReturnType = isExpressionFunction || inferrer.strongMode; |
| 470 ClosureContext oldClosureContext = inferrer.closureContext; | 454 ClosureContext oldClosureContext = inferrer.closureContext; |
| 471 inferrer.closureContext = | 455 ClosureContext closureContext = |
| 472 new ClosureContext(isAsync, isGenerator, returnContext); | 456 new ClosureContext(inferrer, function.asyncMarker, returnContext); |
| 457 inferrer.closureContext = closureContext; |
| 473 inferrer.inferStatement(function.body); | 458 inferrer.inferStatement(function.body); |
| 474 | 459 |
| 475 // If the closure is declared with `async*` or `sync*`, let `M` be the least | 460 // If the closure is declared with `async*` or `sync*`, let `M` be the least |
| 476 // upper bound of the types of the `yield` expressions in `B’`, or `void` if | 461 // upper bound of the types of the `yield` expressions in `B’`, or `void` if |
| 477 // `B’` contains no `yield` expressions. Otherwise, let `M` be the least | 462 // `B’` contains no `yield` expressions. Otherwise, let `M` be the least |
| 478 // upper bound of the types of the `return` expressions in `B’`, or `void` | 463 // upper bound of the types of the `return` expressions in `B’`, or `void` |
| 479 // if `B’` contains no `return` expressions. | 464 // if `B’` contains no `return` expressions. |
| 480 DartType inferredReturnType; | 465 DartType inferredReturnType; |
| 481 if (needToSetReturnType || typeNeeded) { | 466 if (needToSetReturnType || typeNeeded) { |
| 482 inferredReturnType = inferrer.inferReturnType( | 467 inferredReturnType = |
| 483 inferrer.closureContext.inferredReturnType, isExpressionFunction); | 468 closureContext.inferReturnType(inferrer, isExpressionFunction); |
| 484 if (!isExpressionFunction && | |
| 485 returnContext != null && | |
| 486 (!inferrer.typeSchemaEnvironment | |
| 487 .isSubtypeOf(inferredReturnType, returnContext) || | |
| 488 returnContext is VoidType)) { | |
| 489 // For block-bodied functions, if the inferred return type isn't a | |
| 490 // subtype of the context (or the context is void), we use the context. | |
| 491 // TODO(paulberry): this is inherited from analyzer; it's not part of | |
| 492 // the spec. See also dartbug.com/29606. | |
| 493 inferredReturnType = greatestClosure(inferrer.coreTypes, returnContext); | |
| 494 } | |
| 495 | |
| 496 // Let `M’` be `M`, adjusted accordingly if the closure is declared with | |
| 497 // `async`, `async*`, or `sync*`. | |
| 498 if (isGenerator) { | |
| 499 if (isAsync) { | |
| 500 inferredReturnType = inferrer.wrapType( | |
| 501 inferredReturnType, inferrer.coreTypes.streamClass); | |
| 502 } else { | |
| 503 inferredReturnType = inferrer.wrapType( | |
| 504 inferredReturnType, inferrer.coreTypes.iterableClass); | |
| 505 } | |
| 506 } else if (isAsync) { | |
| 507 inferredReturnType = inferrer.wrapFutureType(inferredReturnType); | |
| 508 } | |
| 509 } | 469 } |
| 510 | 470 |
| 511 // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B` with | 471 // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B` with |
| 512 // type `<T0, ..., Tn>(R0, ..., Rn) -> M’` (with some of the `Ri` and `xi` | 472 // type `<T0, ..., Tn>(R0, ..., Rn) -> M’` (with some of the `Ri` and `xi` |
| 513 // denoted as optional or named parameters, if appropriate). | 473 // denoted as optional or named parameters, if appropriate). |
| 514 if (needToSetReturnType) { | 474 if (needToSetReturnType) { |
| 515 inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset, | 475 inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset, |
| 516 'returnType', new InstrumentationValueForType(inferredReturnType)); | 476 'returnType', new InstrumentationValueForType(inferredReturnType)); |
| 517 function.returnType = inferredReturnType; | 477 function.returnType = inferredReturnType; |
| 518 } | 478 } |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 } | 760 } |
| 801 | 761 |
| 802 /// Concrete shadow object representing a return statement in kernel form. | 762 /// Concrete shadow object representing a return statement in kernel form. |
| 803 class KernelReturnStatement extends ReturnStatement implements KernelStatement { | 763 class KernelReturnStatement extends ReturnStatement implements KernelStatement { |
| 804 KernelReturnStatement([Expression expression]) : super(expression); | 764 KernelReturnStatement([Expression expression]) : super(expression); |
| 805 | 765 |
| 806 @override | 766 @override |
| 807 void _inferStatement(KernelTypeInferrer inferrer) { | 767 void _inferStatement(KernelTypeInferrer inferrer) { |
| 808 inferrer.listener.returnStatementEnter(this); | 768 inferrer.listener.returnStatementEnter(this); |
| 809 var closureContext = inferrer.closureContext; | 769 var closureContext = inferrer.closureContext; |
| 810 var typeContext = closureContext != null && !closureContext.isGenerator | 770 var typeContext = |
| 811 ? closureContext.returnContext | 771 !closureContext.isGenerator ? closureContext.returnContext : null; |
| 812 : null; | |
| 813 var inferredType = expression != null | 772 var inferredType = expression != null |
| 814 ? inferrer.inferExpression( | 773 ? inferrer.inferExpression(expression, typeContext, true) |
| 815 expression, typeContext, closureContext != null) | |
| 816 : const VoidType(); | 774 : const VoidType(); |
| 817 // Analyzer treats bare `return` statements as having no effect on the | 775 // Analyzer treats bare `return` statements as having no effect on the |
| 818 // inferred type of the closure. TODO(paulberry): is this what we want | 776 // inferred type of the closure. TODO(paulberry): is this what we want |
| 819 // for Fasta? | 777 // for Fasta? |
| 820 if (expression != null) { | 778 if (expression != null) { |
| 821 closureContext?.handleReturn(inferrer, inferredType); | 779 closureContext.handleReturn(inferrer, inferredType); |
| 822 } | 780 } |
| 823 inferrer.listener.returnStatementExit(this); | 781 inferrer.listener.returnStatementExit(this); |
| 824 } | 782 } |
| 825 } | 783 } |
| 826 | 784 |
| 827 /// Common base class for shadow objects representing statements in kernel | 785 /// Common base class for shadow objects representing statements in kernel |
| 828 /// form. | 786 /// form. |
| 829 abstract class KernelStatement extends Statement { | 787 abstract class KernelStatement extends Statement { |
| 830 /// Calls back to [inferrer] to perform type inference for whatever concrete | 788 /// Calls back to [inferrer] to perform type inference for whatever concrete |
| 831 /// type of [KernelStatement] this is. | 789 /// type of [KernelStatement] this is. |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1347 | 1305 |
| 1348 /// Concrete shadow object representing a yield statement in kernel form. | 1306 /// Concrete shadow object representing a yield statement in kernel form. |
| 1349 class KernelYieldStatement extends YieldStatement implements KernelStatement { | 1307 class KernelYieldStatement extends YieldStatement implements KernelStatement { |
| 1350 KernelYieldStatement(Expression expression, {bool isYieldStar: false}) | 1308 KernelYieldStatement(Expression expression, {bool isYieldStar: false}) |
| 1351 : super(expression, isYieldStar: isYieldStar); | 1309 : super(expression, isYieldStar: isYieldStar); |
| 1352 | 1310 |
| 1353 @override | 1311 @override |
| 1354 void _inferStatement(KernelTypeInferrer inferrer) { | 1312 void _inferStatement(KernelTypeInferrer inferrer) { |
| 1355 inferrer.listener.yieldStatementEnter(this); | 1313 inferrer.listener.yieldStatementEnter(this); |
| 1356 var closureContext = inferrer.closureContext; | 1314 var closureContext = inferrer.closureContext; |
| 1357 var typeContext = closureContext != null && closureContext.isGenerator | 1315 var typeContext = |
| 1358 ? closureContext.returnContext | 1316 closureContext.isGenerator ? closureContext.returnContext : null; |
| 1359 : null; | |
| 1360 if (isYieldStar && typeContext != null) { | 1317 if (isYieldStar && typeContext != null) { |
| 1361 if (closureContext == null) { | 1318 typeContext = inferrer.wrapType( |
| 1362 typeContext = null; | 1319 typeContext, |
| 1363 } else { | 1320 closureContext.isAsync |
| 1364 typeContext = inferrer.wrapType( | 1321 ? inferrer.coreTypes.streamClass |
| 1365 typeContext, | 1322 : inferrer.coreTypes.iterableClass); |
| 1366 closureContext.isAsync | |
| 1367 ? inferrer.coreTypes.streamClass | |
| 1368 : inferrer.coreTypes.iterableClass); | |
| 1369 } | |
| 1370 } | 1323 } |
| 1371 var inferredType = inferrer.inferExpression( | 1324 var inferredType = inferrer.inferExpression( |
| 1372 expression, typeContext, closureContext != null); | 1325 expression, typeContext, closureContext != null); |
| 1373 closureContext?.handleYield(inferrer, isYieldStar, inferredType); | 1326 closureContext?.handleYield(inferrer, isYieldStar, inferredType); |
| 1374 inferrer.listener.yieldStatementExit(this); | 1327 inferrer.listener.yieldStatementExit(this); |
| 1375 } | 1328 } |
| 1376 } | 1329 } |
| OLD | NEW |