File Coverage

blib/lib/Perl/ToPerl6/Theme.pm
Criterion Covered Total %
statement 53 64 82.8
branch 4 12 33.3
condition 3 6 50.0
subroutine 14 15 93.3
pod 4 4 100.0
total 78 101 77.2


line stmt bran cond sub pod time code
1             package Perl::ToPerl6::Theme;
2              
3 1     1   22 use 5.006001;
  1         3  
4 1     1   6 use strict;
  1         2  
  1         23  
5 1     1   4 use warnings;
  1         2  
  1         33  
6 1     1   4 use English qw(-no_match_vars);
  1         3  
  1         10  
7 1     1   474 use Readonly;
  1         2  
  1         43  
8              
9 1     1   5 use Exporter 'import';
  1         1  
  1         27  
10              
11 1     1   4 use List::MoreUtils qw(any);
  1         3  
  1         12  
12              
13 1     1   420 use Perl::ToPerl6::Utils qw{ :characters :data_conversion };
  1         1  
  1         61  
14 1     1   262 use Perl::ToPerl6::Exception::Fatal::Internal qw{ &throw_internal };
  1         2  
  1         91  
15             use Perl::ToPerl6::Exception::Configuration::Option::Global::ParameterValue
16 1     1   7 qw{ &throw_global_value };
  1         1  
  1         28  
