File Coverage

blib/lib/Eval/TypeTiny/CodeAccumulator.pm
Criterion Covered Total %
statement 73 75 97.3
branch 6 10 60.0
condition 5 10 50.0
subroutine 20 20 100.0
pod 14 14 100.0
total 118 129 91.4


line stmt bran cond sub pod time code
1             package Eval::TypeTiny::CodeAccumulator;
2              
3 68     68   898551 use 5.008001;
  68         287  
4 68     68   437 use strict;
  68         148  
  68         1930  
5 68     68   374 use warnings;
  68         184  
  68         6369  
6              
7             BEGIN {
8 68 50   68   3527 if ( $] < 5.010 ) { require Devel::TypeTiny::Perl58Compat }
  0         0  
9             }
10              
11             BEGIN {
12 68     68   270 $Eval::TypeTiny::CodeAccumulator::AUTHORITY = 'cpan:TOBYINK';
13 68         88865 $Eval::TypeTiny::CodeAccumulator::VERSION = '2.010001';
14             }
15              
16             $Eval::TypeTiny::CodeAccumulator::VERSION =~ tr/_//d;
17              
18             sub new {
19 414     414 1 1477 my $class = shift;
20              
21 414 50       2520 my %self = @_ == 1 ? %{$_[0]} : @_;
  0         0  
22 414   50     3076 $self{env} ||= {};
23 414   50     2334 $self{code} ||= [];
24 414   50     3628 $self{placeholders} ||= {};
25 414   50     2270 $self{indent} ||= '';
26              
27 414         1740 bless \%self, $class;
28             }
29              
30 474     474 1 1015 sub code { join( "\n", @{ $_[0]{code} } ) }
  474         5575  
31 340     340 1 1859 sub description { $_[0]{description} }
32 340     340 1 1994 sub env { $_[0]{env} }
33              
34             sub add_line {
35 7763     7763 1 14720 my $self = shift;
36 7763         14866 my $indent = $self->{indent};
37              
38 7763         11714 push @{ $self->{code} }, map { $indent . $_ } map { split /\n/ } @_;
  7763         18116  
  10021         38827  
  7763         23830  
39              
40 7763         19779 $self;
41             }
42              
43             sub addf {
44 103     103 1 204 my $self = shift;
45 103         183 my $fmt = shift;
46 103         366 $self->add_line( sprintf $fmt, @_ );
47             }
48              
49             sub increase_indent {
50 121     121 1 239 $_[0]{indent} .= "\t";
51 121         215 $_[0];
52             }
53              
54             sub decrease_indent {
55 121     121 1 567 $_[0]{indent} =~ s/\t$//;
56 121         257 $_[0];
57             }
58              
59             sub add_gap {
60 2136     2136 1 3662 push @{ $_[0]{code} }, '';
  2136         8294  
61             }
62              
63             sub add_placeholder {
64 4     4 1 9 my ( $self, $for ) = ( shift, @_ );
65 4   50     14 my $indent = $self->{indent} || '';
66              
67             $self->{placeholders}{$for} = [
68 4         12 scalar( @{ $self->{code} } ),
69             $self->{indent},
70 4         7 ];
71 4         5 push @{ $self->{code} }, "$indent# placeholder [ $for ]";
  4         8  
72              
73 4 100       12 if ( defined wantarray ) {
74 2     1   9 return sub { $self->fill_placeholder( $for, @_ ) };
  1         4  
75             }
76             }
77              
78             sub fill_placeholder {
79 2     2 1 5 my ( $self, $for, @lines ) = ( shift, @_ );
80              
81 2 50       3 my ( $line_number, $indent ) = @{ delete $self->{placeholders}{$for} or die };
  2         14  
82 2         7 my @indented_lines = map { $indent . $_ } map { split /\n/ } @lines;
  2         8  
  2         6  
83 2         3 splice( @{ $self->{code} }, $line_number, 1, @indented_lines );
  2         7  
84              
85 2         6 $self;
86             }
87              
88             sub add_variable {
89 294     294 1 2301 my ( $self, $suggested_name, $reference ) = ( shift, @_ );
90            
91 294         583 my $actual_name = $suggested_name;
92 294         567 my $i = 1;
93 294         1180 while ( exists $self->{env}{$actual_name} ) {
94 67         218 $actual_name = sprintf '%s_%d', $suggested_name, ++$i;
95             }
96              
97 294         4210 $self->{env}{$actual_name} = $reference;
98              
99 294         1139 $actual_name;
100             }
101              
102             sub finalize {
103 340     340 1 736 my $self = shift;
104              
105 340         657 for my $p ( values %{ $self->{placeholders} } ) {
  340         1523  
106 2         2 splice( @{ $self->{code} }, $p->[0], 1 );
  2         5  
107             }
108              
109 340         776 $self;
110             }
111              
112             sub compile {
113 340     340 1 989 my ( $self, %opts ) = ( shift, @_ );
114              
115 340 50       2850 $self->{finalized}++ or $self->finalize();
116              
117 340         3603 require Eval::TypeTiny;
118 340         1354 return Eval::TypeTiny::eval_closure(
119             description => $self->description,
120             %opts,
121             source => $self->code,
122             environment => $self->env,
123             );
124             }
125              
126             1;
127              
128             __END__