File Coverage

blib/lib/Data/Pulp/Pulper.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Data::Pulp::Pulper;
2              
3 6     6   87 use Moose;
  6         15  
  6         61  
4 6     6   59675 use MooseX::AttributeHelpers;
  0            
  0            
5             use Data::Pulp::Carp;
6              
7             sub parse {
8             my $class = shift;
9              
10             my ( @rule, @case, $in_case, $empty_then, $nil_then, $default_then );
11             while ( @_ ) {
12             my $token = shift;
13             if ( $token eq 'case' || $token eq 'if_type' || $token eq 'if_value' || $token eq 'if_object' ) {
14             $in_case = 1;
15             push @case, [ $token, shift ];
16             }
17             elsif ( $in_case ) {
18             if ( $token eq 'then' ) {
19             my $then = shift;
20             push @rule, map { Data::Pulp::Rule->new( kind => $_->[0], matcher => $_->[1], then => $then ) } @case;
21             $in_case = 0;
22             }
23             else {
24             croak "Unrecognized token in case: $token";
25             }
26             }
27             elsif ( $token eq 'empty' ) {
28             $empty_then = shift;
29             }
30             elsif ( $token eq 'nil' ) {
31             $nil_then = shift;
32             }
33             elsif ( $token eq 'default' ) {
34             $default_then = shift;
35             }
36             elsif ( $token eq 'then' ) {
37             croak "Then without opening case ($token)";
38             }
39             else {
40             croak "Unrecognized token in case: $token";
41             }
42             }
43              
44             return __PACKAGE__->new( rule_list => \@rule, empty_then => $empty_then, nil_then => $nil_then, default_then => $default_then );
45             }
46              
47             has [qw/ empty_then nil_then default_then /] => qw/is ro isa Maybe[CodeRef]/;
48             has rule_list => qw/metaclass Collection::Array reader _rule_list isa ArrayRef/, default => sub { [] }, provides => {qw/
49             elements rule_list
50             /};
51              
52             sub pulp {
53             my $self = shift;
54             my $value = shift;
55              
56             my $then;
57             if ( defined $value ) {
58             if ( ref $value || length $value ) {
59             for my $rule ( $self->rule_list ) {
60             if ( $rule->match( $value ) ) {
61             $then = $rule->then;
62             last;
63             }
64             }
65             }
66             elsif ( $then = $self->empty_then ) {
67             }
68             }
69             elsif ( $then = $self->nil_then ) {
70             }
71              
72             $then = $self->default_then unless $then;
73              
74             if ( $then ) {
75             local $_ = $value;
76             return $then->( $_ );
77             }
78              
79             return $value; # Unmolested
80             }
81              
82             sub prepare {
83             my $self = shift;
84             return Data::Pulp::Set->new( pulper => $self, source => shift );
85             }
86              
87             sub set {
88             return shift->prepare( @_ );
89             }
90              
91             package Data::Pulp::Set;
92              
93             use Moose;
94             use Data::Pulp::Carp;
95              
96             use List::Enumerator qw/E/;
97              
98             has pulper => qw/is ro required 1 isa Data::Pulp::Pulper/;
99             has source => qw/is ro/;
100             has _list => qw/is ro lazy_build 1/, handles => [qw/ is_empty /];
101             sub _build__list {
102             my $self = shift;
103              
104             my $source = $self->source;
105             my @list;
106             if ( ref $source eq 'ARRAY' ) {
107             my $count = 0;
108             @list = map { [ $count++, $_ ] } @$source;
109             }
110             elsif ( ref $source eq 'HASH' ) {
111             @list = map { [ $_, $source->{$_} ] } keys %$source;
112             }
113             else {
114             @list = ( [ undef, $source ] );
115             }
116              
117             return E \@list;
118             }
119              
120             sub pulp_value {
121             my $self = shift;
122             my $value = shift;
123             return $self->pulper->pulp( $value );
124             }
125              
126             sub pulp_pair {
127             my $self = shift;
128             my $pair = shift;
129             return $self->pulp_value( $pair->[1] );
130             }
131              
132             sub all {
133             my $self = shift;
134             return $self->_list->map( sub { $self->pulp_pair( $_ ) } );
135             }
136              
137             sub pulp {
138             return shift->first( @_ );
139             }
140              
141             sub get {
142             return shift->first( @_ );
143             }
144              
145             sub first {
146             my $self = shift;
147             return if $self->is_empty;
148             return $self->pulp_pair( $self->_list->first );
149             }
150              
151             sub last {
152             my $self = shift;
153             return if $self->is_empty;
154             return $self->pulp_pair( $self->_list->last );
155             }
156              
157             sub next {
158             my $self = shift;
159             return if $self->is_empty;
160             my $pair;
161             eval {
162             $pair = $self->_list->next;
163             };
164             return unless $pair;
165             return $self->pulp_pair( $pair );
166             }
167              
168             package Data::Pulp::Rule;
169              
170             use Moose;
171             use Data::Pulp::Carp;
172              
173             has kind => qw/is ro required 1 isa Str/;
174             has matcher => qw/is ro required 1 isa Str|CodeRef|RegexpRef/;
175             has then => qw/is ro required 1 isa CodeRef/;
176              
177             sub match {
178             my $self = shift;
179             my $value = shift;
180              
181             my $matcher = $self->matcher;
182             my $kind = $self->kind;
183              
184             if ($kind eq 'case') {
185             }
186             elsif ($kind eq 'if_value') {
187             return unless ! ref $value;
188             }
189             elsif ($kind eq 'if_type') {
190             $value = ref $value;
191             }
192             elsif ($kind eq 'if_object') {
193             return unless blessed $value;
194             }
195             else {
196             croak "Don't know how to match kind \"$kind\"";
197             }
198              
199             if ( ref $matcher eq 'CODE' ) {
200             local $_ = $value;
201             return $matcher->( $value );
202             }
203             elsif ( ref $matcher eq 'Regexp' ) { # Meh, not really used
204             return $value =~ $matcher;
205             }
206             elsif ( ! ref $matcher ) { # Meh, not really used
207             return $value eq $matcher;
208             }
209             else {
210             croak "Don't understand matcher \"$matcher\"";
211             }
212             }
213              
214             sub run {
215             my $self = shift;
216             my $value = shift;
217            
218             {
219             local $_ = $value;
220             return $self->then->( $value );
221             }
222             }
223              
224             1;