| 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, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 /// | 36 /// |
| 37 /// For example, when building a kernel representation for `a[x] = b`, after | 37 /// For example, when building a kernel representation for `a[x] = b`, after |
| 38 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to | 38 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to |
| 39 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an | 39 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an |
| 40 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be | 40 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be |
| 41 /// called. | 41 /// called. |
| 42 abstract class Accessor { | 42 abstract class Accessor { |
| 43 final BuilderHelper helper; | 43 final BuilderHelper helper; |
| 44 final Token token; | 44 final Token token; |
| 45 | 45 |
| 46 // [builtBinary] and [builtGetter] capture the inner nodes. Used by | |
| 47 // dart2js+rasta for determining how subexpressions map to legacy dart2js Ast | |
| 48 // nodes. This will be removed once dart2js type analysis (aka inference) is | |
| 49 // reimplemented on kernel. | |
| 50 Expression builtBinary; | |
| 51 Expression builtGetter; | |
| 52 | |
| 53 Accessor(this.helper, this.token); | 46 Accessor(this.helper, this.token); |
| 54 | 47 |
| 55 /// Builds an [Expression] representing a read from the accessor. | 48 /// Builds an [Expression] representing a read from the accessor. |
| 56 Expression buildSimpleRead() { | 49 Expression buildSimpleRead() { |
| 57 return _finish(_makeSimpleRead()); | 50 return _finish(_makeSimpleRead()); |
| 58 } | 51 } |
| 59 | 52 |
| 60 /// Builds an [Expression] representing an assignment with the accessor on | 53 /// Builds an [Expression] representing an assignment with the accessor on |
| 61 /// the LHS and [value] on the RHS. | 54 /// the LHS and [value] on the RHS. |
| 62 /// | 55 /// |
| (...skipping 23 matching lines...) Expand all Loading... |
| 86 _makeWrite(value, false), new VariableGet(tmp), type))); | 79 _makeWrite(value, false), new VariableGet(tmp), type))); |
| 87 } | 80 } |
| 88 | 81 |
| 89 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) | 82 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) |
| 90 /// with the accessor on the LHS and [value] on the RHS. | 83 /// with the accessor on the LHS and [value] on the RHS. |
| 91 Expression buildCompoundAssignment(Name binaryOperator, Expression value, | 84 Expression buildCompoundAssignment(Name binaryOperator, Expression value, |
| 92 {int offset: TreeNode.noOffset, | 85 {int offset: TreeNode.noOffset, |
| 93 bool voidContext: false, | 86 bool voidContext: false, |
| 94 Procedure interfaceTarget}) { | 87 Procedure interfaceTarget}) { |
| 95 return _finish(_makeWrite( | 88 return _finish(_makeWrite( |
| 96 builtBinary = makeBinary( | 89 makeBinary(_makeRead(), binaryOperator, interfaceTarget, value, |
| 97 _makeRead(), binaryOperator, interfaceTarget, value, | |
| 98 offset: offset), | 90 offset: offset), |
| 99 voidContext)); | 91 voidContext)); |
| 100 } | 92 } |
| 101 | 93 |
| 102 /// Returns an [Expression] representing a pre-increment or pre-decrement | 94 /// Returns an [Expression] representing a pre-increment or pre-decrement |
| 103 /// of the accessor. | 95 /// of the accessor. |
| 104 Expression buildPrefixIncrement(Name binaryOperator, | 96 Expression buildPrefixIncrement(Name binaryOperator, |
| 105 {int offset: TreeNode.noOffset, | 97 {int offset: TreeNode.noOffset, |
| 106 bool voidContext: false, | 98 bool voidContext: false, |
| 107 Procedure interfaceTarget}) { | 99 Procedure interfaceTarget}) { |
| 108 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), | 100 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), |
| 109 offset: offset, | 101 offset: offset, |
| 110 voidContext: voidContext, | 102 voidContext: voidContext, |
| 111 interfaceTarget: interfaceTarget); | 103 interfaceTarget: interfaceTarget); |
| 112 } | 104 } |
| 113 | 105 |
| 114 /// Returns an [Expression] representing a post-increment or post-decrement | 106 /// Returns an [Expression] representing a post-increment or post-decrement |
| 115 /// of the accessor. | 107 /// of the accessor. |
| 116 Expression buildPostfixIncrement(Name binaryOperator, | 108 Expression buildPostfixIncrement(Name binaryOperator, |
| 117 {int offset: TreeNode.noOffset, | 109 {int offset: TreeNode.noOffset, |
| 118 bool voidContext: false, | 110 bool voidContext: false, |
| 119 Procedure interfaceTarget}) { | 111 Procedure interfaceTarget}) { |
| 120 if (voidContext) { | 112 if (voidContext) { |
| 121 return buildPrefixIncrement(binaryOperator, | 113 return buildPrefixIncrement(binaryOperator, |
| 122 offset: offset, voidContext: true, interfaceTarget: interfaceTarget); | 114 offset: offset, voidContext: true, interfaceTarget: interfaceTarget); |
| 123 } | 115 } |
| 124 var value = new VariableDeclaration.forValue(_makeRead()); | 116 var value = new VariableDeclaration.forValue(_makeRead()); |
| 125 valueAccess() => new VariableGet(value); | 117 valueAccess() => new VariableGet(value); |
| 126 var dummy = new VariableDeclaration.forValue(_makeWrite( | 118 var dummy = new VariableDeclaration.forValue(_makeWrite( |
| 127 builtBinary = makeBinary( | 119 makeBinary( |
| 128 valueAccess(), binaryOperator, interfaceTarget, new IntLiteral(1), | 120 valueAccess(), binaryOperator, interfaceTarget, new IntLiteral(1), |
| 129 offset: offset), | 121 offset: offset), |
| 130 true)); | 122 true)); |
| 131 return _finish(makeLet(value, makeLet(dummy, valueAccess()))); | 123 return _finish(makeLet(value, makeLet(dummy, valueAccess()))); |
| 132 } | 124 } |
| 133 | 125 |
| 134 Expression _makeSimpleRead() => _makeRead(); | 126 Expression _makeSimpleRead() => _makeRead(); |
| 135 | 127 |
| 136 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 128 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| 137 return _makeWrite(value, voidContext); | 129 return _makeWrite(value, voidContext); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 ..fileOffset = offsetForToken(token); | 201 ..fileOffset = offsetForToken(token); |
| 210 } | 202 } |
| 211 | 203 |
| 212 receiverAccess() { | 204 receiverAccess() { |
| 213 _receiverVariable ??= new VariableDeclaration.forValue(receiver); | 205 _receiverVariable ??= new VariableDeclaration.forValue(receiver); |
| 214 return new VariableGet(_receiverVariable) | 206 return new VariableGet(_receiverVariable) |
| 215 ..fileOffset = offsetForToken(token); | 207 ..fileOffset = offsetForToken(token); |
| 216 } | 208 } |
| 217 | 209 |
| 218 Expression _makeRead() => | 210 Expression _makeRead() => |
| 219 builtGetter = new KernelPropertyGet(receiverAccess(), name, getter) | 211 new KernelPropertyGet(receiverAccess(), name, getter) |
| 220 ..fileOffset = offsetForToken(token); | 212 ..fileOffset = offsetForToken(token); |
| 221 | 213 |
| 222 Expression _makeWrite(Expression value, bool voidContext) { | 214 Expression _makeWrite(Expression value, bool voidContext) { |
| 223 return new KernelPropertySet(receiverAccess(), name, value, setter) | 215 return new KernelPropertySet(receiverAccess(), name, value, setter) |
| 224 ..fileOffset = offsetForToken(token); | 216 ..fileOffset = offsetForToken(token); |
| 225 } | 217 } |
| 226 | 218 |
| 227 Expression _finish(Expression body) => makeLet(_receiverVariable, body); | 219 Expression _finish(Expression body) => makeLet(_receiverVariable, body); |
| 228 } | 220 } |
| 229 | 221 |
| 230 /// Special case of [PropertyAccessor] to avoid creating an indirect access to | 222 /// Special case of [PropertyAccessor] to avoid creating an indirect access to |
| 231 /// 'this'. | 223 /// 'this'. |
| 232 class ThisPropertyAccessor extends Accessor { | 224 class ThisPropertyAccessor extends Accessor { |
| 233 Name name; | 225 Name name; |
| 234 Member getter, setter; | 226 Member getter, setter; |
| 235 | 227 |
| 236 ThisPropertyAccessor( | 228 ThisPropertyAccessor( |
| 237 BuilderHelper helper, this.name, this.getter, this.setter, Token token) | 229 BuilderHelper helper, this.name, this.getter, this.setter, Token token) |
| 238 : super(helper, token); | 230 : super(helper, token); |
| 239 | 231 |
| 240 Expression _makeRead() => | 232 Expression _makeRead() => |
| 241 builtGetter = new KernelPropertyGet(new ThisExpression(), name, getter) | 233 new KernelPropertyGet(new ThisExpression(), name, getter) |
| 242 ..fileOffset = offsetForToken(token); | 234 ..fileOffset = offsetForToken(token); |
| 243 | 235 |
| 244 Expression _makeWrite(Expression value, bool voidContext) { | 236 Expression _makeWrite(Expression value, bool voidContext) { |
| 245 return new KernelPropertySet(new ThisExpression(), name, value, setter) | 237 return new KernelPropertySet(new ThisExpression(), name, value, setter) |
| 246 ..fileOffset = offsetForToken(token); | 238 ..fileOffset = offsetForToken(token); |
| 247 } | 239 } |
| 248 } | 240 } |
| 249 | 241 |
| 250 class NullAwarePropertyAccessor extends Accessor { | 242 class NullAwarePropertyAccessor extends Accessor { |
| 251 VariableDeclaration receiver; | 243 VariableDeclaration receiver; |
| 252 Name name; | 244 Name name; |
| 253 Member getter, setter; | 245 Member getter, setter; |
| 254 DartType type; | 246 DartType type; |
| 255 | 247 |
| 256 NullAwarePropertyAccessor(BuilderHelper helper, Expression receiver, | 248 NullAwarePropertyAccessor(BuilderHelper helper, Expression receiver, |
| 257 this.name, this.getter, this.setter, this.type, Token token) | 249 this.name, this.getter, this.setter, this.type, Token token) |
| 258 : this.receiver = makeOrReuseVariable(receiver), | 250 : this.receiver = makeOrReuseVariable(receiver), |
| 259 super(helper, token); | 251 super(helper, token); |
| 260 | 252 |
| 261 receiverAccess() => new VariableGet(receiver); | 253 receiverAccess() => new VariableGet(receiver); |
| 262 | 254 |
| 263 Expression _makeRead() => | 255 Expression _makeRead() => |
| 264 builtGetter = new KernelPropertyGet(receiverAccess(), name, getter); | 256 new KernelPropertyGet(receiverAccess(), name, getter); |
| 265 | 257 |
| 266 Expression _makeWrite(Expression value, bool voidContext) { | 258 Expression _makeWrite(Expression value, bool voidContext) { |
| 267 return new KernelPropertySet(receiverAccess(), name, value, setter); | 259 return new KernelPropertySet(receiverAccess(), name, value, setter); |
| 268 } | 260 } |
| 269 | 261 |
| 270 Expression _finish(Expression body) => makeLet( | 262 Expression _finish(Expression body) => makeLet( |
| 271 receiver, | 263 receiver, |
| 272 new ConditionalExpression( | 264 new ConditionalExpression( |
| 273 buildIsNull(receiverAccess()), new NullLiteral(), body, type)); | 265 buildIsNull(receiverAccess()), new NullLiteral(), body, type)); |
| 274 } | 266 } |
| 275 | 267 |
| 276 class SuperPropertyAccessor extends Accessor { | 268 class SuperPropertyAccessor extends Accessor { |
| 277 Name name; | 269 Name name; |
| 278 Member getter, setter; | 270 Member getter, setter; |
| 279 | 271 |
| 280 SuperPropertyAccessor( | 272 SuperPropertyAccessor( |
| 281 BuilderHelper helper, this.name, this.getter, this.setter, Token token) | 273 BuilderHelper helper, this.name, this.getter, this.setter, Token token) |
| 282 : super(helper, token); | 274 : super(helper, token); |
| 283 | 275 |
| 284 Expression _makeRead() { | 276 Expression _makeRead() { |
| 285 if (getter == null) return makeInvalidRead(); | 277 if (getter == null) return makeInvalidRead(); |
| 286 // TODO(ahe): Use [DirectPropertyGet] when possible. | 278 // TODO(ahe): Use [DirectPropertyGet] when possible. |
| 287 return builtGetter = new SuperPropertyGet(name, getter) | 279 return new SuperPropertyGet(name, getter) |
| 288 ..fileOffset = offsetForToken(token); | 280 ..fileOffset = offsetForToken(token); |
| 289 } | 281 } |
| 290 | 282 |
| 291 Expression _makeWrite(Expression value, bool voidContext) { | 283 Expression _makeWrite(Expression value, bool voidContext) { |
| 292 if (setter == null) return makeInvalidWrite(value); | 284 if (setter == null) return makeInvalidWrite(value); |
| 293 // TODO(ahe): Use [DirectPropertySet] when possible. | 285 // TODO(ahe): Use [DirectPropertySet] when possible. |
| 294 return new SuperPropertySet(name, value, setter) | 286 return new SuperPropertySet(name, value, setter) |
| 295 ..fileOffset = offsetForToken(token); | 287 ..fileOffset = offsetForToken(token); |
| 296 } | 288 } |
| 297 } | 289 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 return new VariableGet(receiverVariable) | 328 return new VariableGet(receiverVariable) |
| 337 ..fileOffset = offsetForToken(token); | 329 ..fileOffset = offsetForToken(token); |
| 338 } | 330 } |
| 339 | 331 |
| 340 indexAccess() { | 332 indexAccess() { |
| 341 indexVariable ??= new VariableDeclaration.forValue(index); | 333 indexVariable ??= new VariableDeclaration.forValue(index); |
| 342 return new VariableGet(indexVariable)..fileOffset = offsetForToken(token); | 334 return new VariableGet(indexVariable)..fileOffset = offsetForToken(token); |
| 343 } | 335 } |
| 344 | 336 |
| 345 Expression _makeRead() { | 337 Expression _makeRead() { |
| 346 return builtGetter = new KernelMethodInvocation(receiverAccess(), | 338 return new KernelMethodInvocation(receiverAccess(), indexGetName, |
| 347 indexGetName, new KernelArguments(<Expression>[indexAccess()]), getter) | 339 new KernelArguments(<Expression>[indexAccess()]), getter) |
| 348 ..fileOffset = offsetForToken(token); | 340 ..fileOffset = offsetForToken(token); |
| 349 } | 341 } |
| 350 | 342 |
| 351 Expression _makeWrite(Expression value, bool voidContext) { | 343 Expression _makeWrite(Expression value, bool voidContext) { |
| 352 if (!voidContext) return _makeWriteAndReturn(value); | 344 if (!voidContext) return _makeWriteAndReturn(value); |
| 353 return new KernelMethodInvocation(receiverAccess(), indexSetName, | 345 return new KernelMethodInvocation(receiverAccess(), indexSetName, |
| 354 new KernelArguments(<Expression>[indexAccess(), value]), setter) | 346 new KernelArguments(<Expression>[indexAccess(), value]), setter) |
| 355 ..fileOffset = offsetForToken(token); | 347 ..fileOffset = offsetForToken(token); |
| 356 } | 348 } |
| 357 | 349 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 if (!voidContext) return _makeWriteAndReturn(value); | 389 if (!voidContext) return _makeWriteAndReturn(value); |
| 398 return new KernelMethodInvocation(new ThisExpression(), indexSetName, | 390 return new KernelMethodInvocation(new ThisExpression(), indexSetName, |
| 399 new KernelArguments(<Expression>[index, value]), setter); | 391 new KernelArguments(<Expression>[index, value]), setter); |
| 400 } | 392 } |
| 401 | 393 |
| 402 indexAccess() { | 394 indexAccess() { |
| 403 indexVariable ??= new VariableDeclaration.forValue(index); | 395 indexVariable ??= new VariableDeclaration.forValue(index); |
| 404 return new VariableGet(indexVariable); | 396 return new VariableGet(indexVariable); |
| 405 } | 397 } |
| 406 | 398 |
| 407 Expression _makeRead() => builtGetter = new KernelMethodInvocation( | 399 Expression _makeRead() => new KernelMethodInvocation(new ThisExpression(), |
| 408 new ThisExpression(), | 400 indexGetName, new KernelArguments(<Expression>[indexAccess()]), getter); |
| 409 indexGetName, | |
| 410 new KernelArguments(<Expression>[indexAccess()]), | |
| 411 getter); | |
| 412 | 401 |
| 413 Expression _makeWrite(Expression value, bool voidContext) { | 402 Expression _makeWrite(Expression value, bool voidContext) { |
| 414 if (!voidContext) return _makeWriteAndReturn(value); | 403 if (!voidContext) return _makeWriteAndReturn(value); |
| 415 return new KernelMethodInvocation(new ThisExpression(), indexSetName, | 404 return new KernelMethodInvocation(new ThisExpression(), indexSetName, |
| 416 new KernelArguments(<Expression>[indexAccess(), value]), setter); | 405 new KernelArguments(<Expression>[indexAccess(), value]), setter); |
| 417 } | 406 } |
| 418 | 407 |
| 419 _makeWriteAndReturn(Expression value) { | 408 _makeWriteAndReturn(Expression value) { |
| 420 var valueVariable = new VariableDeclaration.forValue(value); | 409 var valueVariable = new VariableDeclaration.forValue(value); |
| 421 var dummy = new VariableDeclaration.forValue(new KernelMethodInvocation( | 410 var dummy = new VariableDeclaration.forValue(new KernelMethodInvocation( |
| (...skipping 26 matching lines...) Expand all Loading... |
| 448 Expression _makeSimpleRead() => new SuperMethodInvocation( | 437 Expression _makeSimpleRead() => new SuperMethodInvocation( |
| 449 indexGetName, new KernelArguments(<Expression>[index]), getter); | 438 indexGetName, new KernelArguments(<Expression>[index]), getter); |
| 450 | 439 |
| 451 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 440 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| 452 if (!voidContext) return _makeWriteAndReturn(value); | 441 if (!voidContext) return _makeWriteAndReturn(value); |
| 453 return new SuperMethodInvocation( | 442 return new SuperMethodInvocation( |
| 454 indexSetName, new KernelArguments(<Expression>[index, value]), setter); | 443 indexSetName, new KernelArguments(<Expression>[index, value]), setter); |
| 455 } | 444 } |
| 456 | 445 |
| 457 Expression _makeRead() { | 446 Expression _makeRead() { |
| 458 return builtGetter = new SuperMethodInvocation( | 447 return new SuperMethodInvocation( |
| 459 indexGetName, new KernelArguments(<Expression>[indexAccess()]), getter); | 448 indexGetName, new KernelArguments(<Expression>[indexAccess()]), getter); |
| 460 } | 449 } |
| 461 | 450 |
| 462 Expression _makeWrite(Expression value, bool voidContext) { | 451 Expression _makeWrite(Expression value, bool voidContext) { |
| 463 if (!voidContext) return _makeWriteAndReturn(value); | 452 if (!voidContext) return _makeWriteAndReturn(value); |
| 464 return new SuperMethodInvocation(indexSetName, | 453 return new SuperMethodInvocation(indexSetName, |
| 465 new KernelArguments(<Expression>[indexAccess(), value]), setter); | 454 new KernelArguments(<Expression>[indexAccess(), value]), setter); |
| 466 } | 455 } |
| 467 | 456 |
| 468 _makeWriteAndReturn(Expression value) { | 457 _makeWriteAndReturn(Expression value) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 482 } | 471 } |
| 483 | 472 |
| 484 class StaticAccessor extends Accessor { | 473 class StaticAccessor extends Accessor { |
| 485 Member readTarget; | 474 Member readTarget; |
| 486 Member writeTarget; | 475 Member writeTarget; |
| 487 | 476 |
| 488 StaticAccessor( | 477 StaticAccessor( |
| 489 BuilderHelper helper, this.readTarget, this.writeTarget, Token token) | 478 BuilderHelper helper, this.readTarget, this.writeTarget, Token token) |
| 490 : super(helper, token); | 479 : super(helper, token); |
| 491 | 480 |
| 492 Expression _makeRead() => builtGetter = readTarget == null | 481 Expression _makeRead() => readTarget == null |
| 493 ? makeInvalidRead() | 482 ? makeInvalidRead() |
| 494 : helper.makeStaticGet(readTarget, token); | 483 : helper.makeStaticGet(readTarget, token); |
| 495 | 484 |
| 496 Expression _makeWrite(Expression value, bool voidContext) { | 485 Expression _makeWrite(Expression value, bool voidContext) { |
| 497 return writeTarget == null | 486 return writeTarget == null |
| 498 ? makeInvalidWrite(value) | 487 ? makeInvalidWrite(value) |
| 499 : new StaticSet(writeTarget, value) | 488 : new StaticSet(writeTarget, value) |
| 500 ..fileOffset = offsetForToken(token); | 489 ..fileOffset = offsetForToken(token); |
| 501 } | 490 } |
| 502 } | 491 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 | 532 |
| 544 VariableDeclaration makeOrReuseVariable(Expression value) { | 533 VariableDeclaration makeOrReuseVariable(Expression value) { |
| 545 // TODO: Devise a way to remember if a variable declaration was reused | 534 // TODO: Devise a way to remember if a variable declaration was reused |
| 546 // or is fresh (hence needs a let binding). | 535 // or is fresh (hence needs a let binding). |
| 547 return new VariableDeclaration.forValue(value); | 536 return new VariableDeclaration.forValue(value); |
| 548 } | 537 } |
| 549 | 538 |
| 550 Expression wrapInvalid(Expression e) { | 539 Expression wrapInvalid(Expression e) { |
| 551 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); | 540 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); |
| 552 } | 541 } |
| OLD | NEW |