| 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 |