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 |