X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=lib%2FSub%2FNary.pm;h=52a3f8402e4c4783a0441da8ed35b24f4466ad9f;hb=02510517a867d6f89d6dac825672e183e075e97e;hp=21f53b0be6480a9b9e308d6677a783b533f13afa;hpb=93afac3588786704db6d9549d3bf469ba1b5598d;p=perl%2Fmodules%2FSub-Nary.git diff --git a/lib/Sub/Nary.pm b/lib/Sub/Nary.pm index 21f53b0..52a3f84 100644 --- a/lib/Sub/Nary.pm +++ b/lib/Sub/Nary.pm @@ -262,7 +262,7 @@ sub inspect { my $op = $op->first; my ($r1, $l1) = $self->inspect($op); - return $r1, $l1 if $r1 and zero $l1; + return $r1, $l1 if defined $r1 and zero $l1; my $c = count $l1; $op = $op->sibling; @@ -273,7 +273,7 @@ sub inspect { if (null $op) { # If the logop has no else branch, it can also return the *scalar* result of # the conditional - $l3 = { 1 => $c }; + $l3 = { 1 => 1 }; } else { ($r3, $l3) = $self->inspect($op); } @@ -311,18 +311,20 @@ sub inspect_kids { $op = $op->first; redo; } - diag "> $n ($c)" if $DEBUG; + diag "> $n" if $DEBUG; my ($rc, $lc) = $self->inspect($op); + $c = 1 - count $r; + diag Dumper [ $c, $r, \@l, $rc, $lc ] if $DEBUG; $r = add $r, scale $c, $rc if defined $rc; - if ($rc and not defined $lc) { + if (not defined $lc) { @l = (); last; } push @l, scale $c, $lc; - $c *= count $lc if defined $lc; } - my $l = combine @l; +# diag Dumper \@l if $DEBUG; + my $l = scale +(1 - count $r), normalize combine @l; return $r, $l; } @@ -438,7 +440,7 @@ sub pp_const { if ($c eq 'AV') { $n = $sv->FILL + 1 } elsif ($c eq 'HV') { - $n = 2 * $sv->FILL + $n = 2 * $sv->KEYS } return undef, $n @@ -482,16 +484,32 @@ sub pp_leaveloop { $op = $op->first; my ($r1, $l1); - if (name($op) eq 'enteriter') { + my $for; + if (name($op) eq 'enteriter') { # for loop ? + $for = 1; ($r1, $l1) = $self->inspect($op); - return $r1, $l1 if $r1 and zero $l1; + return $r1, $l1 if defined $r1 and zero $l1; } $op = $op->sibling; - my $r = (name($op->first) eq 'and') ? ($self->inspect($op->first->first->sibling))[0] - : ($self->inspect($op))[0]; + my ($r2, $l2); + if (name($op->first) eq 'and') { + ($r2, $l2) = $self->inspect($op->first->first); + return $r2, $l2 if defined $r2 and zero $l2; + my $c = count $l2; + return { list => 1 }, undef if !$for and defined $r2; + my ($r3, $l3) = $self->inspect($op->first->first->sibling); + return { list => 1 }, undef if defined $r3 and defined $l3; + $r2 = add $r2, scale $c, $r3; + } else { + ($r2, $l2) = $self->inspect($op); + return { list => 1 }, undef if defined $r2 and defined $l2; + } + + my $r = (defined $r1) ? add $r1, scale +(1 - count $r1), $r2 + : $r2; my $c = 1 - count $r; - diag "& leaveloop" if $DEBUG; + diag "& leaveloop $c" if $DEBUG; return $r, $c ? { 0 => $c } : undef; } @@ -522,7 +540,7 @@ sub pp_flip { } my $c = 1 - count $r; - return $r, ($l && $c) ? { 'list' => $c } : undef + return $r, $c ? { 'list' => $c } : undef } sub pp_grepwhile { @@ -533,20 +551,20 @@ sub pp_grepwhile { $op = $op->first->sibling; my ($r2, $l2) = $self->inspect($op->sibling); - return $r2, $l2 if $r2 and zero $l2; - diag Dumper [ $r2, $l2 ] if $DEBUG; - my $c = count $l2; # First one to happen + return $r2, $l2 if defined $r2 and zero $l2; + my $c2 = count $l2; # First one to happen my ($r1, $l1) = $self->inspect($op); - diag Dumper [ $r1, $l1 ] if $DEBUG; - return (add $r2, scale $c, $r1), undef if $r1 and zero $l1 and not zero $l2; - return { 'list' => 1 }, undef if list $l2; + return (add $r2, scale $c2, $r1), undef if defined $r1 and zero $l1 + and not zero $l2; + diag Dumper [ [ $r1, $l1 ], [ $r2, $l2 ] ] if $DEBUG; + my $c1 = count $l1; $l2 = { $l2 => 1 } unless ref $l2; - my $r = add $r2, scale $c, - normalize - add map { power $r1, $_, $l2->{$_} } keys %$l2; - $c = 1 - count $r; + my $r = add $r2, + scale $c2, + add map { scale $l2->{$_}, cumulate $r1, $_, $c1 } keys %$l2; + my $c = 1 - count $r; return $r, $c ? { ((zero $l2) ? 0 : 'list') => $c } : undef; } @@ -558,18 +576,20 @@ sub pp_mapwhile { $op = $op->first->sibling; my ($r2, $l2) = $self->inspect($op->sibling); - return $r2, $l2 if $r2 and zero $l2; - my $c = count $l2; # First one to happen + return $r2, $l2 if defined $r2 and zero $l2; + my $c2 = count $l2; # First one to happen my ($r1, $l1) = $self->inspect($op); - return (add $r2, scale $c, $r1), undef if $r1 and zero $l1 and not zero $l2; + return (add $r2, scale $c2, $r1), undef if defined $r1 and zero $l1 + and not zero $l2; diag Dumper [ [ $r1, $l1 ], [ $r2, $l2 ] ] if $DEBUG; + my $c1 = count $l1; $l2 = { $l2 => 1 } unless ref $l2; - my $r = add $r2, scale $c, - normalize - add map { power $r1, $_, $l2->{$_} } keys %$l2; - $c = 1 - count $r; + my $r = add $r2, + scale $c2, + add map { scale $l2->{$_}, cumulate $r1, $_, $c1 } keys %$l2; + my $c = 1 - count $r; my $l = scale $c, normalize add map { power $l1, $_, $l2->{$_} } keys %$l2; return $r, $l; }