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 import 'package:front_end/src/fasta/builder/ast_factory.dart'; |
| 6 |
5 /// A library to help transform compounds and null-aware accessors into | 7 /// A library to help transform compounds and null-aware accessors into |
6 /// let expressions. | 8 /// let expressions. |
7 | 9 |
8 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; | 10 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; |
9 | 11 |
10 import 'package:front_end/src/fasta/scanner/token.dart' show Token; | 12 import 'package:front_end/src/fasta/scanner/token.dart' show Token; |
11 | 13 |
12 import 'package:front_end/src/fasta/kernel/fasta_accessors.dart' | 14 import 'package:front_end/src/fasta/kernel/fasta_accessors.dart' |
13 show BuilderHelper; | 15 show BuilderHelper; |
14 | 16 |
15 import 'package:kernel/ast.dart'; | 17 import 'package:kernel/ast.dart' hide MethodInvocation; |
16 | 18 |
17 final Name indexGetName = new Name("[]"); | 19 final Name indexGetName = new Name("[]"); |
18 | 20 |
19 final Name indexSetName = new Name("[]="); | 21 final Name indexSetName = new Name("[]="); |
20 | 22 |
21 /// An [Accessor] represents a subexpression for which we can't yet build a | 23 /// An [Accessor] represents a subexpression for which we can't yet build a |
22 /// kernel [Expression] because we don't yet know the context in which it is | 24 /// kernel [Expression] because we don't yet know the context in which it is |
23 /// used. | 25 /// used. |
24 /// | 26 /// |
25 /// Once the context is known, an [Accessor] can be converted into an | 27 /// Once the context is known, an [Accessor] can be converted into an |
26 /// [Expression] by calling a "build" method. | 28 /// [Expression] by calling a "build" method. |
27 /// | 29 /// |
28 /// For example, when building a kernel representation for `a[x] = b`, after | 30 /// For example, when building a kernel representation for `a[x] = b`, after |
29 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to | 31 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to |
30 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an | 32 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an |
31 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be | 33 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be |
32 /// called. | 34 /// called. |
33 abstract class Accessor { | 35 abstract class Accessor { |
| 36 final BuilderHelper helper; |
34 final Token token; | 37 final Token token; |
35 | 38 |
36 // [builtBinary] and [builtGetter] capture the inner nodes. Used by | 39 // [builtBinary] and [builtGetter] capture the inner nodes. Used by |
37 // dart2js+rasta for determining how subexpressions map to legacy dart2js Ast | 40 // dart2js+rasta for determining how subexpressions map to legacy dart2js Ast |
38 // nodes. This will be removed once dart2js type analysis (aka inference) is | 41 // nodes. This will be removed once dart2js type analysis (aka inference) is |
39 // reimplemented on kernel. | 42 // reimplemented on kernel. |
40 Expression builtBinary; | 43 Expression builtBinary; |
41 Expression builtGetter; | 44 Expression builtGetter; |
42 | 45 |
43 Accessor(this.token); | 46 Accessor(this.helper, this.token); |
44 | 47 |
45 /// Builds an [Expression] representing a read from the accessor. | 48 /// Builds an [Expression] representing a read from the accessor. |
46 Expression buildSimpleRead() { | 49 Expression buildSimpleRead() { |
47 return _finish(_makeSimpleRead()); | 50 return _finish(_makeSimpleRead()); |
48 } | 51 } |
49 | 52 |
50 /// Builds an [Expression] representing an assignment with the accessor on | 53 /// Builds an [Expression] representing an assignment with the accessor on |
51 /// the LHS and [value] on the RHS. | 54 /// the LHS and [value] on the RHS. |
52 /// | 55 /// |
53 /// The returned expression evaluates to the assigned value, unless | 56 /// The returned expression evaluates to the assigned value, unless |
54 /// [voidContext] is true, in which case it may evaluate to anything. | 57 /// [voidContext] is true, in which case it may evaluate to anything. |
55 Expression buildAssignment(Expression value, {bool voidContext: false}) { | 58 Expression buildAssignment(Expression value, {bool voidContext: false}) { |
56 return _finish(_makeSimpleWrite(value, voidContext)); | 59 return _finish(_makeSimpleWrite(value, voidContext)); |
57 } | 60 } |
58 | 61 |
59 /// Returns an [Expression] representing a null-aware assignment (`??=`) with | 62 /// Returns an [Expression] representing a null-aware assignment (`??=`) with |
60 /// the accessor on the LHS and [value] on the RHS. | 63 /// the accessor on the LHS and [value] on the RHS. |
61 /// | 64 /// |
62 /// The returned expression evaluates to the assigned value, unless | 65 /// The returned expression evaluates to the assigned value, unless |
63 /// [voidContext] is true, in which case it may evaluate to anything. | 66 /// [voidContext] is true, in which case it may evaluate to anything. |
64 /// | 67 /// |
65 /// [type] is the static type of the RHS. | 68 /// [type] is the static type of the RHS. |
66 Expression buildNullAwareAssignment(Expression value, DartType type, | 69 Expression buildNullAwareAssignment(Expression value, DartType type, |
67 {bool voidContext: false}) { | 70 {bool voidContext: false}) { |
68 if (voidContext) { | 71 if (voidContext) { |
69 return _finish(new ConditionalExpression(buildIsNull(_makeRead()), | 72 return _finish(new ConditionalExpression( |
70 _makeWrite(value, false), new NullLiteral(), type)); | 73 buildIsNull(helper.astFactory, _makeRead()), |
| 74 _makeWrite(value, false), |
| 75 new NullLiteral(), |
| 76 type)); |
71 } | 77 } |
72 var tmp = new VariableDeclaration.forValue(_makeRead()); | 78 var tmp = new VariableDeclaration.forValue(_makeRead()); |
73 return _finish(makeLet( | 79 return _finish(makeLet( |
74 tmp, | 80 tmp, |
75 new ConditionalExpression(buildIsNull(new VariableGet(tmp)), | 81 new ConditionalExpression( |
76 _makeWrite(value, false), new VariableGet(tmp), type))); | 82 buildIsNull(helper.astFactory, new VariableGet(tmp)), |
| 83 _makeWrite(value, false), |
| 84 new VariableGet(tmp), |
| 85 type))); |
77 } | 86 } |
78 | 87 |
79 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) | 88 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) |
80 /// with the accessor on the LHS and [value] on the RHS. | 89 /// with the accessor on the LHS and [value] on the RHS. |
81 Expression buildCompoundAssignment(Name binaryOperator, Expression value, | 90 Expression buildCompoundAssignment(Name binaryOperator, Expression value, |
82 {int offset: TreeNode.noOffset, | 91 {int offset: TreeNode.noOffset, |
83 bool voidContext: false, | 92 bool voidContext: false, |
84 Procedure interfaceTarget}) { | 93 Procedure interfaceTarget}) { |
85 return _finish(_makeWrite( | 94 return _finish(_makeWrite( |
86 builtBinary = makeBinary( | 95 builtBinary = makeBinary(helper.astFactory, _makeRead(), binaryOperator, |
87 _makeRead(), binaryOperator, interfaceTarget, value, | 96 interfaceTarget, value, |
88 offset: offset), | 97 offset: offset), |
89 voidContext)); | 98 voidContext)); |
90 } | 99 } |
91 | 100 |
92 /// Returns an [Expression] representing a pre-increment or pre-decrement | 101 /// Returns an [Expression] representing a pre-increment or pre-decrement |
93 /// of the accessor. | 102 /// of the accessor. |
94 Expression buildPrefixIncrement(Name binaryOperator, | 103 Expression buildPrefixIncrement(Name binaryOperator, |
95 {int offset: TreeNode.noOffset, | 104 {int offset: TreeNode.noOffset, |
96 bool voidContext: false, | 105 bool voidContext: false, |
97 Procedure interfaceTarget}) { | 106 Procedure interfaceTarget}) { |
98 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), | 107 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), |
99 offset: offset, | 108 offset: offset, |
100 voidContext: voidContext, | 109 voidContext: voidContext, |
101 interfaceTarget: interfaceTarget); | 110 interfaceTarget: interfaceTarget); |
102 } | 111 } |
103 | 112 |
104 /// Returns an [Expression] representing a post-increment or post-decrement | 113 /// Returns an [Expression] representing a post-increment or post-decrement |
105 /// of the accessor. | 114 /// of the accessor. |
106 Expression buildPostfixIncrement(Name binaryOperator, | 115 Expression buildPostfixIncrement(Name binaryOperator, |
107 {int offset: TreeNode.noOffset, | 116 {int offset: TreeNode.noOffset, |
108 bool voidContext: false, | 117 bool voidContext: false, |
109 Procedure interfaceTarget}) { | 118 Procedure interfaceTarget}) { |
110 if (voidContext) { | 119 if (voidContext) { |
111 return buildPrefixIncrement(binaryOperator, | 120 return buildPrefixIncrement(binaryOperator, |
112 offset: offset, voidContext: true, interfaceTarget: interfaceTarget); | 121 offset: offset, voidContext: true, interfaceTarget: interfaceTarget); |
113 } | 122 } |
114 var value = new VariableDeclaration.forValue(_makeRead()); | 123 var value = new VariableDeclaration.forValue(_makeRead()); |
115 valueAccess() => new VariableGet(value); | 124 valueAccess() => new VariableGet(value); |
116 var dummy = new VariableDeclaration.forValue(_makeWrite( | 125 var dummy = new VariableDeclaration.forValue(_makeWrite( |
117 builtBinary = makeBinary( | 126 builtBinary = makeBinary(helper.astFactory, valueAccess(), |
118 valueAccess(), binaryOperator, interfaceTarget, new IntLiteral(1), | 127 binaryOperator, interfaceTarget, new IntLiteral(1), |
119 offset: offset), | 128 offset: offset), |
120 true)); | 129 true)); |
121 return _finish(makeLet(value, makeLet(dummy, valueAccess()))); | 130 return _finish(makeLet(value, makeLet(dummy, valueAccess()))); |
122 } | 131 } |
123 | 132 |
124 Expression _makeSimpleRead() => _makeRead(); | 133 Expression _makeSimpleRead() => _makeRead(); |
125 | 134 |
126 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 135 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
127 return _makeWrite(value, voidContext); | 136 return _makeWrite(value, voidContext); |
128 } | 137 } |
(...skipping 13 matching lines...) Expand all Loading... |
142 /// [value]. | 151 /// [value]. |
143 /// | 152 /// |
144 /// At runtime, [value] will be evaluated before throwing an exception. | 153 /// At runtime, [value] will be evaluated before throwing an exception. |
145 makeInvalidWrite(Expression value) => wrapInvalid(value); | 154 makeInvalidWrite(Expression value) => wrapInvalid(value); |
146 } | 155 } |
147 | 156 |
148 abstract class VariableAccessor extends Accessor { | 157 abstract class VariableAccessor extends Accessor { |
149 VariableDeclaration variable; | 158 VariableDeclaration variable; |
150 DartType promotedType; | 159 DartType promotedType; |
151 | 160 |
152 BuilderHelper get helper; | 161 VariableAccessor( |
153 | 162 BuilderHelper helper, this.variable, this.promotedType, Token token) |
154 VariableAccessor(this.variable, this.promotedType, Token token) | 163 : super(helper, token); |
155 : super(token); | |
156 | 164 |
157 Expression _makeRead() { | 165 Expression _makeRead() { |
158 var fact = helper.typePromoter | 166 var fact = helper.typePromoter |
159 .getFactForAccess(variable, helper.functionNestingLevel); | 167 .getFactForAccess(variable, helper.functionNestingLevel); |
160 var scope = helper.typePromoter.currentScope; | 168 var scope = helper.typePromoter.currentScope; |
161 return helper.astFactory.variableGet(variable, fact, scope, token); | 169 return helper.astFactory.variableGet(variable, fact, scope, token); |
162 } | 170 } |
163 | 171 |
164 Expression _makeWrite(Expression value, bool voidContext) { | 172 Expression _makeWrite(Expression value, bool voidContext) { |
165 helper.typePromoter.mutateVariable(variable, helper.functionNestingLevel); | 173 helper.typePromoter.mutateVariable(variable, helper.functionNestingLevel); |
166 return variable.isFinal || variable.isConst | 174 return variable.isFinal || variable.isConst |
167 ? makeInvalidWrite(value) | 175 ? makeInvalidWrite(value) |
168 : new VariableSet(variable, value) | 176 : new VariableSet(variable, value) |
169 ..fileOffset = offsetForToken(token); | 177 ..fileOffset = offsetForToken(token); |
170 } | 178 } |
171 } | 179 } |
172 | 180 |
173 class PropertyAccessor extends Accessor { | 181 class PropertyAccessor extends Accessor { |
174 VariableDeclaration _receiverVariable; | 182 VariableDeclaration _receiverVariable; |
175 Expression receiver; | 183 Expression receiver; |
176 Name name; | 184 Name name; |
177 Member getter, setter; | 185 Member getter, setter; |
178 | 186 |
179 static Accessor make( | 187 static Accessor make(BuilderHelper helper, Expression receiver, Name name, |
180 Expression receiver, Name name, Member getter, Member setter, | 188 Member getter, Member setter, |
181 {Token token}) { | 189 {Token token}) { |
182 if (receiver is ThisExpression) { | 190 if (receiver is ThisExpression) { |
183 return new ThisPropertyAccessor(name, getter, setter, token); | 191 return new ThisPropertyAccessor(helper, name, getter, setter, token); |
184 } else { | 192 } else { |
185 return new PropertyAccessor.internal( | 193 return new PropertyAccessor.internal( |
186 receiver, name, getter, setter, token); | 194 helper, receiver, name, getter, setter, token); |
187 } | 195 } |
188 } | 196 } |
189 | 197 |
190 PropertyAccessor.internal( | 198 PropertyAccessor.internal(BuilderHelper helper, this.receiver, this.name, |
191 this.receiver, this.name, this.getter, this.setter, Token token) | 199 this.getter, this.setter, Token token) |
192 : super(token); | 200 : super(helper, token); |
193 | 201 |
194 Expression _makeSimpleRead() => new PropertyGet(receiver, name, getter) | 202 Expression _makeSimpleRead() => |
195 ..fileOffset = offsetForToken(token); | 203 helper.astFactory.propertyGet(receiver, name, getter) |
| 204 ..fileOffset = offsetForToken(token); |
196 | 205 |
197 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 206 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
198 return new PropertySet(receiver, name, value, setter) | 207 return helper.astFactory.propertySet(receiver, name, value, setter) |
199 ..fileOffset = offsetForToken(token); | 208 ..fileOffset = offsetForToken(token); |
200 } | 209 } |
201 | 210 |
202 receiverAccess() { | 211 receiverAccess() { |
203 _receiverVariable ??= new VariableDeclaration.forValue(receiver); | 212 _receiverVariable ??= new VariableDeclaration.forValue(receiver); |
204 return new VariableGet(_receiverVariable) | 213 return new VariableGet(_receiverVariable) |
205 ..fileOffset = offsetForToken(token); | 214 ..fileOffset = offsetForToken(token); |
206 } | 215 } |
207 | 216 |
208 Expression _makeRead() => | 217 Expression _makeRead() => builtGetter = helper.astFactory |
209 builtGetter = new PropertyGet(receiverAccess(), name, getter) | 218 .propertyGet(receiverAccess(), name, getter) |
210 ..fileOffset = offsetForToken(token); | 219 ..fileOffset = offsetForToken(token); |
211 | 220 |
212 Expression _makeWrite(Expression value, bool voidContext) { | 221 Expression _makeWrite(Expression value, bool voidContext) { |
213 return new PropertySet(receiverAccess(), name, value, setter) | 222 return helper.astFactory.propertySet(receiverAccess(), name, value, setter) |
214 ..fileOffset = offsetForToken(token); | 223 ..fileOffset = offsetForToken(token); |
215 } | 224 } |
216 | 225 |
217 Expression _finish(Expression body) => makeLet(_receiverVariable, body); | 226 Expression _finish(Expression body) => makeLet(_receiverVariable, body); |
218 } | 227 } |
219 | 228 |
220 /// Special case of [PropertyAccessor] to avoid creating an indirect access to | 229 /// Special case of [PropertyAccessor] to avoid creating an indirect access to |
221 /// 'this'. | 230 /// 'this'. |
222 class ThisPropertyAccessor extends Accessor { | 231 class ThisPropertyAccessor extends Accessor { |
223 Name name; | 232 Name name; |
224 Member getter, setter; | 233 Member getter, setter; |
225 | 234 |
226 ThisPropertyAccessor(this.name, this.getter, this.setter, Token token) | 235 ThisPropertyAccessor( |
227 : super(token); | 236 BuilderHelper helper, this.name, this.getter, this.setter, Token token) |
| 237 : super(helper, token); |
228 | 238 |
229 Expression _makeRead() => | 239 Expression _makeRead() => builtGetter = helper.astFactory |
230 builtGetter = new PropertyGet(new ThisExpression(), name, getter) | 240 .propertyGet(new ThisExpression(), name, getter) |
231 ..fileOffset = offsetForToken(token); | 241 ..fileOffset = offsetForToken(token); |
232 | 242 |
233 Expression _makeWrite(Expression value, bool voidContext) { | 243 Expression _makeWrite(Expression value, bool voidContext) { |
234 return new PropertySet(new ThisExpression(), name, value, setter) | 244 return helper.astFactory |
235 ..fileOffset = offsetForToken(token); | 245 .propertySet(new ThisExpression(), name, value, setter) |
| 246 ..fileOffset = offsetForToken(token); |
236 } | 247 } |
237 } | 248 } |
238 | 249 |
239 class NullAwarePropertyAccessor extends Accessor { | 250 class NullAwarePropertyAccessor extends Accessor { |
240 VariableDeclaration receiver; | 251 VariableDeclaration receiver; |
241 Name name; | 252 Name name; |
242 Member getter, setter; | 253 Member getter, setter; |
243 DartType type; | 254 DartType type; |
244 | 255 |
245 NullAwarePropertyAccessor(Expression receiver, this.name, this.getter, | 256 NullAwarePropertyAccessor(BuilderHelper helper, Expression receiver, |
246 this.setter, this.type, Token token) | 257 this.name, this.getter, this.setter, this.type, Token token) |
247 : this.receiver = makeOrReuseVariable(receiver), | 258 : this.receiver = makeOrReuseVariable(receiver), |
248 super(token); | 259 super(helper, token); |
249 | 260 |
250 receiverAccess() => new VariableGet(receiver); | 261 receiverAccess() => new VariableGet(receiver); |
251 | 262 |
252 Expression _makeRead() => | 263 Expression _makeRead() => builtGetter = |
253 builtGetter = new PropertyGet(receiverAccess(), name, getter); | 264 helper.astFactory.propertyGet(receiverAccess(), name, getter); |
254 | 265 |
255 Expression _makeWrite(Expression value, bool voidContext) { | 266 Expression _makeWrite(Expression value, bool voidContext) { |
256 return new PropertySet(receiverAccess(), name, value, setter); | 267 return helper.astFactory.propertySet(receiverAccess(), name, value, setter); |
257 } | 268 } |
258 | 269 |
259 Expression _finish(Expression body) => makeLet( | 270 Expression _finish(Expression body) => makeLet( |
260 receiver, | 271 receiver, |
261 new ConditionalExpression( | 272 new ConditionalExpression( |
262 buildIsNull(receiverAccess()), new NullLiteral(), body, type)); | 273 buildIsNull(helper.astFactory, receiverAccess()), |
| 274 new NullLiteral(), |
| 275 body, |
| 276 type)); |
263 } | 277 } |
264 | 278 |
265 class SuperPropertyAccessor extends Accessor { | 279 class SuperPropertyAccessor extends Accessor { |
266 Name name; | 280 Name name; |
267 Member getter, setter; | 281 Member getter, setter; |
268 | 282 |
269 SuperPropertyAccessor(this.name, this.getter, this.setter, Token token) | 283 SuperPropertyAccessor( |
270 : super(token); | 284 BuilderHelper helper, this.name, this.getter, this.setter, Token token) |
| 285 : super(helper, token); |
271 | 286 |
272 Expression _makeRead() { | 287 Expression _makeRead() { |
273 if (getter == null) return makeInvalidRead(); | 288 if (getter == null) return makeInvalidRead(); |
274 // TODO(ahe): Use [DirectPropertyGet] when possible. | 289 // TODO(ahe): Use [DirectPropertyGet] when possible. |
275 return builtGetter = new SuperPropertyGet(name, getter) | 290 return builtGetter = new SuperPropertyGet(name, getter) |
276 ..fileOffset = offsetForToken(token); | 291 ..fileOffset = offsetForToken(token); |
277 } | 292 } |
278 | 293 |
279 Expression _makeWrite(Expression value, bool voidContext) { | 294 Expression _makeWrite(Expression value, bool voidContext) { |
280 if (setter == null) return makeInvalidWrite(value); | 295 if (setter == null) return makeInvalidWrite(value); |
281 // TODO(ahe): Use [DirectPropertySet] when possible. | 296 // TODO(ahe): Use [DirectPropertySet] when possible. |
282 return new SuperPropertySet(name, value, setter) | 297 return new SuperPropertySet(name, value, setter) |
283 ..fileOffset = offsetForToken(token); | 298 ..fileOffset = offsetForToken(token); |
284 } | 299 } |
285 } | 300 } |
286 | 301 |
287 class IndexAccessor extends Accessor { | 302 class IndexAccessor extends Accessor { |
288 Expression receiver; | 303 Expression receiver; |
289 Expression index; | 304 Expression index; |
290 VariableDeclaration receiverVariable; | 305 VariableDeclaration receiverVariable; |
291 VariableDeclaration indexVariable; | 306 VariableDeclaration indexVariable; |
292 Procedure getter, setter; | 307 Procedure getter, setter; |
293 | 308 |
294 static Accessor make( | 309 static Accessor make(BuilderHelper helper, Expression receiver, |
295 Expression receiver, Expression index, Procedure getter, Procedure setter, | 310 Expression index, Procedure getter, Procedure setter, |
296 {Token token}) { | 311 {Token token}) { |
297 if (receiver is ThisExpression) { | 312 if (receiver is ThisExpression) { |
298 return new ThisIndexAccessor(index, getter, setter, token); | 313 return new ThisIndexAccessor(helper, index, getter, setter, token); |
299 } else { | 314 } else { |
300 return new IndexAccessor.internal(receiver, index, getter, setter, token); | 315 return new IndexAccessor.internal( |
| 316 helper, receiver, index, getter, setter, token); |
301 } | 317 } |
302 } | 318 } |
303 | 319 |
304 IndexAccessor.internal( | 320 IndexAccessor.internal(BuilderHelper helper, this.receiver, this.index, |
305 this.receiver, this.index, this.getter, this.setter, Token token) | 321 this.getter, this.setter, Token token) |
306 : super(token); | 322 : super(helper, token); |
307 | 323 |
308 Expression _makeSimpleRead() => new MethodInvocation( | 324 Expression _makeSimpleRead() => helper.astFactory.methodInvocation( |
309 receiver, indexGetName, new Arguments(<Expression>[index]), getter) | 325 receiver, indexGetName, new Arguments(<Expression>[index]), getter) |
310 ..fileOffset = offsetForToken(token); | 326 ..fileOffset = offsetForToken(token); |
311 | 327 |
312 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 328 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
313 if (!voidContext) return _makeWriteAndReturn(value); | 329 if (!voidContext) return _makeWriteAndReturn(value); |
314 return new MethodInvocation(receiver, indexSetName, | 330 return helper.astFactory.methodInvocation(receiver, indexSetName, |
315 new Arguments(<Expression>[index, value]), setter) | 331 new Arguments(<Expression>[index, value]), setter) |
316 ..fileOffset = offsetForToken(token); | 332 ..fileOffset = offsetForToken(token); |
317 } | 333 } |
318 | 334 |
319 receiverAccess() { | 335 receiverAccess() { |
320 // We cannot reuse the receiver if it is a variable since it might be | 336 // We cannot reuse the receiver if it is a variable since it might be |
321 // reassigned in the index expression. | 337 // reassigned in the index expression. |
322 receiverVariable ??= new VariableDeclaration.forValue(receiver); | 338 receiverVariable ??= new VariableDeclaration.forValue(receiver); |
323 return new VariableGet(receiverVariable) | 339 return new VariableGet(receiverVariable) |
324 ..fileOffset = offsetForToken(token); | 340 ..fileOffset = offsetForToken(token); |
325 } | 341 } |
326 | 342 |
327 indexAccess() { | 343 indexAccess() { |
328 indexVariable ??= new VariableDeclaration.forValue(index); | 344 indexVariable ??= new VariableDeclaration.forValue(index); |
329 return new VariableGet(indexVariable)..fileOffset = offsetForToken(token); | 345 return new VariableGet(indexVariable)..fileOffset = offsetForToken(token); |
330 } | 346 } |
331 | 347 |
332 Expression _makeRead() { | 348 Expression _makeRead() { |
333 return builtGetter = new MethodInvocation(receiverAccess(), indexGetName, | 349 return builtGetter = helper.astFactory.methodInvocation(receiverAccess(), |
334 new Arguments(<Expression>[indexAccess()]), getter) | 350 indexGetName, new Arguments(<Expression>[indexAccess()]), getter) |
335 ..fileOffset = offsetForToken(token); | 351 ..fileOffset = offsetForToken(token); |
336 } | 352 } |
337 | 353 |
338 Expression _makeWrite(Expression value, bool voidContext) { | 354 Expression _makeWrite(Expression value, bool voidContext) { |
339 if (!voidContext) return _makeWriteAndReturn(value); | 355 if (!voidContext) return _makeWriteAndReturn(value); |
340 return new MethodInvocation(receiverAccess(), indexSetName, | 356 return helper.astFactory.methodInvocation(receiverAccess(), indexSetName, |
341 new Arguments(<Expression>[indexAccess(), value]), setter) | 357 new Arguments(<Expression>[indexAccess(), value]), setter) |
342 ..fileOffset = offsetForToken(token); | 358 ..fileOffset = offsetForToken(token); |
343 } | 359 } |
344 | 360 |
345 // TODO(dmitryas): remove this method after the "[]=" operator of the Context | 361 // TODO(dmitryas): remove this method after the "[]=" operator of the Context |
346 // class is made to return a value. | 362 // class is made to return a value. |
347 _makeWriteAndReturn(Expression value) { | 363 _makeWriteAndReturn(Expression value) { |
348 // The call to []= does not return the value like direct-style assignments | 364 // The call to []= does not return the value like direct-style assignments |
349 // do. We need to bind the value in a let. | 365 // do. We need to bind the value in a let. |
350 var valueVariable = new VariableDeclaration.forValue(value); | 366 var valueVariable = new VariableDeclaration.forValue(value); |
351 var dummy = new VariableDeclaration.forValue(new MethodInvocation( | 367 var dummy = new VariableDeclaration.forValue(helper.astFactory |
352 receiverAccess(), | 368 .methodInvocation( |
353 indexSetName, | 369 receiverAccess(), |
354 new Arguments( | 370 indexSetName, |
355 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 371 new Arguments( |
356 setter) | 372 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
357 ..fileOffset = offsetForToken(token)); | 373 setter) |
| 374 ..fileOffset = offsetForToken(token)); |
358 return makeLet( | 375 return makeLet( |
359 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 376 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
360 } | 377 } |
361 | 378 |
362 Expression _finish(Expression body) { | 379 Expression _finish(Expression body) { |
363 return makeLet(receiverVariable, makeLet(indexVariable, body)); | 380 return makeLet(receiverVariable, makeLet(indexVariable, body)); |
364 } | 381 } |
365 } | 382 } |
366 | 383 |
367 /// Special case of [IndexAccessor] to avoid creating an indirect access to | 384 /// Special case of [IndexAccessor] to avoid creating an indirect access to |
368 /// 'this'. | 385 /// 'this'. |
369 class ThisIndexAccessor extends Accessor { | 386 class ThisIndexAccessor extends Accessor { |
370 Expression index; | 387 Expression index; |
371 VariableDeclaration indexVariable; | 388 VariableDeclaration indexVariable; |
372 Procedure getter, setter; | 389 Procedure getter, setter; |
373 | 390 |
374 ThisIndexAccessor(this.index, this.getter, this.setter, Token token) | 391 ThisIndexAccessor( |
375 : super(token); | 392 BuilderHelper helper, this.index, this.getter, this.setter, Token token) |
| 393 : super(helper, token); |
376 | 394 |
377 Expression _makeSimpleRead() { | 395 Expression _makeSimpleRead() { |
378 return new MethodInvocation(new ThisExpression(), indexGetName, | 396 return helper.astFactory.methodInvocation(new ThisExpression(), |
379 new Arguments(<Expression>[index]), getter); | 397 indexGetName, new Arguments(<Expression>[index]), getter); |
380 } | 398 } |
381 | 399 |
382 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 400 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
383 if (!voidContext) return _makeWriteAndReturn(value); | 401 if (!voidContext) return _makeWriteAndReturn(value); |
384 return new MethodInvocation(new ThisExpression(), indexSetName, | 402 return helper.astFactory.methodInvocation(new ThisExpression(), |
385 new Arguments(<Expression>[index, value]), setter); | 403 indexSetName, new Arguments(<Expression>[index, value]), setter); |
386 } | 404 } |
387 | 405 |
388 indexAccess() { | 406 indexAccess() { |
389 indexVariable ??= new VariableDeclaration.forValue(index); | 407 indexVariable ??= new VariableDeclaration.forValue(index); |
390 return new VariableGet(indexVariable); | 408 return new VariableGet(indexVariable); |
391 } | 409 } |
392 | 410 |
393 Expression _makeRead() => builtGetter = new MethodInvocation( | 411 Expression _makeRead() => builtGetter = helper.astFactory.methodInvocation( |
394 new ThisExpression(), | 412 new ThisExpression(), |
395 indexGetName, | 413 indexGetName, |
396 new Arguments(<Expression>[indexAccess()]), | 414 new Arguments(<Expression>[indexAccess()]), |
397 getter); | 415 getter); |
398 | 416 |
399 Expression _makeWrite(Expression value, bool voidContext) { | 417 Expression _makeWrite(Expression value, bool voidContext) { |
400 if (!voidContext) return _makeWriteAndReturn(value); | 418 if (!voidContext) return _makeWriteAndReturn(value); |
401 return new MethodInvocation(new ThisExpression(), indexSetName, | 419 return helper.astFactory.methodInvocation( |
402 new Arguments(<Expression>[indexAccess(), value]), setter); | 420 new ThisExpression(), |
| 421 indexSetName, |
| 422 new Arguments(<Expression>[indexAccess(), value]), |
| 423 setter); |
403 } | 424 } |
404 | 425 |
405 _makeWriteAndReturn(Expression value) { | 426 _makeWriteAndReturn(Expression value) { |
406 var valueVariable = new VariableDeclaration.forValue(value); | 427 var valueVariable = new VariableDeclaration.forValue(value); |
407 var dummy = new VariableDeclaration.forValue(new MethodInvocation( | 428 var dummy = new VariableDeclaration.forValue(helper.astFactory |
408 new ThisExpression(), | 429 .methodInvocation( |
409 indexSetName, | 430 new ThisExpression(), |
410 new Arguments( | 431 indexSetName, |
411 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 432 new Arguments( |
412 setter)); | 433 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
| 434 setter)); |
413 return makeLet( | 435 return makeLet( |
414 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 436 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
415 } | 437 } |
416 | 438 |
417 Expression _finish(Expression body) => makeLet(indexVariable, body); | 439 Expression _finish(Expression body) => makeLet(indexVariable, body); |
418 } | 440 } |
419 | 441 |
420 class SuperIndexAccessor extends Accessor { | 442 class SuperIndexAccessor extends Accessor { |
421 Expression index; | 443 Expression index; |
422 VariableDeclaration indexVariable; | 444 VariableDeclaration indexVariable; |
423 Member getter, setter; | 445 Member getter, setter; |
424 | 446 |
425 SuperIndexAccessor(this.index, this.getter, this.setter, Token token) | 447 SuperIndexAccessor( |
426 : super(token); | 448 BuilderHelper helper, this.index, this.getter, this.setter, Token token) |
| 449 : super(helper, token); |
427 | 450 |
428 indexAccess() { | 451 indexAccess() { |
429 indexVariable ??= new VariableDeclaration.forValue(index); | 452 indexVariable ??= new VariableDeclaration.forValue(index); |
430 return new VariableGet(indexVariable); | 453 return new VariableGet(indexVariable); |
431 } | 454 } |
432 | 455 |
433 Expression _makeSimpleRead() => new SuperMethodInvocation( | 456 Expression _makeSimpleRead() => new SuperMethodInvocation( |
434 indexGetName, new Arguments(<Expression>[index]), getter); | 457 indexGetName, new Arguments(<Expression>[index]), getter); |
435 | 458 |
436 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 459 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
(...skipping 23 matching lines...) Expand all Loading... |
460 return makeLet( | 483 return makeLet( |
461 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 484 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
462 } | 485 } |
463 | 486 |
464 Expression _finish(Expression body) { | 487 Expression _finish(Expression body) { |
465 return makeLet(indexVariable, body); | 488 return makeLet(indexVariable, body); |
466 } | 489 } |
467 } | 490 } |
468 | 491 |
469 class StaticAccessor extends Accessor { | 492 class StaticAccessor extends Accessor { |
470 final BuilderHelper helper; | |
471 Member readTarget; | 493 Member readTarget; |
472 Member writeTarget; | 494 Member writeTarget; |
473 | 495 |
474 StaticAccessor(this.helper, this.readTarget, this.writeTarget, Token token) | 496 StaticAccessor( |
475 : super(token); | 497 BuilderHelper helper, this.readTarget, this.writeTarget, Token token) |
| 498 : super(helper, token); |
476 | 499 |
477 Expression _makeRead() => builtGetter = readTarget == null | 500 Expression _makeRead() => builtGetter = readTarget == null |
478 ? makeInvalidRead() | 501 ? makeInvalidRead() |
479 : helper.makeStaticGet(readTarget, token); | 502 : helper.makeStaticGet(readTarget, token); |
480 | 503 |
481 Expression _makeWrite(Expression value, bool voidContext) { | 504 Expression _makeWrite(Expression value, bool voidContext) { |
482 return writeTarget == null | 505 return writeTarget == null |
483 ? makeInvalidWrite(value) | 506 ? makeInvalidWrite(value) |
484 : new StaticSet(writeTarget, value) | 507 : new StaticSet(writeTarget, value) |
485 ..fileOffset = offsetForToken(token); | 508 ..fileOffset = offsetForToken(token); |
486 } | 509 } |
487 } | 510 } |
488 | 511 |
489 class ReadOnlyAccessor extends Accessor { | 512 class ReadOnlyAccessor extends Accessor { |
490 Expression expression; | 513 Expression expression; |
491 VariableDeclaration value; | 514 VariableDeclaration value; |
492 | 515 |
493 ReadOnlyAccessor(this.expression, Token token) : super(token); | 516 ReadOnlyAccessor(BuilderHelper helper, this.expression, Token token) |
| 517 : super(helper, token); |
494 | 518 |
495 Expression _makeSimpleRead() => expression; | 519 Expression _makeSimpleRead() => expression; |
496 | 520 |
497 Expression _makeRead() { | 521 Expression _makeRead() { |
498 value ??= new VariableDeclaration.forValue(expression); | 522 value ??= new VariableDeclaration.forValue(expression); |
499 return new VariableGet(value); | 523 return new VariableGet(value); |
500 } | 524 } |
501 | 525 |
502 Expression _makeWrite(Expression value, bool voidContext) => | 526 Expression _makeWrite(Expression value, bool voidContext) => |
503 makeInvalidWrite(value); | 527 makeInvalidWrite(value); |
504 | 528 |
505 Expression _finish(Expression body) => makeLet(value, body); | 529 Expression _finish(Expression body) => makeLet(value, body); |
506 } | 530 } |
507 | 531 |
508 Expression makeLet(VariableDeclaration variable, Expression body) { | 532 Expression makeLet(VariableDeclaration variable, Expression body) { |
509 if (variable == null) return body; | 533 if (variable == null) return body; |
510 return new Let(variable, body); | 534 return new Let(variable, body); |
511 } | 535 } |
512 | 536 |
513 Expression makeBinary( | 537 Expression makeBinary(AstFactory astFactory, Expression left, Name operator, |
514 Expression left, Name operator, Procedure interfaceTarget, Expression right, | 538 Procedure interfaceTarget, Expression right, |
515 {int offset: TreeNode.noOffset}) { | 539 {int offset: TreeNode.noOffset}) { |
516 return new MethodInvocation( | 540 return astFactory.methodInvocation( |
517 left, operator, new Arguments(<Expression>[right]), interfaceTarget) | 541 left, operator, new Arguments(<Expression>[right]), interfaceTarget) |
518 ..fileOffset = offset; | 542 ..fileOffset = offset; |
519 } | 543 } |
520 | 544 |
521 final Name _equalOperator = new Name('=='); | 545 final Name _equalOperator = new Name('=='); |
522 | 546 |
523 Expression buildIsNull(Expression value, {int offset: TreeNode.noOffset}) { | 547 Expression buildIsNull(AstFactory astFactory, Expression value, |
524 return makeBinary(value, _equalOperator, null, new NullLiteral(), | 548 {int offset: TreeNode.noOffset}) { |
| 549 return makeBinary(astFactory, value, _equalOperator, null, new NullLiteral(), |
525 offset: offset); | 550 offset: offset); |
526 } | 551 } |
527 | 552 |
528 VariableDeclaration makeOrReuseVariable(Expression value) { | 553 VariableDeclaration makeOrReuseVariable(Expression value) { |
529 // TODO: Devise a way to remember if a variable declaration was reused | 554 // TODO: Devise a way to remember if a variable declaration was reused |
530 // or is fresh (hence needs a let binding). | 555 // or is fresh (hence needs a let binding). |
531 return new VariableDeclaration.forValue(value); | 556 return new VariableDeclaration.forValue(value); |
532 } | 557 } |
533 | 558 |
534 Expression wrapInvalid(Expression e) { | 559 Expression wrapInvalid(Expression e) { |
535 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); | 560 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); |
536 } | 561 } |
OLD | NEW |