<commit_before># for our tantrums
my class X::TypeCheck::Splice { ... }
my class Supply { ... }
my class Supplier { ... }

my sub combinations(Int() $n, Int() $k) {
    return () if $k < 0;
    return ((),) if $n < 1 || $k < 1;

    fail X::OutOfRange.new(
      :what("First parameter"),
      :got($n),
      :range("1..2147483647"),
    ) if nqp::isbig_I(nqp::decont($n));
    fail X::OutOfRange.new(
      :what("Second parameter"),
      :got($k),
      :range("1..2147483647"),
    ) if nqp::isbig_I(nqp::decont($k));

    Seq.new(class :: does Iterator {
        has int $!n;
        has int $!k;
        has Mu $!stack;
        has Mu $!combination;
        method !SET-SELF(\n,\k) {
            $!n = n;
            $!k = k;
            $!stack       := nqp::list_i(0);
            $!combination := nqp::list();
            self
        }
        method new(\n,\k) { nqp::create(self)!SET-SELF(n,k) }

        method pull-one() {
            my int $n = $!n;
            my int $k = $!k;

            while (my int $elems = nqp::elems($!stack)) {
                my int $index = $elems - 1;
                my int $value = nqp::pop_i($!stack);

                while nqp::islt_i($value, $n) && nqp::islt_i($index, $k) {
                    nqp::bindpos($!combination, $index, +$value);
#?if jvm
# temporary fix for RT #128123
                    $index++;
                    $value++;
#?endif
#?if !jvm
                    ++$index;
                    ++$value;
#?endif
                    nqp::push_i($!stack, $value);
                }
                return nqp::clone($!combination) if nqp::iseq_i($index, $k);
            }
            IterationEnd
        }
        method count-only { ([*] ($!n ... 0) Z/ 1 .. min($!n - $!k, $!k)).Int }
        method bool-only(--> True) { }
    }.new($n, $k))
}

sub find-reducer-for-op($op) {
    try my %prec := $op.prec;
    return &METAOP_REDUCE_LEFT if (nqp::isnull(%prec) or ! %prec);
    my $reducer = %prec<prec> eq 'f='
        ?? 'listinfix'
        !! %prec<assoc> // 'left';
    ::('&METAOP_REDUCE_' ~ $reducer.uc);
}

