File Coverage

blib/lib/Devel/Chitin/OpTree/LOGOP.pm
Criterion Covered Total %
statement 85 88 96.5
branch 26 28 92.8
condition 14 21 66.6
subroutine 19 20 95.0
pod 0 13 0.0
total 144 170 84.7


line stmt bran cond sub pod time code
1             package Devel::Chitin::OpTree::LOGOP;
2 35     35   194 use base 'Devel::Chitin::OpTree::UNOP';
  35         58  
  35         3467  
3              
4             our $VERSION = '0.12'; # TRIAL
5              
6 35     35   193 use strict;
  35         55  
  35         637  
7 35     35   150 use warnings;
  35         67  
  35         32969  
8              
9             sub other {
10 44     44 0 120 shift->{children}->[1];
11             }
12              
13 0     0 0 0 sub pp_entertry { '' }
14              
15             sub pp_regcomp {
16 7     7 0 10 my $self = shift;
17 7         21 my %params = @_;
18              
19 7         18 my $rx_op = $self->first;
20 7         16 my $rx_op_name = $rx_op->op->name;
21 7 100 66     29 $rx_op = $rx_op->first if ($rx_op_name eq 'regcmaybe'
22             or $rx_op_name eq 'regcreset');
23              
24 7         10 my $deparsed;
25 7         27 join('', $rx_op->deparse(skip_parens => 1,
26             skip_quotes => 1,
27             skip_concat => 1,
28             join_with => '',
29             %params));
30             }
31              
32             sub pp_substcont {
33 1     1 0 3 my $self = shift;
34 1         4 join('', $self->first->deparse(skip_concat => 1, skip_quotes => 1));
35             }
36              
37             # The arrangement looks like this
38             # mapwhile
39             # mapstart
40             # padrange
41             # null
42             # block-or-expr
43             # ...
44             # list-0
45             # list-1
46             # ...
47             sub pp_mapwhile {
48 4     4 0 9 _deparse_map_grep(shift, 'map');
49             }
50              
51             sub pp_grepwhile {
52 4     4 0 9 _deparse_map_grep(shift, 'grep');
53             }
54              
55             sub _deparse_map_grep {
56 8     8   13 my($self, $function) = @_;
57              
58 8         20 my $mapstart = $self->first;
59 8         13 my $children = $mapstart->children;
60              
61 8         21 my $block_or_expr = $mapstart->children->[1]->first;
62 8 100       24 $block_or_expr = $block_or_expr->first if $block_or_expr->is_null;
63              
64 8         22 my @map_params = map { $_->deparse } @$children[2 .. $#$children];
  12         20  
65 8 100       21 if ($block_or_expr->is_scopelike) {
66             # map { ... } @list
67 4   66     18 my $use_parens = (@map_params > 1 or substr($map_params[0], 0, 1) ne '@');
68              
69 4 100       11 "${function} " . $block_or_expr->deparse . ' '
    100          
70             . ($use_parens ? '(' : '')
71             . join(', ', @map_params)
72             . ($use_parens ? ')' : '');
73              
74             } else {
75             # map(expr, @list)
76              
77 4         10 "${function}("
78             . $block_or_expr->deparse
79             . ', '
80             . join(', ', @map_params)
81             . ')';
82             }
83             }
84              
85             sub pp_and {
86 8     8 0 15 my $self = shift;
87 8         23 my $left = $self->first->deparse;
88 8         30 my $right = $self->other->deparse;
89 8 100       33 if ($self->is_if_statement) {
    100          
90 3         8 $left = _format_if_conditional($left);
91 3         8 $right = _format_if_block($right);
92 3         19 "if ($left) $right";
93              
94             } elsif ($self->is_posfix_if) {
95 1         6 "$right if $left";
96              
97             } else {
98 4         23 "$left && $right";
99             }
100             }
101              
102             sub pp_or {
103 4     4 0 8 my $self = shift;
104 4 100       13 if ($self->is_if_statement) {
    100          
105 1         2 my $condition;
106 1 50 33     4 if ($self->first->is_null
107             and $self->first->_ex_name eq 'pp_not'
108             ) {
109             # starting with 5.12
110 0         0 $condition = $self->first->first->deparse;
111             } else {
112             # perl 5.10.1 and older
113 1         5 $condition = $self->first->deparse;
114             }
115 1         4 $condition = _format_if_conditional($condition);
116 1         3 my $code = _format_if_block($self->other->deparse);
117 1         7 "unless ($condition) $code";
118              
119             } elsif ($self->is_posfix_if) {
120 1         4 $self->other->deparse . ' unless ' . $self->first->deparse;
121              
122             } else {
123 2         6 $self->first->deparse . ' || ' . $self->other->deparse;
124             }
125             }
126              
127             sub pp_dor {
128 1     1 0 2 my $self = shift;
129 1         4 $self->first->deparse . ' // ' . $self->other->deparse;
130             }
131              
132             sub _format_if_conditional {
133 10     10   19 my $code = shift;
134 10 50       25 if (index($code, ';') == 0) {
135 0         0 substr($code, 1);
136             } else {
137 10         19 $code;
138             }
139             }
140              
141             sub _format_if_block {
142 16     16   24 my $code = shift;
143 16 100       37 if (index($code,"\n") >=0 ) {
144 6         14 $code =~ s/^{ \n/{\n/;
145 6         11 $code =~ s/ }$/\n}/;
146             } else {
147             # make even one-liner blocks indented
148 10         39 $code =~ s/^{ /{\n\t/;
149 10         31 $code =~ s/ }$/\n}/;
150             }
151 16         31 $code;
152             }
153              
154 1     1 0 5 sub pp_andassign { _and_or_assign(shift, '&&=') }
155 1     1 0 5 sub pp_orassign { _and_or_assign(shift, '||=') }
156 1     1 0 6 sub pp_dorassign { _and_or_assign(shift, '//=') }
157             sub _and_or_assign {
158 3     3   8 my($self, $op) = @_;
159 3         9 my $var = $self->first->deparse;
160 3         10 my $value = $self->other->first->deparse; # skip over sassign (other)
161 3         15 join(' ', $var, $op, $value);
162             }
163              
164             sub pp_cond_expr {
165 7     7 0 12 my $self = shift;
166 7         16 my $children = $self->children;
167              
168 7         16 my($cond, $true, $false) = @$children;
169 7         14 my($cond_code, $true_code, $false_code) = map { $_->deparse } ($cond, $true, $false);
  21         42  
170              
171 7 100 100     19 if ($true->is_scopelike and $false->is_scopelike) {
    100 66        
      66        
      66        
172 2         8 $true_code = _format_if_block($true_code);
173 2         5 $false_code = _format_if_block($false_code);
174 2         6 $cond_code = _format_if_conditional($cond_code);
175 2         15 "if ($cond_code) $true_code else $false_code";
176              
177             } elsif ($true->is_scopelike
178             and $false->is_null
179             and ( $false->first->op->name eq 'cond_expr' or $false->first->op->name eq 'and' )
180             ) {
181 4         8 $true_code = _format_if_block($true_code);
182 4         9 $false_code = _format_if_block($false_code);
183 4         6 $cond_code = _format_if_conditional($cond_code);
184 4         25 "if ($cond_code) $true_code els$false_code";
185              
186             } else {
187 1         4 $cond->deparse . ' ? ' . $true->deparse . ' : ' . $false->deparse;
188             }
189             }
190              
191             1;
192              
193             __END__