File Coverage

blib/lib/Mylisp/ToPerl.pm
Criterion Covered Total %
statement 14 440 3.1
branch 0 32 0.0
condition n/a
subroutine 5 58 8.6
pod 0 53 0.0
total 19 583 3.2


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