File Coverage

blib/lib/Contextual/Return/Wrapper.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Contextual::Return::Wrapper;
2              
3 3     3   25589 use 5.008009;
  3         9  
  3         98  
4 3     3   15 use strict;
  3         5  
  3         90  
5 3     3   14 use warnings;
  3         9  
  3         129  
6              
7             our $VERSION = '0.01';
8              
9 3     3   3070 use Class::ISA ;
  0            
  0            
10             use List::Util qw( first ) ;
11              
12             my $function_code_ref ;
13             my $behavior_of ;
14              
15             $behavior_of->{Listify}{CODE} = sub {
16             my ( $ref, $symbol_name, @context ) = @_ ;
17              
18             return sub { @{ [ $ref->( @_ ) ] }[0..$#_] } ;
19             } ;
20              
21             $behavior_of->{ReturnContext}{CODE} = sub {
22             my ( $ref, $symbol_name, @context ) = @_ ;
23              
24             my %behavior = map { $_->[1] => $_->[3] } @context ;
25             $behavior{requires} ||= {} ;
26              
27             return sub {
28             my $context = wantarray ?
29             $behavior{requires}{void}
30             || $behavior{requires}{scalar}
31             : defined wantarray
32             ? $behavior{requires}{array}
33             || $behavior{requires}{void}
34             || $behavior{scalar}
35             : $behavior{requires}{array}
36             || $behavior{requires}{scalar}
37             || $behavior{void} ;
38              
39             return ( $context || sub { shift ; @_ }
40             )->( $symbol_name, $ref->( @_ ) ) ;
41             } ;
42             } ;
43              
44             $behavior_of->{ReturnContext}{requires}{array} = { array => sub {
45             carp( "$_[0]() requires array context" ) ;
46             shift ; @_ ;
47             } } ;
48             $behavior_of->{ReturnContext}{requires}{scalar} = { scalar => sub {
49             carp( "$_[0]() requires scalar context" ) ;
50             shift ; @_ ;
51             } } ;
52             $behavior_of->{ReturnContext}{requires}{void} = { void => sub {
53             carp( "$_[0]() requires void context" ) ;
54             shift ; @_ ;
55             } } ;
56              
57             $behavior_of->{ReturnContext}{scalar}{first} = sub { shift ; $_[0] } ;
58             $behavior_of->{ReturnContext}{scalar}{last} = sub { shift ; $_[-1] } ;
59             $behavior_of->{ReturnContext}{scalar}{count} = sub { shift ; @_ } ;
60             $behavior_of->{ReturnContext}{scalar}{arrayref} = sub { shift ; [ @_ ] } ;
61             $behavior_of->{ReturnContext}{scalar}{array_ref} = sub { shift ; [ @_ ] } ;
62             $behavior_of->{ReturnContext}{scalar}{warn} = sub {
63             carp( "$_[0]() called in scalar context" ) ;
64             shift ; @_ ;
65             } ;
66              
67             $behavior_of->{ReturnContext}{void}{warn} = sub {
68             carp( "$_[0]() called in void context" ) ;
69             shift ; @_ ;
70             } ;
71              
72             sub carp {
73             printf STDERR "Warning: %s at %s line %d.\n",
74             $_[0], @{ [ caller( 2 ) ] }[ 1, 2 ] ;
75             }
76              
77             sub usage {
78             my ( $package, $symbol, $referent, $attr, $behave_how_arg,
79             $phase, @debug ) = @_ ;
80             $attr, @debug
81              
82             }
83              
84             sub MODIFY_CODE_ATTRIBUTES {
85             my( $package, $ref, $symbol_name, @args ) = @_ ;
86             my $bad_argument = $symbol_name ;
87              
88             if ( $symbol_name =~ s{ ( \(.*?\) ) \Z }{}msx ) {
89             @args = eval( $1 ) ;
90             return $bad_argument unless defined $args[0] ;
91             }
92            
93             my %behavior_args = @args == 0
94             ? ('') x2
95             : ( @args, ( @args %2 ? ('') : () ) ) ;
96              
97             return ( $symbol_name )
98             unless exists $behavior_of->{$symbol_name}->{CODE} ;
99              
100             my @closure_inputs = map { [ @$_, _value_of( $behavior_of, @$_ ) ] }
101             map { [ $symbol_name,
102             ( $_ ? ( $_ => $behavior_args{$_} ) : () )
103             ] }
104             keys %behavior_args ;
105              
106             my $bad = first { ! $_->[-1] } @closure_inputs ;
107             return sprintf qq[%s( %s => '%s' )], @$bad if $bad ;
108              
109             $function_code_ref->{$ref} = [ @closure_inputs ] ;
110             return () ;
111             }
112              
113             sub import {
114             my ( $package ) = @_ ;
115              
116             no strict qw( refs ) ;
117             no warnings qw( redefine ) ;
118              
119             do {
120             my @context = @{ $function_code_ref->{ $_->[2] } } ;
121             *{"$_->[0]"} = $behavior_of->{ $context[0][0] }->{CODE}->(
122             $_->[2], $_->[1], @context ) ;
123             } foreach
124             grep $_->[2] && $function_code_ref->{ $_->[2] },
125             map { [ $_, *{"$_"}{NAME}, *{"$_"}{CODE} ] }
126             map {"${package}::$_"}
127             keys %{"${package}::"} ;
128              
129             goto &export ;
130             }
131              
132             sub export {
133             my ( $package ) = @_ ;
134              
135             my ( $match, $super ) ;
136             my @super = Class::ISA::super_path( $package ) ;
137             my @siblings = @super ;
138              
139             while ( @siblings && ! ( $match = __PACKAGE__ eq shift @siblings )
140             ) {} ;
141             ## See perlmonks node 1047054
142             first { $super = $_->can('import') } $match ? @siblings : @super ;
143             goto &$super if $super ;
144             return ;
145             }
146              
147             sub _value_of {
148             my ( $ref, $key, @more ) = @_ ;
149             return @more && exists $ref->{$key}
150             ? _value_of( $ref->{$key}, @more )
151             : $ref->{$key} ;
152             }
153              
154             1;
155             __END__