| 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 // Note: copied from package:kernel at revision 7346348. | 5 // Note: copied from package:kernel at revision 7346348. |
| 6 | 6 |
| 7 /// A library to help transform compounds and null-aware accessors into | 7 /// A library to help transform compounds and null-aware accessors into |
| 8 /// let expressions. | 8 /// let expressions. |
| 9 library kernel.frontend.accessors; | 9 library kernel.frontend.accessors; |
| 10 | 10 |
| 11 import 'package:kernel/ast.dart'; | 11 import 'package:kernel/ast.dart'; |
| 12 | 12 |
| 13 /// An [Accessor] represents a subexpression for which we can't yet build a |
| 14 /// kernel [Expression] because we don't yet know the context in which it is |
| 15 /// used. |
| 16 /// |
| 17 /// Once the context is known, an [Accessor] can be converted into an |
| 18 /// [Expression] by calling a "build" method. |
| 19 /// |
| 20 /// For example, when building a kernel representation for `a[x] = b`, after |
| 21 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to |
| 22 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an |
| 23 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be |
| 24 /// called. |
| 13 abstract class Accessor { | 25 abstract class Accessor { |
| 26 /// Builds an [Expression] representing a read from the accessor. |
| 14 Expression buildSimpleRead() { | 27 Expression buildSimpleRead() { |
| 15 return _finish(_makeSimpleRead()); | 28 return _finish(_makeSimpleRead()); |
| 16 } | 29 } |
| 17 | 30 |
| 18 /// Returns an assignment to the accessor. | 31 /// Builds an [Expression] representing an assignment with the accessor on |
| 32 /// the LHS and [value] on the RHS. |
| 19 /// | 33 /// |
| 20 /// The returned expression evaluates to the assigned value, unless | 34 /// The returned expression evaluates to the assigned value, unless |
| 21 /// [voidContext] is true, in which case it may evaluate to anything. | 35 /// [voidContext] is true, in which case it may evaluate to anything. |
| 22 Expression buildAssignment(Expression value, {bool voidContext: false}) { | 36 Expression buildAssignment(Expression value, {bool voidContext: false}) { |
| 23 return _finish(_makeSimpleWrite(value, voidContext)); | 37 return _finish(_makeSimpleWrite(value, voidContext)); |
| 24 } | 38 } |
| 25 | 39 |
| 40 /// Returns an [Expression] representing a null-aware assignment (`??=`) with |
| 41 /// the accessor on the LHS and [value] on the RHS. |
| 42 /// |
| 43 /// The returned expression evaluates to the assigned value, unless |
| 44 /// [voidContext] is true, in which case it may evaluate to anything. |
| 45 /// |
| 46 /// [type] is the static type of the RHS. |
| 26 Expression buildNullAwareAssignment(Expression value, DartType type, | 47 Expression buildNullAwareAssignment(Expression value, DartType type, |
| 27 {bool voidContext: false}) { | 48 {bool voidContext: false}) { |
| 28 if (voidContext) { | 49 if (voidContext) { |
| 29 return _finish(new ConditionalExpression(buildIsNull(_makeRead()), | 50 return _finish(new ConditionalExpression(buildIsNull(_makeRead()), |
| 30 _makeWrite(value, false), new NullLiteral(), type)); | 51 _makeWrite(value, false), new NullLiteral(), type)); |
| 31 } | 52 } |
| 32 var tmp = new VariableDeclaration.forValue(_makeRead()); | 53 var tmp = new VariableDeclaration.forValue(_makeRead()); |
| 33 return _finish(makeLet( | 54 return _finish(makeLet( |
| 34 tmp, | 55 tmp, |
| 35 new ConditionalExpression(buildIsNull(new VariableGet(tmp)), | 56 new ConditionalExpression(buildIsNull(new VariableGet(tmp)), |
| 36 _makeWrite(value, false), new VariableGet(tmp), type))); | 57 _makeWrite(value, false), new VariableGet(tmp), type))); |
| 37 } | 58 } |
| 38 | 59 |
| 60 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) |
| 61 /// with the accessor on the LHS and [value] on the RHS. |
| 39 Expression buildCompoundAssignment(Name binaryOperator, Expression value, | 62 Expression buildCompoundAssignment(Name binaryOperator, Expression value, |
| 40 {bool voidContext: false, Procedure interfaceTarget}) { | 63 {bool voidContext: false, Procedure interfaceTarget}) { |
| 41 return _finish(_makeWrite( | 64 return _finish(_makeWrite( |
| 42 makeBinary(_makeRead(), binaryOperator, interfaceTarget, value), | 65 makeBinary(_makeRead(), binaryOperator, interfaceTarget, value), |
| 43 voidContext)); | 66 voidContext)); |
| 44 } | 67 } |
| 45 | 68 |
| 69 /// Returns an [Expression] representing a pre-increment or pre-decrement |
| 70 /// of the accessor. |
| 46 Expression buildPrefixIncrement(Name binaryOperator, | 71 Expression buildPrefixIncrement(Name binaryOperator, |
| 47 {bool voidContext: false, Procedure interfaceTarget}) { | 72 {bool voidContext: false, Procedure interfaceTarget}) { |
| 48 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), | 73 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), |
| 49 voidContext: voidContext, interfaceTarget: interfaceTarget); | 74 voidContext: voidContext, interfaceTarget: interfaceTarget); |
| 50 } | 75 } |
| 51 | 76 |
| 77 /// Returns an [Expression] representing a post-increment or post-decrement |
| 78 /// of the accessor. |
| 52 Expression buildPostfixIncrement(Name binaryOperator, | 79 Expression buildPostfixIncrement(Name binaryOperator, |
| 53 {bool voidContext: false, Procedure interfaceTarget}) { | 80 {bool voidContext: false, Procedure interfaceTarget}) { |
| 54 if (voidContext) { | 81 if (voidContext) { |
| 55 return buildPrefixIncrement(binaryOperator, | 82 return buildPrefixIncrement(binaryOperator, |
| 56 voidContext: true, interfaceTarget: interfaceTarget); | 83 voidContext: true, interfaceTarget: interfaceTarget); |
| 57 } | 84 } |
| 58 var value = new VariableDeclaration.forValue(_makeRead()); | 85 var value = new VariableDeclaration.forValue(_makeRead()); |
| 59 valueAccess() => new VariableGet(value); | 86 valueAccess() => new VariableGet(value); |
| 60 var dummy = new VariableDeclaration.forValue(_makeWrite( | 87 var dummy = new VariableDeclaration.forValue(_makeWrite( |
| 61 makeBinary( | 88 makeBinary( |
| 62 valueAccess(), binaryOperator, interfaceTarget, new IntLiteral(1)), | 89 valueAccess(), binaryOperator, interfaceTarget, new IntLiteral(1)), |
| 63 true)); | 90 true)); |
| 64 return _finish(makeLet(value, makeLet(dummy, valueAccess()))); | 91 return _finish(makeLet(value, makeLet(dummy, valueAccess()))); |
| 65 } | 92 } |
| 66 | 93 |
| 67 Expression _makeSimpleRead() => _makeRead(); | 94 Expression _makeSimpleRead() => _makeRead(); |
| 68 | 95 |
| 69 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 96 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| 70 return _makeWrite(value, voidContext); | 97 return _makeWrite(value, voidContext); |
| 71 } | 98 } |
| 72 | 99 |
| 73 Expression _makeRead(); | 100 Expression _makeRead(); |
| 74 | 101 |
| 75 Expression _makeWrite(Expression value, bool voidContext); | 102 Expression _makeWrite(Expression value, bool voidContext); |
| 76 | 103 |
| 77 Expression _finish(Expression body) => body; | 104 Expression _finish(Expression body) => body; |
| 78 | 105 |
| 106 /// Returns an [Expression] representing a compile-time error. |
| 107 /// |
| 108 /// At runtime, an exception will be thrown. |
| 79 makeInvalidRead() => new InvalidExpression(); | 109 makeInvalidRead() => new InvalidExpression(); |
| 80 | 110 |
| 111 /// Returns an [Expression] representing a compile-time error wrapping |
| 112 /// [value]. |
| 113 /// |
| 114 /// At runtime, [value] will be evaluated before throwing an exception. |
| 81 makeInvalidWrite(Expression value) => wrapInvalid(value); | 115 makeInvalidWrite(Expression value) => wrapInvalid(value); |
| 82 } | 116 } |
| 83 | 117 |
| 84 class VariableAccessor extends Accessor { | 118 class VariableAccessor extends Accessor { |
| 85 VariableDeclaration variable; | 119 VariableDeclaration variable; |
| 86 DartType promotedType; | 120 DartType promotedType; |
| 87 | 121 |
| 88 VariableAccessor(this.variable, [this.promotedType]); | 122 VariableAccessor(this.variable, [this.promotedType]); |
| 89 | 123 |
| 90 VariableAccessor.internal(this.variable, this.promotedType); | 124 VariableAccessor.internal(this.variable, this.promotedType); |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 | 454 |
| 421 VariableDeclaration makeOrReuseVariable(Expression value) { | 455 VariableDeclaration makeOrReuseVariable(Expression value) { |
| 422 // TODO: Devise a way to remember if a variable declaration was reused | 456 // TODO: Devise a way to remember if a variable declaration was reused |
| 423 // or is fresh (hence needs a let binding). | 457 // or is fresh (hence needs a let binding). |
| 424 return new VariableDeclaration.forValue(value); | 458 return new VariableDeclaration.forValue(value); |
| 425 } | 459 } |
| 426 | 460 |
| 427 Expression wrapInvalid(Expression e) { | 461 Expression wrapInvalid(Expression e) { |
| 428 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); | 462 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); |
| 429 } | 463 } |
| OLD | NEW |