| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library dart2js.ir_nodes; | 4 library dart2js.ir_nodes; |
| 5 | 5 |
| 6 import 'dart:collection'; | 6 import 'dart:collection'; |
| 7 import '../constants/values.dart' as values; | 7 import '../constants/values.dart' as values; |
| 8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
| 9 import '../elements/elements.dart'; | 9 import '../elements/elements.dart'; |
| 10 import '../io/source_information.dart' show SourceInformation; | 10 import '../io/source_information.dart' show SourceInformation; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 import '../native/native.dart' as native show NativeBehavior; | 21 import '../native/native.dart' as native show NativeBehavior; |
| 22 | 22 |
| 23 abstract class Node { | 23 abstract class Node { |
| 24 /// A pointer to the parent node. Is null until set by optimization passes. | 24 /// A pointer to the parent node. Is null until set by optimization passes. |
| 25 Node parent; | 25 Node parent; |
| 26 | 26 |
| 27 /// Workaround for a slow Object.hashCode in the VM. | 27 /// Workaround for a slow Object.hashCode in the VM. |
| 28 static int _usedHashCodes = 0; | 28 static int _usedHashCodes = 0; |
| 29 final int hashCode = ++_usedHashCodes; | 29 final int hashCode = ++_usedHashCodes; |
| 30 | 30 |
| 31 Node() { |
| 32 setParentPointers(); |
| 33 } |
| 34 |
| 31 accept(Visitor visitor); | 35 accept(Visitor visitor); |
| 36 |
| 37 /// Updates the [parent] of the immediate children to refer to this node. |
| 38 /// |
| 39 /// All constructors call this method to initialize parent pointers. |
| 40 void setParentPointers(); |
| 32 } | 41 } |
| 33 | 42 |
| 34 /// Expressions can be evaluated, and may diverge, throw, and/or have | 43 /// Expressions can be evaluated, and may diverge, throw, and/or have |
| 35 /// side-effects. | 44 /// side-effects. |
| 36 /// | 45 /// |
| 37 /// Evaluation continues by stepping into a sub-expression, invoking a | 46 /// Evaluation continues by stepping into a sub-expression, invoking a |
| 38 /// continuation, or throwing an exception. | 47 /// continuation, or throwing an exception. |
| 39 /// | 48 /// |
| 40 /// Expressions do not a return value. Expressions that produce values should | 49 /// Expressions do not a return value. Expressions that produce values should |
| 41 /// invoke a [Continuation] with the result as argument. Alternatively, values | 50 /// invoke a [Continuation] with the result as argument. Alternatively, values |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 Expression body; | 320 Expression body; |
| 312 | 321 |
| 313 LetPrim(this.primitive, [this.body = null]); | 322 LetPrim(this.primitive, [this.body = null]); |
| 314 | 323 |
| 315 Expression plug(Expression expr) { | 324 Expression plug(Expression expr) { |
| 316 assert(body == null); | 325 assert(body == null); |
| 317 return body = expr; | 326 return body = expr; |
| 318 } | 327 } |
| 319 | 328 |
| 320 accept(Visitor visitor) => visitor.visitLetPrim(this); | 329 accept(Visitor visitor) => visitor.visitLetPrim(this); |
| 330 |
| 331 void setParentPointers() { |
| 332 primitive.parent = this; |
| 333 if (body != null) body.parent = this; |
| 334 } |
| 321 } | 335 } |
| 322 | 336 |
| 323 | |
| 324 /// Binding continuations. | 337 /// Binding continuations. |
| 325 /// | 338 /// |
| 326 /// let cont k0(v0 ...) = E0 | 339 /// let cont k0(v0 ...) = E0 |
| 327 /// k1(v1 ...) = E1 | 340 /// k1(v1 ...) = E1 |
| 328 /// ... | 341 /// ... |
| 329 /// in E | 342 /// in E |
| 330 /// | 343 /// |
| 331 /// The bound continuations are in scope in the body and the continuation | 344 /// The bound continuations are in scope in the body and the continuation |
| 332 /// parameters are in scope in the respective continuation bodies. | 345 /// parameters are in scope in the respective continuation bodies. |
| 333 /// | 346 /// |
| (...skipping 13 matching lines...) Expand all Loading... |
| 347 LetCont.many(this.continuations, this.body); | 360 LetCont.many(this.continuations, this.body); |
| 348 | 361 |
| 349 Expression plug(Expression expr) { | 362 Expression plug(Expression expr) { |
| 350 assert(continuations != null && | 363 assert(continuations != null && |
| 351 continuations.isNotEmpty && | 364 continuations.isNotEmpty && |
| 352 continuations.first.body == null); | 365 continuations.first.body == null); |
| 353 return continuations.first.body = expr; | 366 return continuations.first.body = expr; |
| 354 } | 367 } |
| 355 | 368 |
| 356 accept(Visitor visitor) => visitor.visitLetCont(this); | 369 accept(Visitor visitor) => visitor.visitLetCont(this); |
| 370 |
| 371 void setParentPointers() { |
| 372 _setParentsOnNodes(continuations, this); |
| 373 if (body != null) body.parent = this; |
| 374 } |
| 357 } | 375 } |
| 358 | 376 |
| 359 // Binding an exception handler. | 377 // Binding an exception handler. |
| 360 // | 378 // |
| 361 // let handler h(v0, v1) = E0 in E1 | 379 // let handler h(v0, v1) = E0 in E1 |
| 362 // | 380 // |
| 363 // The handler is a two-argument (exception, stack trace) continuation which | 381 // The handler is a two-argument (exception, stack trace) continuation which |
| 364 // is implicitly the error continuation of all the code in its body E1. | 382 // is implicitly the error continuation of all the code in its body E1. |
| 365 // [LetHandler] differs from a [LetCont] binding in that it (1) has the | 383 // [LetHandler] differs from a [LetCont] binding in that it (1) has the |
| 366 // runtime semantics of pushing/popping a handler from the dynamic exception | 384 // runtime semantics of pushing/popping a handler from the dynamic exception |
| 367 // handler stack and (2) it does not have any explicit invocations. | 385 // handler stack and (2) it does not have any explicit invocations. |
| 368 class LetHandler extends InteriorExpression { | 386 class LetHandler extends InteriorExpression { |
| 369 Continuation handler; | 387 Continuation handler; |
| 370 Expression body; | 388 Expression body; |
| 371 | 389 |
| 372 LetHandler(this.handler, this.body); | 390 LetHandler(this.handler, this.body); |
| 373 | 391 |
| 374 accept(Visitor visitor) => visitor.visitLetHandler(this); | 392 accept(Visitor visitor) => visitor.visitLetHandler(this); |
| 393 |
| 394 void setParentPointers() { |
| 395 handler.parent = this; |
| 396 if (body != null) body.parent = this; |
| 397 } |
| 375 } | 398 } |
| 376 | 399 |
| 377 /// Binding mutable variables. | 400 /// Binding mutable variables. |
| 378 /// | 401 /// |
| 379 /// let mutable v = P in E | 402 /// let mutable v = P in E |
| 380 /// | 403 /// |
| 381 /// [MutableVariable]s can be seen as ref cells that are not first-class | 404 /// [MutableVariable]s can be seen as ref cells that are not first-class |
| 382 /// values. They are therefore not [Primitive]s and not bound by [LetPrim] | 405 /// values. They are therefore not [Primitive]s and not bound by [LetPrim] |
| 383 /// to prevent unrestricted use of references to them. During one-pass | 406 /// to prevent unrestricted use of references to them. During one-pass |
| 384 /// construction, a [LetMutable] with an empty body is use to represent the | 407 /// construction, a [LetMutable] with an empty body is use to represent the |
| 385 /// one-hole context 'let mutable v = P in []'. | 408 /// one-hole context 'let mutable v = P in []'. |
| 386 class LetMutable extends InteriorExpression { | 409 class LetMutable extends InteriorExpression { |
| 387 final MutableVariable variable; | 410 final MutableVariable variable; |
| 388 final Reference<Primitive> value; | 411 final Reference<Primitive> value; |
| 389 Expression body; | 412 Expression body; |
| 390 | 413 |
| 391 LetMutable(this.variable, Primitive value) | 414 LetMutable(this.variable, Primitive value) |
| 392 : this.value = new Reference<Primitive>(value); | 415 : this.value = new Reference<Primitive>(value); |
| 393 | 416 |
| 394 Expression plug(Expression expr) { | 417 Expression plug(Expression expr) { |
| 395 return body = expr; | 418 return body = expr; |
| 396 } | 419 } |
| 397 | 420 |
| 398 accept(Visitor visitor) => visitor.visitLetMutable(this); | 421 accept(Visitor visitor) => visitor.visitLetMutable(this); |
| 422 |
| 423 void setParentPointers() { |
| 424 variable.parent = this; |
| 425 value.parent = this; |
| 426 if (body != null) body.parent = this; |
| 427 } |
| 399 } | 428 } |
| 400 | 429 |
| 401 /// Invoke a static function. | 430 /// Invoke a static function. |
| 402 /// | 431 /// |
| 403 /// All optional arguments declared by [target] are passed in explicitly, and | 432 /// All optional arguments declared by [target] are passed in explicitly, and |
| 404 /// occur at the end of [arguments] list, in normalized order. | 433 /// occur at the end of [arguments] list, in normalized order. |
| 405 /// | 434 /// |
| 406 /// Discussion: | 435 /// Discussion: |
| 407 /// All information in the [selector] is technically redundant; it will likely | 436 /// All information in the [selector] is technically redundant; it will likely |
| 408 /// be removed. | 437 /// be removed. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 421 : arguments = _referenceList(args), | 450 : arguments = _referenceList(args), |
| 422 continuation = new Reference<Continuation>(cont); | 451 continuation = new Reference<Continuation>(cont); |
| 423 | 452 |
| 424 InvokeStatic.byReference(this.target, | 453 InvokeStatic.byReference(this.target, |
| 425 this.selector, | 454 this.selector, |
| 426 this.arguments, | 455 this.arguments, |
| 427 this.continuation, | 456 this.continuation, |
| 428 [this.sourceInformation]); | 457 [this.sourceInformation]); |
| 429 | 458 |
| 430 accept(Visitor visitor) => visitor.visitInvokeStatic(this); | 459 accept(Visitor visitor) => visitor.visitInvokeStatic(this); |
| 460 |
| 461 void setParentPointers() { |
| 462 _setParentsOnList(arguments, this); |
| 463 continuation.parent = this; |
| 464 } |
| 431 } | 465 } |
| 432 | 466 |
| 433 /// Invoke a method on an object. | 467 /// Invoke a method on an object. |
| 434 /// | 468 /// |
| 435 /// This includes getters, setters, operators, and index getter/setters. | 469 /// This includes getters, setters, operators, and index getter/setters. |
| 436 /// | 470 /// |
| 437 /// Tearing off a method is treated like a getter invocation (getters and | 471 /// Tearing off a method is treated like a getter invocation (getters and |
| 438 /// tear-offs cannot be distinguished at compile-time). | 472 /// tear-offs cannot be distinguished at compile-time). |
| 439 /// | 473 /// |
| 440 /// The [selector] records the names of named arguments. The value of named | 474 /// The [selector] records the names of named arguments. The value of named |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 this.continuation = new Reference<Continuation>(continuation); | 506 this.continuation = new Reference<Continuation>(continuation); |
| 473 | 507 |
| 474 InvokeMethod.byReference(this.receiver, | 508 InvokeMethod.byReference(this.receiver, |
| 475 this.selector, | 509 this.selector, |
| 476 this.mask, | 510 this.mask, |
| 477 this.arguments, | 511 this.arguments, |
| 478 this.continuation, | 512 this.continuation, |
| 479 this.sourceInformation); | 513 this.sourceInformation); |
| 480 | 514 |
| 481 accept(Visitor visitor) => visitor.visitInvokeMethod(this); | 515 accept(Visitor visitor) => visitor.visitInvokeMethod(this); |
| 516 |
| 517 void setParentPointers() { |
| 518 receiver.parent = this; |
| 519 _setParentsOnList(arguments, this); |
| 520 continuation.parent = this; |
| 521 } |
| 482 } | 522 } |
| 483 | 523 |
| 484 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. | 524 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. |
| 485 /// | 525 /// |
| 486 /// That is, if [receiver] is an instance of a class that overrides [target] | 526 /// That is, if [receiver] is an instance of a class that overrides [target] |
| 487 /// with a different implementation, the overriding implementation is bypassed | 527 /// with a different implementation, the overriding implementation is bypassed |
| 488 /// and [target]'s implementation is invoked. | 528 /// and [target]'s implementation is invoked. |
| 489 /// | 529 /// |
| 490 /// As with [InvokeMethod], this can be used to invoke a method, operator, | 530 /// As with [InvokeMethod], this can be used to invoke a method, operator, |
| 491 /// getter, setter, or index getter/setter. | 531 /// getter, setter, or index getter/setter. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 512 this.target, | 552 this.target, |
| 513 this.selector, | 553 this.selector, |
| 514 List<Primitive> arguments, | 554 List<Primitive> arguments, |
| 515 Continuation continuation, | 555 Continuation continuation, |
| 516 this.sourceInformation) | 556 this.sourceInformation) |
| 517 : this.receiver = new Reference<Primitive>(receiver), | 557 : this.receiver = new Reference<Primitive>(receiver), |
| 518 this.arguments = _referenceList(arguments), | 558 this.arguments = _referenceList(arguments), |
| 519 this.continuation = new Reference<Continuation>(continuation); | 559 this.continuation = new Reference<Continuation>(continuation); |
| 520 | 560 |
| 521 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); | 561 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); |
| 562 |
| 563 void setParentPointers() { |
| 564 receiver.parent = this; |
| 565 _setParentsOnList(arguments, this); |
| 566 continuation.parent = this; |
| 567 } |
| 522 } | 568 } |
| 523 | 569 |
| 524 /// Non-const call to a constructor. | 570 /// Non-const call to a constructor. |
| 525 /// | 571 /// |
| 526 /// The [target] may be a generative constructor (forwarding or normal) | 572 /// The [target] may be a generative constructor (forwarding or normal) |
| 527 /// or a non-redirecting factory. | 573 /// or a non-redirecting factory. |
| 528 /// | 574 /// |
| 529 /// All optional arguments declared by [target] are passed in explicitly, and | 575 /// All optional arguments declared by [target] are passed in explicitly, and |
| 530 /// occur in the [arguments] list, in normalized order. | 576 /// occur in the [arguments] list, in normalized order. |
| 531 /// | 577 /// |
| (...skipping 15 matching lines...) Expand all Loading... |
| 547 InvokeConstructor(this.dartType, | 593 InvokeConstructor(this.dartType, |
| 548 this.target, | 594 this.target, |
| 549 this.selector, | 595 this.selector, |
| 550 List<Primitive> args, | 596 List<Primitive> args, |
| 551 Continuation cont, | 597 Continuation cont, |
| 552 this.sourceInformation) | 598 this.sourceInformation) |
| 553 : arguments = _referenceList(args), | 599 : arguments = _referenceList(args), |
| 554 continuation = new Reference<Continuation>(cont); | 600 continuation = new Reference<Continuation>(cont); |
| 555 | 601 |
| 556 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); | 602 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); |
| 603 |
| 604 void setParentPointers() { |
| 605 _setParentsOnList(arguments, this); |
| 606 continuation.parent = this; |
| 607 } |
| 557 } | 608 } |
| 558 | 609 |
| 559 /// An alias for [value] in a context where the value is known to satisfy | 610 /// An alias for [value] in a context where the value is known to satisfy |
| 560 /// [type]. | 611 /// [type]. |
| 561 /// | 612 /// |
| 562 /// Refinement nodes are inserted before the type propagator pass and removed | 613 /// Refinement nodes are inserted before the type propagator pass and removed |
| 563 /// afterwards, so as not to complicate passes that don't reason about types, | 614 /// afterwards, so as not to complicate passes that don't reason about types, |
| 564 /// but need to reason about value references being identical (i.e. referring | 615 /// but need to reason about value references being identical (i.e. referring |
| 565 /// to the same primitive). | 616 /// to the same primitive). |
| 566 class Refinement extends Primitive { | 617 class Refinement extends Primitive { |
| 567 Reference<Primitive> value; | 618 Reference<Primitive> value; |
| 568 final TypeMask refineType; | 619 final TypeMask refineType; |
| 569 | 620 |
| 570 Refinement(Primitive value, this.refineType) | 621 Refinement(Primitive value, this.refineType) |
| 571 : value = new Reference<Primitive>(value); | 622 : value = new Reference<Primitive>(value); |
| 572 | 623 |
| 573 bool get isSafeForElimination => true; | 624 bool get isSafeForElimination => true; |
| 574 bool get isSafeForReordering => false; | 625 bool get isSafeForReordering => false; |
| 575 | 626 |
| 576 accept(Visitor visitor) => visitor.visitRefinement(this); | 627 accept(Visitor visitor) => visitor.visitRefinement(this); |
| 577 | 628 |
| 578 Primitive get effectiveDefinition => value.definition.effectiveDefinition; | 629 Primitive get effectiveDefinition => value.definition.effectiveDefinition; |
| 630 |
| 631 void setParentPointers() { |
| 632 value.parent = this; |
| 633 } |
| 579 } | 634 } |
| 580 | 635 |
| 581 /// An "is" type test. | 636 /// An "is" type test. |
| 582 /// | 637 /// |
| 583 /// Returns `true` if [value] is an instance of [type]. | 638 /// Returns `true` if [value] is an instance of [type]. |
| 584 /// | 639 /// |
| 585 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might | 640 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might |
| 586 /// be a type variable containing one of these types). This design is chosen | 641 /// be a type variable containing one of these types). This design is chosen |
| 587 /// to simplify code generation for type tests. | 642 /// to simplify code generation for type tests. |
| 588 class TypeTest extends Primitive { | 643 class TypeTest extends Primitive { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 611 TypeTest(Primitive value, | 666 TypeTest(Primitive value, |
| 612 this.dartType, | 667 this.dartType, |
| 613 List<Primitive> typeArguments) | 668 List<Primitive> typeArguments) |
| 614 : this.value = new Reference<Primitive>(value), | 669 : this.value = new Reference<Primitive>(value), |
| 615 this.typeArguments = _referenceList(typeArguments); | 670 this.typeArguments = _referenceList(typeArguments); |
| 616 | 671 |
| 617 accept(Visitor visitor) => visitor.visitTypeTest(this); | 672 accept(Visitor visitor) => visitor.visitTypeTest(this); |
| 618 | 673 |
| 619 bool get isSafeForElimination => true; | 674 bool get isSafeForElimination => true; |
| 620 bool get isSafeForReordering => true; | 675 bool get isSafeForReordering => true; |
| 676 |
| 677 void setParentPointers() { |
| 678 value.parent = this; |
| 679 _setParentsOnList(typeArguments, this); |
| 680 if (interceptor != null) interceptor.parent = this; |
| 681 } |
| 621 } | 682 } |
| 622 | 683 |
| 623 /// An "is" type test for a raw type, performed by testing a flag property. | 684 /// An "is" type test for a raw type, performed by testing a flag property. |
| 624 /// | 685 /// |
| 625 /// Returns `true` if [interceptor] is for [dartType]. | 686 /// Returns `true` if [interceptor] is for [dartType]. |
| 626 class TypeTestViaFlag extends Primitive { | 687 class TypeTestViaFlag extends Primitive { |
| 627 Reference<Primitive> interceptor; | 688 Reference<Primitive> interceptor; |
| 628 final DartType dartType; | 689 final DartType dartType; |
| 629 | 690 |
| 630 TypeTestViaFlag(Primitive interceptor, this.dartType) | 691 TypeTestViaFlag(Primitive interceptor, this.dartType) |
| 631 : this.interceptor = new Reference<Primitive>(interceptor); | 692 : this.interceptor = new Reference<Primitive>(interceptor); |
| 632 | 693 |
| 633 accept(Visitor visitor) => visitor.visitTypeTestViaFlag(this); | 694 accept(Visitor visitor) => visitor.visitTypeTestViaFlag(this); |
| 634 | 695 |
| 635 bool get isSafeForElimination => true; | 696 bool get isSafeForElimination => true; |
| 636 bool get isSafeForReordering => true; | 697 bool get isSafeForReordering => true; |
| 698 |
| 699 void setParentPointers() { |
| 700 interceptor.parent = this; |
| 701 } |
| 637 } | 702 } |
| 638 | 703 |
| 639 /// An "as" type cast. | 704 /// An "as" type cast. |
| 640 /// | 705 /// |
| 641 /// If [value] is `null` or is an instance of [type], [continuation] is invoked | 706 /// If [value] is `null` or is an instance of [type], [continuation] is invoked |
| 642 /// with [value] as argument. Otherwise, a [CastError] is thrown. | 707 /// with [value] as argument. Otherwise, a [CastError] is thrown. |
| 643 /// | 708 /// |
| 644 /// Discussion: | 709 /// Discussion: |
| 645 /// The parameter to [continuation] is redundant since it will always equal | 710 /// The parameter to [continuation] is redundant since it will always equal |
| 646 /// [value], which is typically in scope in the continuation. However, it might | 711 /// [value], which is typically in scope in the continuation. However, it might |
| 647 /// simplify type propagation, since a better type can be computed for the | 712 /// simplify type propagation, since a better type can be computed for the |
| 648 /// continuation parameter without needing flow-sensitive analysis. | 713 /// continuation parameter without needing flow-sensitive analysis. |
| 649 class TypeCast extends CallExpression { | 714 class TypeCast extends CallExpression { |
| 650 Reference<Primitive> value; | 715 Reference<Primitive> value; |
| 651 final DartType dartType; | 716 final DartType dartType; |
| 652 | 717 |
| 653 /// See the corresponding field on [TypeTest]. | 718 /// See the corresponding field on [TypeTest]. |
| 654 final List<Reference<Primitive>> typeArguments; | 719 final List<Reference<Primitive>> typeArguments; |
| 655 final Reference<Continuation> continuation; | 720 final Reference<Continuation> continuation; |
| 656 | 721 |
| 657 TypeCast(Primitive value, | 722 TypeCast(Primitive value, |
| 658 this.dartType, | 723 this.dartType, |
| 659 List<Primitive> typeArguments, | 724 List<Primitive> typeArguments, |
| 660 Continuation cont) | 725 Continuation cont) |
| 661 : this.value = new Reference<Primitive>(value), | 726 : this.value = new Reference<Primitive>(value), |
| 662 this.typeArguments = _referenceList(typeArguments), | 727 this.typeArguments = _referenceList(typeArguments), |
| 663 this.continuation = new Reference<Continuation>(cont); | 728 this.continuation = new Reference<Continuation>(cont); |
| 664 | 729 |
| 665 accept(Visitor visitor) => visitor.visitTypeCast(this); | 730 accept(Visitor visitor) => visitor.visitTypeCast(this); |
| 731 |
| 732 void setParentPointers() { |
| 733 value.parent = this; |
| 734 } |
| 666 } | 735 } |
| 667 | 736 |
| 668 /// Apply a built-in operator. | 737 /// Apply a built-in operator. |
| 669 /// | 738 /// |
| 670 /// It must be known that the arguments have the proper types. | 739 /// It must be known that the arguments have the proper types. |
| 671 class ApplyBuiltinOperator extends Primitive { | 740 class ApplyBuiltinOperator extends Primitive { |
| 672 BuiltinOperator operator; | 741 BuiltinOperator operator; |
| 673 List<Reference<Primitive>> arguments; | 742 List<Reference<Primitive>> arguments; |
| 674 final SourceInformation sourceInformation; | 743 final SourceInformation sourceInformation; |
| 675 | 744 |
| 676 ApplyBuiltinOperator(this.operator, | 745 ApplyBuiltinOperator(this.operator, |
| 677 List<Primitive> arguments, | 746 List<Primitive> arguments, |
| 678 this.sourceInformation) | 747 this.sourceInformation) |
| 679 : this.arguments = _referenceList(arguments); | 748 : this.arguments = _referenceList(arguments); |
| 680 | 749 |
| 681 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); | 750 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); |
| 682 | 751 |
| 683 bool get isSafeForElimination => true; | 752 bool get isSafeForElimination => true; |
| 684 bool get isSafeForReordering => true; | 753 bool get isSafeForReordering => true; |
| 754 |
| 755 void setParentPointers() { |
| 756 _setParentsOnList(arguments, this); |
| 757 } |
| 685 } | 758 } |
| 686 | 759 |
| 687 /// Apply a built-in method. | 760 /// Apply a built-in method. |
| 688 /// | 761 /// |
| 689 /// It must be known that the arguments have the proper types. | 762 /// It must be known that the arguments have the proper types. |
| 690 class ApplyBuiltinMethod extends Primitive { | 763 class ApplyBuiltinMethod extends Primitive { |
| 691 BuiltinMethod method; | 764 BuiltinMethod method; |
| 692 Reference<Primitive> receiver; | 765 Reference<Primitive> receiver; |
| 693 List<Reference<Primitive>> arguments; | 766 List<Reference<Primitive>> arguments; |
| 694 final SourceInformation sourceInformation; | 767 final SourceInformation sourceInformation; |
| 695 | 768 |
| 696 bool receiverIsNotNull; | 769 bool receiverIsNotNull; |
| 697 | 770 |
| 698 ApplyBuiltinMethod(this.method, | 771 ApplyBuiltinMethod(this.method, |
| 699 Primitive receiver, | 772 Primitive receiver, |
| 700 List<Primitive> arguments, | 773 List<Primitive> arguments, |
| 701 this.sourceInformation, | 774 this.sourceInformation, |
| 702 {this.receiverIsNotNull: false}) | 775 {this.receiverIsNotNull: false}) |
| 703 : this.receiver = new Reference<Primitive>(receiver), | 776 : this.receiver = new Reference<Primitive>(receiver), |
| 704 this.arguments = _referenceList(arguments); | 777 this.arguments = _referenceList(arguments); |
| 705 | 778 |
| 706 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); | 779 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); |
| 707 | 780 |
| 708 bool get isSafeForElimination => false; | 781 bool get isSafeForElimination => false; |
| 709 bool get isSafeForReordering => false; | 782 bool get isSafeForReordering => false; |
| 783 |
| 784 void setParentPointers() { |
| 785 receiver.parent = this; |
| 786 _setParentsOnList(arguments, this); |
| 787 } |
| 710 } | 788 } |
| 711 | 789 |
| 712 /// Throw a value. | 790 /// Throw a value. |
| 713 /// | 791 /// |
| 714 /// Throw is an expression, i.e., it always occurs in tail position with | 792 /// Throw is an expression, i.e., it always occurs in tail position with |
| 715 /// respect to a body or expression. | 793 /// respect to a body or expression. |
| 716 class Throw extends TailExpression { | 794 class Throw extends TailExpression { |
| 717 Reference<Primitive> value; | 795 Reference<Primitive> value; |
| 718 | 796 |
| 719 Throw(Primitive value) : value = new Reference<Primitive>(value); | 797 Throw(Primitive value) : value = new Reference<Primitive>(value); |
| 720 | 798 |
| 721 accept(Visitor visitor) => visitor.visitThrow(this); | 799 accept(Visitor visitor) => visitor.visitThrow(this); |
| 800 |
| 801 void setParentPointers() { |
| 802 value.parent = this; |
| 803 } |
| 722 } | 804 } |
| 723 | 805 |
| 724 /// Rethrow | 806 /// Rethrow |
| 725 /// | 807 /// |
| 726 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It | 808 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It |
| 727 /// implicitly throws the exception parameter of the enclosing handler with | 809 /// implicitly throws the exception parameter of the enclosing handler with |
| 728 /// the same stack trace as the enclosing handler. | 810 /// the same stack trace as the enclosing handler. |
| 729 class Rethrow extends TailExpression { | 811 class Rethrow extends TailExpression { |
| 730 accept(Visitor visitor) => visitor.visitRethrow(this); | 812 accept(Visitor visitor) => visitor.visitRethrow(this); |
| 813 void setParentPointers() {} |
| 731 } | 814 } |
| 732 | 815 |
| 733 /// An expression that is known to be unreachable. | 816 /// An expression that is known to be unreachable. |
| 734 /// | 817 /// |
| 735 /// This can be placed as the body of a call continuation, when the caller is | 818 /// This can be placed as the body of a call continuation, when the caller is |
| 736 /// known never to invoke it, e.g. because the calling expression always throws. | 819 /// known never to invoke it, e.g. because the calling expression always throws. |
| 737 class Unreachable extends TailExpression { | 820 class Unreachable extends TailExpression { |
| 738 accept(Visitor visitor) => visitor.visitUnreachable(this); | 821 accept(Visitor visitor) => visitor.visitUnreachable(this); |
| 822 void setParentPointers() {} |
| 739 } | 823 } |
| 740 | 824 |
| 741 /// Gets the value from a [MutableVariable]. | 825 /// Gets the value from a [MutableVariable]. |
| 742 /// | 826 /// |
| 743 /// [MutableVariable]s can be seen as ref cells that are not first-class | 827 /// [MutableVariable]s can be seen as ref cells that are not first-class |
| 744 /// values. A [LetPrim] with a [GetMutable] can then be seen as: | 828 /// values. A [LetPrim] with a [GetMutable] can then be seen as: |
| 745 /// | 829 /// |
| 746 /// let prim p = ![variable] in [body] | 830 /// let prim p = ![variable] in [body] |
| 747 /// | 831 /// |
| 748 class GetMutable extends Primitive { | 832 class GetMutable extends Primitive { |
| 749 final Reference<MutableVariable> variable; | 833 final Reference<MutableVariable> variable; |
| 750 | 834 |
| 751 GetMutable(MutableVariable variable) | 835 GetMutable(MutableVariable variable) |
| 752 : this.variable = new Reference<MutableVariable>(variable); | 836 : this.variable = new Reference<MutableVariable>(variable); |
| 753 | 837 |
| 754 accept(Visitor visitor) => visitor.visitGetMutable(this); | 838 accept(Visitor visitor) => visitor.visitGetMutable(this); |
| 755 | 839 |
| 756 bool get isSafeForElimination => true; | 840 bool get isSafeForElimination => true; |
| 757 bool get isSafeForReordering => false; | 841 bool get isSafeForReordering => false; |
| 842 |
| 843 void setParentPointers() { |
| 844 variable.parent = this; |
| 845 } |
| 758 } | 846 } |
| 759 | 847 |
| 760 /// Assign a [MutableVariable]. | 848 /// Assign a [MutableVariable]. |
| 761 /// | 849 /// |
| 762 /// [MutableVariable]s can be seen as ref cells that are not first-class | 850 /// [MutableVariable]s can be seen as ref cells that are not first-class |
| 763 /// values. This can be seen as a dereferencing assignment: | 851 /// values. This can be seen as a dereferencing assignment: |
| 764 /// | 852 /// |
| 765 /// { [variable] := [value]; [body] } | 853 /// { [variable] := [value]; [body] } |
| 766 class SetMutable extends Primitive { | 854 class SetMutable extends Primitive { |
| 767 final Reference<MutableVariable> variable; | 855 final Reference<MutableVariable> variable; |
| 768 final Reference<Primitive> value; | 856 final Reference<Primitive> value; |
| 769 | 857 |
| 770 SetMutable(MutableVariable variable, Primitive value) | 858 SetMutable(MutableVariable variable, Primitive value) |
| 771 : this.variable = new Reference<MutableVariable>(variable), | 859 : this.variable = new Reference<MutableVariable>(variable), |
| 772 this.value = new Reference<Primitive>(value); | 860 this.value = new Reference<Primitive>(value); |
| 773 | 861 |
| 774 accept(Visitor visitor) => visitor.visitSetMutable(this); | 862 accept(Visitor visitor) => visitor.visitSetMutable(this); |
| 775 | 863 |
| 776 bool get isSafeForElimination => false; | 864 bool get isSafeForElimination => false; |
| 777 bool get isSafeForReordering => false; | 865 bool get isSafeForReordering => false; |
| 866 |
| 867 void setParentPointers() { |
| 868 variable.parent = this; |
| 869 value.parent = this; |
| 870 } |
| 778 } | 871 } |
| 779 | 872 |
| 780 /// Invoke a continuation in tail position. | 873 /// Invoke a continuation in tail position. |
| 781 class InvokeContinuation extends TailExpression { | 874 class InvokeContinuation extends TailExpression { |
| 782 Reference<Continuation> continuation; | 875 Reference<Continuation> continuation; |
| 783 List<Reference<Primitive>> arguments; | 876 List<Reference<Primitive>> arguments; |
| 784 SourceInformation sourceInformation; | 877 SourceInformation sourceInformation; |
| 785 | 878 |
| 786 // An invocation of a continuation is recursive if it occurs in the body of | 879 // An invocation of a continuation is recursive if it occurs in the body of |
| 787 // the continuation itself. | 880 // the continuation itself. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 806 /// | 899 /// |
| 807 /// Used as a placeholder for a jump whose target is not yet created | 900 /// Used as a placeholder for a jump whose target is not yet created |
| 808 /// (e.g., in the translation of break and continue). | 901 /// (e.g., in the translation of break and continue). |
| 809 InvokeContinuation.uninitialized({this.isRecursive: false, | 902 InvokeContinuation.uninitialized({this.isRecursive: false, |
| 810 this.isEscapingTry: false}) | 903 this.isEscapingTry: false}) |
| 811 : continuation = null, | 904 : continuation = null, |
| 812 arguments = null, | 905 arguments = null, |
| 813 sourceInformation = null; | 906 sourceInformation = null; |
| 814 | 907 |
| 815 accept(Visitor visitor) => visitor.visitInvokeContinuation(this); | 908 accept(Visitor visitor) => visitor.visitInvokeContinuation(this); |
| 909 |
| 910 void setParentPointers() { |
| 911 if (continuation != null) continuation.parent = this; |
| 912 if (arguments != null) _setParentsOnList(arguments, this); |
| 913 } |
| 816 } | 914 } |
| 817 | 915 |
| 818 /// Choose between a pair of continuations based on a condition value. | 916 /// Choose between a pair of continuations based on a condition value. |
| 819 /// | 917 /// |
| 820 /// The two continuations must not declare any parameters. | 918 /// The two continuations must not declare any parameters. |
| 821 class Branch extends TailExpression { | 919 class Branch extends TailExpression { |
| 822 final Reference<Primitive> condition; | 920 final Reference<Primitive> condition; |
| 823 final Reference<Continuation> trueContinuation; | 921 final Reference<Continuation> trueContinuation; |
| 824 final Reference<Continuation> falseContinuation; | 922 final Reference<Continuation> falseContinuation; |
| 825 | 923 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 840 | 938 |
| 841 Branch.loose(Primitive condition, | 939 Branch.loose(Primitive condition, |
| 842 Continuation trueCont, | 940 Continuation trueCont, |
| 843 Continuation falseCont) | 941 Continuation falseCont) |
| 844 : this.condition = new Reference<Primitive>(condition), | 942 : this.condition = new Reference<Primitive>(condition), |
| 845 trueContinuation = new Reference<Continuation>(trueCont), | 943 trueContinuation = new Reference<Continuation>(trueCont), |
| 846 falseContinuation = new Reference<Continuation>(falseCont), | 944 falseContinuation = new Reference<Continuation>(falseCont), |
| 847 this.isStrictCheck = false; | 945 this.isStrictCheck = false; |
| 848 | 946 |
| 849 accept(Visitor visitor) => visitor.visitBranch(this); | 947 accept(Visitor visitor) => visitor.visitBranch(this); |
| 948 |
| 949 void setParentPointers() { |
| 950 condition.parent = this; |
| 951 trueContinuation.parent = this; |
| 952 falseContinuation.parent = this; |
| 953 } |
| 850 } | 954 } |
| 851 | 955 |
| 852 /// Directly assigns to a field on a given object. | 956 /// Directly assigns to a field on a given object. |
| 853 class SetField extends Primitive { | 957 class SetField extends Primitive { |
| 854 final Reference<Primitive> object; | 958 final Reference<Primitive> object; |
| 855 FieldElement field; | 959 FieldElement field; |
| 856 final Reference<Primitive> value; | 960 final Reference<Primitive> value; |
| 857 | 961 |
| 858 SetField(Primitive object, this.field, Primitive value) | 962 SetField(Primitive object, this.field, Primitive value) |
| 859 : this.object = new Reference<Primitive>(object), | 963 : this.object = new Reference<Primitive>(object), |
| 860 this.value = new Reference<Primitive>(value); | 964 this.value = new Reference<Primitive>(value); |
| 861 | 965 |
| 862 accept(Visitor visitor) => visitor.visitSetField(this); | 966 accept(Visitor visitor) => visitor.visitSetField(this); |
| 863 | 967 |
| 864 bool get isSafeForElimination => false; | 968 bool get isSafeForElimination => false; |
| 865 bool get isSafeForReordering => false; | 969 bool get isSafeForReordering => false; |
| 970 |
| 971 void setParentPointers() { |
| 972 object.parent = this; |
| 973 value.parent = this; |
| 974 } |
| 866 } | 975 } |
| 867 | 976 |
| 868 /// Directly reads from a field on a given object. | 977 /// Directly reads from a field on a given object. |
| 869 /// | 978 /// |
| 870 /// The [object] must either be `null` or an object that has [field]. | 979 /// The [object] must either be `null` or an object that has [field]. |
| 871 class GetField extends Primitive { | 980 class GetField extends Primitive { |
| 872 final Reference<Primitive> object; | 981 final Reference<Primitive> object; |
| 873 FieldElement field; | 982 FieldElement field; |
| 874 | 983 |
| 875 /// True if the object is known not to be null. | 984 /// True if the object is known not to be null. |
| 876 // TODO(asgerf): This is a placeholder until we agree on how to track | 985 // TODO(asgerf): This is a placeholder until we agree on how to track |
| 877 // side effects. | 986 // side effects. |
| 878 bool objectIsNotNull = false; | 987 bool objectIsNotNull = false; |
| 879 | 988 |
| 880 GetField(Primitive object, this.field) | 989 GetField(Primitive object, this.field) |
| 881 : this.object = new Reference<Primitive>(object); | 990 : this.object = new Reference<Primitive>(object); |
| 882 | 991 |
| 883 accept(Visitor visitor) => visitor.visitGetField(this); | 992 accept(Visitor visitor) => visitor.visitGetField(this); |
| 884 | 993 |
| 885 bool get isSafeForElimination => objectIsNotNull; | 994 bool get isSafeForElimination => objectIsNotNull; |
| 886 bool get isSafeForReordering => false; | 995 bool get isSafeForReordering => false; |
| 887 | 996 |
| 888 toString() => 'GetField($field)'; | 997 toString() => 'GetField($field)'; |
| 998 |
| 999 void setParentPointers() { |
| 1000 object.parent = this; |
| 1001 } |
| 889 } | 1002 } |
| 890 | 1003 |
| 891 /// Get the length of a string or native list. | 1004 /// Get the length of a string or native list. |
| 892 class GetLength extends Primitive { | 1005 class GetLength extends Primitive { |
| 893 final Reference<Primitive> object; | 1006 final Reference<Primitive> object; |
| 894 | 1007 |
| 895 /// True if the object is known not to be null. | 1008 /// True if the object is known not to be null. |
| 896 bool objectIsNotNull = false; | 1009 bool objectIsNotNull = false; |
| 897 | 1010 |
| 898 GetLength(Primitive object) : this.object = new Reference<Primitive>(object); | 1011 GetLength(Primitive object) : this.object = new Reference<Primitive>(object); |
| 899 | 1012 |
| 900 bool get isSafeForElimination => objectIsNotNull; | 1013 bool get isSafeForElimination => objectIsNotNull; |
| 901 bool get isSafeForReordering => false; | 1014 bool get isSafeForReordering => false; |
| 902 | 1015 |
| 903 accept(Visitor v) => v.visitGetLength(this); | 1016 accept(Visitor v) => v.visitGetLength(this); |
| 1017 |
| 1018 void setParentPointers() { |
| 1019 object.parent = this; |
| 1020 } |
| 904 } | 1021 } |
| 905 | 1022 |
| 906 /// Read an entry from a string or native list. | 1023 /// Read an entry from a string or native list. |
| 907 /// | 1024 /// |
| 908 /// [object] must be null or a native list or a string, and [index] must be | 1025 /// [object] must be null or a native list or a string, and [index] must be |
| 909 /// an integer. | 1026 /// an integer. |
| 910 class GetIndex extends Primitive { | 1027 class GetIndex extends Primitive { |
| 911 final Reference<Primitive> object; | 1028 final Reference<Primitive> object; |
| 912 final Reference<Primitive> index; | 1029 final Reference<Primitive> index; |
| 913 | 1030 |
| 914 /// True if the object is known not to be null. | 1031 /// True if the object is known not to be null. |
| 915 bool objectIsNotNull = false; | 1032 bool objectIsNotNull = false; |
| 916 | 1033 |
| 917 GetIndex(Primitive object, Primitive index) | 1034 GetIndex(Primitive object, Primitive index) |
| 918 : this.object = new Reference<Primitive>(object), | 1035 : this.object = new Reference<Primitive>(object), |
| 919 this.index = new Reference<Primitive>(index); | 1036 this.index = new Reference<Primitive>(index); |
| 920 | 1037 |
| 921 bool get isSafeForElimination => objectIsNotNull; | 1038 bool get isSafeForElimination => objectIsNotNull; |
| 922 bool get isSafeForReordering => false; | 1039 bool get isSafeForReordering => false; |
| 923 | 1040 |
| 924 accept(Visitor v) => v.visitGetIndex(this); | 1041 accept(Visitor v) => v.visitGetIndex(this); |
| 1042 |
| 1043 void setParentPointers() { |
| 1044 object.parent = this; |
| 1045 index.parent = this; |
| 1046 } |
| 925 } | 1047 } |
| 926 | 1048 |
| 927 /// Set an entry on a native list. | 1049 /// Set an entry on a native list. |
| 928 /// | 1050 /// |
| 929 /// [object] must be null or a native list, and [index] must be an integer. | 1051 /// [object] must be null or a native list, and [index] must be an integer. |
| 930 /// | 1052 /// |
| 931 /// The primitive itself has no value and may not be referenced. | 1053 /// The primitive itself has no value and may not be referenced. |
| 932 class SetIndex extends Primitive { | 1054 class SetIndex extends Primitive { |
| 933 final Reference<Primitive> object; | 1055 final Reference<Primitive> object; |
| 934 final Reference<Primitive> index; | 1056 final Reference<Primitive> index; |
| 935 final Reference<Primitive> value; | 1057 final Reference<Primitive> value; |
| 936 | 1058 |
| 937 SetIndex(Primitive object, Primitive index, Primitive value) | 1059 SetIndex(Primitive object, Primitive index, Primitive value) |
| 938 : this.object = new Reference<Primitive>(object), | 1060 : this.object = new Reference<Primitive>(object), |
| 939 this.index = new Reference<Primitive>(index), | 1061 this.index = new Reference<Primitive>(index), |
| 940 this.value = new Reference<Primitive>(value); | 1062 this.value = new Reference<Primitive>(value); |
| 941 | 1063 |
| 942 bool get isSafeForElimination => false; | 1064 bool get isSafeForElimination => false; |
| 943 bool get isSafeForReordering => false; | 1065 bool get isSafeForReordering => false; |
| 944 | 1066 |
| 945 accept(Visitor v) => v.visitSetIndex(this); | 1067 accept(Visitor v) => v.visitSetIndex(this); |
| 1068 |
| 1069 void setParentPointers() { |
| 1070 object.parent = this; |
| 1071 index.parent = this; |
| 1072 value.parent = this; |
| 1073 } |
| 946 } | 1074 } |
| 947 | 1075 |
| 948 /// Reads the value of a static field or tears off a static method. | 1076 /// Reads the value of a static field or tears off a static method. |
| 949 /// | 1077 /// |
| 950 /// Note that lazily initialized fields should be read using GetLazyStatic. | 1078 /// Note that lazily initialized fields should be read using GetLazyStatic. |
| 951 class GetStatic extends Primitive { | 1079 class GetStatic extends Primitive { |
| 952 /// Can be [FieldElement] or [FunctionElement]. | 1080 /// Can be [FieldElement] or [FunctionElement]. |
| 953 final Element element; | 1081 final Element element; |
| 954 final SourceInformation sourceInformation; | 1082 final SourceInformation sourceInformation; |
| 955 | 1083 |
| 956 GetStatic(this.element, [this.sourceInformation]); | 1084 GetStatic(this.element, [this.sourceInformation]); |
| 957 | 1085 |
| 958 accept(Visitor visitor) => visitor.visitGetStatic(this); | 1086 accept(Visitor visitor) => visitor.visitGetStatic(this); |
| 959 | 1087 |
| 960 bool get isSafeForElimination { | 1088 bool get isSafeForElimination { |
| 961 return true; | 1089 return true; |
| 962 } | 1090 } |
| 963 bool get isSafeForReordering { | 1091 bool get isSafeForReordering { |
| 964 return element is FunctionElement || element.isFinal; | 1092 return element is FunctionElement || element.isFinal; |
| 965 } | 1093 } |
| 1094 |
| 1095 void setParentPointers() {} |
| 966 } | 1096 } |
| 967 | 1097 |
| 968 /// Sets the value of a static field. | 1098 /// Sets the value of a static field. |
| 969 class SetStatic extends Primitive { | 1099 class SetStatic extends Primitive { |
| 970 final FieldElement element; | 1100 final FieldElement element; |
| 971 final Reference<Primitive> value; | 1101 final Reference<Primitive> value; |
| 972 final SourceInformation sourceInformation; | 1102 final SourceInformation sourceInformation; |
| 973 | 1103 |
| 974 SetStatic(this.element, Primitive value, [this.sourceInformation]) | 1104 SetStatic(this.element, Primitive value, [this.sourceInformation]) |
| 975 : this.value = new Reference<Primitive>(value); | 1105 : this.value = new Reference<Primitive>(value); |
| 976 | 1106 |
| 977 accept(Visitor visitor) => visitor.visitSetStatic(this); | 1107 accept(Visitor visitor) => visitor.visitSetStatic(this); |
| 978 | 1108 |
| 979 bool get isSafeForElimination => false; | 1109 bool get isSafeForElimination => false; |
| 980 bool get isSafeForReordering => false; | 1110 bool get isSafeForReordering => false; |
| 1111 |
| 1112 void setParentPointers() { |
| 1113 value.parent = this; |
| 1114 } |
| 981 } | 1115 } |
| 982 | 1116 |
| 983 /// Reads the value of a lazily initialized static field. | 1117 /// Reads the value of a lazily initialized static field. |
| 984 /// | 1118 /// |
| 985 /// If the field has not yet been initialized, its initializer is evaluated | 1119 /// If the field has not yet been initialized, its initializer is evaluated |
| 986 /// and assigned to the field. | 1120 /// and assigned to the field. |
| 987 /// | 1121 /// |
| 988 /// [continuation] is then invoked with the value of the field as argument. | 1122 /// [continuation] is then invoked with the value of the field as argument. |
| 989 class GetLazyStatic extends CallExpression { | 1123 class GetLazyStatic extends CallExpression { |
| 990 final FieldElement element; | 1124 final FieldElement element; |
| 991 final Reference<Continuation> continuation; | 1125 final Reference<Continuation> continuation; |
| 992 final SourceInformation sourceInformation; | 1126 final SourceInformation sourceInformation; |
| 993 | 1127 |
| 994 GetLazyStatic(this.element, | 1128 GetLazyStatic(this.element, |
| 995 Continuation continuation, | 1129 Continuation continuation, |
| 996 [this.sourceInformation]) | 1130 [this.sourceInformation]) |
| 997 : continuation = new Reference<Continuation>(continuation); | 1131 : continuation = new Reference<Continuation>(continuation); |
| 998 | 1132 |
| 999 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); | 1133 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); |
| 1134 |
| 1135 void setParentPointers() { |
| 1136 continuation.parent = this; |
| 1137 } |
| 1000 } | 1138 } |
| 1001 | 1139 |
| 1002 /// Creates an object for holding boxed variables captured by a closure. | 1140 /// Creates an object for holding boxed variables captured by a closure. |
| 1003 class CreateBox extends Primitive { | 1141 class CreateBox extends Primitive { |
| 1004 accept(Visitor visitor) => visitor.visitCreateBox(this); | 1142 accept(Visitor visitor) => visitor.visitCreateBox(this); |
| 1005 | 1143 |
| 1006 bool get isSafeForElimination => true; | 1144 bool get isSafeForElimination => true; |
| 1007 bool get isSafeForReordering => true; | 1145 bool get isSafeForReordering => true; |
| 1146 |
| 1147 void setParentPointers() {} |
| 1008 } | 1148 } |
| 1009 | 1149 |
| 1010 /// Creates an instance of a class and initializes its fields and runtime type | 1150 /// Creates an instance of a class and initializes its fields and runtime type |
| 1011 /// information. | 1151 /// information. |
| 1012 class CreateInstance extends Primitive { | 1152 class CreateInstance extends Primitive { |
| 1013 final ClassElement classElement; | 1153 final ClassElement classElement; |
| 1014 | 1154 |
| 1015 /// Initial values for the fields on the class. | 1155 /// Initial values for the fields on the class. |
| 1016 /// The order corresponds to the order of fields on the class. | 1156 /// The order corresponds to the order of fields on the class. |
| 1017 final List<Reference<Primitive>> arguments; | 1157 final List<Reference<Primitive>> arguments; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1030 this.sourceInformation) | 1170 this.sourceInformation) |
| 1031 : this.arguments = _referenceList(arguments), | 1171 : this.arguments = _referenceList(arguments), |
| 1032 this.typeInformation = _referenceList(typeInformation); | 1172 this.typeInformation = _referenceList(typeInformation); |
| 1033 | 1173 |
| 1034 accept(Visitor visitor) => visitor.visitCreateInstance(this); | 1174 accept(Visitor visitor) => visitor.visitCreateInstance(this); |
| 1035 | 1175 |
| 1036 bool get isSafeForElimination => true; | 1176 bool get isSafeForElimination => true; |
| 1037 bool get isSafeForReordering => true; | 1177 bool get isSafeForReordering => true; |
| 1038 | 1178 |
| 1039 toString() => 'CreateInstance($classElement)'; | 1179 toString() => 'CreateInstance($classElement)'; |
| 1180 |
| 1181 void setParentPointers() { |
| 1182 _setParentsOnList(arguments, this); |
| 1183 if (typeInformation != null) _setParentsOnList(typeInformation, this); |
| 1184 } |
| 1040 } | 1185 } |
| 1041 | 1186 |
| 1042 class Interceptor extends Primitive { | 1187 class Interceptor extends Primitive { |
| 1043 final Reference<Primitive> input; | 1188 final Reference<Primitive> input; |
| 1044 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); | 1189 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); |
| 1045 final SourceInformation sourceInformation; | 1190 final SourceInformation sourceInformation; |
| 1046 | 1191 |
| 1047 /// If non-null, all uses of this the interceptor call are guaranteed to | 1192 /// If non-null, all uses of this the interceptor call are guaranteed to |
| 1048 /// see this value. | 1193 /// see this value. |
| 1049 /// | 1194 /// |
| 1050 /// The interceptor call is not immediately replaced by the constant, because | 1195 /// The interceptor call is not immediately replaced by the constant, because |
| 1051 /// that might prevent the interceptor from being shared. | 1196 /// that might prevent the interceptor from being shared. |
| 1052 /// | 1197 /// |
| 1053 /// The precise input type is not known when sharing interceptors, because | 1198 /// The precise input type is not known when sharing interceptors, because |
| 1054 /// refinement nodes have been removed by then. So this field carries the | 1199 /// refinement nodes have been removed by then. So this field carries the |
| 1055 /// known constant until we know if it should be shared or replaced by | 1200 /// known constant until we know if it should be shared or replaced by |
| 1056 /// the constant. | 1201 /// the constant. |
| 1057 values.InterceptorConstantValue constantValue; | 1202 values.InterceptorConstantValue constantValue; |
| 1058 | 1203 |
| 1059 Interceptor(Primitive input, this.sourceInformation) | 1204 Interceptor(Primitive input, this.sourceInformation) |
| 1060 : this.input = new Reference<Primitive>(input); | 1205 : this.input = new Reference<Primitive>(input); |
| 1061 | 1206 |
| 1062 accept(Visitor visitor) => visitor.visitInterceptor(this); | 1207 accept(Visitor visitor) => visitor.visitInterceptor(this); |
| 1063 | 1208 |
| 1064 bool get isSafeForElimination => true; | 1209 bool get isSafeForElimination => true; |
| 1065 bool get isSafeForReordering => true; | 1210 bool get isSafeForReordering => true; |
| 1211 |
| 1212 void setParentPointers() { |
| 1213 input.parent = this; |
| 1214 } |
| 1066 } | 1215 } |
| 1067 | 1216 |
| 1068 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. | 1217 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. |
| 1069 class CreateInvocationMirror extends Primitive { | 1218 class CreateInvocationMirror extends Primitive { |
| 1070 final Selector selector; | 1219 final Selector selector; |
| 1071 final List<Reference<Primitive>> arguments; | 1220 final List<Reference<Primitive>> arguments; |
| 1072 | 1221 |
| 1073 CreateInvocationMirror(this.selector, List<Primitive> arguments) | 1222 CreateInvocationMirror(this.selector, List<Primitive> arguments) |
| 1074 : this.arguments = _referenceList(arguments); | 1223 : this.arguments = _referenceList(arguments); |
| 1075 | 1224 |
| 1076 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); | 1225 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); |
| 1077 | 1226 |
| 1078 bool get isSafeForElimination => true; | 1227 bool get isSafeForElimination => true; |
| 1079 bool get isSafeForReordering => true; | 1228 bool get isSafeForReordering => true; |
| 1229 |
| 1230 void setParentPointers() { |
| 1231 _setParentsOnList(arguments, this); |
| 1232 } |
| 1080 } | 1233 } |
| 1081 | 1234 |
| 1082 class ForeignCode extends CallExpression { | 1235 class ForeignCode extends CallExpression { |
| 1083 final js.Template codeTemplate; | 1236 final js.Template codeTemplate; |
| 1084 final TypeMask type; | 1237 final TypeMask type; |
| 1085 final List<Reference<Primitive>> arguments; | 1238 final List<Reference<Primitive>> arguments; |
| 1086 final native.NativeBehavior nativeBehavior; | 1239 final native.NativeBehavior nativeBehavior; |
| 1087 final FunctionElement dependency; | 1240 final FunctionElement dependency; |
| 1088 final Reference<Continuation> continuation; | 1241 final Reference<Continuation> continuation; |
| 1089 | 1242 |
| 1090 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, | 1243 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, |
| 1091 this.nativeBehavior, Continuation continuation, {this.dependency}) | 1244 this.nativeBehavior, Continuation continuation, {this.dependency}) |
| 1092 : this.arguments = _referenceList(arguments), | 1245 : this.arguments = _referenceList(arguments), |
| 1093 this.continuation = new Reference<Continuation>(continuation); | 1246 this.continuation = new Reference<Continuation>(continuation); |
| 1094 | 1247 |
| 1095 accept(Visitor visitor) => visitor.visitForeignCode(this); | 1248 accept(Visitor visitor) => visitor.visitForeignCode(this); |
| 1249 |
| 1250 void setParentPointers() { |
| 1251 _setParentsOnList(arguments, this); |
| 1252 continuation.parent = this; |
| 1253 } |
| 1096 } | 1254 } |
| 1097 | 1255 |
| 1098 class Constant extends Primitive { | 1256 class Constant extends Primitive { |
| 1099 final values.ConstantValue value; | 1257 final values.ConstantValue value; |
| 1100 final SourceInformation sourceInformation; | 1258 final SourceInformation sourceInformation; |
| 1101 | 1259 |
| 1102 Constant(this.value, {this.sourceInformation}) { | 1260 Constant(this.value, {this.sourceInformation}) { |
| 1103 assert(value != null); | 1261 assert(value != null); |
| 1104 } | 1262 } |
| 1105 | 1263 |
| 1106 accept(Visitor visitor) => visitor.visitConstant(this); | 1264 accept(Visitor visitor) => visitor.visitConstant(this); |
| 1107 | 1265 |
| 1108 bool get isSafeForElimination => true; | 1266 bool get isSafeForElimination => true; |
| 1109 bool get isSafeForReordering => true; | 1267 bool get isSafeForReordering => true; |
| 1268 |
| 1269 void setParentPointers() {} |
| 1110 } | 1270 } |
| 1111 | 1271 |
| 1112 class LiteralList extends Primitive { | 1272 class LiteralList extends Primitive { |
| 1113 /// The List type being created; this is not the type argument. | 1273 /// The List type being created; this is not the type argument. |
| 1114 final InterfaceType dartType; | 1274 final InterfaceType dartType; |
| 1115 final List<Reference<Primitive>> values; | 1275 final List<Reference<Primitive>> values; |
| 1116 | 1276 |
| 1117 LiteralList(this.dartType, List<Primitive> values) | 1277 LiteralList(this.dartType, List<Primitive> values) |
| 1118 : this.values = _referenceList(values); | 1278 : this.values = _referenceList(values); |
| 1119 | 1279 |
| 1120 accept(Visitor visitor) => visitor.visitLiteralList(this); | 1280 accept(Visitor visitor) => visitor.visitLiteralList(this); |
| 1121 | 1281 |
| 1122 bool get isSafeForElimination => true; | 1282 bool get isSafeForElimination => true; |
| 1123 bool get isSafeForReordering => true; | 1283 bool get isSafeForReordering => true; |
| 1284 |
| 1285 void setParentPointers() { |
| 1286 _setParentsOnList(values, this); |
| 1287 } |
| 1124 } | 1288 } |
| 1125 | 1289 |
| 1126 class LiteralMapEntry { | 1290 class LiteralMapEntry { |
| 1127 final Reference<Primitive> key; | 1291 final Reference<Primitive> key; |
| 1128 final Reference<Primitive> value; | 1292 final Reference<Primitive> value; |
| 1129 | 1293 |
| 1130 LiteralMapEntry(Primitive key, Primitive value) | 1294 LiteralMapEntry(Primitive key, Primitive value) |
| 1131 : this.key = new Reference<Primitive>(key), | 1295 : this.key = new Reference<Primitive>(key), |
| 1132 this.value = new Reference<Primitive>(value); | 1296 this.value = new Reference<Primitive>(value); |
| 1133 } | 1297 } |
| 1134 | 1298 |
| 1135 class LiteralMap extends Primitive { | 1299 class LiteralMap extends Primitive { |
| 1136 final InterfaceType dartType; | 1300 final InterfaceType dartType; |
| 1137 final List<LiteralMapEntry> entries; | 1301 final List<LiteralMapEntry> entries; |
| 1138 | 1302 |
| 1139 LiteralMap(this.dartType, this.entries); | 1303 LiteralMap(this.dartType, this.entries); |
| 1140 | 1304 |
| 1141 accept(Visitor visitor) => visitor.visitLiteralMap(this); | 1305 accept(Visitor visitor) => visitor.visitLiteralMap(this); |
| 1142 | 1306 |
| 1143 bool get isSafeForElimination => true; | 1307 bool get isSafeForElimination => true; |
| 1144 bool get isSafeForReordering => true; | 1308 bool get isSafeForReordering => true; |
| 1309 |
| 1310 void setParentPointers() { |
| 1311 for (LiteralMapEntry entry in entries) { |
| 1312 entry.key.parent = this; |
| 1313 entry.value.parent = this; |
| 1314 } |
| 1315 } |
| 1145 } | 1316 } |
| 1146 | 1317 |
| 1147 /// Currently unused. | 1318 /// Currently unused. |
| 1148 /// | 1319 /// |
| 1149 /// Nested functions (from Dart code) are translated to classes by closure | 1320 /// Nested functions (from Dart code) are translated to classes by closure |
| 1150 /// conversion, hence they are instantiated with [CreateInstance]. | 1321 /// conversion, hence they are instantiated with [CreateInstance]. |
| 1151 /// | 1322 /// |
| 1152 /// We keep this around for now because it might come in handy when we | 1323 /// We keep this around for now because it might come in handy when we |
| 1153 /// handle async/await in the CPS IR. | 1324 /// handle async/await in the CPS IR. |
| 1154 /// | 1325 /// |
| 1155 /// Instantiates a nested function. [MutableVariable]s are in scope in the | 1326 /// Instantiates a nested function. [MutableVariable]s are in scope in the |
| 1156 /// inner function, but primitives are not shared across function boundaries. | 1327 /// inner function, but primitives are not shared across function boundaries. |
| 1157 class CreateFunction extends Primitive { | 1328 class CreateFunction extends Primitive { |
| 1158 final FunctionDefinition definition; | 1329 final FunctionDefinition definition; |
| 1159 | 1330 |
| 1160 CreateFunction(this.definition); | 1331 CreateFunction(this.definition); |
| 1161 | 1332 |
| 1162 accept(Visitor visitor) => visitor.visitCreateFunction(this); | 1333 accept(Visitor visitor) => visitor.visitCreateFunction(this); |
| 1163 | 1334 |
| 1164 bool get isSafeForElimination => true; | 1335 bool get isSafeForElimination => true; |
| 1165 bool get isSafeForReordering => true; | 1336 bool get isSafeForReordering => true; |
| 1337 |
| 1338 void setParentPointers() {} |
| 1166 } | 1339 } |
| 1167 | 1340 |
| 1168 class Parameter extends Primitive { | 1341 class Parameter extends Primitive { |
| 1169 Parameter(Entity hint) { | 1342 Parameter(Entity hint) { |
| 1170 super.hint = hint; | 1343 super.hint = hint; |
| 1171 } | 1344 } |
| 1172 | 1345 |
| 1173 // In addition to a parent pointer to the containing Continuation or | |
| 1174 // FunctionDefinition, parameters have an index into the list of parameters | |
| 1175 // bound by the parent. This gives constant-time access to the continuation | |
| 1176 // from the parent. | |
| 1177 int parentIndex; | |
| 1178 | |
| 1179 accept(Visitor visitor) => visitor.visitParameter(this); | 1346 accept(Visitor visitor) => visitor.visitParameter(this); |
| 1180 | 1347 |
| 1181 String toString() => 'Parameter(${hint == null ? null : hint.name})'; | 1348 String toString() => 'Parameter(${hint == null ? null : hint.name})'; |
| 1182 | 1349 |
| 1183 bool get isSafeForElimination => true; | 1350 bool get isSafeForElimination => true; |
| 1184 bool get isSafeForReordering => true; | 1351 bool get isSafeForReordering => true; |
| 1352 |
| 1353 void setParentPointers() {} |
| 1185 } | 1354 } |
| 1186 | 1355 |
| 1187 /// Continuations are normally bound by 'let cont'. A continuation with one | 1356 /// Continuations are normally bound by 'let cont'. A continuation with one |
| 1188 /// parameter and no body is used to represent a function's return continuation. | 1357 /// parameter and no body is used to represent a function's return continuation. |
| 1189 /// The return continuation is bound by the function, not by 'let cont'. | 1358 /// The return continuation is bound by the function, not by 'let cont'. |
| 1190 class Continuation extends Definition<Continuation> implements InteriorNode { | 1359 class Continuation extends Definition<Continuation> implements InteriorNode { |
| 1191 final List<Parameter> parameters; | 1360 final List<Parameter> parameters; |
| 1192 Expression body = null; | 1361 Expression body = null; |
| 1193 | 1362 |
| 1194 // In addition to a parent pointer to the containing LetCont, continuations | |
| 1195 // have an index into the list of continuations bound by the LetCont. This | |
| 1196 // gives constant-time access to the continuation from the parent. | |
| 1197 int parent_index; | |
| 1198 | |
| 1199 // A continuation is recursive if it has any recursive invocations. | 1363 // A continuation is recursive if it has any recursive invocations. |
| 1200 bool isRecursive; | 1364 bool isRecursive; |
| 1201 | 1365 |
| 1202 bool get isReturnContinuation => body == null; | 1366 bool get isReturnContinuation => body == null; |
| 1203 | 1367 |
| 1204 Continuation(this.parameters, {this.isRecursive: false}); | 1368 Continuation(this.parameters, {this.isRecursive: false}); |
| 1205 | 1369 |
| 1206 Continuation.retrn() | 1370 Continuation.retrn() |
| 1207 : parameters = <Parameter>[new Parameter(null)], | 1371 : parameters = <Parameter>[new Parameter(null)], |
| 1208 isRecursive = false; | 1372 isRecursive = false; |
| 1209 | 1373 |
| 1210 accept(Visitor visitor) => visitor.visitContinuation(this); | 1374 accept(Visitor visitor) => visitor.visitContinuation(this); |
| 1375 |
| 1376 void setParentPointers() { |
| 1377 _setParentsOnNodes(parameters, this); |
| 1378 if (body != null) body.parent = this; |
| 1379 } |
| 1211 } | 1380 } |
| 1212 | 1381 |
| 1213 /// Common interface for [Primitive] and [MutableVariable]. | 1382 /// Common interface for [Primitive] and [MutableVariable]. |
| 1214 abstract class Variable<T extends Variable<T>> extends Definition<T> { | 1383 abstract class Variable<T extends Variable<T>> extends Definition<T> { |
| 1215 /// Type of value held in the variable. | 1384 /// Type of value held in the variable. |
| 1216 /// | 1385 /// |
| 1217 /// Is `null` until initialized by type propagation. | 1386 /// Is `null` until initialized by type propagation. |
| 1218 TypeMask type; | 1387 TypeMask type; |
| 1219 } | 1388 } |
| 1220 | 1389 |
| 1221 /// Identifies a mutable variable. | 1390 /// Identifies a mutable variable. |
| 1222 class MutableVariable extends Variable<MutableVariable> { | 1391 class MutableVariable extends Variable<MutableVariable> { |
| 1223 Entity hint; | 1392 Entity hint; |
| 1224 | 1393 |
| 1225 MutableVariable(this.hint); | 1394 MutableVariable(this.hint); |
| 1226 | 1395 |
| 1227 accept(Visitor v) => v.visitMutableVariable(this); | 1396 accept(Visitor v) => v.visitMutableVariable(this); |
| 1397 |
| 1398 void setParentPointers() {} |
| 1228 } | 1399 } |
| 1229 | 1400 |
| 1230 /// A function definition, consisting of parameters and a body. | 1401 /// A function definition, consisting of parameters and a body. |
| 1231 /// | 1402 /// |
| 1232 /// There is an explicit parameter for the `this` argument, and a return | 1403 /// There is an explicit parameter for the `this` argument, and a return |
| 1233 /// continuation to invoke when returning from the function. | 1404 /// continuation to invoke when returning from the function. |
| 1234 class FunctionDefinition extends InteriorNode { | 1405 class FunctionDefinition extends InteriorNode { |
| 1235 final ExecutableElement element; | 1406 final ExecutableElement element; |
| 1236 final Parameter thisParameter; | 1407 final Parameter thisParameter; |
| 1237 final List<Parameter> parameters; | 1408 final List<Parameter> parameters; |
| 1238 final Continuation returnContinuation; | 1409 final Continuation returnContinuation; |
| 1239 Expression body; | 1410 Expression body; |
| 1240 | 1411 |
| 1241 FunctionDefinition(this.element, | 1412 FunctionDefinition(this.element, |
| 1242 this.thisParameter, | 1413 this.thisParameter, |
| 1243 this.parameters, | 1414 this.parameters, |
| 1244 this.returnContinuation, | 1415 this.returnContinuation, |
| 1245 this.body); | 1416 this.body); |
| 1246 | 1417 |
| 1247 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); | 1418 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); |
| 1419 |
| 1420 void setParentPointers() { |
| 1421 if (thisParameter != null) thisParameter.parent = this; |
| 1422 _setParentsOnNodes(parameters, this); |
| 1423 returnContinuation.parent = this; |
| 1424 if (body != null) body.parent = this; |
| 1425 } |
| 1248 } | 1426 } |
| 1249 | 1427 |
| 1250 /// Converts the internal representation of a type to a Dart object of type | 1428 /// Converts the internal representation of a type to a Dart object of type |
| 1251 /// [Type]. | 1429 /// [Type]. |
| 1252 class ReifyRuntimeType extends Primitive { | 1430 class ReifyRuntimeType extends Primitive { |
| 1253 /// Reference to the internal representation of a type (as produced, for | 1431 /// Reference to the internal representation of a type (as produced, for |
| 1254 /// example, by [ReadTypeVariable]). | 1432 /// example, by [ReadTypeVariable]). |
| 1255 final Reference<Primitive> value; | 1433 final Reference<Primitive> value; |
| 1256 | 1434 |
| 1257 final SourceInformation sourceInformation; | 1435 final SourceInformation sourceInformation; |
| 1258 | 1436 |
| 1259 ReifyRuntimeType(Primitive value, this.sourceInformation) | 1437 ReifyRuntimeType(Primitive value, this.sourceInformation) |
| 1260 : this.value = new Reference<Primitive>(value); | 1438 : this.value = new Reference<Primitive>(value); |
| 1261 | 1439 |
| 1262 @override | 1440 @override |
| 1263 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); | 1441 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); |
| 1264 | 1442 |
| 1265 bool get isSafeForElimination => true; | 1443 bool get isSafeForElimination => true; |
| 1266 bool get isSafeForReordering => true; | 1444 bool get isSafeForReordering => true; |
| 1445 |
| 1446 void setParentPointers() { |
| 1447 value.parent = this; |
| 1448 } |
| 1267 } | 1449 } |
| 1268 | 1450 |
| 1269 /// Read the value the type variable [variable] from the target object. | 1451 /// Read the value the type variable [variable] from the target object. |
| 1270 /// | 1452 /// |
| 1271 /// The resulting value is an internal representation (and not neccessarily a | 1453 /// The resulting value is an internal representation (and not neccessarily a |
| 1272 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be | 1454 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be |
| 1273 /// used as a Dart value. | 1455 /// used as a Dart value. |
| 1274 class ReadTypeVariable extends Primitive { | 1456 class ReadTypeVariable extends Primitive { |
| 1275 final TypeVariableType variable; | 1457 final TypeVariableType variable; |
| 1276 final Reference<Primitive> target; | 1458 final Reference<Primitive> target; |
| 1277 final SourceInformation sourceInformation; | 1459 final SourceInformation sourceInformation; |
| 1278 | 1460 |
| 1279 ReadTypeVariable(this.variable, Primitive target, this.sourceInformation) | 1461 ReadTypeVariable(this.variable, Primitive target, this.sourceInformation) |
| 1280 : this.target = new Reference<Primitive>(target); | 1462 : this.target = new Reference<Primitive>(target); |
| 1281 | 1463 |
| 1282 @override | 1464 @override |
| 1283 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); | 1465 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); |
| 1284 | 1466 |
| 1285 bool get isSafeForElimination => true; | 1467 bool get isSafeForElimination => true; |
| 1286 bool get isSafeForReordering => true; | 1468 bool get isSafeForReordering => true; |
| 1469 |
| 1470 void setParentPointers() { |
| 1471 target.parent = this; |
| 1472 } |
| 1287 } | 1473 } |
| 1288 | 1474 |
| 1289 /// Representation of a closed type (that is, a type without type variables). | 1475 /// Representation of a closed type (that is, a type without type variables). |
| 1290 /// | 1476 /// |
| 1291 /// The resulting value is constructed from [dartType] by replacing the type | 1477 /// The resulting value is constructed from [dartType] by replacing the type |
| 1292 /// variables with consecutive values from [arguments], in the order generated | 1478 /// variables with consecutive values from [arguments], in the order generated |
| 1293 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are | 1479 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are |
| 1294 /// treated as 'holes' in the term, which means that it must be ensured at | 1480 /// treated as 'holes' in the term, which means that it must be ensured at |
| 1295 /// construction, that duplicate occurences of a type variable in [dartType] | 1481 /// construction, that duplicate occurences of a type variable in [dartType] |
| 1296 /// are assigned the same value. | 1482 /// are assigned the same value. |
| 1297 class TypeExpression extends Primitive { | 1483 class TypeExpression extends Primitive { |
| 1298 final DartType dartType; | 1484 final DartType dartType; |
| 1299 final List<Reference<Primitive>> arguments; | 1485 final List<Reference<Primitive>> arguments; |
| 1300 | 1486 |
| 1301 TypeExpression(this.dartType, | 1487 TypeExpression(this.dartType, |
| 1302 [List<Primitive> arguments = const <Primitive>[]]) | 1488 [List<Primitive> arguments = const <Primitive>[]]) |
| 1303 : this.arguments = _referenceList(arguments); | 1489 : this.arguments = _referenceList(arguments); |
| 1304 | 1490 |
| 1305 @override | 1491 @override |
| 1306 accept(Visitor visitor) { | 1492 accept(Visitor visitor) { |
| 1307 return visitor.visitTypeExpression(this); | 1493 return visitor.visitTypeExpression(this); |
| 1308 } | 1494 } |
| 1309 | 1495 |
| 1310 bool get isSafeForElimination => true; | 1496 bool get isSafeForElimination => true; |
| 1311 bool get isSafeForReordering => true; | 1497 bool get isSafeForReordering => true; |
| 1498 |
| 1499 void setParentPointers() { |
| 1500 _setParentsOnList(arguments, this); |
| 1501 } |
| 1312 } | 1502 } |
| 1313 | 1503 |
| 1314 class Await extends CallExpression { | 1504 class Await extends CallExpression { |
| 1315 final Reference<Primitive> input; | 1505 final Reference<Primitive> input; |
| 1316 final Reference<Continuation> continuation; | 1506 final Reference<Continuation> continuation; |
| 1317 | 1507 |
| 1318 Await(Primitive input, Continuation continuation) | 1508 Await(Primitive input, Continuation continuation) |
| 1319 : this.input = new Reference<Primitive>(input), | 1509 : this.input = new Reference<Primitive>(input), |
| 1320 this.continuation = new Reference<Continuation>(continuation); | 1510 this.continuation = new Reference<Continuation>(continuation); |
| 1321 | 1511 |
| 1322 @override | 1512 @override |
| 1323 accept(Visitor visitor) { | 1513 accept(Visitor visitor) { |
| 1324 return visitor.visitAwait(this); | 1514 return visitor.visitAwait(this); |
| 1325 } | 1515 } |
| 1516 |
| 1517 void setParentPointers() { |
| 1518 input.parent = this; |
| 1519 continuation.parent = this; |
| 1520 } |
| 1326 } | 1521 } |
| 1327 | 1522 |
| 1328 class Yield extends CallExpression { | 1523 class Yield extends CallExpression { |
| 1329 final Reference<Primitive> input; | 1524 final Reference<Primitive> input; |
| 1330 final Reference<Continuation> continuation; | 1525 final Reference<Continuation> continuation; |
| 1331 final bool hasStar; | 1526 final bool hasStar; |
| 1332 | 1527 |
| 1333 Yield(Primitive input, this.hasStar, Continuation continuation) | 1528 Yield(Primitive input, this.hasStar, Continuation continuation) |
| 1334 : this.input = new Reference<Primitive>(input), | 1529 : this.input = new Reference<Primitive>(input), |
| 1335 this.continuation = new Reference<Continuation>(continuation); | 1530 this.continuation = new Reference<Continuation>(continuation); |
| 1336 | 1531 |
| 1337 @override | 1532 @override |
| 1338 accept(Visitor visitor) { | 1533 accept(Visitor visitor) { |
| 1339 return visitor.visitYield(this); | 1534 return visitor.visitYield(this); |
| 1340 } | 1535 } |
| 1536 |
| 1537 void setParentPointers() { |
| 1538 input.parent = this; |
| 1539 continuation.parent = this; |
| 1540 } |
| 1341 } | 1541 } |
| 1342 | 1542 |
| 1343 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { | 1543 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |
| 1344 return definitions.map((e) => new Reference<Primitive>(e)).toList(); | 1544 return definitions.map((e) => new Reference<Primitive>(e)).toList(); |
| 1345 } | 1545 } |
| 1346 | 1546 |
| 1547 void _setParentsOnNodes(List<Node> nodes, Node parent) { |
| 1548 for (Node node in nodes) { |
| 1549 node.parent = parent; |
| 1550 } |
| 1551 } |
| 1552 |
| 1553 void _setParentsOnList(List<Reference> nodes, Node parent) { |
| 1554 for (Reference node in nodes) { |
| 1555 node.parent = parent; |
| 1556 } |
| 1557 } |
| 1558 |
| 1347 abstract class Visitor<T> { | 1559 abstract class Visitor<T> { |
| 1348 const Visitor(); | 1560 const Visitor(); |
| 1349 | 1561 |
| 1350 T visit(Node node); | 1562 T visit(Node node); |
| 1351 | 1563 |
| 1352 // Concrete classes. | 1564 // Concrete classes. |
| 1353 T visitFunctionDefinition(FunctionDefinition node); | 1565 T visitFunctionDefinition(FunctionDefinition node); |
| 1354 | 1566 |
| 1355 // Expressions. | 1567 // Expressions. |
| 1356 T visitLetPrim(LetPrim node); | 1568 T visitLetPrim(LetPrim node); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1398 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); | 1610 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); |
| 1399 T visitGetLength(GetLength node); | 1611 T visitGetLength(GetLength node); |
| 1400 T visitGetIndex(GetIndex node); | 1612 T visitGetIndex(GetIndex node); |
| 1401 T visitSetIndex(SetIndex node); | 1613 T visitSetIndex(SetIndex node); |
| 1402 T visitRefinement(Refinement node); | 1614 T visitRefinement(Refinement node); |
| 1403 | 1615 |
| 1404 // Support for literal foreign code. | 1616 // Support for literal foreign code. |
| 1405 T visitForeignCode(ForeignCode node); | 1617 T visitForeignCode(ForeignCode node); |
| 1406 } | 1618 } |
| 1407 | 1619 |
| 1408 /// Visits all non-recursive children of a CPS term, i.e. anything | 1620 /// Recursively visits all children of a CPS term. |
| 1409 /// not of type [Expression] or [Continuation]. | 1621 /// |
| 1622 /// The user of the class is responsible for avoiding stack overflows from |
| 1623 /// deep recursion, e.g. by overriding methods to cut off recursion at certain |
| 1624 /// points. |
| 1625 /// |
| 1626 /// All recursive invocations occur through the [visit] method, which the |
| 1627 /// subclass may override as a generic way to control the visitor without |
| 1628 /// overriding all visitor methods. |
| 1410 /// | 1629 /// |
| 1411 /// The `process*` methods are called in pre-order for every node visited. | 1630 /// The `process*` methods are called in pre-order for every node visited. |
| 1412 /// These can be overridden without disrupting the visitor traversal. | 1631 /// These can be overridden without disrupting the visitor traversal. |
| 1413 class LeafVisitor implements Visitor { | 1632 class DeepRecursiveVisitor implements Visitor { |
| 1414 const LeafVisitor(); | 1633 const DeepRecursiveVisitor(); |
| 1415 | 1634 |
| 1416 visit(Node node) => node.accept(this); | 1635 visit(Node node) => node.accept(this); |
| 1417 | 1636 |
| 1418 processReference(Reference ref) {} | 1637 processReference(Reference ref) {} |
| 1419 | 1638 |
| 1420 processFunctionDefinition(FunctionDefinition node) {} | 1639 processFunctionDefinition(FunctionDefinition node) {} |
| 1421 visitFunctionDefinition(FunctionDefinition node) { | 1640 visitFunctionDefinition(FunctionDefinition node) { |
| 1422 processFunctionDefinition(node); | 1641 processFunctionDefinition(node); |
| 1423 if (node.thisParameter != null) visit(node.thisParameter); | 1642 if (node.thisParameter != null) visit(node.thisParameter); |
| 1424 node.parameters.forEach(visit); | 1643 node.parameters.forEach(visit); |
| 1425 visit(node.returnContinuation); | 1644 visit(node.returnContinuation); |
| 1645 visit(node.body); |
| 1646 } |
| 1647 |
| 1648 processContinuation(Continuation node) {} |
| 1649 visitContinuation(Continuation node) { |
| 1650 processContinuation(node); |
| 1651 node.parameters.forEach(visit); |
| 1652 if (node.body != null) visit(node.body); |
| 1426 } | 1653 } |
| 1427 | 1654 |
| 1428 // Expressions. | 1655 // Expressions. |
| 1429 | |
| 1430 processLetPrim(LetPrim node) {} | 1656 processLetPrim(LetPrim node) {} |
| 1431 visitLetPrim(LetPrim node) { | 1657 visitLetPrim(LetPrim node) { |
| 1432 processLetPrim(node); | 1658 processLetPrim(node); |
| 1433 visit(node.primitive); | 1659 visit(node.primitive); |
| 1660 visit(node.body); |
| 1434 } | 1661 } |
| 1435 | 1662 |
| 1436 processLetCont(LetCont node) {} | 1663 processLetCont(LetCont node) {} |
| 1437 visitLetCont(LetCont node) { | 1664 visitLetCont(LetCont node) { |
| 1438 processLetCont(node); | 1665 processLetCont(node); |
| 1439 node.continuations.forEach(visit); | 1666 node.continuations.forEach(visit); |
| 1667 visit(node.body); |
| 1440 } | 1668 } |
| 1441 | 1669 |
| 1442 processLetHandler(LetHandler node) {} | 1670 processLetHandler(LetHandler node) {} |
| 1443 visitLetHandler(LetHandler node) { | 1671 visitLetHandler(LetHandler node) { |
| 1444 processLetHandler(node); | 1672 processLetHandler(node); |
| 1673 visit(node.handler); |
| 1674 visit(node.body); |
| 1445 } | 1675 } |
| 1446 | 1676 |
| 1447 processLetMutable(LetMutable node) {} | 1677 processLetMutable(LetMutable node) {} |
| 1448 visitLetMutable(LetMutable node) { | 1678 visitLetMutable(LetMutable node) { |
| 1449 processLetMutable(node); | 1679 processLetMutable(node); |
| 1450 visit(node.variable); | 1680 visit(node.variable); |
| 1451 processReference(node.value); | 1681 processReference(node.value); |
| 1682 visit(node.body); |
| 1452 } | 1683 } |
| 1453 | 1684 |
| 1454 processInvokeStatic(InvokeStatic node) {} | 1685 processInvokeStatic(InvokeStatic node) {} |
| 1455 visitInvokeStatic(InvokeStatic node) { | 1686 visitInvokeStatic(InvokeStatic node) { |
| 1456 processInvokeStatic(node); | 1687 processInvokeStatic(node); |
| 1457 processReference(node.continuation); | 1688 processReference(node.continuation); |
| 1458 node.arguments.forEach(processReference); | 1689 node.arguments.forEach(processReference); |
| 1459 } | 1690 } |
| 1460 | 1691 |
| 1461 processInvokeContinuation(InvokeContinuation node) {} | 1692 processInvokeContinuation(InvokeContinuation node) {} |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1577 visitGetMutable(GetMutable node) { | 1808 visitGetMutable(GetMutable node) { |
| 1578 processGetMutable(node); | 1809 processGetMutable(node); |
| 1579 processReference(node.variable); | 1810 processReference(node.variable); |
| 1580 } | 1811 } |
| 1581 | 1812 |
| 1582 processParameter(Parameter node) {} | 1813 processParameter(Parameter node) {} |
| 1583 visitParameter(Parameter node) { | 1814 visitParameter(Parameter node) { |
| 1584 processParameter(node); | 1815 processParameter(node); |
| 1585 } | 1816 } |
| 1586 | 1817 |
| 1587 processContinuation(Continuation node) {} | |
| 1588 visitContinuation(Continuation node) { | |
| 1589 processContinuation(node); | |
| 1590 node.parameters.forEach(visitParameter); | |
| 1591 } | |
| 1592 | |
| 1593 processInterceptor(Interceptor node) {} | 1818 processInterceptor(Interceptor node) {} |
| 1594 visitInterceptor(Interceptor node) { | 1819 visitInterceptor(Interceptor node) { |
| 1595 processInterceptor(node); | 1820 processInterceptor(node); |
| 1596 processReference(node.input); | 1821 processReference(node.input); |
| 1597 } | 1822 } |
| 1598 | 1823 |
| 1599 processCreateInstance(CreateInstance node) {} | 1824 processCreateInstance(CreateInstance node) {} |
| 1600 visitCreateInstance(CreateInstance node) { | 1825 visitCreateInstance(CreateInstance node) { |
| 1601 processCreateInstance(node); | 1826 processCreateInstance(node); |
| 1602 node.arguments.forEach(processReference); | 1827 node.arguments.forEach(processReference); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1743 /// The `traverse*` methods return the expression to visit next, and may | 1968 /// The `traverse*` methods return the expression to visit next, and may |
| 1744 /// push other subterms onto the stack using [push] or [pushAction] to visit | 1969 /// push other subterms onto the stack using [push] or [pushAction] to visit |
| 1745 /// them later. Actions pushed onto the stack will be executed after the body | 1970 /// them later. Actions pushed onto the stack will be executed after the body |
| 1746 /// has been processed (and the stack actions it pushed have been executed). | 1971 /// has been processed (and the stack actions it pushed have been executed). |
| 1747 /// | 1972 /// |
| 1748 /// By default, the `traverse` methods visit all non-recursive subterms, | 1973 /// By default, the `traverse` methods visit all non-recursive subterms, |
| 1749 /// push all bound continuations on the stack, and return the body of the term. | 1974 /// push all bound continuations on the stack, and return the body of the term. |
| 1750 /// | 1975 /// |
| 1751 /// Subclasses should not override the `visit` methods for the nodes that have | 1976 /// Subclasses should not override the `visit` methods for the nodes that have |
| 1752 /// a `traverse` method. | 1977 /// a `traverse` method. |
| 1753 class RecursiveVisitor extends LeafVisitor { | 1978 class TrampolineRecursiveVisitor extends DeepRecursiveVisitor { |
| 1754 List<StackAction> _stack = <StackAction>[]; | 1979 List<StackAction> _stack = <StackAction>[]; |
| 1755 | 1980 |
| 1756 void pushAction(StackAction callback) { | 1981 void pushAction(StackAction callback) { |
| 1757 _stack.add(callback); | 1982 _stack.add(callback); |
| 1758 } | 1983 } |
| 1759 | 1984 |
| 1760 void push(Continuation cont) { | 1985 void push(Continuation cont) { |
| 1761 _stack.add(() { | 1986 _stack.add(() { |
| 1762 if (cont.isReturnContinuation) { | 1987 if (cont.isReturnContinuation) { |
| 1763 traverseContinuation(cont); | 1988 traverseContinuation(cont); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1838 node = traverseLetPrim(node); | 2063 node = traverseLetPrim(node); |
| 1839 } else { | 2064 } else { |
| 1840 node = traverseLetMutable(node); | 2065 node = traverseLetMutable(node); |
| 1841 } | 2066 } |
| 1842 } | 2067 } |
| 1843 visit(node); | 2068 visit(node); |
| 1844 } | 2069 } |
| 1845 } | 2070 } |
| 1846 | 2071 |
| 1847 /// Visit a just-deleted subterm and unlink all [Reference]s in it. | 2072 /// Visit a just-deleted subterm and unlink all [Reference]s in it. |
| 1848 class RemovalVisitor extends RecursiveVisitor { | 2073 class RemovalVisitor extends TrampolineRecursiveVisitor { |
| 1849 processReference(Reference reference) { | 2074 processReference(Reference reference) { |
| 1850 reference.unlink(); | 2075 reference.unlink(); |
| 1851 } | 2076 } |
| 1852 | 2077 |
| 1853 static void remove(Node node) { | 2078 static void remove(Node node) { |
| 1854 (new RemovalVisitor()).visit(node); | 2079 (new RemovalVisitor()).visit(node); |
| 1855 } | 2080 } |
| 1856 } | 2081 } |
| OLD | NEW |