File Coverage

blib/lib/Spp/Tools.pm
Criterion Covered Total %
statement 144 323 44.5
branch 29 72 40.2
condition n/a
subroutine 19 34 55.8
pod 0 30 0.0
total 192 459 41.8


line stmt bran cond sub pod time code
1             package Spp::Tools;
2              
3 2     2   35 use 5.012;
  2         6  
4 2     2   22 no warnings 'experimental';
  2         3  
  2         91  
5              
6 2     2   12 use Exporter;
  2         4  
  2         146  
7             our @ISA = qw(Exporter);
8             our @EXPORT =
9             qw(is_type is_atoms to_ejson from_ejson char_to_ejson atoms flat match name value offline elen epush eappend eunshift ejoin is_atom_name is_sym is_rept is_look is_tillnot is_atom_str is_sub is_return ast_to_table get_rept_time clean_ast clean_atom see_ast is_exported);
10              
11 2     2   15 use Spp::Builtin;
  2         4  
  2         3852  
12              
13             sub is_type {
14 0     0 0 0 my $str = shift;
15 0         0 return $str ~~ [
16             'Str', 'Int', 'Bool', 'Cursor',
17             'Lint', 'Array', 'Ints', 'Hash',
18             'Str+', 'Int+', 'StrOrArray', 'Str?',
19             'Int?', 'Fn', 'Table', 'Map'
20             ];
21             }
22              
23             sub is_atoms {
24 0     0 0 0 my $atoms = shift;
25 0 0       0 if (is_estr($atoms)) {
26 0         0 for my $atom (@{ atoms($atoms) }) {
  0         0  
27 0 0       0 if (not(is_atom($atom))) { return 0 }
  0         0  
28             }
29 0         0 return 1;
30             }
31 0         0 return 1;
32             }
33              
34             sub to_ejson {
35 3     3 0 6 my $json = shift;
36 3 50       12 if (is_estr($json)) { return $json }
  0         0  
37 3         7 my $chars = [];
38 3         6 my $mode = 0;
39 3         1012 for my $ch (split '', $json) {
40 9324 100       11839 if ($mode == 0) {
    100          
    50          
41 3930         3647 given ($ch) {
42 3930         4340 when ('[') { push @{$chars}, In; }
  855         819  
  855         1325  
43 3075         3107 when (']') { push @{$chars}, Out; }
  855         785  
  855         1235  
44 2220         2208 when ('"') { push @{$chars}, Qstr; $mode = 1 }
  1110         1068  
  1110         1457  
  1110         1410  
45 1110         1053 default {
46 1110 50       1575 if (is_digit($ch)) {
47 0         0 push @{$chars}, Qint;
  0         0  
48 0         0 push @{$chars}, $ch;
  0         0  
49 0         0 $mode = 2;
50             }
51             }
52             }
53             }
54             elsif ($mode == 1) {
55 5370         4774 given ($ch) {
56 5370         5768 when ('"') { $mode = 0 }
  1110         1341  
57 4260         4104 when ("\\") { $mode = 3 }
  24         34  
58 4236         4006 default { push @{$chars}, $ch; }
  4236         3700  
  4236         6188  
59             }
60             }
61             elsif ($mode == 2) {
62 0 0       0 if ($ch eq ',') { $mode = 0 }
  0         0  
63 0 0       0 if ($ch eq ']') { push @{$chars}, Out; $mode = 0 }
  0         0  
  0         0  
  0         0  
64 0 0       0 if (is_digit($ch)) { push @{$chars}, $ch; }
  0         0  
  0         0  
65             }
66             else {
67 24         23 $mode = 1;
68 24         26 given ($ch) {
69 24         29 when ('t') { push @{$chars}, "\t"; }
  0         0  
  0         0  
70 24         32 when ('r') { push @{$chars}, "\r"; }
  0         0  
  0         0  
71 24         37 when ('n') { push @{$chars}, "\n"; }
  0         0  
  0         0  
72 24         28 default { push @{$chars}, $ch; }
  24         21  
  24         38  
73             }
74             }
75             }
76 3         526 return join '', @{$chars};
  3         647  
77             }
78              
79             sub from_ejson {
80 0     0 0 0 my $estr = shift;
81 0 0       0 if (is_str($estr)) { return $estr }
  0         0  
82 0         0 my $chars = [];
83 0         0 my $mode = 0;
84 0         0 for my $ch (split '', $estr) {
85 0 0       0 if ($mode == 0) {
    0          
    0          
86 0         0 given ($ch) {
87 0         0 when (In) { push @{$chars}, '['; }
  0         0  
  0         0  
88 0         0 when (Qstr) { push @{$chars}, '"'; $mode = 1 }
  0         0  
  0         0  
  0         0  
89 0         0 when (Qint) { $mode = 2 }
  0         0  
90 0         0 when (Out) { push @{$chars}, ']'; $mode = 3 }
  0         0  
  0         0  
  0         0  
91             }
92             }
93             elsif ($mode == 1) {
94 0         0 given ($ch) {
95 0         0 when (In) { push @{$chars}, '",['; $mode = 0 }
  0         0  
  0         0  
  0         0  
96 0         0 when (Qstr) { push @{$chars}, '","'; }
  0         0  
  0         0  
97 0         0 when (Qint) { push @{$chars}, '",'; $mode = 2 }
  0         0  
  0         0  
  0         0  
98 0         0 when (Out) { push @{$chars}, '"]'; $mode = 3 }
  0         0  
  0         0  
  0         0  
99 0         0 default { push @{$chars}, char_to_ejson($ch); }
  0         0  
  0         0  
100             }
101             }
102             elsif ($mode == 2) {
103 0         0 given ($ch) {
104 0         0 when (In) { push @{$chars}, ',['; $mode = 0 }
  0         0  
  0         0  
  0         0  
105 0         0 when (Qstr) { push @{$chars}, ',"'; $mode = 1 }
  0         0  
  0         0  
  0         0  
106 0         0 when (Qint) { push @{$chars}, ','; }
  0         0  
  0         0  
107 0         0 when (Out) { push @{$chars}, ']'; $mode = 3 }
  0         0  
  0         0  
  0         0  
108 0         0 default { push @{$chars}, $ch; }
  0         0  
  0         0  
109             }
110             }
111             else {
112 0         0 given ($ch) {
113 0         0 when (In) { push @{$chars}, ',['; $mode = 0 }
  0         0  
  0         0  
  0         0  
114 0         0 when (Qstr) { push @{$chars}, ',"'; $mode = 1 }
  0         0  
  0         0  
  0         0  
115 0         0 when (Qint) { push @{$chars}, ','; $mode = 2 }
  0         0  
  0         0  
  0         0  
116 0         0 when (Out) { push @{$chars}, ']'; }
  0         0  
  0         0  
117             }
118             }
119             }
120 0         0 return join '', @{$chars};
  0         0  
121             }
122              
123             sub char_to_ejson {
124 0     0 0 0 my $ch = shift;
125 0         0 given ($ch) {
126 0         0 when ("\t") { return '\t' }
  0         0  
127 0         0 when ("\n") { return '\n' }
  0         0  
128 0         0 when ("\r") { return '\r' }
  0         0  
129 0         0 when ("\\") { return '\\\\' }
  0         0  
130 0         0 when ('"') { return '\"' }
  0         0  
131 0         0 default { return $ch }
  0         0  
132             }
133             }
134              
135             sub atoms {
136 1254     1254 0 1455 my $estr = shift;
137 1254         1401 my $estrs = [];
138 1254         1403 my $chars = [];
139 1254         1434 my $depth = 0;
140 1254         1363 my $mode = 0;
141 1254         7017 for my $ch (split '', $estr) {
142 58286 100       78898 if ($depth == 0) {
    100          
143 1254 50       1834 if ($ch eq In) { $depth++ }
  1254         1465  
144             }
145             elsif ($depth == 1) {
146 10087         9880 given ($ch) {
147 10087         11571 when (In) {
148 1403         1405 $depth++;
149 1403 100       1877 if ($mode) {
150 1141         1145 push @{$estrs}, join '', @{$chars};
  1141         1283  
  1141         2279  
151 1141         2264 $chars = [];
152             }
153 1403         1540 $mode = 1;
154 1403         1380 push @{$chars}, $ch;
  1403         2380  
155             }
156 8684         9007 when (Qstr) {
157 1489 100       2002 if ($mode) {
158 497         484 push @{$estrs}, join '', @{$chars};
  497         560  
  497         859  
159 497         835 $chars = [];
160             }
161 1489         2070 $mode = 1
162             }
163 7195         7244 when (Qint) {
164 0 0       0 if ($mode) {
165 0         0 push @{$estrs}, join '', @{$chars};
  0         0  
  0         0  
166 0         0 $chars = [];
167             }
168 0         0 $mode = 1
169             }
170 7195         7375 when (Out) {
171 1254 50       1946 if ($mode) { push @{$estrs}, join '', @{$chars}; }
  1254         1158  
  1254         1424  
  1254         4066  
172             }
173 5941         5645 default {
174 5941 50       7982 if ($mode) { push @{$chars}, $ch; }
  5941         5419  
  5941         12711  
175             }
176             }
177             }
178             else {
179 46945 100       58167 if ($ch eq In) { $depth++ }
  4087         3869  
180 46945 100       56275 if ($ch eq Out) { $depth-- }
  5490         5161  
181 46945         43122 push @{$chars}, $ch;
  46945         64306  
182             }
183             }
184 1254         5706 return $estrs;
185             }
186              
187             sub flat {
188 966     966 0 1101 my $estr = shift;
189 966 50       1508 if (is_str($estr)) {
190 0         0 croak("Str: |$estr| could not flat!");
191             }
192 966         1361 my $atoms = atoms($estr);
193 966 50       1951 if (len($atoms) < 2) {
194 0         0 say from_ejson($estr);
195 0         0 croak("flat less two atom");
196             }
197 966         2698 return $atoms->[0], $atoms->[1];
198             }
199              
200             sub match {
201 3     3 0 5 my $estr = shift;
202 3         5 my $atoms = atoms($estr);
203 3 50       9 if (len($atoms) == 0) { error("match with blank") }
  0         0  
204 3 50       9 if (len($atoms) == 1) { return $atoms->[0], Blank }
  0         0  
205 3         14 return $atoms->[0], estr(rest($atoms));
206             }
207              
208             sub name {
209 22     22 0 26 my $estr = shift;
210 22         25 my $atoms = atoms($estr);
211 22         57 return $atoms->[0];
212             }
213              
214             sub value {
215 5     5 0 11 my $estr = shift;
216 5         10 my $atoms = atoms($estr);
217 5         16 return $atoms->[1];
218             }
219              
220             sub offline {
221 0     0 0 0 my $estr = shift;
222 0         0 my $atoms = atoms($estr);
223 0         0 return $atoms->[-1];
224             }
225              
226             sub elen {
227 3     3 0 7 my $estr = shift;
228 3         5 my $atoms = atoms($estr);
229 3         10 return len($atoms);
230             }
231              
232             sub epush {
233 1     1 0 3 my ($array, $elem) = @_;
234 1         5 return add(Chop($array), $elem, Out);
235             }
236              
237             sub eappend {
238 0     0 0 0 my ($a_one, $a_two) = @_;
239 0         0 return add(Chop($a_one), rest_str($a_two));
240             }
241              
242             sub eunshift {
243 3     3 0 7 my ($elem, $array) = @_;
244 3         13 return add(In, $elem, rest_str($array));
245             }
246              
247             sub ejoin {
248 0     0 0 0 my ($estr, $sub) = @_;
249 0         0 return join $sub, @{ atoms($estr) };
  0         0  
250             }
251              
252             sub is_atom_name {
253 14     14 0 20 my ($atom, $name) = @_;
254 14 50       22 if (is_atom($atom)) { return name($atom) eq $name }
  14         23  
255 0         0 return 0;
256             }
257              
258             sub is_sym {
259 0     0 0 0 my $atom = shift;
260 0         0 return is_atom_name($atom, 'Sym');
261             }
262              
263             sub is_rept {
264 7     7 0 10 my $atom = shift;
265 7         10 return is_atom_name($atom, 'rept');
266             }
267              
268             sub is_look {
269 7     7 0 14 my $atom = shift;
270 7         15 return is_atom_name($atom, 'look');
271             }
272              
273             sub is_tillnot {
274 7     7 0 10 my $atom = shift;
275 7 50       13 if (is_atom($atom)) {
276 7         15 given (name($atom)) {
277 7         12 when ('Till') { return 1 }
  0         0  
278 7         10 when ('Not') { return 1 }
  0         0  
279             }
280             }
281 7         16 return 0;
282             }
283              
284             sub is_atom_str {
285 0     0 0 0 my $atom = shift;
286 0         0 return is_atom_name($atom, 'Str');
287             }
288              
289             sub is_sub {
290 0     0 0 0 my $atom = shift;
291 0         0 return is_atom_name($atom, 'Sub');
292             }
293              
294             sub is_return {
295 0     0 0 0 my $atom = shift;
296 0         0 return is_atom_name($atom, '->');
297             }
298              
299             sub ast_to_table {
300 3     3 0 7 my $ast = shift;
301 3         10 my $table = {};
302 3         6 for my $spec (@{ atoms($ast) }) {
  3         10  
303 96         147 my ($name, $rule) = flat($spec);
304 96 50       178 if (exists $table->{$name}) {
305 0         0 say "redefine token: <$name>";
306             }
307 96         226 $table->{$name} = $rule;
308             }
309 3         25 return $table;
310             }
311              
312             sub get_rept_time {
313 77     77 0 101 my $rept = shift;
314 77         92 given ($rept) {
315 77         121 when ('?') { return 0, 1 }
  1         4  
316 76         116 when ('*') { return 0, -1 }
  3         8  
317 73         98 default { return 1, -1 }
  73         147  
318             }
319             }
320              
321             sub clean_ast {
322 0     0 0   my $ast = shift;
323 0 0         if (is_atom($ast)) { return clean_atom($ast) }
  0            
324 0           my $clean_atoms = [];
325 0           for my $atom (@{ atoms($ast) }) {
  0            
326 0           push @{$clean_atoms}, clean_atom($atom);
  0            
327             }
328 0           return estr($clean_atoms);
329             }
330              
331             sub clean_atom {
332 0     0 0   my $atom = shift;
333 0           my ($name, $value) = flat($atom);
334 0 0         if (is_str($value)) { return cons($name, $value) }
  0            
335 0 0         if (is_blank($value)) { return cons($name, $value) }
  0            
336 0 0         if (is_atom($value)) {
337 0           return cons($name, clean_atom($value));
338             }
339 0 0         if (is_atoms($value)) {
340 0           return cons($name, clean_ast($value));
341             }
342 0           say from_ejson($atom);
343 0           croak("ast data error!");
344 0           return False;
345             }
346              
347             sub see_ast {
348 0     0 0   my $ast = shift;
349 0           return from_ejson(clean_ast($ast));
350             }
351              
352             sub is_exported {
353 0     0 0   my $name = shift;
354 0           return not(start_with($name, '_'));
355             }
356             1;