Chromium Code Reviews| 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 BlockRewriter(this._currentBlock) : _insertionIndex = 0; | |
| 48 | |
| 49 BlockRewriter forNestedBlock(Block block) { | |
| 50 return _currentBlock != block ? new BlockRewriter(block) : this; | |
| 51 } | |
| 52 | |
| 53 void transformStatements(Block block, ClosureConverter converter) { | |
| 54 while (_insertionIndex < _currentBlock.statements.length) { | |
| 55 var original = _currentBlock.statements[_insertionIndex]; | |
| 56 var transformed = original.accept(converter); | |
| 57 assert(_currentBlock.statements[_insertionIndex] == original); | |
| 58 if (transformed == null) { | |
| 59 _currentBlock.statements.removeAt(_insertionIndex); | |
| 60 } else { | |
| 61 _currentBlock.statements[_insertionIndex++] = transformed; | |
| 62 transformed.parent = _currentBlock; | |
| 63 } | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 void _insertStatement(Statement statement) { | |
| 68 _currentBlock.statements.insert(_insertionIndex++, statement); | |
| 69 statement.parent = _currentBlock; | |
| 70 } | |
| 71 | |
| 72 void insertContextDeclaration(Class contextClass, Expression accessParent) { | |
| 73 _createDeclaration(contextClass); | |
| 74 _insertStatement(contextDeclaration); | |
| 75 _insertStatement(new ExpressionStatement(new PropertySet( | |
| 76 new VariableGet(contextDeclaration), | |
| 77 new Name('parent'), | |
| 78 accessParent))); | |
| 79 } | |
| 80 | |
| 81 void insertExtendContext(Expression accessContext, Arguments arguments) { | |
| 82 _insertStatement(new ExpressionStatement( | |
| 83 new MethodInvocation(accessContext, new Name('[]='), arguments))); | |
| 84 } | |
| 85 | |
| 86 Block _currentBlock; | |
| 87 int _insertionIndex; | |
|
ahe
2017/02/27 07:36:06
Move to beginning of class declaration.
karlklose
2017/02/28 11:45:15
Done.
| |
| 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 |