OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 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 | 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.rewriter; | 5 library kernel.transformations.closure.rewriter; |
6 | 6 |
7 import '../../ast.dart'; | 7 import '../../ast.dart'; |
8 import 'converter.dart' show ClosureConverter; | 8 import 'converter.dart' show ClosureConverter; |
9 | 9 |
10 /// Used by the [Context] to initialize and update the context variable | 10 /// Used by the [Context] to initialize and update the context variable |
11 /// used to capture the variables closed over by functions. | 11 /// used to capture the variables closed over by functions. |
12 abstract class AstRewriter { | 12 abstract class AstRewriter { |
13 /// The declared variable that holds the context. | 13 /// The declared variable that holds the context. |
14 VariableDeclaration contextDeclaration; | 14 VariableDeclaration contextDeclaration; |
15 | 15 |
16 /// The expression used to initialize the size of the context stored in | 16 /// Expression that is used to initialize the vector representing the context. |
17 /// [contextDeclaration]. This expression is modified when the context is | 17 /// It's [length] field is modified by the [extend] operation |
18 /// extended. | 18 VectorCreation vectorCreation; |
19 IntLiteral contextSize; | |
20 | 19 |
21 /// Creates a new [AstRewriter] for a (nested) [Block]. | 20 /// Creates a new [AstRewriter] for a (nested) [Block]. |
22 BlockRewriter forNestedBlock(Block block); | 21 BlockRewriter forNestedBlock(Block block); |
23 | 22 |
24 /// Inserts an allocation of a context and initializes [contextDeclaration] | 23 /// Inserts an allocation of a context and initializes [contextDeclaration] |
25 /// and [contextSize]. | 24 /// and [vectorCreation]. |
26 void insertContextDeclaration(Class contextClass, Expression accessParent); | 25 void insertContextDeclaration(Expression accessParent); |
27 | 26 |
28 /// Inserts an expression or statement that extends the context, where | 27 /// Inserts an expression or statement that extends the context. |
29 /// [arguments] holds a pair of the new index and the initial value. | 28 void insertExtendContext(VectorSet extender); |
30 void insertExtendContext(Expression accessContext, Arguments arguments); | |
31 | 29 |
32 void _createDeclaration(Class contextClass) { | 30 void _createDeclaration() { |
33 assert(contextDeclaration == null && contextSize == null); | 31 assert(contextDeclaration == null && vectorCreation == null); |
34 | 32 |
35 contextSize = new IntLiteral(0); | 33 // Context size is set to 1 initially, because the 0-th element of it works |
36 contextDeclaration = new VariableDeclaration.forValue( | 34 // as a link to the parent context. |
37 new ConstructorInvocation(contextClass.constructors.first, | 35 vectorCreation = new VectorCreation(1); |
38 new Arguments(<Expression>[contextSize])), | 36 contextDeclaration = new VariableDeclaration.forValue(vectorCreation, |
39 type: new InterfaceType(contextClass)); | 37 type: new VectorType()); |
40 contextDeclaration.name = "#context"; | 38 contextDeclaration.name = "#context"; |
41 } | 39 } |
42 } | 40 } |
43 | 41 |
44 /// Adds a local variable for the context and adds update [Statement]s to the | 42 /// Adds a local variable for the context and adds update [Statement]s to the |
45 /// current block. | 43 /// current block. |
46 class BlockRewriter extends AstRewriter { | 44 class BlockRewriter extends AstRewriter { |
47 Block _currentBlock; | 45 Block _currentBlock; |
48 int _insertionIndex; | 46 int _insertionIndex; |
49 | 47 |
(...skipping 15 matching lines...) Expand all Loading... |
65 transformed.parent = _currentBlock; | 63 transformed.parent = _currentBlock; |
66 } | 64 } |
67 } | 65 } |
68 } | 66 } |
69 | 67 |
70 void _insertStatement(Statement statement) { | 68 void _insertStatement(Statement statement) { |
71 _currentBlock.statements.insert(_insertionIndex++, statement); | 69 _currentBlock.statements.insert(_insertionIndex++, statement); |
72 statement.parent = _currentBlock; | 70 statement.parent = _currentBlock; |
73 } | 71 } |
74 | 72 |
75 void insertContextDeclaration(Class contextClass, Expression accessParent) { | 73 void insertContextDeclaration(Expression accessParent) { |
76 _createDeclaration(contextClass); | 74 _createDeclaration(); |
77 _insertStatement(contextDeclaration); | 75 _insertStatement(contextDeclaration); |
78 if (accessParent is! NullLiteral) { | 76 if (accessParent is! NullLiteral) { |
79 _insertStatement(new ExpressionStatement(new PropertySet( | 77 // Index 0 of a context always points to the parent. |
80 new VariableGet(contextDeclaration), | 78 _insertStatement(new ExpressionStatement( |
81 new Name('parent'), | 79 new VectorSet(new VariableGet(contextDeclaration), 0, accessParent))); |
82 accessParent))); | |
83 } | 80 } |
84 } | 81 } |
85 | 82 |
86 void insertExtendContext(Expression accessContext, Arguments arguments) { | 83 void insertExtendContext(VectorSet extender) { |
87 _insertStatement(new ExpressionStatement( | 84 _insertStatement(new ExpressionStatement(extender)); |
88 new MethodInvocation(accessContext, new Name('[]='), arguments))); | |
89 } | 85 } |
90 } | 86 } |
91 | 87 |
92 /// Creates and updates the context as [Let] bindings around the initializer | 88 /// Creates and updates the context as [Let] bindings around the initializer |
93 /// expression. | 89 /// expression. |
94 class InitializerRewriter extends AstRewriter { | 90 class InitializerRewriter extends AstRewriter { |
95 final Expression initializingExpression; | 91 final Expression initializingExpression; |
96 | 92 |
97 InitializerRewriter(this.initializingExpression) { | 93 InitializerRewriter(this.initializingExpression) { |
98 assert(initializingExpression.parent is FieldInitializer); | 94 assert(initializingExpression.parent is FieldInitializer); |
99 } | 95 } |
100 | 96 |
101 @override | 97 @override |
102 BlockRewriter forNestedBlock(Block block) { | 98 BlockRewriter forNestedBlock(Block block) { |
103 return new BlockRewriter(block); | 99 return new BlockRewriter(block); |
104 } | 100 } |
105 | 101 |
106 @override | 102 @override |
107 void insertContextDeclaration(Class contextClass, Expression accessParent) { | 103 void insertContextDeclaration(Expression accessParent) { |
108 _createDeclaration(contextClass); | 104 _createDeclaration(); |
109 FieldInitializer parent = initializingExpression.parent; | 105 FieldInitializer parent = initializingExpression.parent; |
110 Let binding = new Let(contextDeclaration, initializingExpression); | 106 Let binding = new Let(contextDeclaration, initializingExpression); |
111 initializingExpression.parent = binding; | 107 initializingExpression.parent = binding; |
112 parent.value = binding; | 108 parent.value = binding; |
113 binding.parent = parent; | 109 binding.parent = parent; |
114 } | 110 } |
115 | 111 |
116 @override | 112 @override |
117 void insertExtendContext(Expression accessContext, Arguments arguments) { | 113 void insertExtendContext(VectorSet extender) { |
118 Expression extendContext = | |
119 new MethodInvocation(accessContext, new Name('[]='), arguments); | |
120 Let parent = initializingExpression.parent; | 114 Let parent = initializingExpression.parent; |
121 Let binding = new Let( | 115 Let binding = new Let(new VariableDeclaration(null, initializer: extender), |
122 new VariableDeclaration(null, initializer: extendContext), | |
123 initializingExpression); | 116 initializingExpression); |
124 parent.body = binding; | 117 parent.body = binding; |
125 binding.parent = parent; | 118 binding.parent = parent; |
126 } | 119 } |
127 } | 120 } |
OLD | NEW |