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 |