Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: extend-dump
Fetching contributors…

Cannot retrieve contributors at this time

file 88 lines (80 sloc) 2.893 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
class GatherIter is Iterator {
    has Mu $!coro; # coroutine to execute for more pairs
    has $!reified; # Parcel of this iterator's results
    has $!infinite; # true if iterator is known infinite

    method new($block, Mu :$infinite) {
        my Mu $coro :=
            nqp::clone(nqp::getattr(&coro, Code, '$!do'));
        Q:PIR {
            $P0 = find_lex '$block'
            $P1 = find_lex '$coro'
            $P1($P0)
        };
        pir::setattribute__0PPsP(
            pir::setattribute__0PPsP(nqp::create(self), GatherIter, '$!coro', $coro),
            GatherIter, '$!infinite', $infinite);
    }

    multi method DUMP(GatherIter:D: :$indent-step = 4, :%ctx?) {
        return DUMP(self, :$indent-step) unless %ctx;

        my $flags := ("\x221e" if self.infinite);
        my Mu $attrs := nqp::list();
        nqp::push($attrs, '$!reified' );
        nqp::push($attrs, $!reified );
        nqp::push($attrs, '$!coro' );
        nqp::push($attrs, $!coro );
        self.DUMP-OBJECT-ATTRS($attrs, :$indent-step, :%ctx, :$flags);
    }

    method reify($n = 1) {
        if !$!reified.defined {
            my Mu $rpa := nqp::list();
            my Mu $parcel;
            my $end = Bool::False;
            my $count = nqp::istype($n, Whatever) ?? 1 !! $n;
            while !$end && $count > 0 {
                $parcel := $!coro();
                $end = nqp::p6bool(nqp::isnull($parcel));
                nqp::push($rpa, $parcel) unless $end;
                $count = $count - 1;
            }
            nqp::push($rpa,
                pir::setattribute__0PPsP(
                    pir::setattribute__0PPsP(
                        nqp::create(self), GatherIter, '$!coro', $!coro),
                    GatherIter, '$!infinite', $!infinite))
                unless $end;
            $!reified := nqp::p6parcel($rpa, nqp::null());
        }
        $!reified
    }

    method infinite() { $!infinite }

    my sub coro(\block) {
        Q:PIR {
            .local pmc block, handler, taken
            block = find_lex 'block'
            .yield ()
            handler = root_new ['parrot';'ExceptionHandler']
            handler.'handle_types'(.CONTROL_TAKE)
            set_addr handler, take_handler
            push_eh handler
            $P0 = block()
            $P0.'eager'()
            pop_eh
          gather_done:
            null taken
            .yield (taken)
            goto gather_done
          take_handler:
            .local pmc exception, resume
            .get_results (exception)
            taken = exception['payload']
            resume = exception['resume']
            .yield (taken)
            resume()
            goto gather_done # should never get here
        };
        True
    }
}


sub GATHER(\block, Mu :$infinite) {
    GatherIter.new( block, :$infinite ).list;
}
Something went wrong with that request. Please try again.