17              
18             #-----------------------------------------------------------------------------
19              
20             Readonly::Array our @EXPORT_OK => qw{
21             $RULE_INVALID_CHARACTER_REGEX
22             cook_rule
23             };
24              
25             #-----------------------------------------------------------------------------
26              
27             Readonly::Scalar our $RULE_INVALID_CHARACTER_REGEX =>
28             qr/ ( [^()\s\w\d+\-*&|!] ) /xms;
29              
30             #-----------------------------------------------------------------------------
31              
32             Readonly::Scalar my $CONFIG_KEY => 'theme';
33              
34             #-----------------------------------------------------------------------------
35              
36             sub new {
37              
38 4     4 1 2257 my ( $class, %args ) = @_;
39 4         12 my $self = bless {}, $class;
40 4         17 $self->_init( %args );
41 4         21 return $self;
42             }
43              
44             #-----------------------------------------------------------------------------
45              
46             sub _init {
47              
48 4     4   7 my ($self, %args) = @_;
49 4   66     19 my $rule = $args{-rule} || $EMPTY;
50              
51 4 50       17 if ( $rule =~ m/$RULE_INVALID_CHARACTER_REGEX/xms ) {
52 0         0 throw_global_value
53             option_name => $CONFIG_KEY,
54             option_value => $rule,
55             message_suffix => qq{contains an invalid character: "$1".};
56             }
57              
58 4         10 $self->{_rule} = cook_rule( $rule );
59              
60 4         8 return $self;
61             }
62              
63             #-----------------------------------------------------------------------------
64              
65             sub rule {
66 0     0 1 0 my $self = shift;
67 0         0 return $self->{_rule};
68             }
69              
70             #-----------------------------------------------------------------------------
71              
72             sub transformer_is_thematic {
73              
74 37     37 1 75 my ($self, %args) = @_;
75             my $transformer = $args{-transformer}
76 37   33     109 || throw_internal 'The -transformer argument is required';
77 37 50       790 ref $transformer
78             || throw_internal 'The -transformer must be an object';
79              
80 37 50       194 my $rule = $self->{_rule} or return 1;
81 0         0 my %themes = hashify( $transformer->get_themes() );
82              
83             # This bit of magic turns the rule into a perl expression that can be
84             # eval-ed for truth. Each theme name in the rule is translated to 1 or 0
85             # if the $transformer belongs in that theme. For example:
86             #
87             # 'bugs && (pbp || core)' ...could become... '1 && (0 || 1)'
88              
89 0         0 my $as_code = $rule; #Making a copy, so $rule is preserved
90 0 0       0 $as_code =~ s/ ( [\w\d]+ ) /exists $themes{$1} || 0/gexms;
  0         0  
91 0         0 my $is_thematic = eval $as_code;
92              
93 0 0       0 if ($EVAL_ERROR) {
94 0         0 throw_global_value
95             option_name => $CONFIG_KEY,
96             option_value => $rule,
97             message_suffix => q{contains a syntax error.};
98             }
99              
100 0         0 return $is_thematic;
101             }
102              
103             #-----------------------------------------------------------------------------
104              
105             sub cook_rule {
106 7     7 1 12 my ($raw_rule) = @_;
107 7 50       20 return if not defined $raw_rule;
108              
109             #Translate logical operators
110 7         12 $raw_rule =~ s{\b not \b}{!}ixmsg; # "not" -> "!"
111 7         10 $raw_rule =~ s{\b and \b}{&&}ixmsg; # "and" -> "&&"
112 7         9 $raw_rule =~ s{\b or \b}{||}ixmsg; # "or" -> "||"
113              
114             #Translate algebra operators (for backward compatibility)
115 7         11 $raw_rule =~ s{\A [-] }{!}ixmsg; # "-" -> "!" e.g. difference
116 7         11 $raw_rule =~ s{ [-] }{&& !}ixmsg; # "-" -> "&& !" e.g. difference
117 7         8 $raw_rule =~ s{ [*] }{&&}ixmsg; # "*" -> "&&" e.g. intersection
118 7         10 $raw_rule =~ s{ [+] }{||}ixmsg; # "+" -> "||" e.g. union
119              
120 7         11 my $cooked_rule = lc $raw_rule; #Is now cooked!
121 7         25 return $cooked_rule;
122             }
123              
124              
125             1;
126              
127             __END__
128              
129             #-----------------------------------------------------------------------------
130              
131             =pod
132              
133             =head1 NAME
134              
135             Perl::ToPerl6::Theme - Construct thematic sets of transformers.
136              
137              
138             =head1 DESCRIPTION
139              
140             This is a helper class for evaluating theme expressions into sets of
141             Transformer objects. There are no user-serviceable parts here.
142              
143              
144             =head1 INTERFACE SUPPORT
145              
146             This is considered to be a non-public class. Its interface is subject
147             to change without notice.
148              
149              
150             =head1 METHODS
151              
152             =over
153              
154             =item C<< new( -rule => $rule_expression ) >>
155              
156             Returns a reference to a new Perl::ToPerl6::Theme object. C<-rule> is
157             a string expression that evaluates to true or false for each Transformer..
158             See L<"THEME RULES"> for more information.
159              
160              
161             =item C<< transformer_is_thematic( -transformer => $transformer ) >>
162              
163             Given a reference to a L<Perl::ToPerl6::Transformer|Perl::ToPerl6::Transformer>
164             object, this method returns evaluates the rule against the themes that
165             are associated with the Transformer. Returns 1 if the Transformer satisfies the
166             rule, 0 otherwise.
167              
168              
169             =item C< rule() >
170              
171             Returns the rule expression that was used to construct this Theme.
172             The rule may have been translated into a normalized expression. See
173             L<"THEME RULES"> for more information.
174              
175             =back
176              
177              
178             =head2 THEME RULES
179              
180             A theme rule is a simple boolean expression, where the operands are
181             the names of any of the themes associated with the
182             Perl::ToPerl6::Polices.
183              
184             Theme names can be combined with logical operators to form arbitrarily
185             complex expressions. Precedence is the same as normal mathematics,
186             but you can use parentheses to enforce precedence as well. Supported
187             operators are:
188              
189             Operator Altertative Example
190             ----------------------------------------------------------------
191             && and 'pbp && core'
192             || or 'pbp || (bugs && security)'
193             ! not 'pbp && ! (portability || complexity)
194              
195             See L<Perl::ToPerl6/"CONFIGURATION"> for more information about
196             customizing the themes for each Transformer.
197              
198              
199             =head1 SUBROUTINES
200              
201             =over
202              
203             =item C<cook_rule( $rule )>
204              
205             Standardize a rule into a almost executable Perl code. The "almost"
206             comes from the fact that theme names are left as is.
207              
208              
209             =back
210              
211              
212             =head1 CONSTANTS
213              
214             =over
215              
216             =item C<$RULE_INVALID_CHARACTER_REGEX>
217              
218             A regular expression that will return the first character in the
219             matched expression that is not valid in a rule.
220              
221              
222             =back
223              
224              
225             =head1 AUTHOR
226              
227             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
228              
229              
230             =head1 COPYRIGHT
231              
232             Copyright (c) 2006-2011 Imaginative Software Systems
233              
234             This program is free software; you can redistribute it and/or modify
235             it under the same terms as Perl itself. The full text of this license
236             can be found in the LICENSE file included with this module.
237              
238             =cut
239              
240             ##############################################################################
241             # Local Variables:
242             # mode: cperl
243             # cperl-indent-level: 4
244             # fill-column: 78
245             # indent-tabs-mode: nil
246             # c-indentation-style: bsd
247             # End:
248             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :