File Coverage

blib/lib/Mylisp/ToPerl.pm
Criterion Covered Total %
statement 14 429 3.2
branch 0 30 0.0
condition n/a
subroutine 5 57 8.7
pod 0 52 0.0
total 19 568 3.3


line stmt bran cond sub pod time code
1             package Mylisp::ToPerl;
2              
3 1     1   15 use 5.012;
  1         2  
4 1     1   5 no warnings "experimental";
  1         2  
  1         30  
5              
6 1     1   5 use Exporter;
  1         2  
  1         70  
7             our @ISA = qw(Exporter);
8             our @EXPORT =
9             qw(ast_to_perl ast_to_perl_repl atoms_to_perl atoms_to_perls join_perl_exprs atom_to_perl type_to_perl char_to_perl aindex_to_perl index_to_perl while_to_perl cond_exprs_to_perl exprs_to_perl given_to_perl when_to_perl then_to_perl if_to_perl elif_to_perl else_to_perl for_to_perl iter_to_perl func_to_perl args_to_perl my_to_perl our_to_perl const_to_perl list_to_perl return_to_perl use_to_perl slist_to_perl string_to_perl array_to_perl hash_to_perl pair_to_perl lstr_to_perl str_to_perl bool_to_perl sym_to_perl get_perl_head_str package_to_perl get_export_str oper_to_perl call_to_perl split_to_perl map_to_perl grep_to_perl join_to_perl push_to_perl unshift_to_perl exists_to_perl key_to_perl delete_to_perl);
10 1     1   5 use Spp::Builtin;
  1         1  
  1         177  
11 1     1   6 use Spp::Tools;
  1         1  
  1         2809  
