| 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 16 matching lines...) Expand all Loading... |
| 605 TypeTest(Primitive value, | 660 TypeTest(Primitive value, |
| 606 this.dartType, | 661 this.dartType, |
| 607 List<Primitive> typeArguments) | 662 List<Primitive> typeArguments) |
| 608 : this.value = new Reference<Primitive>(value), | 663 : this.value = new Reference<Primitive>(value), |
| 609 this.typeArguments = _referenceList(typeArguments); | 664 this.typeArguments = _referenceList(typeArguments); |
| 610 | 665 |
| 611 accept(Visitor visitor) => visitor.visitTypeTest(this); | 666 accept(Visitor visitor) => visitor.visitTypeTest(this); |
| 612 | 667 |
| 613 bool get isSafeForElimination => true; | 668 bool get isSafeForElimination => true; |
| 614 bool get isSafeForReordering => true; | 669 bool get isSafeForReordering => true; |
| 670 |
| 671 void setParentPointers() { |
| 672 value.parent = this; |
| 673 _setParentsOnList(typeArguments, this); |
| 674 } |
| 615 } | 675 } |
| 616 | 676 |
| 617 /// An "as" type cast. | 677 /// An "as" type cast. |
| 618 /// | 678 /// |
| 619 /// If [value] is `null` or is an instance of [type], [continuation] is invoked | 679 /// If [value] is `null` or is an instance of [type], [continuation] is invoked |
| 620 /// with [value] as argument. Otherwise, a [CastError] is thrown. | 680 /// with [value] as argument. Otherwise, a [CastError] is thrown. |
| 621 /// | 681 /// |
| 622 /// Discussion: | 682 /// Discussion: |
| 623 /// The parameter to [continuation] is redundant since it will always equal | 683 /// The parameter to [continuation] is redundant since it will always equal |
| 624 /// [value], which is typically in scope in the continuation. However, it might | 684 /// [value], which is typically in scope in the continuation. However, it might |
| 625 /// simplify type propagation, since a better type can be computed for the | 685 /// simplify type propagation, since a better type can be computed for the |
| 626 /// continuation parameter without needing flow-sensitive analysis. | 686 /// continuation parameter without needing flow-sensitive analysis. |
| 627 class TypeCast extends CallExpression { | 687 class TypeCast extends CallExpression { |
| 628 Reference<Primitive> value; | 688 Reference<Primitive> value; |
| 629 final DartType dartType; | 689 final DartType dartType; |
| 630 | 690 |
| 631 /// See the corresponding field on [TypeTest]. | 691 /// See the corresponding field on [TypeTest]. |
| 632 final List<Reference<Primitive>> typeArguments; | 692 final List<Reference<Primitive>> typeArguments; |
| 633 final Reference<Continuation> continuation; | 693 final Reference<Continuation> continuation; |
| 634 | 694 |
| 635 TypeCast(Primitive value, | 695 TypeCast(Primitive value, |
| 636 this.dartType, | 696 this.dartType, |
| 637 List<Primitive> typeArguments, | 697 List<Primitive> typeArguments, |
| 638 Continuation cont) | 698 Continuation cont) |
| 639 : this.value = new Reference<Primitive>(value), | 699 : this.value = new Reference<Primitive>(value), |
| 640 this.typeArguments = _referenceList(typeArguments), | 700 this.typeArguments = _referenceList(typeArguments), |
| 641 this.continuation = new Reference<Continuation>(cont); | 701 this.continuation = new Reference<Continuation>(cont); |
| 642 | 702 |
| 643 accept(Visitor visitor) => visitor.visitTypeCast(this); | 703 accept(Visitor visitor) => visitor.visitTypeCast(this); |
| 704 |
| 705 void setParentPointers() { |
| 706 value.parent = this; |
| 707 } |
| 644 } | 708 } |
| 645 | 709 |
| 646 /// Apply a built-in operator. | 710 /// Apply a built-in operator. |
| 647 /// | 711 /// |
| 648 /// It must be known that the arguments have the proper types. | 712 /// It must be known that the arguments have the proper types. |
| 649 class ApplyBuiltinOperator extends Primitive { | 713 class ApplyBuiltinOperator extends Primitive { |
| 650 BuiltinOperator operator; | 714 BuiltinOperator operator; |
| 651 List<Reference<Primitive>> arguments; | 715 List<Reference<Primitive>> arguments; |
| 652 final SourceInformation sourceInformation; | 716 final SourceInformation sourceInformation; |
| 653 | 717 |
| 654 ApplyBuiltinOperator(this.operator, | 718 ApplyBuiltinOperator(this.operator, |
| 655 List<Primitive> arguments, | 719 List<Primitive> arguments, |
| 656 this.sourceInformation) | 720 this.sourceInformation) |
| 657 : this.arguments = _referenceList(arguments); | 721 : this.arguments = _referenceList(arguments); |
| 658 | 722 |
| 659 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); | 723 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); |
| 660 | 724 |
| 661 bool get isSafeForElimination => true; | 725 bool get isSafeForElimination => true; |
| 662 bool get isSafeForReordering => true; | 726 bool get isSafeForReordering => true; |
| 727 |
| 728 void setParentPointers() { |
| 729 _setParentsOnList(arguments, this); |
| 730 } |
| 663 } | 731 } |
| 664 | 732 |
| 665 /// Apply a built-in method. | 733 /// Apply a built-in method. |
| 666 /// | 734 /// |
| 667 /// It must be known that the arguments have the proper types. | 735 /// It must be known that the arguments have the proper types. |
| 668 class ApplyBuiltinMethod extends Primitive { | 736 class ApplyBuiltinMethod extends Primitive { |
| 669 BuiltinMethod method; | 737 BuiltinMethod method; |
| 670 Reference<Primitive> receiver; | 738 Reference<Primitive> receiver; |
| 671 List<Reference<Primitive>> arguments; | 739 List<Reference<Primitive>> arguments; |
| 672 final SourceInformation sourceInformation; | 740 final SourceInformation sourceInformation; |
| 673 | 741 |
| 674 bool receiverIsNotNull; | 742 bool receiverIsNotNull; |
| 675 | 743 |
| 676 ApplyBuiltinMethod(this.method, | 744 ApplyBuiltinMethod(this.method, |
| 677 Primitive receiver, | 745 Primitive receiver, |
| 678 List<Primitive> arguments, | 746 List<Primitive> arguments, |
| 679 this.sourceInformation, | 747 this.sourceInformation, |
| 680 {this.receiverIsNotNull: false}) | 748 {this.receiverIsNotNull: false}) |
| 681 : this.receiver = new Reference<Primitive>(receiver), | 749 : this.receiver = new Reference<Primitive>(receiver), |
| 682 this.arguments = _referenceList(arguments); | 750 this.arguments = _referenceList(arguments); |
| 683 | 751 |
| 684 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); | 752 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); |
| 685 | 753 |
| 686 bool get isSafeForElimination => false; | 754 bool get isSafeForElimination => false; |
| 687 bool get isSafeForReordering => false; | 755 bool get isSafeForReordering => false; |
| 756 |
| 757 void setParentPointers() { |
| 758 receiver.parent = this; |
| 759 _setParentsOnList(arguments, this); |
| 760 } |
| 688 } | 761 } |
| 689 | 762 |
| 690 /// Throw a value. | 763 /// Throw a value. |
| 691 /// | 764 /// |
| 692 /// Throw is an expression, i.e., it always occurs in tail position with | 765 /// Throw is an expression, i.e., it always occurs in tail position with |
| 693 /// respect to a body or expression. | 766 /// respect to a body or expression. |
| 694 class Throw extends TailExpression { | 767 class Throw extends TailExpression { |
| 695 Reference<Primitive> value; | 768 Reference<Primitive> value; |
| 696 | 769 |
| 697 Throw(Primitive value) : value = new Reference<Primitive>(value); | 770 Throw(Primitive value) : value = new Reference<Primitive>(value); |
| 698 | 771 |
| 699 accept(Visitor visitor) => visitor.visitThrow(this); | 772 accept(Visitor visitor) => visitor.visitThrow(this); |
| 773 |
| 774 void setParentPointers() { |
| 775 value.parent = this; |
| 776 } |
| 700 } | 777 } |
| 701 | 778 |
| 702 /// Rethrow | 779 /// Rethrow |
| 703 /// | 780 /// |
| 704 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It | 781 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It |
| 705 /// implicitly throws the exception parameter of the enclosing handler with | 782 /// implicitly throws the exception parameter of the enclosing handler with |
| 706 /// the same stack trace as the enclosing handler. | 783 /// the same stack trace as the enclosing handler. |
| 707 class Rethrow extends TailExpression { | 784 class Rethrow extends TailExpression { |
| 708 accept(Visitor visitor) => visitor.visitRethrow(this); | 785 accept(Visitor visitor) => visitor.visitRethrow(this); |
| 786 void setParentPointers() {} |
| 709 } | 787 } |
| 710 | 788 |
| 711 /// An expression that is known to be unreachable. | 789 /// An expression that is known to be unreachable. |
| 712 /// | 790 /// |
| 713 /// This can be placed as the body of a call continuation, when the caller is | 791 /// This can be placed as the body of a call continuation, when the caller is |
| 714 /// known never to invoke it, e.g. because the calling expression always throws. | 792 /// known never to invoke it, e.g. because the calling expression always throws. |
| 715 class Unreachable extends TailExpression { | 793 class Unreachable extends TailExpression { |
| 716 accept(Visitor visitor) => visitor.visitUnreachable(this); | 794 accept(Visitor visitor) => visitor.visitUnreachable(this); |
| 795 void setParentPointers() {} |
| 717 } | 796 } |
| 718 | 797 |
| 719 /// Gets the value from a [MutableVariable]. | 798 /// Gets the value from a [MutableVariable]. |
| 720 /// | 799 /// |
| 721 /// [MutableVariable]s can be seen as ref cells that are not first-class | 800 /// [MutableVariable]s can be seen as ref cells that are not first-class |
| 722 /// values. A [LetPrim] with a [GetMutable] can then be seen as: | 801 /// values. A [LetPrim] with a [GetMutable] can then be seen as: |
| 723 /// | 802 /// |
| 724 /// let prim p = ![variable] in [body] | 803 /// let prim p = ![variable] in [body] |
| 725 /// | 804 /// |
| 726 class GetMutable extends Primitive { | 805 class GetMutable extends Primitive { |
| 727 final Reference<MutableVariable> variable; | 806 final Reference<MutableVariable> variable; |
| 728 | 807 |
| 729 GetMutable(MutableVariable variable) | 808 GetMutable(MutableVariable variable) |
| 730 : this.variable = new Reference<MutableVariable>(variable); | 809 : this.variable = new Reference<MutableVariable>(variable); |
| 731 | 810 |
| 732 accept(Visitor visitor) => visitor.visitGetMutable(this); | 811 accept(Visitor visitor) => visitor.visitGetMutable(this); |
| 733 | 812 |
| 734 bool get isSafeForElimination => true; | 813 bool get isSafeForElimination => true; |
| 735 bool get isSafeForReordering => false; | 814 bool get isSafeForReordering => false; |
| 815 |
| 816 void setParentPointers() { |
| 817 variable.parent = this; |
| 818 } |
| 736 } | 819 } |
| 737 | 820 |
| 738 /// Assign a [MutableVariable]. | 821 /// Assign a [MutableVariable]. |
| 739 /// | 822 /// |
| 740 /// [MutableVariable]s can be seen as ref cells that are not first-class | 823 /// [MutableVariable]s can be seen as ref cells that are not first-class |
| 741 /// values. This can be seen as a dereferencing assignment: | 824 /// values. This can be seen as a dereferencing assignment: |
| 742 /// | 825 /// |
| 743 /// { [variable] := [value]; [body] } | 826 /// { [variable] := [value]; [body] } |
| 744 class SetMutable extends Primitive { | 827 class SetMutable extends Primitive { |
| 745 final Reference<MutableVariable> variable; | 828 final Reference<MutableVariable> variable; |
| 746 final Reference<Primitive> value; | 829 final Reference<Primitive> value; |
| 747 | 830 |
| 748 SetMutable(MutableVariable variable, Primitive value) | 831 SetMutable(MutableVariable variable, Primitive value) |
| 749 : this.variable = new Reference<MutableVariable>(variable), | 832 : this.variable = new Reference<MutableVariable>(variable), |
| 750 this.value = new Reference<Primitive>(value); | 833 this.value = new Reference<Primitive>(value); |
| 751 | 834 |
| 752 accept(Visitor visitor) => visitor.visitSetMutable(this); | 835 accept(Visitor visitor) => visitor.visitSetMutable(this); |
| 753 | 836 |
| 754 bool get isSafeForElimination => false; | 837 bool get isSafeForElimination => false; |
| 755 bool get isSafeForReordering => false; | 838 bool get isSafeForReordering => false; |
| 839 |
| 840 void setParentPointers() { |
| 841 variable.parent = this; |
| 842 value.parent = this; |
| 843 } |
| 756 } | 844 } |
| 757 | 845 |
| 758 /// Invoke a continuation in tail position. | 846 /// Invoke a continuation in tail position. |
| 759 class InvokeContinuation extends TailExpression { | 847 class InvokeContinuation extends TailExpression { |
| 760 Reference<Continuation> continuation; | 848 Reference<Continuation> continuation; |
| 761 List<Reference<Primitive>> arguments; | 849 List<Reference<Primitive>> arguments; |
| 762 SourceInformation sourceInformation; | 850 SourceInformation sourceInformation; |
| 763 | 851 |
| 764 // An invocation of a continuation is recursive if it occurs in the body of | 852 // An invocation of a continuation is recursive if it occurs in the body of |
| 765 // the continuation itself. | 853 // the continuation itself. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 784 /// | 872 /// |
| 785 /// Used as a placeholder for a jump whose target is not yet created | 873 /// Used as a placeholder for a jump whose target is not yet created |
| 786 /// (e.g., in the translation of break and continue). | 874 /// (e.g., in the translation of break and continue). |
| 787 InvokeContinuation.uninitialized({this.isRecursive: false, | 875 InvokeContinuation.uninitialized({this.isRecursive: false, |
| 788 this.isEscapingTry: false}) | 876 this.isEscapingTry: false}) |
| 789 : continuation = null, | 877 : continuation = null, |
| 790 arguments = null, | 878 arguments = null, |
| 791 sourceInformation = null; | 879 sourceInformation = null; |
| 792 | 880 |
| 793 accept(Visitor visitor) => visitor.visitInvokeContinuation(this); | 881 accept(Visitor visitor) => visitor.visitInvokeContinuation(this); |
| 882 |
| 883 void setParentPointers() { |
| 884 if (continuation != null) continuation.parent = this; |
| 885 if (arguments != null) _setParentsOnList(arguments, this); |
| 886 } |
| 794 } | 887 } |
| 795 | 888 |
| 796 /// Choose between a pair of continuations based on a condition value. | 889 /// Choose between a pair of continuations based on a condition value. |
| 797 /// | 890 /// |
| 798 /// The two continuations must not declare any parameters. | 891 /// The two continuations must not declare any parameters. |
| 799 class Branch extends TailExpression { | 892 class Branch extends TailExpression { |
| 800 final Reference<Primitive> condition; | 893 final Reference<Primitive> condition; |
| 801 final Reference<Continuation> trueContinuation; | 894 final Reference<Continuation> trueContinuation; |
| 802 final Reference<Continuation> falseContinuation; | 895 final Reference<Continuation> falseContinuation; |
| 803 | 896 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 818 | 911 |
| 819 Branch.loose(Primitive condition, | 912 Branch.loose(Primitive condition, |
| 820 Continuation trueCont, | 913 Continuation trueCont, |
| 821 Continuation falseCont) | 914 Continuation falseCont) |
| 822 : this.condition = new Reference<Primitive>(condition), | 915 : this.condition = new Reference<Primitive>(condition), |
| 823 trueContinuation = new Reference<Continuation>(trueCont), | 916 trueContinuation = new Reference<Continuation>(trueCont), |
| 824 falseContinuation = new Reference<Continuation>(falseCont), | 917 falseContinuation = new Reference<Continuation>(falseCont), |
| 825 this.isStrictCheck = false; | 918 this.isStrictCheck = false; |
| 826 | 919 |
| 827 accept(Visitor visitor) => visitor.visitBranch(this); | 920 accept(Visitor visitor) => visitor.visitBranch(this); |
| 921 |
| 922 void setParentPointers() { |
| 923 condition.parent = this; |
| 924 trueContinuation.parent = this; |
| 925 falseContinuation.parent = this; |
| 926 } |
| 828 } | 927 } |
| 829 | 928 |
| 830 /// Directly assigns to a field on a given object. | 929 /// Directly assigns to a field on a given object. |
| 831 class SetField extends Primitive { | 930 class SetField extends Primitive { |
| 832 final Reference<Primitive> object; | 931 final Reference<Primitive> object; |
| 833 FieldElement field; | 932 FieldElement field; |
| 834 final Reference<Primitive> value; | 933 final Reference<Primitive> value; |
| 835 | 934 |
| 836 SetField(Primitive object, this.field, Primitive value) | 935 SetField(Primitive object, this.field, Primitive value) |
| 837 : this.object = new Reference<Primitive>(object), | 936 : this.object = new Reference<Primitive>(object), |
| 838 this.value = new Reference<Primitive>(value); | 937 this.value = new Reference<Primitive>(value); |
| 839 | 938 |
| 840 accept(Visitor visitor) => visitor.visitSetField(this); | 939 accept(Visitor visitor) => visitor.visitSetField(this); |
| 841 | 940 |
| 842 bool get isSafeForElimination => false; | 941 bool get isSafeForElimination => false; |
| 843 bool get isSafeForReordering => false; | 942 bool get isSafeForReordering => false; |
| 943 |
| 944 void setParentPointers() { |
| 945 object.parent = this; |
| 946 value.parent = this; |
| 947 } |
| 844 } | 948 } |
| 845 | 949 |
| 846 /// Directly reads from a field on a given object. | 950 /// Directly reads from a field on a given object. |
| 847 /// | 951 /// |
| 848 /// The [object] must either be `null` or an object that has [field]. | 952 /// The [object] must either be `null` or an object that has [field]. |
| 849 class GetField extends Primitive { | 953 class GetField extends Primitive { |
| 850 final Reference<Primitive> object; | 954 final Reference<Primitive> object; |
| 851 FieldElement field; | 955 FieldElement field; |
| 852 | 956 |
| 853 /// True if the object is known not to be null. | 957 /// True if the object is known not to be null. |
| 854 // TODO(asgerf): This is a placeholder until we agree on how to track | 958 // TODO(asgerf): This is a placeholder until we agree on how to track |
| 855 // side effects. | 959 // side effects. |
| 856 bool objectIsNotNull = false; | 960 bool objectIsNotNull = false; |
| 857 | 961 |
| 858 GetField(Primitive object, this.field) | 962 GetField(Primitive object, this.field) |
| 859 : this.object = new Reference<Primitive>(object); | 963 : this.object = new Reference<Primitive>(object); |
| 860 | 964 |
| 861 accept(Visitor visitor) => visitor.visitGetField(this); | 965 accept(Visitor visitor) => visitor.visitGetField(this); |
| 862 | 966 |
| 863 bool get isSafeForElimination => objectIsNotNull; | 967 bool get isSafeForElimination => objectIsNotNull; |
| 864 bool get isSafeForReordering => false; | 968 bool get isSafeForReordering => false; |
| 865 | 969 |
| 866 toString() => 'GetField($field)'; | 970 toString() => 'GetField($field)'; |
| 971 |
| 972 void setParentPointers() { |
| 973 object.parent = this; |
| 974 } |
| 867 } | 975 } |
| 868 | 976 |
| 869 /// Get the length of a string or native list. | 977 /// Get the length of a string or native list. |
| 870 class GetLength extends Primitive { | 978 class GetLength extends Primitive { |
| 871 final Reference<Primitive> object; | 979 final Reference<Primitive> object; |
| 872 | 980 |
| 873 /// True if the object is known not to be null. | 981 /// True if the object is known not to be null. |
| 874 bool objectIsNotNull = false; | 982 bool objectIsNotNull = false; |
| 875 | 983 |
| 876 GetLength(Primitive object) : this.object = new Reference<Primitive>(object); | 984 GetLength(Primitive object) : this.object = new Reference<Primitive>(object); |
| 877 | 985 |
| 878 bool get isSafeForElimination => objectIsNotNull; | 986 bool get isSafeForElimination => objectIsNotNull; |
| 879 bool get isSafeForReordering => false; | 987 bool get isSafeForReordering => false; |
| 880 | 988 |
| 881 accept(Visitor v) => v.visitGetLength(this); | 989 accept(Visitor v) => v.visitGetLength(this); |
| 990 |
| 991 void setParentPointers() { |
| 992 object.parent = this; |
| 993 } |
| 882 } | 994 } |
| 883 | 995 |
| 884 /// Read an entry from a string or native list. | 996 /// Read an entry from a string or native list. |
| 885 /// | 997 /// |
| 886 /// [object] must be null or a native list or a string, and [index] must be | 998 /// [object] must be null or a native list or a string, and [index] must be |
| 887 /// an integer. | 999 /// an integer. |
| 888 class GetIndex extends Primitive { | 1000 class GetIndex extends Primitive { |
| 889 final Reference<Primitive> object; | 1001 final Reference<Primitive> object; |
| 890 final Reference<Primitive> index; | 1002 final Reference<Primitive> index; |
| 891 | 1003 |
| 892 /// True if the object is known not to be null. | 1004 /// True if the object is known not to be null. |
| 893 bool objectIsNotNull = false; | 1005 bool objectIsNotNull = false; |
| 894 | 1006 |
| 895 GetIndex(Primitive object, Primitive index) | 1007 GetIndex(Primitive object, Primitive index) |
| 896 : this.object = new Reference<Primitive>(object), | 1008 : this.object = new Reference<Primitive>(object), |
| 897 this.index = new Reference<Primitive>(index); | 1009 this.index = new Reference<Primitive>(index); |
| 898 | 1010 |
| 899 bool get isSafeForElimination => objectIsNotNull; | 1011 bool get isSafeForElimination => objectIsNotNull; |
| 900 bool get isSafeForReordering => false; | 1012 bool get isSafeForReordering => false; |
| 901 | 1013 |
| 902 accept(Visitor v) => v.visitGetIndex(this); | 1014 accept(Visitor v) => v.visitGetIndex(this); |
| 1015 |
| 1016 void setParentPointers() { |
| 1017 object.parent = this; |
| 1018 index.parent = this; |
| 1019 } |
| 903 } | 1020 } |
| 904 | 1021 |
| 905 /// Set an entry on a native list. | 1022 /// Set an entry on a native list. |
| 906 /// | 1023 /// |
| 907 /// [object] must be null or a native list, and [index] must be an integer. | 1024 /// [object] must be null or a native list, and [index] must be an integer. |
| 908 /// | 1025 /// |
| 909 /// The primitive itself has no value and may not be referenced. | 1026 /// The primitive itself has no value and may not be referenced. |
| 910 class SetIndex extends Primitive { | 1027 class SetIndex extends Primitive { |
| 911 final Reference<Primitive> object; | 1028 final Reference<Primitive> object; |
| 912 final Reference<Primitive> index; | 1029 final Reference<Primitive> index; |
| 913 final Reference<Primitive> value; | 1030 final Reference<Primitive> value; |
| 914 | 1031 |
| 915 SetIndex(Primitive object, Primitive index, Primitive value) | 1032 SetIndex(Primitive object, Primitive index, Primitive value) |
| 916 : this.object = new Reference<Primitive>(object), | 1033 : this.object = new Reference<Primitive>(object), |
| 917 this.index = new Reference<Primitive>(index), | 1034 this.index = new Reference<Primitive>(index), |
| 918 this.value = new Reference<Primitive>(value); | 1035 this.value = new Reference<Primitive>(value); |
| 919 | 1036 |
| 920 bool get isSafeForElimination => false; | 1037 bool get isSafeForElimination => false; |
| 921 bool get isSafeForReordering => false; | 1038 bool get isSafeForReordering => false; |
| 922 | 1039 |
| 923 accept(Visitor v) => v.visitSetIndex(this); | 1040 accept(Visitor v) => v.visitSetIndex(this); |
| 1041 |
| 1042 void setParentPointers() { |
| 1043 object.parent = this; |
| 1044 index.parent = this; |
| 1045 value.parent = this; |
| 1046 } |
| 924 } | 1047 } |
| 925 | 1048 |
| 926 /// Reads the value of a static field or tears off a static method. | 1049 /// Reads the value of a static field or tears off a static method. |
| 927 /// | 1050 /// |
| 928 /// Note that lazily initialized fields should be read using GetLazyStatic. | 1051 /// Note that lazily initialized fields should be read using GetLazyStatic. |
| 929 class GetStatic extends Primitive { | 1052 class GetStatic extends Primitive { |
| 930 /// Can be [FieldElement] or [FunctionElement]. | 1053 /// Can be [FieldElement] or [FunctionElement]. |
| 931 final Element element; | 1054 final Element element; |
| 932 final SourceInformation sourceInformation; | 1055 final SourceInformation sourceInformation; |
| 933 | 1056 |
| 934 GetStatic(this.element, [this.sourceInformation]); | 1057 GetStatic(this.element, [this.sourceInformation]); |
| 935 | 1058 |
| 936 accept(Visitor visitor) => visitor.visitGetStatic(this); | 1059 accept(Visitor visitor) => visitor.visitGetStatic(this); |
| 937 | 1060 |
| 938 bool get isSafeForElimination { | 1061 bool get isSafeForElimination { |
| 939 return true; | 1062 return true; |
| 940 } | 1063 } |
| 941 bool get isSafeForReordering { | 1064 bool get isSafeForReordering { |
| 942 return element is FunctionElement || element.isFinal; | 1065 return element is FunctionElement || element.isFinal; |
| 943 } | 1066 } |
| 1067 |
| 1068 void setParentPointers() {} |
| 944 } | 1069 } |
| 945 | 1070 |
| 946 /// Sets the value of a static field. | 1071 /// Sets the value of a static field. |
| 947 class SetStatic extends Primitive { | 1072 class SetStatic extends Primitive { |
| 948 final FieldElement element; | 1073 final FieldElement element; |
| 949 final Reference<Primitive> value; | 1074 final Reference<Primitive> value; |
| 950 final SourceInformation sourceInformation; | 1075 final SourceInformation sourceInformation; |
| 951 | 1076 |
| 952 SetStatic(this.element, Primitive value, [this.sourceInformation]) | 1077 SetStatic(this.element, Primitive value, [this.sourceInformation]) |
| 953 : this.value = new Reference<Primitive>(value); | 1078 : this.value = new Reference<Primitive>(value); |
| 954 | 1079 |
| 955 accept(Visitor visitor) => visitor.visitSetStatic(this); | 1080 accept(Visitor visitor) => visitor.visitSetStatic(this); |
| 956 | 1081 |
| 957 bool get isSafeForElimination => false; | 1082 bool get isSafeForElimination => false; |
| 958 bool get isSafeForReordering => false; | 1083 bool get isSafeForReordering => false; |
| 1084 |
| 1085 void setParentPointers() { |
| 1086 value.parent = this; |
| 1087 } |
| 959 } | 1088 } |
| 960 | 1089 |
| 961 /// Reads the value of a lazily initialized static field. | 1090 /// Reads the value of a lazily initialized static field. |
| 962 /// | 1091 /// |
| 963 /// If the field has not yet been initialized, its initializer is evaluated | 1092 /// If the field has not yet been initialized, its initializer is evaluated |
| 964 /// and assigned to the field. | 1093 /// and assigned to the field. |
| 965 /// | 1094 /// |
| 966 /// [continuation] is then invoked with the value of the field as argument. | 1095 /// [continuation] is then invoked with the value of the field as argument. |
| 967 class GetLazyStatic extends CallExpression { | 1096 class GetLazyStatic extends CallExpression { |
| 968 final FieldElement element; | 1097 final FieldElement element; |
| 969 final Reference<Continuation> continuation; | 1098 final Reference<Continuation> continuation; |
| 970 final SourceInformation sourceInformation; | 1099 final SourceInformation sourceInformation; |
| 971 | 1100 |
| 972 GetLazyStatic(this.element, | 1101 GetLazyStatic(this.element, |
| 973 Continuation continuation, | 1102 Continuation continuation, |
| 974 [this.sourceInformation]) | 1103 [this.sourceInformation]) |
| 975 : continuation = new Reference<Continuation>(continuation); | 1104 : continuation = new Reference<Continuation>(continuation); |
| 976 | 1105 |
| 977 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); | 1106 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); |
| 1107 |
| 1108 void setParentPointers() { |
| 1109 continuation.parent = this; |
| 1110 } |
| 978 } | 1111 } |
| 979 | 1112 |
| 980 /// Creates an object for holding boxed variables captured by a closure. | 1113 /// Creates an object for holding boxed variables captured by a closure. |
| 981 class CreateBox extends Primitive { | 1114 class CreateBox extends Primitive { |
| 982 accept(Visitor visitor) => visitor.visitCreateBox(this); | 1115 accept(Visitor visitor) => visitor.visitCreateBox(this); |
| 983 | 1116 |
| 984 bool get isSafeForElimination => true; | 1117 bool get isSafeForElimination => true; |
| 985 bool get isSafeForReordering => true; | 1118 bool get isSafeForReordering => true; |
| 1119 |
| 1120 void setParentPointers() {} |
| 986 } | 1121 } |
| 987 | 1122 |
| 988 /// Creates an instance of a class and initializes its fields and runtime type | 1123 /// Creates an instance of a class and initializes its fields and runtime type |
| 989 /// information. | 1124 /// information. |
| 990 class CreateInstance extends Primitive { | 1125 class CreateInstance extends Primitive { |
| 991 final ClassElement classElement; | 1126 final ClassElement classElement; |
| 992 | 1127 |
| 993 /// Initial values for the fields on the class. | 1128 /// Initial values for the fields on the class. |
| 994 /// The order corresponds to the order of fields on the class. | 1129 /// The order corresponds to the order of fields on the class. |
| 995 final List<Reference<Primitive>> arguments; | 1130 final List<Reference<Primitive>> arguments; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1008 this.sourceInformation) | 1143 this.sourceInformation) |
| 1009 : this.arguments = _referenceList(arguments), | 1144 : this.arguments = _referenceList(arguments), |
| 1010 this.typeInformation = _referenceList(typeInformation); | 1145 this.typeInformation = _referenceList(typeInformation); |
| 1011 | 1146 |
| 1012 accept(Visitor visitor) => visitor.visitCreateInstance(this); | 1147 accept(Visitor visitor) => visitor.visitCreateInstance(this); |
| 1013 | 1148 |
| 1014 bool get isSafeForElimination => true; | 1149 bool get isSafeForElimination => true; |
| 1015 bool get isSafeForReordering => true; | 1150 bool get isSafeForReordering => true; |
| 1016 | 1151 |
| 1017 toString() => 'CreateInstance($classElement)'; | 1152 toString() => 'CreateInstance($classElement)'; |
| 1153 |
| 1154 void setParentPointers() { |
| 1155 _setParentsOnList(arguments, this); |
| 1156 if (typeInformation != null) _setParentsOnList(typeInformation, this); |
| 1157 } |
| 1018 } | 1158 } |
| 1019 | 1159 |
| 1020 class Interceptor extends Primitive { | 1160 class Interceptor extends Primitive { |
| 1021 final Reference<Primitive> input; | 1161 final Reference<Primitive> input; |
| 1022 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); | 1162 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); |
| 1023 final SourceInformation sourceInformation; | 1163 final SourceInformation sourceInformation; |
| 1024 | 1164 |
| 1025 /// If non-null, all uses of this the interceptor call are guaranteed to | 1165 /// If non-null, all uses of this the interceptor call are guaranteed to |
| 1026 /// see this value. | 1166 /// see this value. |
| 1027 /// | 1167 /// |
| 1028 /// The interceptor call is not immediately replaced by the constant, because | 1168 /// The interceptor call is not immediately replaced by the constant, because |
| 1029 /// that might prevent the interceptor from being shared. | 1169 /// that might prevent the interceptor from being shared. |
| 1030 /// | 1170 /// |
| 1031 /// The precise input type is not known when sharing interceptors, because | 1171 /// The precise input type is not known when sharing interceptors, because |
| 1032 /// refinement nodes have been removed by then. So this field carries the | 1172 /// refinement nodes have been removed by then. So this field carries the |
| 1033 /// known constant until we know if it should be shared or replaced by | 1173 /// known constant until we know if it should be shared or replaced by |
| 1034 /// the constant. | 1174 /// the constant. |
| 1035 values.InterceptorConstantValue constantValue; | 1175 values.InterceptorConstantValue constantValue; |
| 1036 | 1176 |
| 1037 Interceptor(Primitive input, this.sourceInformation) | 1177 Interceptor(Primitive input, this.sourceInformation) |
| 1038 : this.input = new Reference<Primitive>(input); | 1178 : this.input = new Reference<Primitive>(input); |
| 1039 | 1179 |
| 1040 accept(Visitor visitor) => visitor.visitInterceptor(this); | 1180 accept(Visitor visitor) => visitor.visitInterceptor(this); |
| 1041 | 1181 |
| 1042 bool get isSafeForElimination => true; | 1182 bool get isSafeForElimination => true; |
| 1043 bool get isSafeForReordering => true; | 1183 bool get isSafeForReordering => true; |
| 1184 |
| 1185 void setParentPointers() { |
| 1186 input.parent = this; |
| 1187 } |
| 1044 } | 1188 } |
| 1045 | 1189 |
| 1046 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. | 1190 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. |
| 1047 class CreateInvocationMirror extends Primitive { | 1191 class CreateInvocationMirror extends Primitive { |
| 1048 final Selector selector; | 1192 final Selector selector; |
| 1049 final List<Reference<Primitive>> arguments; | 1193 final List<Reference<Primitive>> arguments; |
| 1050 | 1194 |
| 1051 CreateInvocationMirror(this.selector, List<Primitive> arguments) | 1195 CreateInvocationMirror(this.selector, List<Primitive> arguments) |
| 1052 : this.arguments = _referenceList(arguments); | 1196 : this.arguments = _referenceList(arguments); |
| 1053 | 1197 |
| 1054 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); | 1198 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); |
| 1055 | 1199 |
| 1056 bool get isSafeForElimination => true; | 1200 bool get isSafeForElimination => true; |
| 1057 bool get isSafeForReordering => true; | 1201 bool get isSafeForReordering => true; |
| 1202 |
| 1203 void setParentPointers() { |
| 1204 _setParentsOnList(arguments, this); |
| 1205 } |
| 1058 } | 1206 } |
| 1059 | 1207 |
| 1060 class ForeignCode extends CallExpression { | 1208 class ForeignCode extends CallExpression { |
| 1061 final js.Template codeTemplate; | 1209 final js.Template codeTemplate; |
| 1062 final TypeMask type; | 1210 final TypeMask type; |
| 1063 final List<Reference<Primitive>> arguments; | 1211 final List<Reference<Primitive>> arguments; |
| 1064 final native.NativeBehavior nativeBehavior; | 1212 final native.NativeBehavior nativeBehavior; |
| 1065 final FunctionElement dependency; | 1213 final FunctionElement dependency; |
| 1066 final Reference<Continuation> continuation; | 1214 final Reference<Continuation> continuation; |
| 1067 | 1215 |
| 1068 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, | 1216 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, |
| 1069 this.nativeBehavior, Continuation continuation, {this.dependency}) | 1217 this.nativeBehavior, Continuation continuation, {this.dependency}) |
| 1070 : this.arguments = _referenceList(arguments), | 1218 : this.arguments = _referenceList(arguments), |
| 1071 this.continuation = new Reference<Continuation>(continuation); | 1219 this.continuation = new Reference<Continuation>(continuation); |
| 1072 | 1220 |
| 1073 accept(Visitor visitor) => visitor.visitForeignCode(this); | 1221 accept(Visitor visitor) => visitor.visitForeignCode(this); |
| 1222 |
| 1223 void setParentPointers() { |
| 1224 _setParentsOnList(arguments, this); |
| 1225 continuation.parent = this; |
| 1226 } |
| 1074 } | 1227 } |
| 1075 | 1228 |
| 1076 class Constant extends Primitive { | 1229 class Constant extends Primitive { |
| 1077 final values.ConstantValue value; | 1230 final values.ConstantValue value; |
| 1078 final SourceInformation sourceInformation; | 1231 final SourceInformation sourceInformation; |
| 1079 | 1232 |
| 1080 Constant(this.value, {this.sourceInformation}) { | 1233 Constant(this.value, {this.sourceInformation}) { |
| 1081 assert(value != null); | 1234 assert(value != null); |
| 1082 } | 1235 } |
| 1083 | 1236 |
| 1084 accept(Visitor visitor) => visitor.visitConstant(this); | 1237 accept(Visitor visitor) => visitor.visitConstant(this); |
| 1085 | 1238 |
| 1086 bool get isSafeForElimination => true; | 1239 bool get isSafeForElimination => true; |
| 1087 bool get isSafeForReordering => true; | 1240 bool get isSafeForReordering => true; |
| 1241 |
| 1242 void setParentPointers() {} |
| 1088 } | 1243 } |
| 1089 | 1244 |
| 1090 class LiteralList extends Primitive { | 1245 class LiteralList extends Primitive { |
| 1091 /// The List type being created; this is not the type argument. | 1246 /// The List type being created; this is not the type argument. |
| 1092 final InterfaceType dartType; | 1247 final InterfaceType dartType; |
| 1093 final List<Reference<Primitive>> values; | 1248 final List<Reference<Primitive>> values; |
| 1094 | 1249 |
| 1095 LiteralList(this.dartType, List<Primitive> values) | 1250 LiteralList(this.dartType, List<Primitive> values) |
| 1096 : this.values = _referenceList(values); | 1251 : this.values = _referenceList(values); |
| 1097 | 1252 |
| 1098 accept(Visitor visitor) => visitor.visitLiteralList(this); | 1253 accept(Visitor visitor) => visitor.visitLiteralList(this); |
| 1099 | 1254 |
| 1100 bool get isSafeForElimination => true; | 1255 bool get isSafeForElimination => true; |
| 1101 bool get isSafeForReordering => true; | 1256 bool get isSafeForReordering => true; |
| 1257 |
| 1258 void setParentPointers() { |
| 1259 _setParentsOnList(values, this); |
| 1260 } |
| 1102 } | 1261 } |
| 1103 | 1262 |
| 1104 class LiteralMapEntry { | 1263 class LiteralMapEntry { |
| 1105 final Reference<Primitive> key; | 1264 final Reference<Primitive> key; |
| 1106 final Reference<Primitive> value; | 1265 final Reference<Primitive> value; |
| 1107 | 1266 |
| 1108 LiteralMapEntry(Primitive key, Primitive value) | 1267 LiteralMapEntry(Primitive key, Primitive value) |
| 1109 : this.key = new Reference<Primitive>(key), | 1268 : this.key = new Reference<Primitive>(key), |
| 1110 this.value = new Reference<Primitive>(value); | 1269 this.value = new Reference<Primitive>(value); |
| 1111 } | 1270 } |
| 1112 | 1271 |
| 1113 class LiteralMap extends Primitive { | 1272 class LiteralMap extends Primitive { |
| 1114 final InterfaceType dartType; | 1273 final InterfaceType dartType; |
| 1115 final List<LiteralMapEntry> entries; | 1274 final List<LiteralMapEntry> entries; |
| 1116 | 1275 |
| 1117 LiteralMap(this.dartType, this.entries); | 1276 LiteralMap(this.dartType, this.entries); |
| 1118 | 1277 |
| 1119 accept(Visitor visitor) => visitor.visitLiteralMap(this); | 1278 accept(Visitor visitor) => visitor.visitLiteralMap(this); |
| 1120 | 1279 |
| 1121 bool get isSafeForElimination => true; | 1280 bool get isSafeForElimination => true; |
| 1122 bool get isSafeForReordering => true; | 1281 bool get isSafeForReordering => true; |
| 1282 |
| 1283 void setParentPointers() { |
| 1284 for (LiteralMapEntry entry in entries) { |
| 1285 entry.key.parent = this; |
| 1286 entry.value.parent = this; |
| 1287 } |
| 1288 } |
| 1123 } | 1289 } |
| 1124 | 1290 |
| 1125 /// Currently unused. | 1291 /// Currently unused. |
| 1126 /// | 1292 /// |
| 1127 /// Nested functions (from Dart code) are translated to classes by closure | 1293 /// Nested functions (from Dart code) are translated to classes by closure |
| 1128 /// conversion, hence they are instantiated with [CreateInstance]. | 1294 /// conversion, hence they are instantiated with [CreateInstance]. |
| 1129 /// | 1295 /// |
| 1130 /// We keep this around for now because it might come in handy when we | 1296 /// We keep this around for now because it might come in handy when we |
| 1131 /// handle async/await in the CPS IR. | 1297 /// handle async/await in the CPS IR. |
| 1132 /// | 1298 /// |
| 1133 /// Instantiates a nested function. [MutableVariable]s are in scope in the | 1299 /// Instantiates a nested function. [MutableVariable]s are in scope in the |
| 1134 /// inner function, but primitives are not shared across function boundaries. | 1300 /// inner function, but primitives are not shared across function boundaries. |
| 1135 class CreateFunction extends Primitive { | 1301 class CreateFunction extends Primitive { |
| 1136 final FunctionDefinition definition; | 1302 final FunctionDefinition definition; |
| 1137 | 1303 |
| 1138 CreateFunction(this.definition); | 1304 CreateFunction(this.definition); |
| 1139 | 1305 |
| 1140 accept(Visitor visitor) => visitor.visitCreateFunction(this); | 1306 accept(Visitor visitor) => visitor.visitCreateFunction(this); |
| 1141 | 1307 |
| 1142 bool get isSafeForElimination => true; | 1308 bool get isSafeForElimination => true; |
| 1143 bool get isSafeForReordering => true; | 1309 bool get isSafeForReordering => true; |
| 1310 |
| 1311 void setParentPointers() {} |
| 1144 } | 1312 } |
| 1145 | 1313 |
| 1146 class Parameter extends Primitive { | 1314 class Parameter extends Primitive { |
| 1147 Parameter(Entity hint) { | 1315 Parameter(Entity hint) { |
| 1148 super.hint = hint; | 1316 super.hint = hint; |
| 1149 } | 1317 } |
| 1150 | 1318 |
| 1151 // In addition to a parent pointer to the containing Continuation or | |
| 1152 // FunctionDefinition, parameters have an index into the list of parameters | |
| 1153 // bound by the parent. This gives constant-time access to the continuation | |
| 1154 // from the parent. | |
| 1155 int parentIndex; | |
| 1156 | |
| 1157 accept(Visitor visitor) => visitor.visitParameter(this); | 1319 accept(Visitor visitor) => visitor.visitParameter(this); |
| 1158 | 1320 |
| 1159 String toString() => 'Parameter(${hint == null ? null : hint.name})'; | 1321 String toString() => 'Parameter(${hint == null ? null : hint.name})'; |
| 1160 | 1322 |
| 1161 bool get isSafeForElimination => true; | 1323 bool get isSafeForElimination => true; |
| 1162 bool get isSafeForReordering => true; | 1324 bool get isSafeForReordering => true; |
| 1325 |
| 1326 void setParentPointers() {} |
| 1163 } | 1327 } |
| 1164 | 1328 |
| 1165 /// Continuations are normally bound by 'let cont'. A continuation with one | 1329 /// Continuations are normally bound by 'let cont'. A continuation with one |
| 1166 /// parameter and no body is used to represent a function's return continuation. | 1330 /// parameter and no body is used to represent a function's return continuation. |
| 1167 /// The return continuation is bound by the function, not by 'let cont'. | 1331 /// The return continuation is bound by the function, not by 'let cont'. |
| 1168 class Continuation extends Definition<Continuation> implements InteriorNode { | 1332 class Continuation extends Definition<Continuation> implements InteriorNode { |
| 1169 final List<Parameter> parameters; | 1333 final List<Parameter> parameters; |
| 1170 Expression body = null; | 1334 Expression body = null; |
| 1171 | 1335 |
| 1172 // In addition to a parent pointer to the containing LetCont, continuations | |
| 1173 // have an index into the list of continuations bound by the LetCont. This | |
| 1174 // gives constant-time access to the continuation from the parent. | |
| 1175 int parent_index; | |
| 1176 | |
| 1177 // A continuation is recursive if it has any recursive invocations. | 1336 // A continuation is recursive if it has any recursive invocations. |
| 1178 bool isRecursive; | 1337 bool isRecursive; |
| 1179 | 1338 |
| 1180 bool get isReturnContinuation => body == null; | 1339 bool get isReturnContinuation => body == null; |
| 1181 | 1340 |
| 1182 Continuation(this.parameters, {this.isRecursive: false}); | 1341 Continuation(this.parameters, {this.isRecursive: false}); |
| 1183 | 1342 |
| 1184 Continuation.retrn() | 1343 Continuation.retrn() |
| 1185 : parameters = <Parameter>[new Parameter(null)], | 1344 : parameters = <Parameter>[new Parameter(null)], |
| 1186 isRecursive = false; | 1345 isRecursive = false; |
| 1187 | 1346 |
| 1188 accept(Visitor visitor) => visitor.visitContinuation(this); | 1347 accept(Visitor visitor) => visitor.visitContinuation(this); |
| 1348 |
| 1349 void setParentPointers() { |
| 1350 _setParentsOnNodes(parameters, this); |
| 1351 if (body != null) body.parent = this; |
| 1352 } |
| 1189 } | 1353 } |
| 1190 | 1354 |
| 1191 /// Common interface for [Primitive] and [MutableVariable]. | 1355 /// Common interface for [Primitive] and [MutableVariable]. |
| 1192 abstract class Variable<T extends Variable<T>> extends Definition<T> { | 1356 abstract class Variable<T extends Variable<T>> extends Definition<T> { |
| 1193 /// Type of value held in the variable. | 1357 /// Type of value held in the variable. |
| 1194 /// | 1358 /// |
| 1195 /// Is `null` until initialized by type propagation. | 1359 /// Is `null` until initialized by type propagation. |
| 1196 TypeMask type; | 1360 TypeMask type; |
| 1197 } | 1361 } |
| 1198 | 1362 |
| 1199 /// Identifies a mutable variable. | 1363 /// Identifies a mutable variable. |
| 1200 class MutableVariable extends Variable<MutableVariable> { | 1364 class MutableVariable extends Variable<MutableVariable> { |
| 1201 Entity hint; | 1365 Entity hint; |
| 1202 | 1366 |
| 1203 MutableVariable(this.hint); | 1367 MutableVariable(this.hint); |
| 1204 | 1368 |
| 1205 accept(Visitor v) => v.visitMutableVariable(this); | 1369 accept(Visitor v) => v.visitMutableVariable(this); |
| 1370 |
| 1371 void setParentPointers() {} |
| 1206 } | 1372 } |
| 1207 | 1373 |
| 1208 /// A function definition, consisting of parameters and a body. | 1374 /// A function definition, consisting of parameters and a body. |
| 1209 /// | 1375 /// |
| 1210 /// There is an explicit parameter for the `this` argument, and a return | 1376 /// There is an explicit parameter for the `this` argument, and a return |
| 1211 /// continuation to invoke when returning from the function. | 1377 /// continuation to invoke when returning from the function. |
| 1212 class FunctionDefinition extends InteriorNode { | 1378 class FunctionDefinition extends InteriorNode { |
| 1213 final ExecutableElement element; | 1379 final ExecutableElement element; |
| 1214 final Parameter thisParameter; | 1380 final Parameter thisParameter; |
| 1215 final List<Parameter> parameters; | 1381 final List<Parameter> parameters; |
| 1216 final Continuation returnContinuation; | 1382 final Continuation returnContinuation; |
| 1217 Expression body; | 1383 Expression body; |
| 1218 | 1384 |
| 1219 FunctionDefinition(this.element, | 1385 FunctionDefinition(this.element, |
| 1220 this.thisParameter, | 1386 this.thisParameter, |
| 1221 this.parameters, | 1387 this.parameters, |
| 1222 this.returnContinuation, | 1388 this.returnContinuation, |
| 1223 this.body); | 1389 this.body); |
| 1224 | 1390 |
| 1225 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); | 1391 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); |
| 1392 |
| 1393 void setParentPointers() { |
| 1394 if (thisParameter != null) thisParameter.parent = this; |
| 1395 _setParentsOnNodes(parameters, this); |
| 1396 returnContinuation.parent = this; |
| 1397 if (body != null) body.parent = this; |
| 1398 } |
| 1226 } | 1399 } |
| 1227 | 1400 |
| 1228 /// Converts the internal representation of a type to a Dart object of type | 1401 /// Converts the internal representation of a type to a Dart object of type |
| 1229 /// [Type]. | 1402 /// [Type]. |
| 1230 class ReifyRuntimeType extends Primitive { | 1403 class ReifyRuntimeType extends Primitive { |
| 1231 /// Reference to the internal representation of a type (as produced, for | 1404 /// Reference to the internal representation of a type (as produced, for |
| 1232 /// example, by [ReadTypeVariable]). | 1405 /// example, by [ReadTypeVariable]). |
| 1233 final Reference<Primitive> value; | 1406 final Reference<Primitive> value; |
| 1234 | 1407 |
| 1235 final SourceInformation sourceInformation; | 1408 final SourceInformation sourceInformation; |
| 1236 | 1409 |
| 1237 ReifyRuntimeType(Primitive value, this.sourceInformation) | 1410 ReifyRuntimeType(Primitive value, this.sourceInformation) |
| 1238 : this.value = new Reference<Primitive>(value); | 1411 : this.value = new Reference<Primitive>(value); |
| 1239 | 1412 |
| 1240 @override | 1413 @override |
| 1241 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); | 1414 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); |
| 1242 | 1415 |
| 1243 bool get isSafeForElimination => true; | 1416 bool get isSafeForElimination => true; |
| 1244 bool get isSafeForReordering => true; | 1417 bool get isSafeForReordering => true; |
| 1418 |
| 1419 void setParentPointers() { |
| 1420 value.parent = this; |
| 1421 } |
| 1245 } | 1422 } |
| 1246 | 1423 |
| 1247 /// Read the value the type variable [variable] from the target object. | 1424 /// Read the value the type variable [variable] from the target object. |
| 1248 /// | 1425 /// |
| 1249 /// The resulting value is an internal representation (and not neccessarily a | 1426 /// The resulting value is an internal representation (and not neccessarily a |
| 1250 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be | 1427 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be |
| 1251 /// used as a Dart value. | 1428 /// used as a Dart value. |
| 1252 class ReadTypeVariable extends Primitive { | 1429 class ReadTypeVariable extends Primitive { |
| 1253 final TypeVariableType variable; | 1430 final TypeVariableType variable; |
| 1254 final Reference<Primitive> target; | 1431 final Reference<Primitive> target; |
| 1255 final SourceInformation sourceInformation; | 1432 final SourceInformation sourceInformation; |
| 1256 | 1433 |
| 1257 ReadTypeVariable(this.variable, Primitive target, this.sourceInformation) | 1434 ReadTypeVariable(this.variable, Primitive target, this.sourceInformation) |
| 1258 : this.target = new Reference<Primitive>(target); | 1435 : this.target = new Reference<Primitive>(target); |
| 1259 | 1436 |
| 1260 @override | 1437 @override |
| 1261 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); | 1438 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); |
| 1262 | 1439 |
| 1263 bool get isSafeForElimination => true; | 1440 bool get isSafeForElimination => true; |
| 1264 bool get isSafeForReordering => true; | 1441 bool get isSafeForReordering => true; |
| 1442 |
| 1443 void setParentPointers() { |
| 1444 target.parent = this; |
| 1445 } |
| 1265 } | 1446 } |
| 1266 | 1447 |
| 1267 /// Representation of a closed type (that is, a type without type variables). | 1448 /// Representation of a closed type (that is, a type without type variables). |
| 1268 /// | 1449 /// |
| 1269 /// The resulting value is constructed from [dartType] by replacing the type | 1450 /// The resulting value is constructed from [dartType] by replacing the type |
| 1270 /// variables with consecutive values from [arguments], in the order generated | 1451 /// variables with consecutive values from [arguments], in the order generated |
| 1271 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are | 1452 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are |
| 1272 /// treated as 'holes' in the term, which means that it must be ensured at | 1453 /// treated as 'holes' in the term, which means that it must be ensured at |
| 1273 /// construction, that duplicate occurences of a type variable in [dartType] | 1454 /// construction, that duplicate occurences of a type variable in [dartType] |
| 1274 /// are assigned the same value. | 1455 /// are assigned the same value. |
| 1275 class TypeExpression extends Primitive { | 1456 class TypeExpression extends Primitive { |
| 1276 final DartType dartType; | 1457 final DartType dartType; |
| 1277 final List<Reference<Primitive>> arguments; | 1458 final List<Reference<Primitive>> arguments; |
| 1278 | 1459 |
| 1279 TypeExpression(this.dartType, | 1460 TypeExpression(this.dartType, |
| 1280 [List<Primitive> arguments = const <Primitive>[]]) | 1461 [List<Primitive> arguments = const <Primitive>[]]) |
| 1281 : this.arguments = _referenceList(arguments); | 1462 : this.arguments = _referenceList(arguments); |
| 1282 | 1463 |
| 1283 @override | 1464 @override |
| 1284 accept(Visitor visitor) { | 1465 accept(Visitor visitor) { |
| 1285 return visitor.visitTypeExpression(this); | 1466 return visitor.visitTypeExpression(this); |
| 1286 } | 1467 } |
| 1287 | 1468 |
| 1288 bool get isSafeForElimination => true; | 1469 bool get isSafeForElimination => true; |
| 1289 bool get isSafeForReordering => true; | 1470 bool get isSafeForReordering => true; |
| 1471 |
| 1472 void setParentPointers() { |
| 1473 _setParentsOnList(arguments, this); |
| 1474 } |
| 1290 } | 1475 } |
| 1291 | 1476 |
| 1292 class Await extends CallExpression { | 1477 class Await extends CallExpression { |
| 1293 final Reference<Primitive> input; | 1478 final Reference<Primitive> input; |
| 1294 final Reference<Continuation> continuation; | 1479 final Reference<Continuation> continuation; |
| 1295 | 1480 |
| 1296 Await(Primitive input, Continuation continuation) | 1481 Await(Primitive input, Continuation continuation) |
| 1297 : this.input = new Reference<Primitive>(input), | 1482 : this.input = new Reference<Primitive>(input), |
| 1298 this.continuation = new Reference<Continuation>(continuation); | 1483 this.continuation = new Reference<Continuation>(continuation); |
| 1299 | 1484 |
| 1300 @override | 1485 @override |
| 1301 accept(Visitor visitor) { | 1486 accept(Visitor visitor) { |
| 1302 return visitor.visitAwait(this); | 1487 return visitor.visitAwait(this); |
| 1303 } | 1488 } |
| 1489 |
| 1490 void setParentPointers() { |
| 1491 input.parent = this; |
| 1492 continuation.parent = this; |
| 1493 } |
| 1304 } | 1494 } |
| 1305 | 1495 |
| 1306 class Yield extends CallExpression { | 1496 class Yield extends CallExpression { |
| 1307 final Reference<Primitive> input; | 1497 final Reference<Primitive> input; |
| 1308 final Reference<Continuation> continuation; | 1498 final Reference<Continuation> continuation; |
| 1309 final bool hasStar; | 1499 final bool hasStar; |
| 1310 | 1500 |
| 1311 Yield(Primitive input, this.hasStar, Continuation continuation) | 1501 Yield(Primitive input, this.hasStar, Continuation continuation) |
| 1312 : this.input = new Reference<Primitive>(input), | 1502 : this.input = new Reference<Primitive>(input), |
| 1313 this.continuation = new Reference<Continuation>(continuation); | 1503 this.continuation = new Reference<Continuation>(continuation); |
| 1314 | 1504 |
| 1315 @override | 1505 @override |
| 1316 accept(Visitor visitor) { | 1506 accept(Visitor visitor) { |
| 1317 return visitor.visitYield(this); | 1507 return visitor.visitYield(this); |
| 1318 } | 1508 } |
| 1509 |
| 1510 void setParentPointers() { |
| 1511 input.parent = this; |
| 1512 continuation.parent = this; |
| 1513 } |
| 1319 } | 1514 } |
| 1320 | 1515 |
| 1321 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { | 1516 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |
| 1322 return definitions.map((e) => new Reference<Primitive>(e)).toList(); | 1517 return definitions.map((e) => new Reference<Primitive>(e)).toList(); |
| 1323 } | 1518 } |
| 1324 | 1519 |
| 1520 void _setParentsOnNodes(List<Node> nodes, Node parent) { |
| 1521 for (Node node in nodes) { |
| 1522 node.parent = parent; |
| 1523 } |
| 1524 } |
| 1525 |
| 1526 void _setParentsOnList(List<Reference> nodes, Node parent) { |
| 1527 for (Reference node in nodes) { |
| 1528 node.parent = parent; |
| 1529 } |
| 1530 } |
| 1531 |
| 1325 abstract class Visitor<T> { | 1532 abstract class Visitor<T> { |
| 1326 const Visitor(); | 1533 const Visitor(); |
| 1327 | 1534 |
| 1328 T visit(Node node); | 1535 T visit(Node node); |
| 1329 | 1536 |
| 1330 // Concrete classes. | 1537 // Concrete classes. |
| 1331 T visitFunctionDefinition(FunctionDefinition node); | 1538 T visitFunctionDefinition(FunctionDefinition node); |
| 1332 | 1539 |
| 1333 // Expressions. | 1540 // Expressions. |
| 1334 T visitLetPrim(LetPrim node); | 1541 T visitLetPrim(LetPrim node); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1375 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); | 1582 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); |
| 1376 T visitGetLength(GetLength node); | 1583 T visitGetLength(GetLength node); |
| 1377 T visitGetIndex(GetIndex node); | 1584 T visitGetIndex(GetIndex node); |
| 1378 T visitSetIndex(SetIndex node); | 1585 T visitSetIndex(SetIndex node); |
| 1379 T visitRefinement(Refinement node); | 1586 T visitRefinement(Refinement node); |
| 1380 | 1587 |
| 1381 // Support for literal foreign code. | 1588 // Support for literal foreign code. |
| 1382 T visitForeignCode(ForeignCode node); | 1589 T visitForeignCode(ForeignCode node); |
| 1383 } | 1590 } |
| 1384 | 1591 |
| 1385 /// Visits all non-recursive children of a CPS term, i.e. anything | 1592 /// Recursively visits all children of a CPS term. |
| 1386 /// not of type [Expression] or [Continuation]. | 1593 /// |
| 1594 /// The user of the class is responsible for avoiding stack overflows from |
| 1595 /// deep recursion, e.g. by overriding methods to cut off recursion at certain |
| 1596 /// points. |
| 1597 /// |
| 1598 /// All recursive invocations occur through the [visit] method, which the |
| 1599 /// subclass may override as a generic way to control the visitor without |
| 1600 /// overriding all visitor methods. |
| 1387 /// | 1601 /// |
| 1388 /// The `process*` methods are called in pre-order for every node visited. | 1602 /// The `process*` methods are called in pre-order for every node visited. |
| 1389 /// These can be overridden without disrupting the visitor traversal. | 1603 /// These can be overridden without disrupting the visitor traversal. |
| 1390 class LeafVisitor implements Visitor { | 1604 class DeepRecursiveVisitor implements Visitor { |
| 1391 const LeafVisitor(); | 1605 const DeepRecursiveVisitor(); |
| 1392 | 1606 |
| 1393 visit(Node node) => node.accept(this); | 1607 visit(Node node) => node.accept(this); |
| 1394 | 1608 |
| 1395 processReference(Reference ref) {} | 1609 processReference(Reference ref) {} |
| 1396 | 1610 |
| 1397 processFunctionDefinition(FunctionDefinition node) {} | 1611 processFunctionDefinition(FunctionDefinition node) {} |
| 1398 visitFunctionDefinition(FunctionDefinition node) { | 1612 visitFunctionDefinition(FunctionDefinition node) { |
| 1399 processFunctionDefinition(node); | 1613 processFunctionDefinition(node); |
| 1400 if (node.thisParameter != null) visit(node.thisParameter); | 1614 if (node.thisParameter != null) visit(node.thisParameter); |
| 1401 node.parameters.forEach(visit); | 1615 node.parameters.forEach(visit); |
| 1402 visit(node.returnContinuation); | 1616 visit(node.returnContinuation); |
| 1617 visit(node.body); |
| 1618 } |
| 1619 |
| 1620 processContinuation(Continuation node) {} |
| 1621 visitContinuation(Continuation node) { |
| 1622 processContinuation(node); |
| 1623 node.parameters.forEach(visit); |
| 1624 if (node.body != null) visit(node.body); |
| 1403 } | 1625 } |
| 1404 | 1626 |
| 1405 // Expressions. | 1627 // Expressions. |
| 1406 | |
| 1407 processLetPrim(LetPrim node) {} | 1628 processLetPrim(LetPrim node) {} |
| 1408 visitLetPrim(LetPrim node) { | 1629 visitLetPrim(LetPrim node) { |
| 1409 processLetPrim(node); | 1630 processLetPrim(node); |
| 1410 visit(node.primitive); | 1631 visit(node.primitive); |
| 1632 visit(node.body); |
| 1411 } | 1633 } |
| 1412 | 1634 |
| 1413 processLetCont(LetCont node) {} | 1635 processLetCont(LetCont node) {} |
| 1414 visitLetCont(LetCont node) { | 1636 visitLetCont(LetCont node) { |
| 1415 processLetCont(node); | 1637 processLetCont(node); |
| 1416 node.continuations.forEach(visit); | 1638 node.continuations.forEach(visit); |
| 1639 visit(node.body); |
| 1417 } | 1640 } |
| 1418 | 1641 |
| 1419 processLetHandler(LetHandler node) {} | 1642 processLetHandler(LetHandler node) {} |
| 1420 visitLetHandler(LetHandler node) { | 1643 visitLetHandler(LetHandler node) { |
| 1421 processLetHandler(node); | 1644 processLetHandler(node); |
| 1645 visit(node.handler); |
| 1646 visit(node.body); |
| 1422 } | 1647 } |
| 1423 | 1648 |
| 1424 processLetMutable(LetMutable node) {} | 1649 processLetMutable(LetMutable node) {} |
| 1425 visitLetMutable(LetMutable node) { | 1650 visitLetMutable(LetMutable node) { |
| 1426 processLetMutable(node); | 1651 processLetMutable(node); |
| 1427 visit(node.variable); | 1652 visit(node.variable); |
| 1428 processReference(node.value); | 1653 processReference(node.value); |
| 1654 visit(node.body); |
| 1429 } | 1655 } |
| 1430 | 1656 |
| 1431 processInvokeStatic(InvokeStatic node) {} | 1657 processInvokeStatic(InvokeStatic node) {} |
| 1432 visitInvokeStatic(InvokeStatic node) { | 1658 visitInvokeStatic(InvokeStatic node) { |
| 1433 processInvokeStatic(node); | 1659 processInvokeStatic(node); |
| 1434 processReference(node.continuation); | 1660 processReference(node.continuation); |
| 1435 node.arguments.forEach(processReference); | 1661 node.arguments.forEach(processReference); |
| 1436 } | 1662 } |
| 1437 | 1663 |
| 1438 processInvokeContinuation(InvokeContinuation node) {} | 1664 processInvokeContinuation(InvokeContinuation node) {} |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1547 visitGetMutable(GetMutable node) { | 1773 visitGetMutable(GetMutable node) { |
| 1548 processGetMutable(node); | 1774 processGetMutable(node); |
| 1549 processReference(node.variable); | 1775 processReference(node.variable); |
| 1550 } | 1776 } |
| 1551 | 1777 |
| 1552 processParameter(Parameter node) {} | 1778 processParameter(Parameter node) {} |
| 1553 visitParameter(Parameter node) { | 1779 visitParameter(Parameter node) { |
| 1554 processParameter(node); | 1780 processParameter(node); |
| 1555 } | 1781 } |
| 1556 | 1782 |
| 1557 processContinuation(Continuation node) {} | |
| 1558 visitContinuation(Continuation node) { | |
| 1559 processContinuation(node); | |
| 1560 node.parameters.forEach(visitParameter); | |
| 1561 } | |
| 1562 | |
| 1563 processInterceptor(Interceptor node) {} | 1783 processInterceptor(Interceptor node) {} |
| 1564 visitInterceptor(Interceptor node) { | 1784 visitInterceptor(Interceptor node) { |
| 1565 processInterceptor(node); | 1785 processInterceptor(node); |
| 1566 processReference(node.input); | 1786 processReference(node.input); |
| 1567 } | 1787 } |
| 1568 | 1788 |
| 1569 processCreateInstance(CreateInstance node) {} | 1789 processCreateInstance(CreateInstance node) {} |
| 1570 visitCreateInstance(CreateInstance node) { | 1790 visitCreateInstance(CreateInstance node) { |
| 1571 processCreateInstance(node); | 1791 processCreateInstance(node); |
| 1572 node.arguments.forEach(processReference); | 1792 node.arguments.forEach(processReference); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1713 /// The `traverse*` methods return the expression to visit next, and may | 1933 /// The `traverse*` methods return the expression to visit next, and may |
| 1714 /// push other subterms onto the stack using [push] or [pushAction] to visit | 1934 /// push other subterms onto the stack using [push] or [pushAction] to visit |
| 1715 /// them later. Actions pushed onto the stack will be executed after the body | 1935 /// them later. Actions pushed onto the stack will be executed after the body |
| 1716 /// has been processed (and the stack actions it pushed have been executed). | 1936 /// has been processed (and the stack actions it pushed have been executed). |
| 1717 /// | 1937 /// |
| 1718 /// By default, the `traverse` methods visit all non-recursive subterms, | 1938 /// By default, the `traverse` methods visit all non-recursive subterms, |
| 1719 /// push all bound continuations on the stack, and return the body of the term. | 1939 /// push all bound continuations on the stack, and return the body of the term. |
| 1720 /// | 1940 /// |
| 1721 /// Subclasses should not override the `visit` methods for the nodes that have | 1941 /// Subclasses should not override the `visit` methods for the nodes that have |
| 1722 /// a `traverse` method. | 1942 /// a `traverse` method. |
| 1723 class RecursiveVisitor extends LeafVisitor { | 1943 class TrampolineRecursiveVisitor extends DeepRecursiveVisitor { |
| 1724 List<StackAction> _stack = <StackAction>[]; | 1944 List<StackAction> _stack = <StackAction>[]; |
| 1725 | 1945 |
| 1726 void pushAction(StackAction callback) { | 1946 void pushAction(StackAction callback) { |
| 1727 _stack.add(callback); | 1947 _stack.add(callback); |
| 1728 } | 1948 } |
| 1729 | 1949 |
| 1730 void push(Continuation cont) { | 1950 void push(Continuation cont) { |
| 1731 _stack.add(() { | 1951 _stack.add(() { |
| 1732 if (cont.isReturnContinuation) { | 1952 if (cont.isReturnContinuation) { |
| 1733 traverseContinuation(cont); | 1953 traverseContinuation(cont); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1808 node = traverseLetPrim(node); | 2028 node = traverseLetPrim(node); |
| 1809 } else { | 2029 } else { |
| 1810 node = traverseLetMutable(node); | 2030 node = traverseLetMutable(node); |
| 1811 } | 2031 } |
| 1812 } | 2032 } |
| 1813 visit(node); | 2033 visit(node); |
| 1814 } | 2034 } |
| 1815 } | 2035 } |
| 1816 | 2036 |
| 1817 /// Visit a just-deleted subterm and unlink all [Reference]s in it. | 2037 /// Visit a just-deleted subterm and unlink all [Reference]s in it. |
| 1818 class RemovalVisitor extends RecursiveVisitor { | 2038 class RemovalVisitor extends TrampolineRecursiveVisitor { |
| 1819 processReference(Reference reference) { | 2039 processReference(Reference reference) { |
| 1820 reference.unlink(); | 2040 reference.unlink(); |
| 1821 } | 2041 } |
| 1822 | 2042 |
| 1823 static void remove(Node node) { | 2043 static void remove(Node node) { |
| 1824 (new RemovalVisitor()).visit(node); | 2044 (new RemovalVisitor()).visit(node); |
| 1825 } | 2045 } |
| 1826 } | 2046 } |
| OLD | NEW |