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 |