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 |