12              
13             sub ast_to_perl {
14 0     0 0   my $ast = shift;
15 0           my $head_str = get_perl_head_str($ast);
16 0           my $exprs_str = atoms_to_perl($ast);
17 0           my $perl_str = add($head_str, $exprs_str);
18 0           return tidy_perl($perl_str);
19             }
20              
21             sub ast_to_perl_repl {
22 0     0 0   my $ast = shift;
23 0           return atoms_to_perl($ast);
24             }
25              
26             sub atoms_to_perl {
27 0     0 0   my $atoms = shift;
28 0           my $strs = atoms_to_perls($atoms);
29 0           return join_perl_exprs($strs);
30             }
31              
32             sub atoms_to_perls {
33 0     0 0   my $atoms = shift;
34             return estr(
35 0           [map { atom_to_perl($_) } @{ atoms($atoms) }]);
  0            
  0            
36             }
37              
38             sub join_perl_exprs {
39 0     0 0   my $exprs = shift;
40 0           my $strs = [];
41 0           my $end_char = ';';
42 0           for my $expr (@{ atoms($exprs) }) {
  0            
43 0 0         if ($end_char ~~ [';', '}']) { push @{$strs}, $expr; }
  0            
  0            
44 0           else { push @{$strs}, ';'; push @{$strs}, $expr; }
  0            
  0            
  0            
45 0           $end_char = last_char($expr);
46             }
47 0           return join ' ', @{$strs};
  0            
48             }
49              
50             sub atom_to_perl {
51 0     0 0   my $atom = shift;
52 0           my ($name, $args) = flat($atom);
53 0           given ($name) {
54 0           when ('Aindex') { return aindex_to_perl($args) }
  0            
55 0           when ('while') { return while_to_perl($args) }
  0            
56 0           when ('for') { return for_to_perl($args) }
  0            
57 0           when ('given') { return given_to_perl($args) }
  0            
58 0           when ('when') { return when_to_perl($args) }
  0            
59 0           when ('then') { return then_to_perl($args) }
  0            
60 0           when ('if') { return if_to_perl($args) }
  0            
61 0           when ('elif') { return elif_to_perl($args) }
  0            
62 0           when ('else') { return else_to_perl($args) }
  0            
63 0           when ('func') { return func_to_perl($args) }
  0            
64 0           when ('my') { return my_to_perl($args) }
  0            
65 0           when ('our') { return our_to_perl($args) }
  0            
66 0           when ('const') { return const_to_perl($args) }
  0            
67 0           when ('use') { return use_to_perl($args) }
  0            
68 0           when ('return') { return return_to_perl($args) }
  0            
69 0           when ('String') { return string_to_perl($args) }
  0            
70 0           when ('Array') { return array_to_perl($args) }
  0            
71 0           when ('Hash') { return hash_to_perl($args) }
  0            
72 0           when ('Lstr') { return lstr_to_perl($args) }
  0            
73 0           when ('Str') { return str_to_perl($args) }
  0            
74 0           when ('Char') { return char_to_perl($args) }
  0            
75 0           when ('Bool') { return bool_to_perl($args) }
  0            
76 0           when ('Sym') { return sym_to_perl($args) }
  0            
77 0           when ('Type') { return type_to_perl($args) }
  0            
78 0           when ('Int') { return $args }
  0            
79 0           when ('Ns') { return $args }
  0            
80 0           when ('package') { return ' ' }
  0            
81 0           when ('end') { return '1;' }
  0            
82 0           default {
83 0           my $strs = atoms_to_perls($args);
84 0           return oper_to_perl($name, $strs)
85             }
86             }
87             }
88              
89             sub type_to_perl {
90 0     0 0   my $value = shift;
91 0           given ($value) {
92 0           when ('Int') { return '0' }
  0            
93 0           when ('Str') { return "''" }
  0            
94 0           when ('Bool') { return '1' }
  0            
95 0           when ('Array') { return '[]' }
  0            
96 0           when ('Hash') { return '{} ' }
  0            
97 0           default { return '{}' }
  0            
98             }
99             }
100              
101             sub char_to_perl {
102 0     0 0   my $args = shift;
103 0           my $last_char = last_char($args);
104 0           given ($last_char) {
105 0           when ('b') { return "''" }
  0            
106 0           when ('n') { return '"\n"' }
  0            
107 0           when ('t') { return '"\t"' }
  0            
108 0           when ('r') { return '"\r"' }
  0            
109 0           when ('s') { return "' '" }
  0            
110 0           when ('\\') { return '"\\\\"' }
  0            
111 0           default { return "'$last_char'" }
  0            
112             }
113             }
114              
115             sub aindex_to_perl {
116 0     0 0   my $args = shift;
117 0           my $strs = atoms_to_perls($args);
118 0           my ($name, $indexs) = match($strs);
119             my $indexs_strs =
120 0           [map { index_to_perl($_) } @{ atoms($indexs) }];
  0            
  0            
121 0           my $str = join '', @{$indexs_strs};
  0            
122 0           return "$name\->$str ";
123             }
124              
125             sub index_to_perl {
126 0     0 0   my $index = shift;
127 0           my $char = last_char($index);
128 0 0         if (is_digit($char)) { return "[$index]" }
  0            
129 0           return "{$index}";
130             }
131              
132             sub while_to_perl {
133 0     0 0   my $args = shift;
134 0           my $str = cond_exprs_to_perl($args);
135 0           return "while $str";
136             }
137              
138             sub cond_exprs_to_perl {
139 0     0 0   my $args = shift;
140 0           my $strs = atoms_to_perls($args);
141 0           my ($cond, $exprs_strs) = match($strs);
142 0           my $exprs_str = exprs_to_perl($exprs_strs);
143 0 0         if (first_char($cond) eq chr(40)) {
144 0           return "$cond $exprs_str";
145             }
146 0           return "($cond) $exprs_str";
147             }
148              
149             sub exprs_to_perl {
150 0     0 0   my $strs = shift;
151 0           my $str = join_perl_exprs($strs);
152 0           return "{ $str }";
153             }
154              
155             sub given_to_perl {
156 0     0 0   my $args = shift;
157 0           my $str = cond_exprs_to_perl($args);
158 0           return "given $str";
159             }
160              
161             sub when_to_perl {
162 0     0 0   my $args = shift;
163 0           my $str = cond_exprs_to_perl($args);
164 0           return "when $str";
165             }
166              
167             sub then_to_perl {
168 0     0 0   my $args = shift;
169 0           my $str = atoms_to_perl($args);
170 0           return "default { $str }";
171             }
172              
173             sub if_to_perl {
174 0     0 0   my $exprs = shift;
175 0           my $str = cond_exprs_to_perl($exprs);
176 0           return "if $str";
177             }
178              
179             sub elif_to_perl {
180 0     0 0   my $exprs = shift;
181 0           my $str = cond_exprs_to_perl($exprs);
182 0           return "elsif $str";
183             }
184              
185             sub else_to_perl {
186 0     0 0   my $exprs = shift;
187 0           my $str = atoms_to_perl($exprs);
188 0           return "else { $str }";
189             }
190              
191             sub for_to_perl {
192 0     0 0   my $args = shift;
193 0           my ($iter_expr, $exprs) = match($args);
194 0           my $iter_str = iter_to_perl($iter_expr);
195 0           my $exprs_str = atoms_to_perl($exprs);
196 0           return "for $iter_str { $exprs_str } ";
197             }
198              
199             sub iter_to_perl {
200 0     0 0   my $expr = shift;
201 0           my ($loop, $iter_atom) = flat($expr);
202 0           my $iter = value($iter_atom);
203 0 0         if ($iter eq '@args') { return "my $loop ($iter)" }
  0            
204 0           my $iter_char = first_char($iter);
205 0           my $iter_str = atom_to_perl($iter_atom);
206 0           given ($iter_char) {
207 0           when ('$') { return "my $loop (split '', $iter_str)" }
  0            
208 0           when ('%') { return "my $loop (keys %{$iter_str})" }
  0            
209 0           default { return "my $loop (\@{$iter_str})" }
  0            
210             }
211             }
212              
213             sub func_to_perl {
214 0     0 0   my $atoms = shift;
215 0           my ($args, $rest) = match($atoms);
216 0           my ($return, $exprs) = match($rest);
217 0           my ($call, $func_args) = flat($args);
218 0           my $args_str = args_to_perl($func_args);
219 0           my $exprs_strs = atoms_to_perls($exprs);
220 0           my $exprs_str = join_perl_exprs($exprs_strs);
221 0           my $name = sym_to_perl($call);
222 0           return "sub $name { $args_str $exprs_str }";
223             }
224              
225             sub args_to_perl {
226 0     0 0   my $args = shift;
227 0 0         if (is_blank($args)) { return ' ' }
  0            
228 0           my $strs = [map { sym_to_perl($_) }
229 0           @{ [map { name($_) } @{ atoms($args) }] }];
  0            
  0            
  0            
230 0           my $str = join ', ', @{$strs};
  0            
231 0 0         if (len($strs) == 1) {
232 0 0         if ($str eq '@args') { return "my $str = \@_;" }
  0            
233 0           return "my $str = shift;";
234             }
235 0           return "my ($str) = \@_;";
236             }
237              
238             sub my_to_perl {
239 0     0 0   my $args = shift;
240 0           my ($sym, $value) = flat($args);
241 0           my $value_str = atom_to_perl($value);
242 0           my $name = atom_to_perl($sym);
243 0           return "my $name = $value_str";
244             }
245              
246             sub our_to_perl {
247 0     0 0   my $args = shift;
248 0           my ($sym, $value) = flat($args);
249 0           my $value_str = atom_to_perl($value);
250 0           my $list = value($sym);
251 0           my $list_str = list_to_perl($list);
252 0           return "my $list_str = $value_str";
253             }
254              
255             sub const_to_perl {
256 0     0 0   my $args = shift;
257 0           my $strs = atoms_to_perls($args);
258 0           my ($name, $value_str) = flat($strs);
259 0           return "our $name = $value_str";
260             }
261              
262             sub list_to_perl {
263 0     0 0   my $list = shift;
264 0           my $strs = atoms_to_perls($list);
265 0           my $str = ejoin($strs, ', ');
266 0           return "($str)";
267             }
268              
269             sub return_to_perl {
270 0     0 0   my $args = shift;
271 0           my $strs = atoms_to_perls($args);
272 0           my $str = ejoin($strs, ', ');
273 0           return "return $str";
274             }
275 0     0 0   sub use_to_perl { my $args = shift; return "use $args;" }
  0            
