Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Get rid of HYPER runtime cost for recursion hint
Suggested by timotimo++
  • Loading branch information
niner committed Sep 14, 2015
1 parent 99ee82c commit 87a74dc
Showing 1 changed file with 16 additions and 16 deletions.
32 changes: 16 additions & 16 deletions src/core/metaops.pm
Expand Up @@ -311,11 +311,11 @@ sub METAOP_HYPER_CALL(\list, |args) { deepmap(-> $c { $c(|args) }, list) }

proto sub HYPER(|) { * }

multi sub HYPER(&op, \left, \right, :$dwim-left, :$dwim-right, :$recursing) {
multi sub HYPER(&op, \left, \right, :$dwim-left, :$dwim-right) {
op(left, right);
}

multi sub HYPER(&op, Associative:D \left, Associative:D \right, :$dwim-left, :$dwim-right, :$recursing) {
multi sub HYPER(&op, Associative:D \left, Associative:D \right, :$dwim-left, :$dwim-right) {
my %keyset;
if !$dwim-left {
%keyset{$_} = 1 for left.keys;
Expand All @@ -329,59 +329,59 @@ multi sub HYPER(&op, Associative:D \left, Associative:D \right, :$dwim-left, :$d
my @keys = %keyset.keys;
my $type = left.WHAT;
my \result := $type.new;
result = @keys Z=> HYPER(&op, left{@keys}, right{@keys}, :$dwim-left, :$dwim-right, :recursing);
result = @keys Z=> HYPER(&op, left{@keys}, right{@keys}, :$dwim-left, :$dwim-right);
nqp::iscont(left) ?? result.item !! result;
}

multi sub HYPER(&op, Associative:D \left, \right, :$dwim-left, :$dwim-right, :$recursing) {
multi sub HYPER(&op, Associative:D \left, \right, :$dwim-left, :$dwim-right) {
my @keys = left.keys;
my $type = left.WHAT;
my \result := $type.new;
result = @keys Z=> HYPER(&op, left{@keys}, right, :$dwim-left, :$dwim-right, :recursing);
result = @keys Z=> HYPER(&op, left{@keys}, right, :$dwim-left, :$dwim-right);
nqp::iscont(left) ?? result.item !! result;
}

multi sub HYPER(&op, \left, Associative:D \right, :$dwim-left, :$dwim-right, :$recursing) {
multi sub HYPER(&op, \left, Associative:D \right, :$dwim-left, :$dwim-right) {
my @keys = right.keys;
my $type = right.WHAT;
my \result := $type.new;
result = @keys Z=> HYPER(&op, left, right{@keys}, :$dwim-left, :$dwim-right, :recursing);
result = @keys Z=> HYPER(&op, left, right{@keys}, :$dwim-left, :$dwim-right);
nqp::iscont(right) ?? result.item !! result;
}

multi sub HYPER(&operator, Positional:D \left, \right, :$dwim-left, :$dwim-right, :$recursing) {
multi sub HYPER(&operator, Positional:D \left, \right, :$dwim-left, :$dwim-right) {
my @result;
X::HyperOp::Infinite.new(:side<left>, :&operator).throw if left.is-lazy;
my int $elems = left.elems;
X::HyperOp::NonDWIM.new(:&operator, :left-elems($elems), :right-elems(1), :$recursing).throw
X::HyperOp::NonDWIM.new(:&operator, :left-elems($elems), :right-elems(1), :recursing(callframe(3).code.name eq 'HYPER')).throw
unless $elems == 1 or $elems > 1 and $dwim-right or $elems == 0 and $dwim-left || $dwim-right;
my \lefti := left.iterator;
my int $i = 0;
until (my \value := lefti.pull-one) =:= IterationEnd {
@result[$i++] := HYPER(&operator, value, right, :$dwim-left, :$dwim-right, :recursing);
@result[$i++] := HYPER(&operator, value, right, :$dwim-left, :$dwim-right);
}
# Coerce to the original type if it's a subtype of List
my $type = nqp::istype(left, List) ?? left.WHAT !! List;
nqp::iscont(left) ?? $type(|@result.eager).item !! $type(|@result.eager)
}

multi sub HYPER(&operator, \left, Positional:D \right, :$dwim-left, :$dwim-right, :$recursing) {
multi sub HYPER(&operator, \left, Positional:D \right, :$dwim-left, :$dwim-right) {
my @result;
X::HyperOp::Infinite.new(:side<right>, :&operator).throw if right.is-lazy;
my int $elems = right.elems;
X::HyperOp::NonDWIM.new(:&operator, :left-elems(1), :right-elems($elems), :$recursing).throw
X::HyperOp::NonDWIM.new(:&operator, :left-elems(1), :right-elems($elems), :recursing(callframe(3).code.name eq 'HYPER')).throw
unless $elems == 1 or $elems > 1 and $dwim-left or $elems == 0 and $dwim-left || $dwim-right;
my \righti := right.iterator;
my int $i = 0;
until (my \value := righti.pull-one) =:= IterationEnd {
@result[$i++] := HYPER(&operator, left, value, :$dwim-left, :$dwim-right, :recursing);
@result[$i++] := HYPER(&operator, left, value, :$dwim-left, :$dwim-right);
}
# Coerce to the original type if it's a subtype of List
my $type = nqp::istype(right, List) ?? right.WHAT !! List;
nqp::iscont(right) ?? $type(|@result.eager).item !! $type(|@result.eager)
}

multi sub HYPER(&operator, Iterable:D \left, Iterable:D \right, :$dwim-left, :$dwim-right, :$recursing) {
multi sub HYPER(&operator, Iterable:D \left, Iterable:D \right, :$dwim-left, :$dwim-right) {
my \left-iterator = left.iterator;
my \right-iterator = right.iterator;

Expand Down Expand Up @@ -454,14 +454,14 @@ multi sub HYPER(&operator, Iterable:D \left, Iterable:D \right, :$dwim-left, :$d
my \leftv := lefti.pull-one;
my \rightv := righti.pull-one;

X::HyperOp::NonDWIM.new(:&operator, :left-elems(lefti.count-elems), :right-elems(righti.count-elems), :$recursing).throw
X::HyperOp::NonDWIM.new(:&operator, :left-elems(lefti.count-elems), :right-elems(righti.count-elems), :recursing(callframe(3).code.name eq 'HYPER')).throw
if !$dwim-left and !$dwim-right and (lefti.ended != righti.ended);

last if ($dwim-left and $dwim-right) ?? (lefti.ended and righti.ended) !!
(($dwim-left or lefti.ended) and ($dwim-right or righti.ended));
last if $++ == 0 and ($dwim-left and lefti.ended or $dwim-right and righti.ended);

result.push(HYPER(&operator, leftv, rightv, :$dwim-left, :$dwim-right, :recursing));
result.push(HYPER(&operator, leftv, rightv, :$dwim-left, :$dwim-right));
}

# Coerce to the original type
Expand Down

1 comment on commit 87a74dc

@vendethiel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't the callframe actually poison the scope, thus making optimizations there hard/impossible?

Please sign in to comment.