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 /// A library to help transform compounds and null-aware accessors into | 5 /// A library to help transform compounds and null-aware accessors into |
6 /// let expressions. | 6 /// let expressions. |
7 library kernel.frontend.accessors; | 7 library kernel.frontend.accessors; |
8 | 8 |
9 import '../ast.dart'; | 9 import '../ast.dart'; |
10 | 10 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 DartType promotedType; | 144 DartType promotedType; |
145 | 145 |
146 VariableAccessor(this.variable, this.promotedType, int offset) | 146 VariableAccessor(this.variable, this.promotedType, int offset) |
147 : super(offset); | 147 : super(offset); |
148 | 148 |
149 _makeRead() => new VariableGet(variable, promotedType)..fileOffset = offset; | 149 _makeRead() => new VariableGet(variable, promotedType)..fileOffset = offset; |
150 | 150 |
151 _makeWrite(Expression value, bool voidContext) { | 151 _makeWrite(Expression value, bool voidContext) { |
152 return variable.isFinal || variable.isConst | 152 return variable.isFinal || variable.isConst |
153 ? makeInvalidWrite(value) | 153 ? makeInvalidWrite(value) |
154 : new VariableSet(variable, value)..fileOffset = offset; | 154 : new VariableSet(variable, value) |
| 155 ..fileOffset = offset; |
155 } | 156 } |
156 } | 157 } |
157 | 158 |
158 class PropertyAccessor extends Accessor { | 159 class PropertyAccessor extends Accessor { |
159 VariableDeclaration _receiverVariable; | 160 VariableDeclaration _receiverVariable; |
160 Expression receiver; | 161 Expression receiver; |
161 Name name; | 162 Name name; |
162 Member getter, setter; | 163 Member getter, setter; |
163 | 164 |
164 static Accessor make( | 165 static Accessor make( |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 this.receiver, this.index, this.getter, this.setter, int offset) | 286 this.receiver, this.index, this.getter, this.setter, int offset) |
286 : super(offset); | 287 : super(offset); |
287 | 288 |
288 _makeSimpleRead() => new MethodInvocation( | 289 _makeSimpleRead() => new MethodInvocation( |
289 receiver, indexGetName, new Arguments(<Expression>[index]), getter) | 290 receiver, indexGetName, new Arguments(<Expression>[index]), getter) |
290 ..fileOffset = offset; | 291 ..fileOffset = offset; |
291 | 292 |
292 _makeSimpleWrite(Expression value, bool voidContext) { | 293 _makeSimpleWrite(Expression value, bool voidContext) { |
293 if (!voidContext) return _makeWriteAndReturn(value); | 294 if (!voidContext) return _makeWriteAndReturn(value); |
294 return new MethodInvocation(receiver, indexSetName, | 295 return new MethodInvocation(receiver, indexSetName, |
295 new Arguments(<Expression>[index, value]), setter)..fileOffset = offset; | 296 new Arguments(<Expression>[index, value]), setter) |
| 297 ..fileOffset = offset; |
296 } | 298 } |
297 | 299 |
298 receiverAccess() { | 300 receiverAccess() { |
299 // We cannot reuse the receiver if it is a variable since it might be | 301 // We cannot reuse the receiver if it is a variable since it might be |
300 // reassigned in the index expression. | 302 // reassigned in the index expression. |
301 receiverVariable ??= new VariableDeclaration.forValue(receiver); | 303 receiverVariable ??= new VariableDeclaration.forValue(receiver); |
302 return new VariableGet(receiverVariable)..fileOffset = offset; | 304 return new VariableGet(receiverVariable)..fileOffset = offset; |
303 } | 305 } |
304 | 306 |
305 indexAccess() { | 307 indexAccess() { |
306 indexVariable ??= new VariableDeclaration.forValue(index); | 308 indexVariable ??= new VariableDeclaration.forValue(index); |
307 return new VariableGet(indexVariable)..fileOffset = offset; | 309 return new VariableGet(indexVariable)..fileOffset = offset; |
308 } | 310 } |
309 | 311 |
310 _makeRead() { | 312 _makeRead() { |
311 return builtGetter = new MethodInvocation( | 313 return builtGetter = new MethodInvocation(receiverAccess(), indexGetName, |
312 receiverAccess(), | 314 new Arguments(<Expression>[indexAccess()]), getter) |
313 indexGetName, | 315 ..fileOffset = offset; |
314 new Arguments(<Expression>[indexAccess()]), | |
315 getter)..fileOffset = offset; | |
316 } | 316 } |
317 | 317 |
318 _makeWrite(Expression value, bool voidContext) { | 318 _makeWrite(Expression value, bool voidContext) { |
319 if (!voidContext) return _makeWriteAndReturn(value); | 319 if (!voidContext) return _makeWriteAndReturn(value); |
320 return new MethodInvocation( | 320 return new MethodInvocation(receiverAccess(), indexSetName, |
321 receiverAccess(), | 321 new Arguments(<Expression>[indexAccess(), value]), setter) |
322 indexSetName, | 322 ..fileOffset = offset; |
323 new Arguments(<Expression>[indexAccess(), value]), | |
324 setter)..fileOffset = offset; | |
325 } | 323 } |
326 | 324 |
327 // TODO(dmitryas): remove this method after the "[]=" operator of the Context | 325 // TODO(dmitryas): remove this method after the "[]=" operator of the Context |
328 // class is made to return a value. | 326 // class is made to return a value. |
329 _makeWriteAndReturn(Expression value) { | 327 _makeWriteAndReturn(Expression value) { |
330 // The call to []= does not return the value like direct-style assignments | 328 // The call to []= does not return the value like direct-style assignments |
331 // do. We need to bind the value in a let. | 329 // do. We need to bind the value in a let. |
332 var valueVariable = new VariableDeclaration.forValue(value); | 330 var valueVariable = new VariableDeclaration.forValue(value); |
333 var dummy = new VariableDeclaration.forValue(new MethodInvocation( | 331 var dummy = new VariableDeclaration.forValue(new MethodInvocation( |
334 receiverAccess(), | 332 receiverAccess(), |
335 indexSetName, | 333 indexSetName, |
336 new Arguments( | 334 new Arguments( |
337 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 335 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
338 setter)..fileOffset = offset); | 336 setter) |
| 337 ..fileOffset = offset); |
339 return makeLet( | 338 return makeLet( |
340 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 339 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
341 } | 340 } |
342 | 341 |
343 Expression _finish(Expression body) { | 342 Expression _finish(Expression body) { |
344 return makeLet(receiverVariable, makeLet(indexVariable, body)); | 343 return makeLet(receiverVariable, makeLet(indexVariable, body)); |
345 } | 344 } |
346 } | 345 } |
347 | 346 |
348 /// Special case of [IndexAccessor] to avoid creating an indirect access to | 347 /// Special case of [IndexAccessor] to avoid creating an indirect access to |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 return makeLet(indexVariable, body); | 442 return makeLet(indexVariable, body); |
444 } | 443 } |
445 } | 444 } |
446 | 445 |
447 class StaticAccessor extends Accessor { | 446 class StaticAccessor extends Accessor { |
448 Member readTarget; | 447 Member readTarget; |
449 Member writeTarget; | 448 Member writeTarget; |
450 | 449 |
451 StaticAccessor(this.readTarget, this.writeTarget, int offset) : super(offset); | 450 StaticAccessor(this.readTarget, this.writeTarget, int offset) : super(offset); |
452 | 451 |
453 _makeRead() => builtGetter = readTarget == null | 452 _makeRead() => builtGetter = |
454 ? makeInvalidRead() | 453 readTarget == null ? makeInvalidRead() : new StaticGet(readTarget) |
455 : new StaticGet(readTarget)..fileOffset = offset; | 454 ..fileOffset = offset; |
456 | 455 |
457 _makeWrite(Expression value, bool voidContext) { | 456 _makeWrite(Expression value, bool voidContext) { |
458 return writeTarget == null | 457 return writeTarget == null |
459 ? makeInvalidWrite(value) | 458 ? makeInvalidWrite(value) |
460 : new StaticSet(writeTarget, value)..fileOffset = offset; | 459 : new StaticSet(writeTarget, value) |
| 460 ..fileOffset = offset; |
461 } | 461 } |
462 } | 462 } |
463 | 463 |
464 class ReadOnlyAccessor extends Accessor { | 464 class ReadOnlyAccessor extends Accessor { |
465 Expression expression; | 465 Expression expression; |
466 VariableDeclaration value; | 466 VariableDeclaration value; |
467 | 467 |
468 ReadOnlyAccessor(this.expression, int offset) : super(offset); | 468 ReadOnlyAccessor(this.expression, int offset) : super(offset); |
469 | 469 |
470 _makeSimpleRead() => expression; | 470 _makeSimpleRead() => expression; |
(...skipping 30 matching lines...) Expand all Loading... |
501 | 501 |
502 VariableDeclaration makeOrReuseVariable(Expression value) { | 502 VariableDeclaration makeOrReuseVariable(Expression value) { |
503 // TODO: Devise a way to remember if a variable declaration was reused | 503 // TODO: Devise a way to remember if a variable declaration was reused |
504 // or is fresh (hence needs a let binding). | 504 // or is fresh (hence needs a let binding). |
505 return new VariableDeclaration.forValue(value); | 505 return new VariableDeclaration.forValue(value); |
506 } | 506 } |
507 | 507 |
508 Expression wrapInvalid(Expression e) { | 508 Expression wrapInvalid(Expression e) { |
509 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); | 509 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); |
510 } | 510 } |
OLD | NEW |