276              
277             sub slist_to_perl {
278 0     0 0   my $list = shift;
279 0           my $names = [map { value($_) } @{ atoms($list) }];
  0            
  0            
280 0           my $strs = [map { sym_to_perl($_) } @{$names}];
  0            
  0            
281 0           my $str = join ' ', @{$strs};
  0            
282 0           return "qw($str)";
283             }
284              
285             sub string_to_perl {
286 0     0 0   my $atoms = shift;
287 0           my $strs = [];
288 0           for my $atom (@{ atoms($atoms) }) {
  0            
289 0           my ($type, $value) = flat($atom);
290 0           given ($type) {
291 0           when ('Sym') {
292 0           my $name = sym_to_perl($value);
293 0           push @{$strs}, $name;
  0            
294             }
295 0           default { push @{$strs}, $value; }
  0            
  0            
296             }
297             }
298 0           my $str = join '', @{$strs};
  0            
299 0           return "\"$str\"";
300             }
301              
302             sub array_to_perl {
303 0     0 0   my $array = shift;
304 0           my $atoms = atoms_to_perls($array);
305 0           my $atoms_str = ejoin($atoms, ', ');
306 0           return "[$atoms_str]";
307             }
308              
309             sub hash_to_perl {
310 0     0 0   my $pairs = shift;
311 0           my $strs = [];
312 0           for my $pair (@{ atoms($pairs) }) {
  0            
313 0           my ($name, $args) = flat($pair);
314 0 0         if ($name eq 'Pair') {
315 0           push @{$strs}, pair_to_perl($args);
  0            
316             }
317             }
318 0           my $str = join ', ', @{$strs};
  0            
319 0           return "{$str} ";
320             }
321              
322             sub pair_to_perl {
323 0     0 0   my $pair = shift;
324 0           my $strs = atoms_to_perls($pair);
325 0           return ejoin($strs, ' => ');
326             }
327              
328             sub lstr_to_perl {
329 0     0 0   my $str = shift;
330 0           return "<<'EOF'\n$str\nEOF\n";
331             }
332 0     0 0   sub str_to_perl { my $str = shift; return "'$str'" }
  0            
