| 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'; | 5 import 'package:front_end/src/fasta/builder/ast_factory.dart'; |
| 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 | 9 |
| 10 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; | 10 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 } else { | 314 } else { |
| 315 return new IndexAccessor.internal( | 315 return new IndexAccessor.internal( |
| 316 helper, receiver, index, getter, setter, token); | 316 helper, receiver, index, getter, setter, token); |
| 317 } | 317 } |
| 318 } | 318 } |
| 319 | 319 |
| 320 IndexAccessor.internal(BuilderHelper helper, this.receiver, this.index, | 320 IndexAccessor.internal(BuilderHelper helper, this.receiver, this.index, |
| 321 this.getter, this.setter, Token token) | 321 this.getter, this.setter, Token token) |
| 322 : super(helper, token); | 322 : super(helper, token); |
| 323 | 323 |
| 324 Expression _makeSimpleRead() => helper.astFactory.methodInvocation( | 324 Expression _makeSimpleRead() => helper.astFactory.methodInvocation(receiver, |
| 325 receiver, indexGetName, new Arguments(<Expression>[index]), getter) | 325 indexGetName, helper.astFactory.arguments(<Expression>[index]), getter) |
| 326 ..fileOffset = offsetForToken(token); | 326 ..fileOffset = offsetForToken(token); |
| 327 | 327 |
| 328 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 328 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| 329 if (!voidContext) return _makeWriteAndReturn(value); | 329 if (!voidContext) return _makeWriteAndReturn(value); |
| 330 return helper.astFactory.methodInvocation(receiver, indexSetName, | 330 return helper.astFactory.methodInvocation(receiver, indexSetName, |
| 331 new Arguments(<Expression>[index, value]), setter) | 331 helper.astFactory.arguments(<Expression>[index, value]), setter) |
| 332 ..fileOffset = offsetForToken(token); | 332 ..fileOffset = offsetForToken(token); |
| 333 } | 333 } |
| 334 | 334 |
| 335 receiverAccess() { | 335 receiverAccess() { |
| 336 // 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 |
| 337 // reassigned in the index expression. | 337 // reassigned in the index expression. |
| 338 receiverVariable ??= new VariableDeclaration.forValue(receiver); | 338 receiverVariable ??= new VariableDeclaration.forValue(receiver); |
| 339 return new VariableGet(receiverVariable) | 339 return new VariableGet(receiverVariable) |
| 340 ..fileOffset = offsetForToken(token); | 340 ..fileOffset = offsetForToken(token); |
| 341 } | 341 } |
| 342 | 342 |
| 343 indexAccess() { | 343 indexAccess() { |
| 344 indexVariable ??= new VariableDeclaration.forValue(index); | 344 indexVariable ??= new VariableDeclaration.forValue(index); |
| 345 return new VariableGet(indexVariable)..fileOffset = offsetForToken(token); | 345 return new VariableGet(indexVariable)..fileOffset = offsetForToken(token); |
| 346 } | 346 } |
| 347 | 347 |
| 348 Expression _makeRead() { | 348 Expression _makeRead() { |
| 349 return builtGetter = helper.astFactory.methodInvocation(receiverAccess(), | 349 return builtGetter = helper.astFactory.methodInvocation( |
| 350 indexGetName, new Arguments(<Expression>[indexAccess()]), getter) | 350 receiverAccess(), |
| 351 indexGetName, |
| 352 helper.astFactory.arguments(<Expression>[indexAccess()]), |
| 353 getter) |
| 351 ..fileOffset = offsetForToken(token); | 354 ..fileOffset = offsetForToken(token); |
| 352 } | 355 } |
| 353 | 356 |
| 354 Expression _makeWrite(Expression value, bool voidContext) { | 357 Expression _makeWrite(Expression value, bool voidContext) { |
| 355 if (!voidContext) return _makeWriteAndReturn(value); | 358 if (!voidContext) return _makeWriteAndReturn(value); |
| 356 return helper.astFactory.methodInvocation(receiverAccess(), indexSetName, | 359 return helper.astFactory.methodInvocation(receiverAccess(), indexSetName, |
| 357 new Arguments(<Expression>[indexAccess(), value]), setter) | 360 helper.astFactory.arguments(<Expression>[indexAccess(), value]), setter) |
| 358 ..fileOffset = offsetForToken(token); | 361 ..fileOffset = offsetForToken(token); |
| 359 } | 362 } |
| 360 | 363 |
| 361 // TODO(dmitryas): remove this method after the "[]=" operator of the Context | 364 // TODO(dmitryas): remove this method after the "[]=" operator of the Context |
| 362 // class is made to return a value. | 365 // class is made to return a value. |
| 363 _makeWriteAndReturn(Expression value) { | 366 _makeWriteAndReturn(Expression value) { |
| 364 // The call to []= does not return the value like direct-style assignments | 367 // The call to []= does not return the value like direct-style assignments |
| 365 // do. We need to bind the value in a let. | 368 // do. We need to bind the value in a let. |
| 366 var valueVariable = new VariableDeclaration.forValue(value); | 369 var valueVariable = new VariableDeclaration.forValue(value); |
| 367 var dummy = new VariableDeclaration.forValue(helper.astFactory | 370 var dummy = new VariableDeclaration.forValue(helper.astFactory |
| 368 .methodInvocation( | 371 .methodInvocation( |
| 369 receiverAccess(), | 372 receiverAccess(), |
| 370 indexSetName, | 373 indexSetName, |
| 371 new Arguments( | 374 helper.astFactory.arguments( |
| 372 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 375 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
| 373 setter) | 376 setter) |
| 374 ..fileOffset = offsetForToken(token)); | 377 ..fileOffset = offsetForToken(token)); |
| 375 return makeLet( | 378 return makeLet( |
| 376 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 379 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
| 377 } | 380 } |
| 378 | 381 |
| 379 Expression _finish(Expression body) { | 382 Expression _finish(Expression body) { |
| 380 return makeLet(receiverVariable, makeLet(indexVariable, body)); | 383 return makeLet(receiverVariable, makeLet(indexVariable, body)); |
| 381 } | 384 } |
| 382 } | 385 } |
| 383 | 386 |
| 384 /// Special case of [IndexAccessor] to avoid creating an indirect access to | 387 /// Special case of [IndexAccessor] to avoid creating an indirect access to |
| 385 /// 'this'. | 388 /// 'this'. |
| 386 class ThisIndexAccessor extends Accessor { | 389 class ThisIndexAccessor extends Accessor { |
| 387 Expression index; | 390 Expression index; |
| 388 VariableDeclaration indexVariable; | 391 VariableDeclaration indexVariable; |
| 389 Procedure getter, setter; | 392 Procedure getter, setter; |
| 390 | 393 |
| 391 ThisIndexAccessor( | 394 ThisIndexAccessor( |
| 392 BuilderHelper helper, this.index, this.getter, this.setter, Token token) | 395 BuilderHelper helper, this.index, this.getter, this.setter, Token token) |
| 393 : super(helper, token); | 396 : super(helper, token); |
| 394 | 397 |
| 395 Expression _makeSimpleRead() { | 398 Expression _makeSimpleRead() { |
| 396 return helper.astFactory.methodInvocation(new ThisExpression(), | 399 return helper.astFactory.methodInvocation(new ThisExpression(), |
| 397 indexGetName, new Arguments(<Expression>[index]), getter); | 400 indexGetName, helper.astFactory.arguments(<Expression>[index]), getter); |
| 398 } | 401 } |
| 399 | 402 |
| 400 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 403 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| 401 if (!voidContext) return _makeWriteAndReturn(value); | 404 if (!voidContext) return _makeWriteAndReturn(value); |
| 402 return helper.astFactory.methodInvocation(new ThisExpression(), | 405 return helper.astFactory.methodInvocation( |
| 403 indexSetName, new Arguments(<Expression>[index, value]), setter); | 406 new ThisExpression(), |
| 407 indexSetName, |
| 408 helper.astFactory.arguments(<Expression>[index, value]), |
| 409 setter); |
| 404 } | 410 } |
| 405 | 411 |
| 406 indexAccess() { | 412 indexAccess() { |
| 407 indexVariable ??= new VariableDeclaration.forValue(index); | 413 indexVariable ??= new VariableDeclaration.forValue(index); |
| 408 return new VariableGet(indexVariable); | 414 return new VariableGet(indexVariable); |
| 409 } | 415 } |
| 410 | 416 |
| 411 Expression _makeRead() => builtGetter = helper.astFactory.methodInvocation( | 417 Expression _makeRead() => builtGetter = helper.astFactory.methodInvocation( |
| 412 new ThisExpression(), | 418 new ThisExpression(), |
| 413 indexGetName, | 419 indexGetName, |
| 414 new Arguments(<Expression>[indexAccess()]), | 420 helper.astFactory.arguments(<Expression>[indexAccess()]), |
| 415 getter); | 421 getter); |
| 416 | 422 |
| 417 Expression _makeWrite(Expression value, bool voidContext) { | 423 Expression _makeWrite(Expression value, bool voidContext) { |
| 418 if (!voidContext) return _makeWriteAndReturn(value); | 424 if (!voidContext) return _makeWriteAndReturn(value); |
| 419 return helper.astFactory.methodInvocation( | 425 return helper.astFactory.methodInvocation( |
| 420 new ThisExpression(), | 426 new ThisExpression(), |
| 421 indexSetName, | 427 indexSetName, |
| 422 new Arguments(<Expression>[indexAccess(), value]), | 428 helper.astFactory.arguments(<Expression>[indexAccess(), value]), |
| 423 setter); | 429 setter); |
| 424 } | 430 } |
| 425 | 431 |
| 426 _makeWriteAndReturn(Expression value) { | 432 _makeWriteAndReturn(Expression value) { |
| 427 var valueVariable = new VariableDeclaration.forValue(value); | 433 var valueVariable = new VariableDeclaration.forValue(value); |
| 428 var dummy = new VariableDeclaration.forValue(helper.astFactory | 434 var dummy = new VariableDeclaration.forValue(helper.astFactory |
| 429 .methodInvocation( | 435 .methodInvocation( |
| 430 new ThisExpression(), | 436 new ThisExpression(), |
| 431 indexSetName, | 437 indexSetName, |
| 432 new Arguments( | 438 helper.astFactory.arguments( |
| 433 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 439 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
| 434 setter)); | 440 setter)); |
| 435 return makeLet( | 441 return makeLet( |
| 436 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 442 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
| 437 } | 443 } |
| 438 | 444 |
| 439 Expression _finish(Expression body) => makeLet(indexVariable, body); | 445 Expression _finish(Expression body) => makeLet(indexVariable, body); |
| 440 } | 446 } |
| 441 | 447 |
| 442 class SuperIndexAccessor extends Accessor { | 448 class SuperIndexAccessor extends Accessor { |
| 443 Expression index; | 449 Expression index; |
| 444 VariableDeclaration indexVariable; | 450 VariableDeclaration indexVariable; |
| 445 Member getter, setter; | 451 Member getter, setter; |
| 446 | 452 |
| 447 SuperIndexAccessor( | 453 SuperIndexAccessor( |
| 448 BuilderHelper helper, this.index, this.getter, this.setter, Token token) | 454 BuilderHelper helper, this.index, this.getter, this.setter, Token token) |
| 449 : super(helper, token); | 455 : super(helper, token); |
| 450 | 456 |
| 451 indexAccess() { | 457 indexAccess() { |
| 452 indexVariable ??= new VariableDeclaration.forValue(index); | 458 indexVariable ??= new VariableDeclaration.forValue(index); |
| 453 return new VariableGet(indexVariable); | 459 return new VariableGet(indexVariable); |
| 454 } | 460 } |
| 455 | 461 |
| 456 Expression _makeSimpleRead() => new SuperMethodInvocation( | 462 Expression _makeSimpleRead() => new SuperMethodInvocation( |
| 457 indexGetName, new Arguments(<Expression>[index]), getter); | 463 indexGetName, helper.astFactory.arguments(<Expression>[index]), getter); |
| 458 | 464 |
| 459 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 465 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| 460 if (!voidContext) return _makeWriteAndReturn(value); | 466 if (!voidContext) return _makeWriteAndReturn(value); |
| 461 return new SuperMethodInvocation( | 467 return new SuperMethodInvocation(indexSetName, |
| 462 indexSetName, new Arguments(<Expression>[index, value]), setter); | 468 helper.astFactory.arguments(<Expression>[index, value]), setter); |
| 463 } | 469 } |
| 464 | 470 |
| 465 Expression _makeRead() { | 471 Expression _makeRead() { |
| 466 return builtGetter = new SuperMethodInvocation( | 472 return builtGetter = new SuperMethodInvocation(indexGetName, |
| 467 indexGetName, new Arguments(<Expression>[indexAccess()]), getter); | 473 helper.astFactory.arguments(<Expression>[indexAccess()]), getter); |
| 468 } | 474 } |
| 469 | 475 |
| 470 Expression _makeWrite(Expression value, bool voidContext) { | 476 Expression _makeWrite(Expression value, bool voidContext) { |
| 471 if (!voidContext) return _makeWriteAndReturn(value); | 477 if (!voidContext) return _makeWriteAndReturn(value); |
| 472 return new SuperMethodInvocation(indexSetName, | 478 return new SuperMethodInvocation( |
| 473 new Arguments(<Expression>[indexAccess(), value]), setter); | 479 indexSetName, |
| 480 helper.astFactory.arguments(<Expression>[indexAccess(), value]), |
| 481 setter); |
| 474 } | 482 } |
| 475 | 483 |
| 476 _makeWriteAndReturn(Expression value) { | 484 _makeWriteAndReturn(Expression value) { |
| 477 var valueVariable = new VariableDeclaration.forValue(value); | 485 var valueVariable = new VariableDeclaration.forValue(value); |
| 478 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation( | 486 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation( |
| 479 indexSetName, | 487 indexSetName, |
| 480 new Arguments( | 488 helper.astFactory.arguments( |
| 481 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 489 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
| 482 setter)); | 490 setter)); |
| 483 return makeLet( | 491 return makeLet( |
| 484 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 492 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
| 485 } | 493 } |
| 486 | 494 |
| 487 Expression _finish(Expression body) { | 495 Expression _finish(Expression body) { |
| 488 return makeLet(indexVariable, body); | 496 return makeLet(indexVariable, body); |
| 489 } | 497 } |
| 490 } | 498 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 } | 538 } |
| 531 | 539 |
| 532 Expression makeLet(VariableDeclaration variable, Expression body) { | 540 Expression makeLet(VariableDeclaration variable, Expression body) { |
| 533 if (variable == null) return body; | 541 if (variable == null) return body; |
| 534 return new Let(variable, body); | 542 return new Let(variable, body); |
| 535 } | 543 } |
| 536 | 544 |
| 537 Expression makeBinary(AstFactory astFactory, Expression left, Name operator, | 545 Expression makeBinary(AstFactory astFactory, Expression left, Name operator, |
| 538 Procedure interfaceTarget, Expression right, | 546 Procedure interfaceTarget, Expression right, |
| 539 {int offset: TreeNode.noOffset}) { | 547 {int offset: TreeNode.noOffset}) { |
| 540 return astFactory.methodInvocation( | 548 return astFactory.methodInvocation(left, operator, |
| 541 left, operator, new Arguments(<Expression>[right]), interfaceTarget) | 549 astFactory.arguments(<Expression>[right]), interfaceTarget) |
| 542 ..fileOffset = offset; | 550 ..fileOffset = offset; |
| 543 } | 551 } |
| 544 | 552 |
| 545 final Name _equalOperator = new Name('=='); | 553 final Name _equalOperator = new Name('=='); |
| 546 | 554 |
| 547 Expression buildIsNull(AstFactory astFactory, Expression value, | 555 Expression buildIsNull(AstFactory astFactory, Expression value, |
| 548 {int offset: TreeNode.noOffset}) { | 556 {int offset: TreeNode.noOffset}) { |
| 549 return makeBinary(astFactory, value, _equalOperator, null, new NullLiteral(), | 557 return makeBinary(astFactory, value, _equalOperator, null, new NullLiteral(), |
| 550 offset: offset); | 558 offset: offset); |
| 551 } | 559 } |
| 552 | 560 |
| 553 VariableDeclaration makeOrReuseVariable(Expression value) { | 561 VariableDeclaration makeOrReuseVariable(Expression value) { |
| 554 // TODO: Devise a way to remember if a variable declaration was reused | 562 // TODO: Devise a way to remember if a variable declaration was reused |
| 555 // or is fresh (hence needs a let binding). | 563 // or is fresh (hence needs a let binding). |
| 556 return new VariableDeclaration.forValue(value); | 564 return new VariableDeclaration.forValue(value); |
| 557 } | 565 } |
| 558 | 566 |
| 559 Expression wrapInvalid(Expression e) { | 567 Expression wrapInvalid(Expression e) { |
| 560 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); | 568 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); |
| 561 } | 569 } |
| OLD | NEW |