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   155 use strict;
  27         60  
  27         626  
4 27     27   136 use warnings;
  27         53  
  27         575  
5              
6 27     27   9115 use App::RecordStream::DomainLanguage::Executor;
  27         88  
  27         760  
7 27     27   168 use App::RecordStream::DomainLanguage::Value;
  27         65  
  27         579  
8 27     27   134 use App::RecordStream::Executor;
  27         62  
  27         14027  
9              
10             sub new
11             {
12 438     438 0 49830 my $class = shift;
13 438         820 my $code = shift;
14 438         731 my $vars = shift;
15              
16 438         1369 $code = App::RecordStream::Executor->transform_code($code);
17 438         1056 $code = _transform_angles($code);
18              
19 438         1340 my $this =
20             {
21             'CODE' => $code,
22             'VARS' => $vars,
23             };
24              
25 438         893 bless $this, $class;
26              
27 438         1590 return $this;
28             }
29              
30             sub evaluate_as
31             {
32 389     389 0 43749 my $this = shift;
33 389         693 my $type = shift;
34 389   100     1342 my $vars = shift || {};
35              
36 389         1459 my $executor = App::RecordStream::DomainLanguage::Executor->new();
37 389         1353 $executor->import_registry();
38              
39 389         917 for my $var (%{$this->{'VARS'}})
  389         1347  
40             {
41 42         74 for my $ref (@{$this->{'VARS'}->{$var}})
  42         131  
42             {
43 36         104 $executor->set_ref($var, $ref);
44             }
45             }
46              
47 389         1081 for my $var (keys(%$vars))
48             {
49 302 50       1577 if(0)
50             {
51             }
52 0         0 elsif($var =~ /^\$(.*)$/)
53             {
54 302         1131 $executor->set_scalar($1, $vars->{$var});
55             }
56             else
57             {
58 0         0 die "Bad var for snippet: '$var'";
59             }
60             }
61 389         1427 my $result = $executor->exec($this->{'CODE'});
62              
63 389         1302 return App::RecordStream::DomainLanguage::Value::cast_or_die($type, $result);
64             }
65              
66             sub _transform_angles
67             {
68 438     438   742 my $code = shift;
69              
70 438         712 my $pos = 0;
71 438         786 my $out = '';
72 438         699 while(1)
73             {
74 484         1028 my $top_level_entrance = index($code, '<<', $pos);
75 484 100       1126 if($top_level_entrance == -1)
76             {
77 438         1120 $out .= substr($code, $pos);
78 438         835 last;
79             }
80              
81 46         101 my $level = 1;
82 46         86 my $pos2 = $top_level_entrance + 2;
83 46         95 my $top_level_exit;
84 46         84 while(1)
85             {
86 46         103 my $next_enter = index($code, '<<', $pos2);
87 46         91 my $next_exit = index($code, '>>', $pos2);
88              
89 46 50 33     237 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     247 if($next_exit != -1 && ($next_enter == -1 || $next_exit < $next_enter))
      66        
97             {
98 46         76 --$level;
99 46 50       110 if($level == 0)
100             {
101 46         112 $top_level_exit = $next_exit;
102 46         91 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         122 $out .= substr($code, $pos, $top_level_entrance - $pos);
112 46         165 $out .= _quote_snippet(substr($code, $top_level_entrance + 2, $top_level_exit - $top_level_entrance - 2));
113 46         118 $pos = $top_level_exit + 2;
114             }
115              
116 438         981 return $out;
117             }
118              
119             sub _quote_snippet
120             {
121 46     46   143 my $code = shift;
122              
123 46         95 my @vars;
124 46 100       178 if($code =~ s/^([a-zA-Z_][a-zA-Z_0-9]*(,[a-zA-Z_][a-zA-Z_0-9]*)*)\|//)
125             {
126 4         21 @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         192 return "snip(App::RecordStream::DomainLanguage::Snippet->new('$code', {" . join(", ", map { "'$_' => [\\\$$_, \\\@$_, \\\%$_]" } @vars) . "}))";
  6         34  
132             }
133              
134             1;