Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: unfaster-words
Fetching contributors…

Cannot retrieve contributors at this time

file 142 lines (127 sloc) 5.245 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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
my class MapIter is Iterator {
    has $!reified; # Parcel we return after reifying
    has Mu $!listiter; # the list we're consuming
    has Mu $!flattens; # flag to flatten input list
    has $!block; # the block we're applying
    has $!first; # Is this the first iterator in the sequence?
    has Mu $!items; # reified items we haven't consumed yet

    method new($list, $block, Mu $flattens = Bool::True) {
        my $new := nqp::create(self);
        $new.BUILD(nqp::p6listiter(nqp::qlist(nqp::p6decont($list)), $new),
                   $block, $flattens, True);
        $new;
    }

    method BUILD(Mu \listiter, \block, Mu \flattens, $first = False) {
        nqp::bindattr(listiter, ListIter, '$!list', self) if nqp::isconcrete(listiter);
        $!listiter := listiter;
        $!block = block;
        $!first = $first;
        $!flattens = flattens;
        self
    }

    method flattens() { $!flattens }

    method reify($n = 1) {
        unless nqp::isconcrete($!reified) {
            my $argc = $!block.count;
            $argc = 1 if $argc < 1;
            my $block := nqp::p6decont($!block);
            my Mu $rpa := nqp::list();

            if $!first {
                $!items := nqp::qlist();
                pir::perl6_set_block_first_flag__0P($block)
                  if (nqp::can($block, 'phasers') && $block.phasers('FIRST'));
            }

            my $count = $n;
            if nqp::istype($count, Whatever) {
                $!listiter.reify(*)
                  if $!listiter && nqp::elems($!items) < $argc;
                $count = (nqp::elems($!items) / $argc).floor;
                $count = 1 if $count < 1;
                $count = 100000 if $count > 100000;
            }

            my int $NEXT = nqp::can($block, 'fire_phasers')
                             && +$block.phasers('NEXT');

            Q:PIR {
                .local int argc, count, NEXT
                .local pmc handler, self, MapIter, items, args, result, block, rpa
                $P0 = find_lex '$argc'
                argc = repr_unbox_int $P0
                $P0 = find_lex '$count'
                count = repr_unbox_int $P0
                self = find_lex 'self'
                rpa = find_lex '$rpa'
                MapIter = find_lex 'MapIter'
                items = getattribute self, MapIter, '$!items'
                args = new 'QRPA'
                block = find_lex '$block'
                handler = root_new ['parrot';'ExceptionHandler']
                NEXT = find_lex '$NEXT'

                set_addr handler, catch
                handler.'handle_types'(.CONTROL_LOOP_LAST, .CONTROL_LOOP_NEXT, .CONTROL_LOOP_REDO)
                push_eh handler

              iter_loop:
                $I0 = elements rpa
                unless $I0 < count goto iter_done
                $I0 = elements items
                if $I0 >= argc goto have_items
                $I0 = argc - $I0
                $P0 = getattribute self, MapIter, '$!listiter'
                unless $P0 goto have_items
                $P0.'reify'($I0)
              have_items:
                args = 0
                perl6_shiftpush args, items, argc
                unless args goto iter_done
              redo:
                result = block(args :flat)
                push rpa, result
                goto next
              catch:
                .local pmc exception, type
                .get_results (exception)
                result = getattribute exception, 'payload'
                push rpa, result
                type = getattribute exception, 'type'
                if type == .CONTROL_LOOP_REDO goto redo
                if type == .CONTROL_LOOP_LAST goto last
              next:
                unless NEXT goto iter_loop
                block.'fire_phasers'('NEXT')
                goto iter_loop
              last:
                $P0 = find_lex 'Any'
                setattribute self, MapIter, '$!items', $P0
                setattribute self, MapIter, '$!listiter', $P0
              iter_done:
                pop_eh
            };

            if $!items || $!listiter {
                my $nextiter := nqp::create(self).BUILD($!listiter, $!block, $!flattens);
                nqp::bindattr($nextiter, MapIter, '$!items', $!items);
                nqp::push($rpa, $nextiter);
            }
            elsif nqp::can($block, 'fire_phasers') {
                $block.fire_phasers('LAST');
            }

            $!reified := nqp::p6parcel($rpa, nqp::null());
            # release references to objects we no longer need/own
            $!items := Any;
            $!listiter := Any;
            $!block := Any;

        }
        $!reified;
    }

    method REIFY(Parcel \parcel, Mu \nextiter) {
        nqp::splice($!items, nqp::getattr(parcel, Parcel, '$!storage'),
                    nqp::elems($!items), 0);
        $!listiter := nextiter;
        parcel
    }

    method DUMP() {
        self.DUMP-ID() ~ '('
          ~ ':reified(' ~ DUMP($!reified) ~ '), '
          ~ ':items(' ~ DUMP($!items) ~'), '
          ~ ':listiter(' ~ DUMP($!listiter) ~ ')'
          ~ ')'
    }
}
Something went wrong with that request. Please try again.