333              
334             sub bool_to_perl {
335 0     0 0   my $bool = shift;
336 0 0         if ($bool eq 'true') { return '1' }
  0            
337 0           return '0';
338             }
339              
340             sub sym_to_perl {
341 0     0 0   my $name = shift;
342 0           my $chars = [];
343 0 0         if ($name eq '@args') { return $name }
  0            
344 0           for my $char (split '', $name) {
345 0           given ($char) {
346 0           when ('-') { push @{$chars}, '_'; }
  0            
  0            
347 0           when ('@') { push @{$chars}, '$'; }
  0            
  0            
348 0           when ('%') { push @{$chars}, '$'; }
  0            
  0            
349 0           default { push @{$chars}, $char; }
  0            
  0            
350             }
351             }
352 0           return join '', @{$chars};
  0            
353             }
354              
355             sub get_perl_head_str {
356 0     0 0   my $exprs = shift;
357 0           my $func_names = [];
358 0           my $head_str = 'str';
359 0           for my $expr (@{ atoms($exprs) }) {
  0            
360 0           my ($name, $value) = flat($expr);
361 0 0         if ($name eq 'package') {
362 0           $head_str = package_to_perl($value);
363             }
364 0 0         if ($name eq 'func') {
365 0           push @{$func_names}, name(name($value));
  0            
366             }
367             }
368 0           my $export_str = get_export_str($func_names);
369 0           return add($head_str, $export_str);
370             }
371              
372             sub package_to_perl {
373 0     0 0   my $ns = shift;
374 0           my $package_str = "package $ns;";
375 0           my $head_str = <<'EOF'
376              
377              
378             use 5.012;
379             no warnings "experimental";
380              
381             use Exporter;
382             our @ISA = qw(Exporter);
383             EOF
384             ;
385 0           return add($package_str, $head_str);
386             }
387              
388             sub get_export_str {
389 0     0 0   my $names = shift;
390 0           my $export_names = [grep { is_exported($_) } @{$names}];
  0            
  0            
391             my $perl_names =
392 0           [map { sym_to_perl($_) } @{$export_names}];
  0            
  0            
393 0           my $names_str = join ' ', @{$perl_names};
  0            
394 0           return "our \@EXPORT = qw($names_str);";
395             }
396              
397             sub oper_to_perl {
398 0     0 0   my ($name, $strs) = @_;
399 0 0         if (
400             $name ~~ [
401             '=', '+', '-', '==', '>=', '!=', '>', '<',
402             '<=', '&&', '||', '~~', 'gt', 'ge', 'lt', 'x',
403             'eq', 'le', 'ne', 'in'
404             ]
405             )
406             {
407 0           my $oper_str = ejoin($strs, " $name ");
408 0           return "$oper_str";
409             }
410 0           return call_to_perl($name, $strs);
411             }
412              
413             sub call_to_perl {
414 0     0 0   my ($name, $strs) = @_;
415 0           my $str = ejoin($strs, ', ');
416 0           given ($name) {
417 0           when ('split') { return split_to_perl($strs) }
  0            
418 0           when ('map') { return map_to_perl($strs) }
  0            
419 0           when ('grep') { return grep_to_perl($strs) }
  0            
420 0           when ('join') { return join_to_perl($strs) }
  0            
421 0           when ('push') { return push_to_perl($strs) }
  0            
422 0           when ('unshift') { return unshift_to_perl($strs) }
  0            
423 0           when ('exists') { return exists_to_perl($strs) }
  0            
424 0           when ('delete') { return delete_to_perl($strs) }
  0            
425 0           when ('say') { return "say $str" }
  0            
426 0           when ('print') { return "print $str" }
  0            
427 0           when ('chop') { return "Chop($str)" }
  0            
428 0           when ('inc') { return "$str++" }
  0            
429 0           when ('dec') { return "$str --" }
  0            
430 0           when ('stdin') { return "<STDIN>" }
  0            
431 0           when ('shift') { return "shift \@{$str};" }
  0            
432 0           when ('nextif') { return "next if $str" }
  0            
433 0           when ('exitif') { return "exit() if $str" }
  0            
434 0           default {
435 0           my $action = sym_to_perl($name);
436 0           return "$action($str)"
437             }
438             }
439             }
440              
441             sub split_to_perl {
442 0     0 0   my $strs = shift;
443 0 0         if (elen($strs) == 1) {
444 0           my $array = name($strs);
445 0           return "split '', $array";
446             }
447 0           my ($list, $sub_str) = flat($strs);
448 0           return "[ split $sub_str, $list ]";
449             }
450              
451             sub map_to_perl {
452 0     0 0   my $strs = shift;
453 0           my ($fn, $array) = flat($strs);
454 0           return "[ map { $fn(\$_) } \@{$array} ]";
455             }
456              
457             sub grep_to_perl {
458 0     0 0   my $strs = shift;
459 0           my ($fn, $array) = flat($strs);
460 0           return "[ grep { $fn(\$_) } \@{$array} ]";
461             }
462              
463             sub join_to_perl {
464 0     0 0   my $strs = shift;
465 0           my $array = name($strs);
466 0 0         if (elen($strs) == 1) { return "join '', \@{$array} " }
  0            
467 0           my $char = value($strs);
468 0           return "join $char, \@{$array};";
469             }
470              
471             sub push_to_perl {
472 0     0 0   my $strs = shift;
473 0           my ($array, $elem) = flat($strs);
474 0           return "push \@{$array}, $elem;";
475             }
476              
477             sub unshift_to_perl {
478 0     0 0   my $strs = shift;
479 0           my ($array, $elem) = flat($strs);
480 0           return "unshift \@{$array}, $elem;";
481             }
482              
483             sub exists_to_perl {
484 0     0 0   my $strs = shift;
485 0           my ($hash, $keys) = match($strs);
486             my $keys_str = join '',
487 0           @{ [map { key_to_perl($_) } @{ atoms($keys) }] };
  0            
  0            
  0            
488 0           return "exists $hash\->$keys_str";
489             }
490 0     0 0   sub key_to_perl { my $key = shift; return "{$key}" }
  0            
491              
492             sub delete_to_perl {
493 0     0 0   my $strs = shift;
494 0           my ($hash, $key) = flat($strs);
495 0           return "delete $hash\->{$key};";
496             }
497             1;