Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(815)

Side by Side Diff: pkg/kernel/lib/transformations/closure/rewriter.dart

Issue 2712473003: closure conversion: Support closures in initializers (Closed)
Patch Set: Address comments Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « pkg/kernel/lib/transformations/closure/converter.dart ('k') | pkg/kernel/testcases/closures/closure_in_constructor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698