OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library kernel.transformations.closure.rewriter; |
| 6 |
| 7 import '../../ast.dart'; |
| 8 import 'converter.dart' show ClosureConverter; |
| 9 |
| 10 /// Used by the [Context] to initialize and update the context variable |
| 11 /// used to capture the variables closed over by functions. |
| 12 abstract class AstRewriter { |
| 13 /// The declared variable that holds the context. |
| 14 VariableDeclaration contextDeclaration; |
| 15 |
| 16 /// The expression used to initialize the size of the context stored in |
| 17 /// [contextDeclaration]. This expression is modified when the context is |
| 18 /// extended. |
| 19 IntLiteral contextSize; |
| 20 |
| 21 /// Creates a new [AstRewriter] for a (nested) [Block]. |
| 22 BlockRewriter forNestedBlock(Block block); |
| 23 |
| 24 /// Inserts an allocation of a context and initializes [contextDeclaration] |
| 25 /// and [contextSize]. |
| 26 void insertContextDeclaration(Class contextClass, Expression accessParent); |
| 27 |
| 28 /// Inserts an expression or statement that extends the context, where |
| 29 /// [arguments] holds a pair of the new index and the initial value. |
| 30 void insertExtendContext(Expression accessContext, Arguments arguments); |
| 31 |
| 32 void _createDeclaration(Class contextClass) { |
| 33 assert(contextDeclaration == null && contextSize == null); |
| 34 |
| 35 contextSize = new IntLiteral(0); |
| 36 contextDeclaration = new VariableDeclaration.forValue( |
| 37 new ConstructorInvocation(contextClass.constructors.first, |
| 38 new Arguments(<Expression>[contextSize])), |
| 39 type: new InterfaceType(contextClass)); |
| 40 contextDeclaration.name = "#context"; |
| 41 } |
| 42 } |
| 43 |
| 44 /// Adds a local variable for the context and adds update [Statement]s to the |
| 45 /// current block. |
| 46 class BlockRewriter extends AstRewriter { |
| 47 Block _currentBlock; |
| 48 int _insertionIndex; |
| 49 |
| 50 BlockRewriter(this._currentBlock) : _insertionIndex = 0; |
| 51 |
| 52 BlockRewriter forNestedBlock(Block block) { |
| 53 return _currentBlock != block ? new BlockRewriter(block) : this; |
| 54 } |
| 55 |
| 56 void transformStatements(Block block, ClosureConverter converter) { |
| 57 while (_insertionIndex < _currentBlock.statements.length) { |
| 58 var original = _currentBlock.statements[_insertionIndex]; |
| 59 var transformed = original.accept(converter); |
| 60 assert(_currentBlock.statements[_insertionIndex] == original); |
| 61 if (transformed == null) { |
| 62 _currentBlock.statements.removeAt(_insertionIndex); |
| 63 } else { |
| 64 _currentBlock.statements[_insertionIndex++] = transformed; |
| 65 transformed.parent = _currentBlock; |
| 66 } |
| 67 } |
| 68 } |
| 69 |
| 70 void _insertStatement(Statement statement) { |
| 71 _currentBlock.statements.insert(_insertionIndex++, statement); |
| 72 statement.parent = _currentBlock; |
| 73 } |
| 74 |
| 75 void insertContextDeclaration(Class contextClass, Expression accessParent) { |
| 76 _createDeclaration(contextClass); |
| 77 _insertStatement(contextDeclaration); |
| 78 _insertStatement(new ExpressionStatement(new PropertySet( |
| 79 new VariableGet(contextDeclaration), |
| 80 new Name('parent'), |
| 81 accessParent))); |
| 82 } |
| 83 |
| 84 void insertExtendContext(Expression accessContext, Arguments arguments) { |
| 85 _insertStatement(new ExpressionStatement( |
| 86 new MethodInvocation(accessContext, new Name('[]='), arguments))); |
| 87 } |
| 88 } |
| 89 |
| 90 /// Creates and updates the context as [Let] bindings around the initializer |
| 91 /// expression. |
| 92 class InitializerRewriter extends AstRewriter { |
| 93 final Expression initializingExpression; |
| 94 |
| 95 InitializerRewriter(this.initializingExpression) { |
| 96 assert(initializingExpression.parent is FieldInitializer); |
| 97 } |
| 98 |
| 99 @override |
| 100 BlockRewriter forNestedBlock(Block block) { |
| 101 return new BlockRewriter(block); |
| 102 } |
| 103 |
| 104 @override |
| 105 void insertContextDeclaration(Class contextClass, Expression accessParent) { |
| 106 _createDeclaration(contextClass); |
| 107 FieldInitializer parent = initializingExpression.parent; |
| 108 Let binding = new Let(contextDeclaration, initializingExpression); |
| 109 initializingExpression.parent = binding; |
| 110 parent.value = binding; |
| 111 binding.parent = parent; |
| 112 } |
| 113 |
| 114 @override |
| 115 void insertExtendContext(Expression accessContext, Arguments arguments) { |
| 116 Expression extendContext = |
| 117 new MethodInvocation(accessContext, new Name('[]='), arguments); |
| 118 Let parent = initializingExpression.parent; |
| 119 Let binding = new Let( |
| 120 new VariableDeclaration(null, initializer: extendContext), |
| 121 initializingExpression); |
| 122 parent.body = binding; |
| 123 binding.parent = parent; |
| 124 } |
| 125 } |
OLD | NEW |