| 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 | 7 |
| 8 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart' | 8 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart' |
| 9 show | 9 show |
| 10 KernelArguments, | 10 KernelArguments, |
| 11 KernelComplexAssign, |
| 12 KernelConditionalExpression, |
| 11 KernelMethodInvocation, | 13 KernelMethodInvocation, |
| 12 KernelPropertyGet, | 14 KernelPropertyGet, |
| 13 KernelPropertySet, | 15 KernelPropertySet, |
| 16 KernelVariableDeclaration, |
| 14 KernelVariableGet, | 17 KernelVariableGet, |
| 15 KernelVariableSet; | 18 KernelVariableSet; |
| 16 | 19 |
| 17 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; | 20 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; |
| 18 | 21 |
| 19 import 'package:front_end/src/scanner/token.dart' show Token; | 22 import 'package:front_end/src/scanner/token.dart' show Token; |
| 20 | 23 |
| 21 import 'package:front_end/src/fasta/kernel/fasta_accessors.dart' | 24 import 'package:front_end/src/fasta/kernel/fasta_accessors.dart' |
| 22 show BuilderHelper; | 25 show BuilderHelper; |
| 23 | 26 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 /// Returns an [Expression] representing a null-aware assignment (`??=`) with | 65 /// Returns an [Expression] representing a null-aware assignment (`??=`) with |
| 63 /// the accessor on the LHS and [value] on the RHS. | 66 /// the accessor on the LHS and [value] on the RHS. |
| 64 /// | 67 /// |
| 65 /// The returned expression evaluates to the assigned value, unless | 68 /// The returned expression evaluates to the assigned value, unless |
| 66 /// [voidContext] is true, in which case it may evaluate to anything. | 69 /// [voidContext] is true, in which case it may evaluate to anything. |
| 67 /// | 70 /// |
| 68 /// [type] is the static type of the RHS. | 71 /// [type] is the static type of the RHS. |
| 69 Expression buildNullAwareAssignment(Expression value, DartType type, | 72 Expression buildNullAwareAssignment(Expression value, DartType type, |
| 70 {bool voidContext: false}) { | 73 {bool voidContext: false}) { |
| 71 if (voidContext) { | 74 if (voidContext) { |
| 72 return _finish(new ConditionalExpression(buildIsNull(_makeRead()), | 75 return _finish(new KernelConditionalExpression( |
| 73 _makeWrite(value, false), new NullLiteral(), type)); | 76 buildIsNull(_makeRead()), _makeWrite(value, false), new NullLiteral(), |
| 77 isNullAwareCombiner: true)); |
| 74 } | 78 } |
| 75 var tmp = new VariableDeclaration.forValue(_makeRead()); | 79 var tmp = new VariableDeclaration.forValue(_makeRead()); |
| 76 return _finish(makeLet( | 80 return _finish(makeLet( |
| 77 tmp, | 81 tmp, |
| 78 new ConditionalExpression(buildIsNull(new VariableGet(tmp)), | 82 new KernelConditionalExpression(buildIsNull(new VariableGet(tmp)), |
| 79 _makeWrite(value, false), new VariableGet(tmp), type))); | 83 _makeWrite(value, false), new VariableGet(tmp), |
| 84 isNullAwareCombiner: true))); |
| 80 } | 85 } |
| 81 | 86 |
| 82 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) | 87 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) |
| 83 /// with the accessor on the LHS and [value] on the RHS. | 88 /// with the accessor on the LHS and [value] on the RHS. |
| 84 Expression buildCompoundAssignment(Name binaryOperator, Expression value, | 89 Expression buildCompoundAssignment(Name binaryOperator, Expression value, |
| 85 {int offset: TreeNode.noOffset, | 90 {int offset: TreeNode.noOffset, |
| 86 bool voidContext: false, | 91 bool voidContext: false, |
| 87 Procedure interfaceTarget}) { | 92 Procedure interfaceTarget}) { |
| 88 return _finish(_makeWrite( | 93 return _finish(_makeWrite( |
| 89 makeBinary(_makeRead(), binaryOperator, interfaceTarget, value, | 94 makeBinary(_makeRead(), binaryOperator, interfaceTarget, value, |
| 90 offset: offset), | 95 offset: offset, isCombiner: true), |
| 91 voidContext)); | 96 voidContext)); |
| 92 } | 97 } |
| 93 | 98 |
| 94 /// Returns an [Expression] representing a pre-increment or pre-decrement | 99 /// Returns an [Expression] representing a pre-increment or pre-decrement |
| 95 /// of the accessor. | 100 /// of the accessor. |
| 96 Expression buildPrefixIncrement(Name binaryOperator, | 101 Expression buildPrefixIncrement(Name binaryOperator, |
| 97 {int offset: TreeNode.noOffset, | 102 {int offset: TreeNode.noOffset, |
| 98 bool voidContext: false, | 103 bool voidContext: false, |
| 99 Procedure interfaceTarget}) { | 104 Procedure interfaceTarget}) { |
| 100 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), | 105 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), |
| 101 offset: offset, | 106 offset: offset, |
| 102 voidContext: voidContext, | 107 voidContext: voidContext, |
| 103 interfaceTarget: interfaceTarget); | 108 interfaceTarget: interfaceTarget); |
| 104 } | 109 } |
| 105 | 110 |
| 106 /// Returns an [Expression] representing a post-increment or post-decrement | 111 /// Returns an [Expression] representing a post-increment or post-decrement |
| 107 /// of the accessor. | 112 /// of the accessor. |
| 108 Expression buildPostfixIncrement(Name binaryOperator, | 113 Expression buildPostfixIncrement(Name binaryOperator, |
| 109 {int offset: TreeNode.noOffset, | 114 {int offset: TreeNode.noOffset, |
| 110 bool voidContext: false, | 115 bool voidContext: false, |
| 111 Procedure interfaceTarget}) { | 116 Procedure interfaceTarget}) { |
| 112 if (voidContext) { | 117 if (voidContext) { |
| 113 return buildPrefixIncrement(binaryOperator, | 118 return buildPrefixIncrement(binaryOperator, |
| 114 offset: offset, voidContext: true, interfaceTarget: interfaceTarget); | 119 offset: offset, voidContext: true, interfaceTarget: interfaceTarget); |
| 115 } | 120 } |
| 116 var value = new VariableDeclaration.forValue(_makeRead()); | 121 var value = new VariableDeclaration.forValue(_makeRead()); |
| 117 valueAccess() => new VariableGet(value); | 122 valueAccess() => new VariableGet(value); |
| 118 var dummy = new VariableDeclaration.forValue(_makeWrite( | 123 var dummy = new KernelVariableDeclaration.forValue( |
| 119 makeBinary( | 124 _makeWrite( |
| 120 valueAccess(), binaryOperator, interfaceTarget, new IntLiteral(1), | 125 makeBinary(valueAccess(), binaryOperator, interfaceTarget, |
| 121 offset: offset), | 126 new IntLiteral(1), |
| 122 true)); | 127 offset: offset, isCombiner: true), |
| 128 true), |
| 129 helper.functionNestingLevel, |
| 130 isDiscarding: true); |
| 123 return _finish(makeLet(value, makeLet(dummy, valueAccess()))); | 131 return _finish(makeLet(value, makeLet(dummy, valueAccess()))); |
| 124 } | 132 } |
| 125 | 133 |
| 126 Expression _makeSimpleRead() => _makeRead(); | 134 Expression _makeSimpleRead() => _makeRead(); |
| 127 | 135 |
| 128 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 136 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| 129 return _makeWrite(value, voidContext); | 137 return _makeWrite(value, voidContext); |
| 130 } | 138 } |
| 131 | 139 |
| 132 Expression _makeRead(); | 140 Expression _makeRead(); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 | 268 |
| 261 Expression _makeRead() => | 269 Expression _makeRead() => |
| 262 new KernelPropertyGet(receiverAccess(), name, getter); | 270 new KernelPropertyGet(receiverAccess(), name, getter); |
| 263 | 271 |
| 264 Expression _makeWrite(Expression value, bool voidContext) { | 272 Expression _makeWrite(Expression value, bool voidContext) { |
| 265 return new KernelPropertySet(receiverAccess(), name, value, setter); | 273 return new KernelPropertySet(receiverAccess(), name, value, setter); |
| 266 } | 274 } |
| 267 | 275 |
| 268 Expression _finish(Expression body) => makeLet( | 276 Expression _finish(Expression body) => makeLet( |
| 269 receiver, | 277 receiver, |
| 270 new ConditionalExpression( | 278 new KernelConditionalExpression( |
| 271 buildIsNull(receiverAccess()), new NullLiteral(), body, type)); | 279 buildIsNull(receiverAccess()), new NullLiteral(), body)); |
| 272 } | 280 } |
| 273 | 281 |
| 274 class SuperPropertyAccessor extends Accessor { | 282 class SuperPropertyAccessor extends Accessor { |
| 275 Name name; | 283 Name name; |
| 276 Member getter, setter; | 284 Member getter, setter; |
| 277 | 285 |
| 278 SuperPropertyAccessor( | 286 SuperPropertyAccessor( |
| 279 BuilderHelper helper, this.name, this.getter, this.setter, Token token) | 287 BuilderHelper helper, this.name, this.getter, this.setter, Token token) |
| 280 : super(helper, token); | 288 : super(helper, token); |
| 281 | 289 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 interfaceTarget: setter) | 364 interfaceTarget: setter) |
| 357 ..fileOffset = offsetForToken(token); | 365 ..fileOffset = offsetForToken(token); |
| 358 } | 366 } |
| 359 | 367 |
| 360 // TODO(dmitryas): remove this method after the "[]=" operator of the Context | 368 // TODO(dmitryas): remove this method after the "[]=" operator of the Context |
| 361 // class is made to return a value. | 369 // class is made to return a value. |
| 362 _makeWriteAndReturn(Expression value) { | 370 _makeWriteAndReturn(Expression value) { |
| 363 // The call to []= does not return the value like direct-style assignments | 371 // The call to []= does not return the value like direct-style assignments |
| 364 // do. We need to bind the value in a let. | 372 // do. We need to bind the value in a let. |
| 365 var valueVariable = new VariableDeclaration.forValue(value); | 373 var valueVariable = new VariableDeclaration.forValue(value); |
| 366 var dummy = new VariableDeclaration.forValue(new KernelMethodInvocation( | 374 var dummy = new KernelVariableDeclaration.forValue( |
| 367 receiverAccess(), | 375 new KernelMethodInvocation( |
| 368 indexSetName, | 376 receiverAccess(), |
| 369 new KernelArguments( | 377 indexSetName, |
| 370 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 378 new KernelArguments( |
| 371 interfaceTarget: setter) | 379 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
| 372 ..fileOffset = offsetForToken(token)); | 380 interfaceTarget: setter) |
| 381 ..fileOffset = offsetForToken(token), |
| 382 helper.functionNestingLevel, |
| 383 isDiscarding: true); |
| 373 return makeLet( | 384 return makeLet( |
| 374 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 385 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
| 375 } | 386 } |
| 376 | 387 |
| 377 Expression _finish(Expression body) { | 388 Expression _finish(Expression body) { |
| 378 return makeLet(receiverVariable, makeLet(indexVariable, body)); | 389 if (receiverVariable == null) { |
| 390 assert(indexVariable == null); |
| 391 return body; |
| 392 } else { |
| 393 return new KernelComplexAssign( |
| 394 receiverVariable, makeLet(indexVariable, body)); |
| 395 } |
| 379 } | 396 } |
| 380 } | 397 } |
| 381 | 398 |
| 382 /// Special case of [IndexAccessor] to avoid creating an indirect access to | 399 /// Special case of [IndexAccessor] to avoid creating an indirect access to |
| 383 /// 'this'. | 400 /// 'this'. |
| 384 class ThisIndexAccessor extends Accessor { | 401 class ThisIndexAccessor extends Accessor { |
| 385 Expression index; | 402 Expression index; |
| 386 VariableDeclaration indexVariable; | 403 VariableDeclaration indexVariable; |
| 387 Procedure getter, setter; | 404 Procedure getter, setter; |
| 388 | 405 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 Expression _finish(Expression body) => makeLet(value, body); | 541 Expression _finish(Expression body) => makeLet(value, body); |
| 525 } | 542 } |
| 526 | 543 |
| 527 Expression makeLet(VariableDeclaration variable, Expression body) { | 544 Expression makeLet(VariableDeclaration variable, Expression body) { |
| 528 if (variable == null) return body; | 545 if (variable == null) return body; |
| 529 return new Let(variable, body); | 546 return new Let(variable, body); |
| 530 } | 547 } |
| 531 | 548 |
| 532 Expression makeBinary( | 549 Expression makeBinary( |
| 533 Expression left, Name operator, Procedure interfaceTarget, Expression right, | 550 Expression left, Name operator, Procedure interfaceTarget, Expression right, |
| 534 {int offset: TreeNode.noOffset}) { | 551 {int offset: TreeNode.noOffset, bool isCombiner: false}) { |
| 535 return new KernelMethodInvocation( | 552 return new KernelMethodInvocation( |
| 536 left, operator, new KernelArguments(<Expression>[right]), | 553 left, operator, new KernelArguments(<Expression>[right]), |
| 537 interfaceTarget: interfaceTarget) | 554 interfaceTarget: interfaceTarget, isCombiner: isCombiner) |
| 538 ..fileOffset = offset; | 555 ..fileOffset = offset; |
| 539 } | 556 } |
| 540 | 557 |
| 541 Expression buildIsNull(Expression value, {int offset: TreeNode.noOffset}) { | 558 Expression buildIsNull(Expression value, {int offset: TreeNode.noOffset}) { |
| 542 return makeBinary(value, equalsName, null, new NullLiteral(), offset: offset); | 559 return makeBinary(value, equalsName, null, new NullLiteral(), offset: offset); |
| 543 } | 560 } |
| 544 | 561 |
| 545 VariableDeclaration makeOrReuseVariable(Expression value) { | 562 VariableDeclaration makeOrReuseVariable(Expression value) { |
| 546 // TODO: Devise a way to remember if a variable declaration was reused | 563 // TODO: Devise a way to remember if a variable declaration was reused |
| 547 // or is fresh (hence needs a let binding). | 564 // or is fresh (hence needs a let binding). |
| 548 return new VariableDeclaration.forValue(value); | 565 return new VariableDeclaration.forValue(value); |
| 549 } | 566 } |
| OLD | NEW |