# A List is a (potentially infite) immutable list. The immutability is not
# deep; a List may contain Scalar containers that can be assigned to. However,
# it is not possible to shift/unshift/push/pop/splice/bind. A List is also
# Positional, and so may be indexed.
my class List does Iterable does Positional { # declared in BOOTSTRAP
    # class List is Cool {
    #   The reified elements in the list so far (that is, those that we already
    #   have produced the values for).
    #   has $!reified;
    # 
    #   Object that reifies the rest of the list. We don't just inline it into
    #   the List class itself, because a STORE on Array can clear things and
    #   upset an ongoing iteration. (An easy way to create such a case is to
    #   assign an array with lazy parts into itself.)
    #   has $!todo;

    # The object that goes into $!todo.
    class Reifier {
        # Our copy of the reified elements in the list so far.
        has $!reified;

        # The current iterator, if any, that we're working our way through in
        # order to lazily reify values. Must be depleted before $!future is
        # considered.
        has Iterator $!current-iter;

        # The (possibly lazy) values we've not yet incorporated into the list. The
        # only thing we can't simply copy from $!future into $!reified is a Slip
        # (and so the only reason to have a $!future is that there is at least one
        # Slip).
        has $!future;

        # The reification target (what .reify-* will .push to). Exists so we can
        # share the reification code between List/Array. List just uses its own
        # $!reified buffer; the Array one shoves stuff into Scalar containers
        # first.
        has $!reification-target;

        method reify-at-least(int $elems) {
            $!current-iter := Iterator
              if $!current-iter.DEFINITE 
              && $!current-iter.push-at-least($!reification-target,
                   nqp::sub_i($elems,nqp::elems($!reified))) =:= IterationEnd;

            # there is a future
            if $!future.DEFINITE {

                # still need and can get something from the future
                while nqp::islt_i(nqp::elems($!reified),$elems)
                  && nqp::elems($!future) {
                    my \current := nqp::shift($!future);
                    if nqp::istype(current, Slip) && nqp::isconcrete(current) {
                        my \iter := current.iterator;

                        # The iterator produced enough values to fill the need,
                        # but did not reach its end. We save it for next time.
                        # We know we'll exit the loop, since the < $elems check
                        # must be False (unless the iterator broke contract).
                        $!current-iter := iter
                          unless iter.push-at-least(
                            $!reification-target,
                            nqp::sub_i($elems,nqp::elems($!reified))
                          ) =:= IterationEnd;
                    }
                    else {
                        nqp::stmts(  # doesn't sink
                          $!reification-target.push(current);
                        );
                    }
                }

                # that was the future
                $!future := Mu unless nqp::elems($!future);
            }

            nqp::elems($!reified);
        }

        method reify-until-lazy() {
            $!current-iter := Iterator
              if $!current-iter.DEFINITE
              && $!current-iter.push-until-lazy($!reification-target)
                   =:= IterationEnd;

            if $!future.DEFINITE && !$!current-iter.DEFINITE {
                while nqp::elems($!future) {
                    my \current = nqp::shift($!future);
                    if nqp::istype(current, Slip) && nqp::isconcrete(current) {
                        my \iter = current.iterator;
                        unless iter.push-until-lazy($!reification-target) =:= IterationEnd {
                            $!current-iter := iter;
                            last;
                        }
                    }
                    else {<commit_msg>Remove some =:= from hot paths<commit_after># for our tantrums
my class X::TypeCheck::Splice { ... }
my class Supply { ... }
my class Supplier { ... }

my sub combinations(Int() $n, Int() $k) {
    return () if $k < 0;
    return ((),) if $n < 1 || $k < 1;

    fail X::OutOfRange.new(
      :what("First parameter"),
      :got($n),
      :range("1..2147483647"),
    ) if nqp::isbig_I(nqp::decont($n));
    fail X::OutOfRange.new(
      :what("Second parameter"),
      :got($k),
      :range("1..2147483647"),
    ) if nqp::isbig_I(nqp::decont($k));

    Seq.new(class :: does Iterator {
        has int $!n;
        has int $!k;
        has Mu $!stack;
        has Mu $!combination;
        method !SET-SELF(\n,\k) {
            $!n = n;
            $!k = k;
            $!stack       := nqp::list_i(0);
            $!combination := nqp::list();
            self
        }
        method new(\n,\k) { nqp::create(self)!SET-SELF(n,k) }

        method pull-one() {
            my int $n = $!n;
            my int $k = $!k;

            while (my int $elems = nqp::elems($!stack)) {
                my int $index = $elems - 1;
                my int $value = nqp::pop_i($!stack);

                while nqp::islt_i($value, $n) && nqp::islt_i($index, $k) {
                    nqp::bindpos($!combination, $index, +$value);
#?if jvm
# temporary fix for RT #128123
                    $index++;
                    $value++;
#?endif
#?if !jvm
                    ++$index;
                    ++$value;
#?endif
                    nqp::push_i($!stack, $value);
                }
                return nqp::clone($!combination) if nqp::iseq_i($index, $k);
            }
            IterationEnd
        }
        method count-only { ([*] ($!n ... 0) Z/ 1 .. min($!n - $!k, $!k)).Int }
        method bool-only(--> True) { }
    }.new($n, $k))
}

sub find-reducer-for-op($op) {
    try my %prec := $op.prec;
    return &METAOP_REDUCE_LEFT if (nqp::isnull(%prec) or ! %prec);
    my $reducer = %prec<prec> eq 'f='
        ?? 'listinfix'
        !! %prec<assoc> // 'left';
    ::('&METAOP_REDUCE_' ~ $reducer.uc);
}

# A List is a (potentially infite) immutable list. The immutability is not
# deep; a List may contain Scalar containers that can be assigned to. However,
# it is not possible to shift/unshift/push/pop/splice/bind. A List is also
# Positional, and so may be indexed.
my class List does Iterable does Positional { # declared in BOOTSTRAP
    # class List is Cool {
    #   The reified elements in the list so far (that is, those that we already
    #   have produced the values for).
    #   has $!reified;
    # 
    #   Object that reifies the rest of the list. We don't just inline it into
    #   the List class itself, because a STORE on Array can clear things and
    #   upset an ongoing iteration. (An easy way to create such a case is to
    #   assign an array with lazy parts into itself.)
    #   has $!todo;

    # The object that goes into $!todo.
    class Reifier {
        # Our copy of the reified elements in the list so far.
        has $!reified;

        # The current iterator, if any, that we're working our way through in
        # order to lazily reify values. Must be depleted before $!future is
        # considered.
        has Iterator $!current-iter;

        # The (possibly lazy) values we've not yet incorporated into the list. The
        # only thing we can't simply copy from $!future into $!reified is a Slip
        # (and so the only reason to have a $!future is that there is at least one
        # Slip).
        has $!future;

        # The reification target (what .reify-* will .push to). Exists so we can
        # share the reification code between List/Array. List just uses its own
        # $!reified buffer; the Array one shoves stuff into Scalar containers
        # first.
        has $!reification-target;

        method reify-at-least(int $elems) {
            $!current-iter := Iterator
              if $!current-iter.DEFINITE 
              && nqp::eqaddr(
                   $!current-iter.push-at-least(
                     $!reification-target,
                     nqp::sub_i($elems,nqp::elems($!reified))
                   ),
                   IterationEnd
                 );

            # there is a future
            if $!future.DEFINITE {

                # still need and can get something from the future
                while nqp::islt_i(nqp::elems($!reified),$elems)
                  && nqp::elems($!future) {
                    my \current := nqp::shift($!future);
                    if nqp::istype(current, Slip) && nqp::isconcrete(current) {
                        my \iter := current.iterator;

                        # The iterator produced enough values to fill the need,
                        # but did not reach its end. We save it for next time.
                        # We know we'll exit the loop, since the < $elems check
                        # must be False (unless the iterator broke contract).
                        $!current-iter := iter
                          unless nqp::eqaddr(
                            iter.push-at-least(
                              $!reification-target,
                              nqp::sub_i($elems,nqp::elems($!reified))
                            ),
                            IterationEnd
                          );
                    }
                    else {
                        nqp::stmts(  # doesn't sink
                          $!reification-target.push(current);
                        );
                    }
                }

                # that was the future
                $!future := Mu unless nqp::elems($!future);
            }

            nqp::elems($!reified);
        }

        method reify-until-lazy() {
            $!current-iter := Iterator
              if $!current-iter.DEFINITE
              && nqp::eqaddr(
                   $!current-iter.push-until-lazy($!reification-target),
                   IterationEnd
                 );

            if $!future.DEFINITE && !$!current-iter.DEFINITE {
                while nqp::elems($!future) {
                    my \current = nqp::shift($!future);
                    if nqp::istype(current, Slip) && nqp::isconcrete(current) {
                        my \iter = current.iterator;
                        unless nqp::eqaddr(
                          iter.push-until-lazy($!reification-target),
                          IterationEnd
                        ) {
                            $!current-iter := iter;
                            last;
                        }
                    }
                    else {
{'fraction_non_alphanumeric': 0.12455707903250655, 'fraction_numerical': 0.005392081343398552, 'mean_word_length': 1.4621657500474114, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '182937', 'n_tokens_mistral': 3956, 'n_tokens_neox': 3730, 'n_words': 1105}