File Coverage

blib/lib/Want.pm
Criterion Covered Total %
statement 75 79 94.9
branch 66 74 89.1
condition 22 30 73.3
subroutine 12 12 100.0
pod 5 8 62.5
total 180 203 88.6


line stmt bran cond sub pod time code
1             package Want;
2              
3             require 5.006;
4 7     7   5606 use Carp 'croak';
  7         10  
  7         400  
5 7     7   27 use strict;
  7         9  
  7         202  
6 7     7   25 use warnings;
  7         10  
  7         7105  
7              
8             require Exporter;
9             require DynaLoader;
10              
11             our @ISA = qw(Exporter DynaLoader);
12              
13             our @EXPORT = qw(want rreturn lnoreturn);
14             our @EXPORT_OK = qw(howmany wantref);
15             our $VERSION = '0.26';
16              
17             bootstrap Want $VERSION;
18              
19             my %reftype = (
20             ARRAY => 1,
21             HASH => 1,
22             CODE => 1,
23             GLOB => 1,
24             OBJECT => 1,
25             );
26              
27             sub _wantone {
28 153     153   167 my ($uplevel, $arg) = @_;
29            
30 153         193 my $wantref = wantref($uplevel + 1);
31 153 100 66     853 if ($arg =~ /^\d+$/) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
32 17         63 my $want_count = want_count($uplevel);
33 17   100     110 return ($want_count == -1 || $want_count >= $arg);
34             }
35             elsif (lc($arg) eq 'infinity') {
36 6         42 return (want_count($uplevel) == -1);
37             }
38             elsif ($arg eq 'REF') {
39 2         5 return $wantref;
40             }
41             elsif ($reftype{$arg}) {
42 26         70 return ($wantref eq $arg);
43             }
44             elsif ($arg eq 'REFSCALAR') {
45 3         8 return ($wantref eq 'SCALAR');
46             }
47             elsif ($arg eq 'LVALUE') {
48 14         54 return want_lvalue($uplevel);
49             }
50             elsif ($arg eq 'RVALUE') {
51 8         53 return !want_lvalue($uplevel);
52             }
53             elsif ($arg eq 'VOID') {
54 4         22 return !defined(wantarray_up($uplevel));
55             }
56             elsif ($arg eq 'SCALAR') {
57 10         32 my $gimme = wantarray_up($uplevel);
58 10   66     81 return (defined($gimme) && 0 == $gimme);
59             }
60             elsif ($arg eq 'BOOL' || $arg eq 'BOOLEAN') {
61 47         55 return want_boolean(bump_level($uplevel));
62             }
63             elsif ($arg eq 'LIST') {
64 11         57 return wantarray_up($uplevel);
65             }
66             elsif ($arg eq 'COUNT') {
67 0         0 croak("want: COUNT must be the *only* parameter");
68             }
69             elsif ($arg eq 'ASSIGN') {
70 5         8 return !!wantassign($uplevel + 1);
71             }
72             else {
73 0         0 croak ("want: Unrecognised specifier $arg");
74             }
75             }
76              
77             sub want {
78 164 100 100 164 1 6422 if (@_ == 1 && $_[0] eq 'ASSIGN') {
79 12         16 @_ = (1);
80 12         19 goto &wantassign;
81             }
82 152         198 want_uplevel(1, @_);
83             }
84              
85             # Simulate the propagation of context through a return value.
86             sub bump_level {
87 246     246 0 187 my ($level) = @_;
88 246         168 for(;;) {
89 246         967 my ($p, $r) = parent_op_name($level+1);
90 246 50 66     823 if ($p eq "return"
      33        
91             or $p eq "(none)" && $r =~ /^leavesub(lv)?$/)
92             {
93 0         0 ++$level
94             }
95             else {
96 246         506 return $level
97             }
98             }
99             }
100              
101             sub want_uplevel {
102 152     152 0 182 my ($level, @args) = @_;
103              
104             # Deal with special cases (for RFC21-consistency):
105 152 100       233 if (1 == @args) {
106 133         180 @_ = (1 + $level);
107 133 100       205 goto &wantref if $args[0] eq 'REF';
108 128 100       182 goto &howmany if $args[0] eq 'COUNT';
109 113 50       162 goto &wantassign if $args[0] eq 'ASSIGN';
110             }
111              
112 132         348 for my $arg (map split, @args) {
113 153 100       312 if ($arg =~ /^!(.*)/) {
114 28 100       48 return 0 unless !_wantone(2 + $level, $1);
115             }
116             else {
117 125 100       185 return 0 unless _wantone(2 + $level, $arg);
118             }
119             }
120            
121 74         176 return 1;
122             }
123              
124             sub howmany () {
125 18     18 1 57 my $level = bump_level(@_, 1);
126 18         56 my $count = want_count($level);
127 18 100       49 return ($count < 0 ? undef : $count);
128             }
129              
130             sub wantref {
131 169     169 1 1057 my $level = bump_level(@_, 1);
132 169         401 my $n = parent_op_name($level);
133 169 100 100     1029 if ($n eq 'rv2av') {
    100 66        
    100          
    100          
    100          
    100          
    50          
134 19         30 return "ARRAY";
135             }
136             elsif ($n eq 'rv2hv') {
137 20         24 return "HASH";
138             }
139             elsif ($n eq 'rv2cv' || $n eq 'entersub') {
140 9         15 return "CODE";
141             }
142             elsif ($n eq 'rv2gv' || $n eq 'gelem') {
143 2         4 return "GLOB";
144             }
145             elsif ($n eq 'rv2sv') {
146 1         4 return "SCALAR";
147             }
148             elsif ($n eq 'method_call') {
149 2         3 return 'OBJECT';
150             }
151             elsif ($n eq 'multideref') {
152 0         0 return first_multideref_type($level);
153             }
154             else {
155 116         149 return "";
156             }
157             }
158              
159             sub wantassign {
160 17     17 0 13 my $uplevel = shift();
161 17 100       38 return unless want_lvalue($uplevel);
162 12         11 my $r = want_assign(bump_level($uplevel));
163 12 100       15 if (want('BOOL')) {
164 8   66     30 return (defined($r) && 0 != $r);
165             }
166             else {
167 4 50       6 return $r ? (want('SCALAR') ? $r->[$#$r] : @$r) : ();
    50          
168             }
169             }
170              
171             sub rreturn (@) {
172 2 100   2 1 340 if (want_lvalue(1)) {
173 1         150 croak "Can't rreturn in lvalue context";
174             }
175 1         6 double_return();
176              
177             # Extra scope needed to work with perl-5.19.7 or greater.
178             # Prevents the return being optimised out, which is needed
179             # since it's actually going to be used a stack level above
180             # this sub.
181             {
182 1 50       1 return wantarray ? @_ : $_[$#_];
  1         5  
183             }
184             }
185              
186             sub lnoreturn () {
187 5 100 66 5 1 155 if (!want_lvalue(1) || !want_assign(1)) {
188 1         78 croak "Can't lnoreturn except in ASSIGN context";
189             }
190 4         7 double_return();
191              
192             # Extra scope needed to work with perl-5.19.7 or greater.
193             # Prevents the return being optimised out, which is needed
194             # since it's actually going to be used a stack level above
195             # this sub.
196             {
197 4         3 return disarm_temp(my $undef);
  4         9  
198             }
199             }
200              
201             # Some naughty people were relying on these internal methods.
202             *_wantref = \&wantref;
203             *_wantassign = \&wantassign;
204              
205             1;
206              
207             __END__