OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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.context; | 5 library kernel.transformations.closure.context; |
6 | 6 |
7 import '../../ast.dart' | 7 import '../../ast.dart' |
8 show | 8 show |
9 Arguments, | 9 Arguments, |
10 Class, | 10 Class, |
11 Expression, | 11 Expression, |
12 IntLiteral, | 12 IntLiteral, |
13 MethodInvocation, | 13 MethodInvocation, |
14 Name, | 14 Name, |
15 NullLiteral, | 15 NullLiteral, |
16 PropertyGet, | 16 PropertyGet, |
17 StringLiteral, | 17 StringLiteral, |
18 Throw, | 18 Throw, |
19 VariableDeclaration, | 19 VariableDeclaration, |
20 VariableGet, | 20 VariableGet, |
21 VariableSet; | 21 VariableSet, |
| 22 VectorGet, |
| 23 VectorSet, |
| 24 VectorCopy; |
22 | 25 |
23 import '../../frontend/accessors.dart' | 26 import '../../frontend/accessors.dart' show Accessor, VariableAccessor; |
24 show Accessor, IndexAccessor, VariableAccessor; | |
25 | 27 |
26 import 'converter.dart' show ClosureConverter; | 28 import 'converter.dart' show ClosureConverter; |
27 | 29 |
28 abstract class Context { | 30 abstract class Context { |
29 /// Returns a new expression for accessing this context. | 31 /// Returns a new expression for accessing this context. |
30 Expression get expression; | 32 Expression get expression; |
31 | 33 |
32 /// Returns an accessor (or null) for accessing this context. | 34 /// Returns an accessor (or null) for accessing this context. |
33 Accessor get accessor; | 35 Accessor get accessor; |
34 | 36 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 converter, accessor, <List<VariableDeclaration>>[]); | 105 converter, accessor, <List<VariableDeclaration>>[]); |
104 } | 106 } |
105 } | 107 } |
106 | 108 |
107 class LocalContext extends Context { | 109 class LocalContext extends Context { |
108 final ClosureConverter converter; | 110 final ClosureConverter converter; |
109 final Context parent; | 111 final Context parent; |
110 final VariableDeclaration self; | 112 final VariableDeclaration self; |
111 final IntLiteral size; | 113 final IntLiteral size; |
112 final List<VariableDeclaration> variables = <VariableDeclaration>[]; | 114 final List<VariableDeclaration> variables = <VariableDeclaration>[]; |
113 final Map<VariableDeclaration, Arguments> initializers = | 115 final Map<VariableDeclaration, VectorSet> initializers = |
114 <VariableDeclaration, Arguments>{}; | 116 <VariableDeclaration, VectorSet>{}; |
115 | 117 |
116 LocalContext._internal(this.converter, this.parent, this.self, this.size); | 118 LocalContext._internal(this.converter, this.parent, this.self, this.size); |
117 | 119 |
118 factory LocalContext(ClosureConverter converter, Context parent) { | 120 factory LocalContext(ClosureConverter converter, Context parent) { |
119 Class contextClass = converter.contextClass; | 121 Class contextClass = converter.contextClass; |
120 assert(contextClass.constructors.length == 1); | 122 assert(contextClass.constructors.length == 1); |
121 converter.rewriter | 123 converter.rewriter.insertContextDeclaration(parent.expression); |
122 .insertContextDeclaration(contextClass, parent.expression); | |
123 | 124 |
124 return new LocalContext._internal(converter, parent, | 125 return new LocalContext._internal(converter, parent, |
125 converter.rewriter.contextDeclaration, converter.rewriter.contextSize); | 126 converter.rewriter.contextDeclaration, converter.rewriter.contextSize); |
126 } | 127 } |
127 | 128 |
128 Expression get expression => accessor.buildSimpleRead(); | 129 Expression get expression => accessor.buildSimpleRead(); |
129 | 130 |
130 Accessor get accessor => new VariableAccessor(self); | 131 Accessor get accessor => new VariableAccessor(self); |
131 | 132 |
132 void extend(VariableDeclaration variable, Expression value) { | 133 void extend(VariableDeclaration variable, Expression value) { |
133 Arguments arguments = | 134 // Increase index by 1, because the parent occupies item 0, and all other |
134 new Arguments(<Expression>[new IntLiteral(variables.length), value]); | 135 // variables are therefore shifted by 1. |
135 converter.rewriter.insertExtendContext(expression, arguments); | 136 IntLiteral index = new IntLiteral(variables.length + 1); |
| 137 VectorSet initializer = new VectorSet(expression, index, value); |
| 138 index.parent = initializer; |
| 139 value.parent = initializer; |
| 140 |
| 141 converter.rewriter.insertExtendContext(initializer); |
136 ++size.value; | 142 ++size.value; |
137 variables.add(variable); | 143 variables.add(variable); |
138 initializers[variable] = arguments; | 144 initializers[variable] = initializer; |
139 } | 145 } |
140 | 146 |
141 void update(VariableDeclaration variable, Expression value) { | 147 void update(VariableDeclaration variable, Expression value) { |
142 Arguments arguments = initializers[variable]; | 148 VectorSet initializer = initializers[variable]; |
143 arguments.positional[1] = value; | 149 initializer.value = value; |
144 value.parent = arguments; | 150 value.parent = initializer; |
145 } | 151 } |
146 | 152 |
147 Expression lookup(VariableDeclaration variable) { | 153 Expression lookup(VariableDeclaration variable) { |
148 var index = variables.indexOf(variable); | 154 var index = variables.indexOf(variable); |
| 155 // Increase index by 1 in case of success, because the parent occupies |
| 156 // item 0, and all other variables are therefore shifted by 1. |
149 return index == -1 | 157 return index == -1 |
150 ? parent.lookup(variable) | 158 ? parent.lookup(variable) |
151 : new MethodInvocation(expression, new Name('[]'), | 159 : new VectorGet(expression, new IntLiteral(index + 1)); |
152 new Arguments(<Expression>[new IntLiteral(index)])); | |
153 } | 160 } |
154 | 161 |
155 Expression assign(VariableDeclaration variable, Expression value, | 162 Expression assign(VariableDeclaration variable, Expression value, |
156 {bool voidContext: false}) { | 163 {bool voidContext: false}) { |
157 var index = variables.indexOf(variable); | 164 var index = variables.indexOf(variable); |
| 165 // Increase index by 1 in case of success, because the parent occupies |
| 166 // item 0, and all other variables are therefore shifted by 1. |
158 return index == -1 | 167 return index == -1 |
159 ? parent.assign(variable, value, voidContext: voidContext) | 168 ? parent.assign(variable, value, voidContext: voidContext) |
160 : IndexAccessor | 169 : new VectorSet(expression, new IntLiteral(index + 1), value); |
161 .make(expression, new IntLiteral(index), null, null) | |
162 .buildAssignment(value, voidContext: voidContext); | |
163 } | 170 } |
164 | 171 |
165 Context toNestedContext([Accessor accessor]) { | 172 Context toNestedContext([Accessor accessor]) { |
166 accessor ??= this.accessor; | 173 accessor ??= this.accessor; |
167 List<List<VariableDeclaration>> variabless = <List<VariableDeclaration>>[]; | 174 List<List<VariableDeclaration>> variabless = <List<VariableDeclaration>>[]; |
168 var current = this; | 175 var current = this; |
169 while (current != null && current is! NoContext) { | 176 while (current != null && current is! NoContext) { |
170 if (current is LocalContext) { | 177 if (current is LocalContext) { |
171 variabless.add(current.variables); | 178 variabless.add(current.variables); |
172 current = current.parent; | 179 current = current.parent; |
173 } else if (current is NestedContext) { | 180 } else if (current is NestedContext) { |
174 variabless.addAll((current as NestedContext).variabless); | 181 variabless.addAll((current as NestedContext).variabless); |
175 current = null; | 182 current = null; |
176 } | 183 } |
177 } | 184 } |
178 return new NestedContext(converter, accessor, variabless); | 185 return new NestedContext(converter, accessor, variabless); |
179 } | 186 } |
180 | 187 |
181 Expression clone() { | 188 Expression clone() { |
182 self.isFinal = false; | 189 self.isFinal = false; |
183 return new VariableSet( | 190 return new VariableSet(self, new VectorCopy(new VariableGet(self))); |
184 self, | |
185 new MethodInvocation( | |
186 new VariableGet(self), new Name("copy"), new Arguments.empty())); | |
187 } | 191 } |
188 } | 192 } |
189 | 193 |
190 class NestedContext extends Context { | 194 class NestedContext extends Context { |
191 final ClosureConverter converter; | 195 final ClosureConverter converter; |
192 final Accessor accessor; | 196 final Accessor accessor; |
193 final List<List<VariableDeclaration>> variabless; | 197 final List<List<VariableDeclaration>> variabless; |
194 | 198 |
195 NestedContext(this.converter, this.accessor, this.variabless); | 199 NestedContext(this.converter, this.accessor, this.variabless); |
196 | 200 |
197 Expression get expression { | 201 Expression get expression { |
198 return accessor?.buildSimpleRead() ?? new NullLiteral(); | 202 return accessor?.buildSimpleRead() ?? new NullLiteral(); |
199 } | 203 } |
200 | 204 |
201 void extend(VariableDeclaration variable, Expression value) { | 205 void extend(VariableDeclaration variable, Expression value) { |
202 converter.context = new LocalContext(converter, this) | 206 converter.context = new LocalContext(converter, this) |
203 ..extend(variable, value); | 207 ..extend(variable, value); |
204 } | 208 } |
205 | 209 |
206 Expression lookup(VariableDeclaration variable) { | 210 Expression lookup(VariableDeclaration variable) { |
207 Expression context = expression; | 211 Expression context = expression; |
208 for (var variables in variabless) { | 212 for (var variables in variabless) { |
209 var index = variables.indexOf(variable); | 213 var index = variables.indexOf(variable); |
210 if (index != -1) { | 214 if (index != -1) { |
211 return new MethodInvocation(context, new Name('[]'), | 215 // Increase index by 1, because the parent occupies item 0, and all |
212 new Arguments(<Expression>[new IntLiteral(index)])); | 216 // other variables are therefore shifted by 1. |
| 217 return new VectorGet(context, new IntLiteral(index + 1)); |
213 } | 218 } |
214 context = new PropertyGet(context, new Name('parent')); | 219 // Item 0 of a context always points to its parent. |
| 220 context = new VectorGet(context, new IntLiteral(0)); |
215 } | 221 } |
216 throw 'Unbound NestedContext.lookup($variable)'; | 222 throw 'Unbound NestedContext.lookup($variable)'; |
217 } | 223 } |
218 | 224 |
219 Expression assign(VariableDeclaration variable, Expression value, | 225 Expression assign(VariableDeclaration variable, Expression value, |
220 {bool voidContext: false}) { | 226 {bool voidContext: false}) { |
221 Expression context = expression; | 227 Expression context = expression; |
222 for (List<VariableDeclaration> variables in variabless) { | 228 for (List<VariableDeclaration> variables in variabless) { |
223 var index = variables.indexOf(variable); | 229 var index = variables.indexOf(variable); |
224 if (index != -1) { | 230 if (index != -1) { |
225 return IndexAccessor | 231 // Increase index by 1, because the parent occupies item 0, and all |
226 .make(context, new IntLiteral(index), null, null) | 232 // other variables are therefore shifted by 1. |
227 .buildAssignment(value, voidContext: voidContext); | 233 return new VectorSet(context, new IntLiteral(index + 1), value); |
228 } | 234 } |
229 context = new PropertyGet(context, new Name('parent')); | 235 // Item 0 of a context always points to its parent. |
| 236 context = new VectorGet(context, new IntLiteral(0)); |
230 } | 237 } |
231 throw 'Unbound NestedContext.lookup($variable)'; | 238 throw 'Unbound NestedContext.lookup($variable)'; |
232 } | 239 } |
233 | 240 |
234 Context toNestedContext([Accessor accessor]) { | 241 Context toNestedContext([Accessor accessor]) { |
235 return new NestedContext(converter, accessor ?? this.accessor, variabless); | 242 return new NestedContext(converter, accessor ?? this.accessor, variabless); |
236 } | 243 } |
237 } | 244 } |
OLD | NEW |