Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 kernel.transformations.closure.converter; | 5 library kernel.transformations.closure.converter; |
| 6 | 6 |
| 7 import '../../ast.dart' | 7 import '../../ast.dart' |
| 8 show | 8 show |
| 9 Arguments, | 9 Arguments, |
| 10 Block, | 10 Block, |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 parent.body = initializerExpression; | 223 parent.body = initializerExpression; |
| 224 } else if (parent is FieldInitializer) { | 224 } else if (parent is FieldInitializer) { |
| 225 parent.value = initializerExpression; | 225 parent.value = initializerExpression; |
| 226 } else { | 226 } else { |
| 227 throw "Found unexpected node '${node.runtimeType}, expected a 'Let' " | 227 throw "Found unexpected node '${node.runtimeType}, expected a 'Let' " |
| 228 "or a 'FieldInitializer'."; | 228 "or a 'FieldInitializer'."; |
| 229 } | 229 } |
| 230 } | 230 } |
| 231 } | 231 } |
| 232 rewriter = null; | 232 rewriter = null; |
| 233 context = null; | |
| 233 // Transform constructor body. | 234 // Transform constructor body. |
| 234 FunctionNode function = node.function; | 235 FunctionNode function = node.function; |
| 235 if (function.body != null && function.body is! EmptyStatement) { | 236 if (function.body != null && function.body is! EmptyStatement) { |
| 236 setupContextForFunctionBody(function); | 237 setupContextForFunctionBody(function); |
| 237 VariableDeclaration self = thisAccess[currentMemberFunction]; | 238 VariableDeclaration self = thisAccess[currentMemberFunction]; |
| 238 if (self != null) { | 239 if (self != null) { |
| 239 context.extend(self, new ThisExpression()); | 240 context.extend(self, new ThisExpression()); |
| 240 } | 241 } |
| 241 node.function.accept(this); | 242 node.function.accept(this); |
| 242 resetContext(); | 243 resetContext(); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 node.canonicalName?.unbind(); | 418 node.canonicalName?.unbind(); |
| 418 addGetterForwarder(oldName, node); | 419 addGetterForwarder(oldName, node); |
| 419 } else if (node.kind == ProcedureKind.Method) { | 420 } else if (node.kind == ProcedureKind.Method) { |
| 420 addTearOffMethod(tearOffName, node); | 421 addTearOffMethod(tearOffName, node); |
| 421 } | 422 } |
| 422 } | 423 } |
| 423 } | 424 } |
| 424 | 425 |
| 425 FunctionNode function = node.function; | 426 FunctionNode function = node.function; |
| 426 if (function.body != null) { | 427 if (function.body != null) { |
| 428 bool hadSingleStatementBody = function.body is! Block; | |
|
karlklose
2017/06/19 11:58:14
Please check if this is still required.
Dmitry Stefantsov
2017/06/19 12:12:44
Thanks for pointing to this! Apparently, DillLibr
| |
| 429 | |
| 427 setupContextForFunctionBody(function); | 430 setupContextForFunctionBody(function); |
| 428 VariableDeclaration self = thisAccess[currentMemberFunction]; | 431 VariableDeclaration self = thisAccess[currentMemberFunction]; |
| 429 if (self != null) { | 432 if (self != null) { |
| 430 context.extend(self, new ThisExpression()); | 433 context.extend(self, new ThisExpression()); |
| 431 } | 434 } |
| 432 node.transformChildren(this); | 435 node.transformChildren(this); |
| 433 resetContext(); | 436 resetContext(); |
| 437 | |
| 438 // Here a special case is handled: the body of the procedure was a single | |
| 439 // statement and after the transformation it is a block with a single | |
| 440 // statement inside. In this case we make this statement the body of the | |
| 441 // procedure again. It is required to follow the conventions imposed by | |
| 442 // [addClass] in [DillLibraryBuilder]. | |
| 443 // See [dill_library_builder.dart] | |
| 444 // (../../../../front_end/lib/src/fasta/dill/dill_library_builder.dart) | |
| 445 // for details. | |
| 446 if (hadSingleStatementBody && function.body is Block) { | |
| 447 Block body = function.body; | |
| 448 if (body.statements.length == 1) { | |
| 449 function.body = body.statements[0]; | |
| 450 function.body.parent = function; | |
| 451 } | |
| 452 } | |
| 434 } | 453 } |
| 435 | 454 |
| 436 return node; | 455 return node; |
| 437 } | 456 } |
| 438 | 457 |
| 439 void setupContextForFunctionBody(FunctionNode function) { | 458 void setupContextForFunctionBody(FunctionNode function) { |
| 440 Statement body = function.body; | 459 Statement body = function.body; |
| 441 assert(body != null); | 460 assert(body != null); |
| 442 currentMemberFunction = function; | 461 currentMemberFunction = function; |
| 443 // Ensure that the body is a block which becomes the current block. | 462 // Ensure that the body is a block which becomes the current block. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 .forEach(extendContextWith); | 495 .forEach(extendContextWith); |
| 477 assert(node.body != null); | 496 assert(node.body != null); |
| 478 node.body = node.body.accept(this); | 497 node.body = node.body.accept(this); |
| 479 node.body.parent = node; | 498 node.body.parent = node; |
| 480 return node; | 499 return node; |
| 481 } | 500 } |
| 482 | 501 |
| 483 TreeNode visitBlock(Block node) { | 502 TreeNode visitBlock(Block node) { |
| 484 return saveContext(() { | 503 return saveContext(() { |
| 485 BlockRewriter blockRewriter = rewriter = rewriter.forNestedBlock(node); | 504 BlockRewriter blockRewriter = rewriter = rewriter.forNestedBlock(node); |
| 486 blockRewriter.transformStatements(node, this); | 505 blockRewriter.transformStatements(this); |
| 487 return node; | 506 return node; |
| 488 }); | 507 }); |
| 489 } | 508 } |
| 490 | 509 |
| 491 TreeNode visitVariableDeclaration(VariableDeclaration node) { | 510 TreeNode visitVariableDeclaration(VariableDeclaration node) { |
| 492 node.transformChildren(this); | 511 node.transformChildren(this); |
| 493 | 512 |
| 494 if (!capturedVariables.contains(node)) return node; | 513 if (!capturedVariables.contains(node)) return node; |
| 495 if (node.initializer == null && node.parent is FunctionNode) { | 514 if (node.initializer == null && node.parent is FunctionNode) { |
| 496 // If the variable is a function parameter and doesn't have an | 515 // If the variable is a function parameter and doesn't have an |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 620 return super.visitForInStatement(node); | 639 return super.visitForInStatement(node); |
| 621 } | 640 } |
| 622 | 641 |
| 623 TreeNode visitThisExpression(ThisExpression node) { | 642 TreeNode visitThisExpression(ThisExpression node) { |
| 624 return isOuterMostContext | 643 return isOuterMostContext |
| 625 ? node | 644 ? node |
| 626 : context.lookup(thisAccess[currentMemberFunction]); | 645 : context.lookup(thisAccess[currentMemberFunction]); |
| 627 } | 646 } |
| 628 | 647 |
| 629 TreeNode visitStaticGet(StaticGet node) { | 648 TreeNode visitStaticGet(StaticGet node) { |
| 630 Member target = node.target; | 649 // TODO(dmitryas): Add support for tear-offs. When added, uncomment this. |
| 631 if (target is Procedure && target.kind == ProcedureKind.Method) { | 650 // |
| 632 VariableDeclaration contextVariable = new VariableDeclaration( | 651 // Member target = node.target; |
| 633 "#contextParameter", | 652 // if (target is Procedure && target.kind == ProcedureKind.Method) { |
| 634 type: const VectorType()); | 653 // VariableDeclaration contextVariable = new VariableDeclaration( |
| 635 Expression expression = getTearOffExpression( | 654 // "#contextParameter", |
| 636 null, node.target, contextVariable, new NullLiteral()); | 655 // type: const VectorType()); |
| 637 expression.transformChildren(this); | 656 // Expression expression = getTearOffExpression( |
| 638 return expression; | 657 // null, node.target, contextVariable, new NullLiteral()); |
| 639 } | 658 // expression.transformChildren(this); |
| 659 // return expression; | |
| 660 // } | |
| 640 return super.visitStaticGet(node); | 661 return super.visitStaticGet(node); |
| 641 } | 662 } |
| 642 | 663 |
| 643 TreeNode visitPropertyGet(PropertyGet node) { | 664 TreeNode visitPropertyGet(PropertyGet node) { |
| 644 Name tearOffName = tearOffGetterNames[node.name]; | 665 Name tearOffName = tearOffGetterNames[node.name]; |
| 645 if (tearOffName != null) { | 666 if (tearOffName != null) { |
| 646 MethodInvocation replacement = new MethodInvocation( | 667 PropertyGet replacement = new PropertyGet(node.receiver, tearOffName); |
| 647 node.receiver, tearOffName, new Arguments(<Expression>[])); | 668 return super.visitPropertyGet(replacement); |
| 648 return super.visitMethodInvocation(replacement); | |
| 649 } | 669 } |
| 650 return super.visitPropertyGet(node); | 670 return super.visitPropertyGet(node); |
| 651 } | 671 } |
| 652 | 672 |
| 653 TreeNode visitCatch(Catch node) { | 673 TreeNode visitCatch(Catch node) { |
| 654 VariableDeclaration exception = node.exception; | 674 VariableDeclaration exception = node.exception; |
| 655 VariableDeclaration stackTrace = node.stackTrace; | 675 VariableDeclaration stackTrace = node.stackTrace; |
| 656 if (stackTrace != null && capturedVariables.contains(stackTrace)) { | 676 if (stackTrace != null && capturedVariables.contains(stackTrace)) { |
| 657 Block block = node.body = ensureBlock(node.body); | 677 Block block = node.body = ensureBlock(node.body); |
| 658 block.parent = node; | 678 block.parent = node; |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 864 "#contextParameter", | 884 "#contextParameter", |
| 865 type: const VectorType()); | 885 type: const VectorType()); |
| 866 Context parent = context; | 886 Context parent = context; |
| 867 context = context.toNestedContext( | 887 context = context.toNestedContext( |
| 868 new VariableAccessor(contextVariable, null, TreeNode.noOffset)); | 888 new VariableAccessor(contextVariable, null, TreeNode.noOffset)); |
| 869 | 889 |
| 870 body.addStatement(new ReturnStatement(getTearOffExpression( | 890 body.addStatement(new ReturnStatement(getTearOffExpression( |
| 871 self, procedure, contextVariable, parent.expression))); | 891 self, procedure, contextVariable, parent.expression))); |
| 872 | 892 |
| 873 Procedure tearOffMethod = new Procedure( | 893 Procedure tearOffMethod = new Procedure( |
| 874 name, ProcedureKind.Method, tearOffMethodFunction, | 894 name, ProcedureKind.Getter, tearOffMethodFunction, |
| 875 fileUri: currentFileUri); | 895 fileUri: currentFileUri); |
| 876 newClassMembers.add(tearOffMethod); | 896 newClassMembers.add(tearOffMethod); |
| 877 | 897 |
| 878 resetContext(); | 898 resetContext(); |
| 879 }); | 899 }); |
| 880 } finally { | 900 } finally { |
| 881 currentMember = oldCurrentMember; | 901 currentMember = oldCurrentMember; |
| 882 currentMemberFunction = oldCurrentMemberFunction; | 902 currentMemberFunction = oldCurrentMemberFunction; |
| 883 } | 903 } |
| 884 } | 904 } |
| 885 } | 905 } |
| OLD | NEW |