From: Vincent Pit Date: Sat, 29 Nov 2008 23:46:05 +0000 (+0100) Subject: Work in progress X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FSub-Nary.git;a=commitdiff_plain;h=refs%2Fheads%2Fexitdie Work in progress --- diff --git a/lib/Sub/Nary.pm b/lib/Sub/Nary.pm index 2f700b6..313381f 100644 --- a/lib/Sub/Nary.pm +++ b/lib/Sub/Nary.pm @@ -213,7 +213,7 @@ sub power { my %ops; $ops{$_} = 1 for scalops; -$ops{$_} = 0 for qw/stub nextstate pushmark iter unstack/; +$ops{$_} = 0 for qw/stub nextstate iter unstack/; $ops{$_} = 1 for qw/padsv/; $ops{$_} = 'list' for qw/padav/; $ops{$_} = 'list' for qw/padhv rv2hv/; @@ -234,11 +234,33 @@ $ops{$_} = { 0 => 0.5, 4 => 0.5 } for qw/gnbyname gnbyaddr gnetent/; $ops{$_} = { 0 => 0.5, 3 => 0.5 } for qw/gpbyname gpbynumber gprotoent/; $ops{$_} = { 0 => 0.5, 4 => 0.5 } for qw/gsbyname gsbyport gservent/; +# Stolen from B::Deparse + +sub padval { $_[0]->{cv}->[0]->PADLIST->ARRAYelt(1)->ARRAYelt($_[1]) } + +sub gv_or_padgv { + my ($self, $op) = @_; + if (class($op) eq 'PADOP') { + return $self->padval($op->padix) + } else { # class($op) eq "SVOP" + return $op->gv; + } +} + +sub const_sv { + my ($self, $op) = @_; + my $sv = $op->sv; + # the constant could be in the pad (under useithreads) + $sv = $self->padval($op->targ) unless $$sv; + return $sv; +} + sub enter { my ($self, $cv) = @_; return undef, 'list' if class($cv) ne 'CV'; my $op = $cv->ROOT; + return undef, 'list' if null $op; my $tag = tag($op); return undef, { %{$self->{cache}->{$tag}} } if exists $self->{cache}->{$tag}; @@ -256,54 +278,91 @@ sub enter { return undef, $r; } +use Test::More; +use Data::Dumper; + sub inspect { my ($self, $op) = @_; my $n = name($op); - return add($self->inspect_kids($op)), undef if $n eq 'return'; - my $meth = $self->can('pp_' . $n); return $self->$meth($op) if $meth; + my $l; if (exists $ops{$n}) { - my $l = $ops{$n}; + $l = $ops{$n}; $l = { %$l } if ref $l; - return undef, $l; } - if (class($op) eq 'LOGOP' and not null $op->first) { - my @res; + my $c = class($op); + $meth = $self->can('OPc_' . $c); + if ($meth) { + my ($r, $lc) = $self->$meth($op); + $lc = $l if defined $l; + return $r, $lc; + } - my $op = $op->first; - my ($r1, $l1) = $self->inspect($op); - return $r1, $l1 if defined $r1 and zero $l1; - my $c = count $l1; + return undef, (defined $l) ? $l : 0; +} - $op = $op->sibling; - my ($r2, $l2) = $self->inspect($op); +# UNOPs - $op = $op->sibling; - my ($r3, $l3); - if (null $op) { - # If the logop has no else branch, it can also return the *scalar* result of - # the conditional - $l3 = { 1 => 1 }; - } else { - ($r3, $l3) = $self->inspect($op); - } +sub OPc_UNOP { $_[0]->inspect($_[1]->first); } - my $r = add $r1, scale $c / 2, add $r2, $r3; - my $l = scale $c / 2, add $l2, $l3; - return $r, $l - } +# BINOPs + +sub OPc_BINOP { + my ($self, $op) = @_; + + my ($r, $l1) = $self->inspect($op->first); + return $r, $l1 unless defined $l1; + + my ($r2, $l2) = $self->inspect($op->last); + my $c = 1 - count $r; + $r = add $r, scale $c, $r2 if defined $r2; + + my $l = scale +(1 - count $r), normalize combine $l1, $l2; - return $self->inspect_kids($op); + return $r, $l; } -sub inspect_kids { +# LOGOPs + +sub OPc_LOGOP { my ($self, $op) = @_; + my @res; + + $op = $op->first; + return undef, 0 if null $op; + + my ($r1, $l1) = $self->inspect($op); + return $r1, $l1 if defined $r1 and zero $l1; + my $c = count $l1; + + $op = $op->sibling; + my ($r2, $l2) = $self->inspect($op); + + $op = $op->sibling; + my ($r3, $l3); + if (null $op) { + # If the logop has no else branch, it can also return the *scalar* result of + # the conditional + $l3 = { 1 => 1 }; + } else { + ($r3, $l3) = $self->inspect($op); + } - return undef, 0 unless $op->flags & OPf_KIDS; + my $r = add $r1, scale $c / 2, add $r2, $r3; + my $l = scale $c / 2, add $l2, $l3; + return $r, $l; + + return $self->OPc_LISTOP($op); +} + +# LISTOPs + +sub OPc_LISTOP { + my ($self, $op) = @_; $op = $op->first; return undef, 0 if null $op; @@ -340,26 +399,7 @@ sub inspect_kids { return $r, $l; } -# Stolen from B::Deparse - -sub padval { $_[0]->{cv}->[0]->PADLIST->ARRAYelt(1)->ARRAYelt($_[1]) } - -sub gv_or_padgv { - my ($self, $op) = @_; - if (class($op) eq 'PADOP') { - return $self->padval($op->padix) - } else { # class($op) eq "SVOP" - return $op->gv; - } -} - -sub const_sv { - my ($self, $op) = @_; - my $sv = $op->sv; - # the constant could be in the pad (under useithreads) - $sv = $self->padval($op->targ) unless $$sv; - return $sv; -} +sub pp_return { add($_[0]->OPc_LISTOP($_[1])), undef } sub pp_entersub { my ($self, $op) = @_; @@ -388,8 +428,8 @@ sub pp_entersub { $next = $next->sibling; } $n = name($op) - } while ($op->flags & OPf_KIDS and { map { $_ => 1 } qw/null leave/ }->{$n}); - return 'list', undef unless { map { $_ => 1 } qw/gv refgen/ }->{$n}; + } while $op->flags & OPf_KIDS and ($n eq 'null' or $n eq 'leave'); + return 'list', undef unless $n eq 'gv' or $n eq 'refgen'; local $self->{sub} = 1; my ($rc, $lc) = $self->inspect($op); return $r, scale $c, $lc; @@ -429,7 +469,7 @@ sub pp_exit { sub pp_die { my ($self, $op) = @_; - my ($r, undef) = $self->inspect_kids($op); + my ($r, undef) = $self->OPc_LISTOP($op); if (defined $r) { my $c = 1 - count $r; $r->{die} = $c if $c; @@ -505,6 +545,8 @@ sub pp_sassign { return $r, $c ? { 1 => $c } : undef } +=cut + sub pp_aassign { my ($self, $op) = @_; @@ -517,10 +559,12 @@ sub pp_aassign { $self->inspect($op); } +=cut + sub pp_leavetry { my ($self, $op) = @_; - my ($r, $l) = $self->inspect_kids($op); + my ($r, $l) = $self->OPc_LISTOP($op); if (defined $r) { my $d = delete $r->{die}; return $r, $l if not defined $d; diff --git a/samples/cx.pl b/samples/cx.pl index 14cb237..9143830 100755 --- a/samples/cx.pl +++ b/samples/cx.pl @@ -71,7 +71,7 @@ sub ifr { } my $code = \&wut; - +$code = sub { for (do { return 1, 2, 3 }) { } return 1, 2; }; print STDERR $bd->coderef2text($code), "\n"; B::Concise::walk_output(\*STDERR); diff --git a/t/92-pod-coverage.t b/t/92-pod-coverage.t index b16040e..777f79e 100644 --- a/t/92-pod-coverage.t +++ b/t/92-pod-coverage.t @@ -16,7 +16,7 @@ eval "use Pod::Coverage $min_pc"; plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage" if $@; all_pod_coverage_ok({ also_private => [ - qr/^inspect/, qr/^pp_/, qw/enter/, + qr/^inspect/, qr/^pp_/, qr/^OPc_/, qw/enter/, qw/tag scalops/, qw/null zero count scale normalize add combine cumulate power/, qw/name const_sv gv_or_padgv padval/