File Coverage

blib/lib/App/RecordStream/DomainLanguage/Snippet.pm
Criterion Covered Total %
statement 68 76 89.4
branch 8 12 66.6
condition 9 14 64.2
subroutine 9 9 100.0
pod 0 2 0.0
total 94 113 83.1


line stmt bran cond sub pod time code
1             package App::RecordStream::DomainLanguage::Snippet;
2              
3 27     27   148 use strict;
  27         57  
  27         1281  
4 27     27   159 use warnings;
  27         54  
  27         687  
5              
6 27     27   7367 use App::RecordStream::DomainLanguage::Executor;
  27         92  
  27         882  
7 27     27   172 use App::RecordStream::DomainLanguage::Value;
  27         60  
  27         651  
8 27     27   140 use App::RecordStream::Executor;
  27         61  
  27         15486  
9              
10             sub new
11             {
12 438     438 0 45838 my $class = shift;
13 438         811 my $code = shift;
14 438         763 my $vars = shift;
15              
16 438         1322 $code = App::RecordStream::Executor->transform_code($code);
17 438         1165 $code = _transform_angles($code);
18              
19 438         1401 my $this =
20             {
21             'CODE' => $code,
22             'VARS' => $vars,
23             };
24              
25 438         972 bless $this, $class;
26              
27 438         1577 return $this;
28             }
29              
30             sub evaluate_as
31             {
32 389     389 0 59396 my $this = shift;
33 389         722 my $type = shift;
34 389   100     1440 my $vars = shift || {};
35              
36 389         1636 my $executor = App::RecordStream::DomainLanguage::Executor->new();
37 389         1344 $executor->import_registry();
38              
39 389         1236 for my $var (%{$this->{'VARS'}})
  389         1596  
40             {
41 42         59 for my $ref (@{$this->{'VARS'}->{$var}})
  42         95  
42             {
43 36         84 $executor->set_ref($var, $ref);
44             }
45             }
46              
47 389         1191 for my $var (keys(%$vars))
48             {
49 302 50       1831 if(0)
50             {
51             }
52 0         0 elsif($var =~ /^\$(.*)$/)
53             {
54 302         1268 $executor->set_scalar($1, $vars->{$var});
55             }
56             else
57             {
58 0         0 die "Bad var for snippet: '$var'";
59             }
60             }
61 389         1543 my $result = $executor->exec($this->{'CODE'});
62              
63 389         1461 return App::RecordStream::DomainLanguage::Value::cast_or_die($type, $result);
64             }
65              
66             sub _transform_angles
67             {
68 438     438   818 my $code = shift;
69              
70 438         1029 my $pos = 0;
71 438         707 my $out = '';
72 438         671 while(1)
73             {
74 484         1237 my $top_level_entrance = index($code, '<<', $pos);
75 484 100       1160 if($top_level_entrance == -1)
76             {
77 438         1214 $out .= substr($code, $pos);
78 438         922 last;
79             }
80              
81 46         94 my $level = 1;
82 46         96 my $pos2 = $top_level_entrance + 2;
83 46         83 my $top_level_exit;
84 46         80 while(1)
85             {
86 46         107 my $next_enter = index($code, '<<', $pos2);
87 46         86 my $next_exit = index($code, '>>', $pos2);
88              
89 46 50 33     535 if($next_enter != -1 && ($next_exit == -1 || $next_enter < $next_exit))
      66        
90             {
91 0         0 ++$level;
92 0         0 $pos2 = $next_enter + 2;
93 0         0 next;
94             }
95              
96 46 50 66     242 if($next_exit != -1 && ($next_enter == -1 || $next_exit < $next_enter))
      66        
97             {
98 46         69 --$level;
99 46 50       109 if($level == 0)
100             {
101 46         71 $top_level_exit = $next_exit;
102 46         82 last;
103             }
104 0         0 $pos2 = $next_enter + 2;
105 0         0 next;
106             }
107              
108 0         0 die "Unbalanced << and >> in snippet: $code";
109             }
110              
111 46         131 $out .= substr($code, $pos, $top_level_entrance - $pos);
112 46         192 $out .= _quote_snippet(substr($code, $top_level_entrance + 2, $top_level_exit - $top_level_entrance - 2));
113 46         108 $pos = $top_level_exit + 2;
114             }
115              
116 438         978 return $out;
117             }
118              
119             sub _quote_snippet
120             {
121 46     46   123 my $code = shift;
122              
123 46         88 my @vars;
124 46 100       155 if($code =~ s/^([a-zA-Z_][a-zA-Z_0-9]*(,[a-zA-Z_][a-zA-Z_0-9]*)*)\|//)
125             {
126 4         17 @vars = split(/,/, $1);
127             }
128              
129             # Could not get typeglobs to work. References go in, references come out,
130             # you can't explain that...
131 46         203 return "snip(App::RecordStream::DomainLanguage::Snippet->new('$code', {" . join(", ", map { "'$_' => [\\\$$_, \\\@$_, \\\%$_]" } @vars) . "}))";
  6         30  
132             }
133              
134             1;