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