@@ -36,9 +36,9 @@ data ParAff eff a
36
36
| ?Par (Aff eff a)
37
37
38
38
*/
39
- var MAP = "Map"
40
- var APPLY = "Apply"
41
- var ALT = "Alt"
39
+ var MAP = "Map" ;
40
+ var APPLY = "Apply" ;
41
+ var ALT = "Alt" ;
42
42
43
43
// Various constructors used in interpretation
44
44
var CONS = "Cons" ; // Cons-list, for stacks
@@ -571,108 +571,79 @@ exports._sequential = function (isLeft, fromLeft, fromRight, left, right, runAff
571
571
// The root pointer of the tree.
572
572
var root = EMPTY ;
573
573
574
- // Walks the applicative tree, substituting non-applicative nodes with
575
- // `FORKED` nodes. In this tree, all applicative nodes use the `_3` slot
576
- // as a mutable slot for memoization. In an unresolved state, the `_3`
577
- // slot is `EMPTY`. In the cases of `ALT` and `APPLY`, we always walk
578
- // the left side first, because both operations are left-associative. As
579
- // we `RETURN` from those branches, we then walk the right side.
580
- function run ( ) {
581
- var status = CONTINUE ;
582
- var step = par ;
583
- var head = null ;
584
- var tail = null ;
585
- var tmp , tid ;
574
+ // Walks a tree, invoking all the cancelers. Returns the table of pending
575
+ // cancellation threads.
576
+ function kill ( error , par , cb ) {
577
+ var step = par ;
578
+ var fail = null ;
579
+ var head = null ;
580
+ var tail = null ;
581
+ var count = 0 ;
582
+ var kills = { } ;
583
+ var tmp , kid ;
586
584
587
585
loop: while ( 1 ) {
588
586
tmp = null ;
589
- tid = null ;
590
587
591
- switch ( status ) {
592
- case CONTINUE :
593
- switch ( step . tag ) {
594
- case MAP :
595
- if ( head ) {
596
- tail = new Aff ( CONS , head , tail ) ;
597
- }
598
- head = new Aff ( MAP , step . _1 , EMPTY , EMPTY ) ;
599
- step = step . _2 ;
600
- break ;
601
- case APPLY :
602
- if ( head ) {
603
- tail = new Aff ( CONS , head , tail ) ;
604
- }
605
- head = new Aff ( APPLY , EMPTY , step . _2 , EMPTY ) ;
606
- step = step . _1 ;
607
- break ;
608
- case ALT :
609
- if ( head ) {
610
- tail = new Aff ( CONS , head , tail ) ;
611
- }
612
- head = new Aff ( ALT , EMPTY , step . _2 , EMPTY ) ;
613
- step = step . _1 ;
614
- break ;
615
- default :
616
- // When we hit a leaf value, we suspend the stack in the `FORKED`.
617
- // When the thread resolves, it can bubble back up the tree.
618
- tid = threadId ++ ;
619
- status = RETURN ;
620
- tmp = step ;
621
- step = new Aff ( FORKED , tid , new Aff ( CONS , head , tail ) , EMPTY ) ;
622
- // We prime the effect, but don't immediately run it. We need to
623
- // walk the entire tree first before actually running effects
624
- // because they may all be synchronous and resolve immediately, at
625
- // which point it would attempt to resolve against an incomplete
626
- // tree.
627
- threads [ tid ] = new Aff ( THUNK , runAff ( resolve ( step ) ) ( tmp ) ) ;
588
+ switch ( step . tag ) {
589
+ case FORKED :
590
+ tmp = threads [ step . _1 ] ;
591
+ // If we haven't forked the thread yet (such as with a sync Alt),
592
+ // then we should just remove it from the queue and continue.
593
+ if ( tmp . tag === THUNK ) {
594
+ delete threads [ step . _1 ] ;
595
+ cb ( right ( void 0 ) ) ( ) ;
596
+ } else {
597
+ // Again, we prime the effect but don't run it yet, so that we can
598
+ // collect all the threads first.
599
+ kills [ count ++ ] = runAff ( function ( result ) {
600
+ return function ( ) {
601
+ count -- ;
602
+ if ( fail === null && isLeft ( result ) ) {
603
+ fail = result ;
604
+ }
605
+ // We can resolve the callback when all threads have died.
606
+ if ( count === 0 ) {
607
+ cb ( fail || right ( void 0 ) ) ( ) ;
608
+ }
609
+ } ;
610
+ } ) ( tmp . _1 . kill ( error ) ) ;
628
611
}
629
- break ;
630
- case RETURN :
631
- // Terminal case, we are back at the root.
612
+ // Terminal case.
632
613
if ( head === null ) {
633
614
break loop;
634
615
}
635
- // If we are done with the right side, we need to continue down the
636
- // left. Otherwise we should continue up the stack.
637
- if ( head . _1 === EMPTY ) {
638
- head . _1 = step ;
639
- status = CONTINUE ;
640
- step = head . _2 ;
641
- head . _2 = EMPTY ;
616
+ // Go down the right side of the tree.
617
+ step = head . _2 ;
618
+ if ( tail === null ) {
619
+ head = null ;
642
620
} else {
643
- head . _2 = step ;
644
- step = head ;
645
- if ( tail === null ) {
646
- head = null ;
647
- } else {
648
- head = tail . _1 ;
649
- tail = tail . _2 ;
650
- }
621
+ head = tail . _1 ;
622
+ tail = tail . _2 ;
651
623
}
624
+ break ;
625
+ case MAP :
626
+ step = step . _2 ;
627
+ break ;
628
+ case APPLY :
629
+ case ALT :
630
+ if ( head ) {
631
+ tail = new Aff ( CONS , head , tail ) ;
632
+ }
633
+ head = step ;
634
+ step = step . _1 ;
635
+ break ;
652
636
}
653
637
}
654
638
655
- // Keep a reference to the tree root so it can be cancelled.
656
- root = step ;
657
-
658
- // Walk the primed threads and fork them. We store the actual `Thread`
659
- // reference so we can cancel them when needed.
660
- for ( tid = 0 ; tid < threadId ; tid ++ ) {
661
- tmp = threads [ tid ] ;
662
- if ( tmp && tmp . tag === THUNK ) {
663
- threads [ tid ] = new Aff ( THREAD , tmp . _1 ( ) ) ;
664
- }
639
+ // Run the cancelation effects. We alias `count` because it's mutable.
640
+ kid = 0 ;
641
+ tmp = count ;
642
+ for ( ; kid < tmp ; kid ++ ) {
643
+ kills [ kid ] = kills [ kid ] ( ) ;
665
644
}
666
- }
667
645
668
- function resolve ( thread ) {
669
- return function ( result ) {
670
- return function ( ) {
671
- delete threads [ thread . _1 ] ;
672
- thread . _3 = result ;
673
- join ( result , thread . _2 . _1 , thread . _2 . _2 ) ;
674
- } ;
675
- } ;
646
+ return kills ;
676
647
}
677
648
678
649
// When a thread resolves, we need to bubble back up the tree with the
@@ -787,77 +758,108 @@ exports._sequential = function (isLeft, fromLeft, fromRight, left, right, runAff
787
758
}
788
759
}
789
760
790
- // Walks a tree, invoking all the cancelers. Returns the table of pending
791
- // cancellation threads.
792
- function kill ( error , par , cb ) {
793
- var step = par ;
794
- var fail = null ;
795
- var head = null ;
796
- var tail = null ;
797
- var count = 0 ;
798
- var kills = { } ;
799
- var tmp , kid ;
761
+ function resolve ( thread ) {
762
+ return function ( result ) {
763
+ return function ( ) {
764
+ delete threads [ thread . _1 ] ;
765
+ thread . _3 = result ;
766
+ join ( result , thread . _2 . _1 , thread . _2 . _2 ) ;
767
+ } ;
768
+ } ;
769
+ }
770
+
771
+ // Walks the applicative tree, substituting non-applicative nodes with
772
+ // `FORKED` nodes. In this tree, all applicative nodes use the `_3` slot
773
+ // as a mutable slot for memoization. In an unresolved state, the `_3`
774
+ // slot is `EMPTY`. In the cases of `ALT` and `APPLY`, we always walk
775
+ // the left side first, because both operations are left-associative. As
776
+ // we `RETURN` from those branches, we then walk the right side.
777
+ function run ( ) {
778
+ var status = CONTINUE ;
779
+ var step = par ;
780
+ var head = null ;
781
+ var tail = null ;
782
+ var tmp , tid ;
800
783
801
784
loop: while ( 1 ) {
802
785
tmp = null ;
786
+ tid = null ;
803
787
804
- switch ( step . tag ) {
805
- case FORKED :
806
- tmp = threads [ step . _1 ] ;
807
- // If we haven't forked the thread yet (such as with a sync Alt),
808
- // then we should just remove it from the queue and continue.
809
- if ( tmp . tag === THUNK ) {
810
- delete threads [ step . _1 ] ;
811
- cb ( right ( void 0 ) ) ( ) ;
812
- } else {
813
- // Again, we prime the effect but don't run it yet, so that we can
814
- // collect all the threads first.
815
- kills [ count ++ ] = runAff ( function ( result ) {
816
- return function ( ) {
817
- count -- ;
818
- if ( fail === null && isLeft ( result ) ) {
819
- fail = result ;
820
- }
821
- // We can resolve the callback when all threads have died.
822
- if ( count === 0 ) {
823
- cb ( fail || right ( void 0 ) ) ( ) ;
824
- }
825
- } ;
826
- } ) ( tmp . _1 . kill ( error ) ) ;
788
+ switch ( status ) {
789
+ case CONTINUE :
790
+ switch ( step . tag ) {
791
+ case MAP :
792
+ if ( head ) {
793
+ tail = new Aff ( CONS , head , tail ) ;
794
+ }
795
+ head = new Aff ( MAP , step . _1 , EMPTY , EMPTY ) ;
796
+ step = step . _2 ;
797
+ break ;
798
+ case APPLY :
799
+ if ( head ) {
800
+ tail = new Aff ( CONS , head , tail ) ;
801
+ }
802
+ head = new Aff ( APPLY , EMPTY , step . _2 , EMPTY ) ;
803
+ step = step . _1 ;
804
+ break ;
805
+ case ALT :
806
+ if ( head ) {
807
+ tail = new Aff ( CONS , head , tail ) ;
808
+ }
809
+ head = new Aff ( ALT , EMPTY , step . _2 , EMPTY ) ;
810
+ step = step . _1 ;
811
+ break ;
812
+ default :
813
+ // When we hit a leaf value, we suspend the stack in the `FORKED`.
814
+ // When the thread resolves, it can bubble back up the tree.
815
+ tid = threadId ++ ;
816
+ status = RETURN ;
817
+ tmp = step ;
818
+ step = new Aff ( FORKED , tid , new Aff ( CONS , head , tail ) , EMPTY ) ;
819
+ // We prime the effect, but don't immediately run it. We need to
820
+ // walk the entire tree first before actually running effects
821
+ // because they may all be synchronous and resolve immediately, at
822
+ // which point it would attempt to resolve against an incomplete
823
+ // tree.
824
+ threads [ tid ] = new Aff ( THUNK , runAff ( resolve ( step ) ) ( tmp ) ) ;
827
825
}
828
- // Terminal case.
826
+ break ;
827
+ case RETURN :
828
+ // Terminal case, we are back at the root.
829
829
if ( head === null ) {
830
830
break loop;
831
831
}
832
- // Go down the right side of the tree.
833
- step = head . _2 ;
834
- if ( tail === null ) {
835
- head = null ;
832
+ // If we are done with the right side, we need to continue down the
833
+ // left. Otherwise we should continue up the stack.
834
+ if ( head . _1 === EMPTY ) {
835
+ head . _1 = step ;
836
+ status = CONTINUE ;
837
+ step = head . _2 ;
838
+ head . _2 = EMPTY ;
836
839
} else {
837
- head = tail . _1 ;
838
- tail = tail . _2 ;
839
- }
840
- break ;
841
- case MAP :
842
- step = step . _2 ;
843
- break ;
844
- case APPLY :
845
- case ALT :
846
- if ( head ) {
847
- tail = new Aff ( CONS , head , tail ) ;
840
+ head . _2 = step ;
841
+ step = head ;
842
+ if ( tail === null ) {
843
+ head = null ;
844
+ } else {
845
+ head = tail . _1 ;
846
+ tail = tail . _2 ;
847
+ }
848
848
}
849
- head = step ;
850
- step = step . _1 ;
851
- break ;
852
849
}
853
850
}
854
851
855
- // Run the cancelation effects. We alias `count` because it's mutable.
856
- for ( kid = 0 , tmp = count ; kid < tmp ; kid ++ ) {
857
- kills [ kid ] = kills [ kid ] ( ) ;
858
- }
852
+ // Keep a reference to the tree root so it can be cancelled.
853
+ root = step ;
859
854
860
- return kills ;
855
+ // Walk the primed threads and fork them. We store the actual `Thread`
856
+ // reference so we can cancel them when needed.
857
+ for ( tid = 0 ; tid < threadId ; tid ++ ) {
858
+ tmp = threads [ tid ] ;
859
+ if ( tmp && tmp . tag === THUNK ) {
860
+ threads [ tid ] = new Aff ( THREAD , tmp . _1 ( ) ) ;
861
+ }
862
+ }
861
863
}
862
864
863
865
function ignore ( ) {
0 commit comments