File Coverage

blib/lib/Mylisp/ToPerl.pm
Criterion Covered Total %
statement 17 488 3.4
branch 0 44 0.0
condition n/a
subroutine 6 59 10.1
pod 0 53 0.0
total 23 644 3.5


line stmt bran cond sub pod time code
1             package Mylisp::ToPerl;
2            
3 1     1   5136 use 5.012;
  1         5  
4 1     1   8 use experimental 'switch';
  1         3  
  1         10  
5            
6 1     1   169 use Exporter;
  1         2  
  1         108  
7             our @ISA = qw(Exporter);
8             our @EXPORT = qw(AstToPerl);
9            
10 1     1   8 use Mylisp::Builtin;
  1         3  
  1         255  
11 1     1   16 use Mylisp::Estr;
  1         5  
  1         224  
12 1     1   9 use Mylisp::LintMyAst;
  1         3  
  1         8782  
13            
14             sub AstToPerl {
15 0     0 0   my ($t,$ast) = @_;
16 0           my $head_str = get_perl_head_str($t,$ast);
17 0           my $exprs_str = exprs_to_perl($t,$ast);
18 0           my $perl_str = add($head_str,$exprs_str,"\n1;");
19 0           $t->{'count'} = 0;
20 0           return $perl_str;
21             }
22            
23             sub get_perl_head_str {
24 0     0 0   my ($t,$exprs) = @_;
25 0           my $names = [];
26 0           my $head_str = '';
27 0           for my $expr (@{atoms($exprs)}) {
  0            
28 0           my ($name,$value) = flat($expr);
29 0           given ($name) {
30 0           when ('package') {
31 0           InContext($t,$value);
32 0           $head_str = package_to_perl($value);
33             }
34 0           when ('func') {
35 0           apush($names,name(first(atoms($value))));
36             }
37             }
38             }
39 0           my $export_str = get_export_str($t,$names);
40 0           return add($head_str,$export_str);
41             }
42            
43             sub package_to_perl {
44 0     0 0   my $ns = shift;
45 0           my $package_str = "package $ns;\n";
46 0           my $head_str = <<'EOF'
47            
48             use 5.012;
49             use experimental 'switch';
50            
51             use Exporter;
52             our @ISA = qw(Exporter);
53             EOF
54             ;;
55 0           return add($package_str,$head_str);
56             }
57            
58             sub get_export_str {
59 0     0 0   my ($t,$names) = @_;
60 0           my $sym_names = [ map { sym_to_perl($_) } @{$names} ];
  0            
  0            
61 0           my $ns = Context($t);
62 0 0         if (not(end_with($ns,'Estr'))) {
63 0           $sym_names = [ grep { is_exported($_) } @{$sym_names} ];
  0            
  0            
64             }
65 0           my $names_str = ajoin(' ',$sym_names);
66 0           return add('our @EXPORT = qw(',"$names_str);\n");
67             }
68            
69             sub is_exported {
70 0     0 0   my $name = shift;
71 0           return is_upper(first_char($name));
72             }
73            
74             sub exprs_to_perl {
75 0     0 0   my ($t,$atoms) = @_;
76 0           my $strs = atoms_to_perl_strs($t,$atoms);
77 0           return ajoin("\n",$strs);
78             }
79            
80             sub atoms_to_perl_strs {
81 0     0 0   my ($t,$atoms) = @_;
82 0           my $strs = [];
83 0           for my $atom (@{atoms($atoms)}) {
  0            
84 0           apush($strs,atom_to_perl($t,$atom));
85             }
86 0           return $strs;
87             }
88            
89             sub atom_to_perl {
90 0     0 0   my ($t,$atom) = @_;
91 0           my ($name,$args) = flat($atom);
92 0           given ($name) {
93 0           when ('Cursor') {
94 0           return exprs_to_perl($t,$args);
95             }
96 0           when ('Lint') {
97 0           return exprs_to_perl($t,$args);
98             }
99 0           when (':ocall') {
100 0           return ocall_to_perl($t,$args);
101             }
102 0           when ('Aindex') {
103 0           return aindex_to_perl($t,$args);
104             }
105 0           when ('Arange') {
106 0           return arange_to_perl($t,$args);
107             }
108 0           when ('while') {
109 0           return while_to_perl($t,$args);
110             }
111 0           when ('for') {
112 0           return for_to_perl($t,$args);
113             }
114 0           when ('given') {
115 0           return given_to_perl($t,$args);
116             }
117 0           when ('when') {
118 0           return when_to_perl($t,$args);
119             }
120 0           when ('then') {
121 0           return then_to_perl($t,$args);
122             }
123 0           when ('if') {
124 0           return if_to_perl($t,$args);
125             }
126 0           when ('elif') {
127 0           return elif_to_perl($t,$args);
128             }
129 0           when ('else') {
130 0           return else_to_perl($t,$args);
131             }
132 0           when ('func') {
133 0           return func_to_perl($t,$args);
134             }
135 0           when ('my') {
136 0           return my_to_perl($t,$args);
137             }
138 0           when ('our') {
139 0           return our_to_perl($t,$args);
140             }
141 0           when ('const') {
142 0           return const_to_perl($t,$args);
143             }
144 0           when ('return') {
145 0           return return_to_perl($t,$args);
146             }
147 0           when ('Array') {
148 0           return array_to_perl($t,$args);
149             }
150 0           when ('Hash') {
151 0           return hash_to_perl($t,$args);
152             }
153 0           when ('exists') {
154 0           return exists_to_perl($t,$args);
155             }
156 0           when ('==') {
157 0           return eq_to_perl($t,$args);
158             }
159 0           when ('!=') {
160 0           return ne_to_perl($t,$args);
161             }
162 0           when ('<=') {
163 0           return le_to_perl($t,$args);
164             }
165 0           when ('>=') {
166 0           return ge_to_perl($t,$args);
167             }
168 0           when ('>') {
169 0           return gt_to_perl($t,$args);
170             }
171 0           when ('<') {
172 0           return lt_to_perl($t,$args);
173             }
174 0           when ('String') {
175 0           return string_to_perl($args);
176             }
177 0           when ('use') {
178 0           return use_to_perl($args);
179             }
180 0           when ('Lstr') {
181 0           return lstr_to_perl($args);
182             }
183 0           when ('Str') {
184 0           return str_to_perl($args);
185             }
186 0           when ('Bool') {
187 0           return bool_to_perl($args);
188             }
189 0           when ('Sym') {
190 0           return sym_to_perl($args);
191             }
192 0           when ('Char') {
193 0           return char_to_perl($args);
194             }
195 0           when ('Int') {
196 0           return $args;
197             }
198 0           when ('package') {
199 0           return '';
200             }
201 0           when ('struct') {
202 0           return '';
203             }
204 0           default {
205 0           return oper_to_perl($t,$name,$args);
206             }
207             }
208             }
209            
210             sub ocall_to_perl {
211 0     0 0   my ($t,$sym_call) = @_;
212 0           my ($sym,$call) = flat($sym_call);
213 0 0         if (IsDefine($t,$call)) {
214 0           my $call_name = name_to_perl($call);
215 0           return "$call_name($sym)";
216             }
217 0           return add($sym,"->{'$call'}");
218             }
219            
220             sub arange_to_perl {
221 0     0 0   my ($t,$args) = @_;
222 0           my ($sym,$range) = match($args);
223 0           my $type = GetAtomType($t,$sym);
224 0           my $range_strs = atoms_to_perl_strs($t,$range);
225 0           my $range_str = ajoin(',',$range_strs);
226 0           my $sym_str = atom_to_perl($t,$sym);
227 0 0         if ($type eq 'Str') {
228 0           return "substr($sym_str, $range_str)";
229             }
230 0           return "subarray($sym_str, $range_str)";
231             }
232            
233             sub aindex_to_perl {
234 0     0 0   my ($t,$args) = @_;
235 0           my ($sym,$indexs) = match($args);
236 0           my $type = GetAtomType($t,$sym);
237 0 0         if ($type eq 'Str') {
238 0           return index_str_to_perl($t,$args);
239             }
240 0           my $indexs_strs = indexs_to_perls($t,$indexs);
241 0           my $index_str = to_str($indexs_strs);
242 0           my $sym_str = sym_to_perl(value($sym));
243 0           return add($sym_str,"->$index_str");
244             }
245            
246             sub indexs_to_perls {
247 0     0 0   my ($t,$indexs) = @_;
248 0           my $strs = [];
249 0           for my $index (@{atoms($indexs)}) {
  0            
250 0           my $type = GetAtomType($t,$index);
251 0           my $index_str = atom_to_perl($t,$index);
252 0 0         if ($type eq 'Int') {
253 0           apush($strs,"[$index_str]");
254             }
255             else {
256 0           apush($strs,"{$index_str}");
257             }
258             }
259 0           return $strs;
260             }
261            
262             sub index_str_to_perl {
263 0     0 0   my ($t,$args) = @_;
264 0           my ($sym,$index) = flat($args);
265 0           my $name = atom_to_perl($t,$sym);
266 0           my $index_str = atom_to_perl($t,$index);
267 0           return "substr($name, $index_str, 1)";
268             }
269            
270             sub while_to_perl {
271 0     0 0   my ($t,$args) = @_;
272 0           my $str = cond_block_to_perl($t,$args);
273 0           my $indent = GetIndent($t);
274 0           return add($indent,"while $str");
275             }
276            
277             sub cond_block_to_perl {
278 0     0 0   my ($t,$args) = @_;
279 0           my ($cond,$exprs) = match($args);
280 0           my $cond_str = atom_to_perl($t,$cond);
281 0           my $exprs_str = block_to_perl($t,$exprs);
282 0           return "($cond_str) $exprs_str";
283             }
284            
285             sub block_to_perl {
286 0     0 0   my ($t,$exprs) = @_;
287 0           InBlock($t);
288 0           my $strs = atoms_to_perl_strs($t,$exprs);
289 0           OutBlock($t);
290 0           my $str = ajoin("\n",$strs);
291 0           my $indent = GetIndent($t);
292 0           return "{\n$str\n$indent}";
293             }
294            
295             sub for_to_perl {
296 0     0 0   my ($t,$args) = @_;
297 0           my ($iter_expr,$exprs) = match($args);
298 0           my $iter_str = iter_to_perl($t,$iter_expr);
299 0           my $exprs_str = block_to_perl($t,$exprs);
300 0           my $indent = GetIndent($t);
301 0           return add($indent,"for $iter_str $exprs_str");
302             }
303            
304             sub iter_to_perl {
305 0     0 0   my ($t,$expr) = @_;
306 0           my ($loop,$iter_atom) = flat($expr);
307 0           my $iter = value($iter_atom);
308 0 0         if ($iter eq '@args') {
309 0           return "my $loop ($iter)";
310             }
311 0           my $iter_str = atom_to_perl($t,$iter_atom);
312 0           my $type = GetAtomType($t,$iter_atom);
313 0           given ($type) {
314 0           when ('Str') {
315 0           return "my $loop (split '', $iter_str)";
316             }
317 0           when ('Table') {
318 0           return "my $loop (keys \%{$iter_str})";
319             }
320 0           default {
321 0           return "my $loop (\@{$iter_str})";
322             }
323             }
324             }
325            
326             sub given_to_perl {
327 0     0 0   my ($t,$args) = @_;
328 0           my $str = cond_block_to_perl($t,$args);
329 0           my $indent = GetIndent($t);
330 0           return add($indent,"given $str");
331             }
332            
333             sub when_to_perl {
334 0     0 0   my ($t,$args) = @_;
335 0           my $str = cond_block_to_perl($t,$args);
336 0           my $indent = GetIndent($t);
337 0           return add($indent,"when $str");
338             }
339            
340             sub then_to_perl {
341 0     0 0   my ($t,$args) = @_;
342 0           my $str = block_to_perl($t,$args);
343 0           my $indent = GetIndent($t);
344 0           return add($indent,"default $str");
345             }
346            
347             sub if_to_perl {
348 0     0 0   my ($t,$exprs) = @_;
349 0           my $str = cond_block_to_perl($t,$exprs);
350 0           my $indent = GetIndent($t);
351 0           return add($indent,"if $str");
352             }
353            
354             sub elif_to_perl {
355 0     0 0   my ($t,$exprs) = @_;
356 0           my $str = cond_block_to_perl($t,$exprs);
357 0           my $indent = GetIndent($t);
358 0           return add($indent,"elsif $str");
359             }
360            
361             sub else_to_perl {
362 0     0 0   my ($t,$exprs) = @_;
363 0           my $str = block_to_perl($t,$exprs);
364 0           my $indent = GetIndent($t);
365 0           return add($indent,"else $str");
366             }
367            
368             sub func_to_perl {
369 0     0 0   my ($t,$atoms) = @_;
370 0           my ($args,$rest) = match($atoms);
371 0           my $exprs = erest($rest);
372 0           my ($call,$func_args) = flat($args);
373 0           my $args_str = args_to_perl($t,$func_args);
374 0           InFunc($t,$call);
375 0           my $exprs_str = exprs_to_perl($t,$exprs);
376 0           OutBlock($t);
377 0           my $name = sym_to_perl($call);
378 0           return "\nsub $name {\n$args_str$exprs_str\n}";
379             }
380            
381             sub args_to_perl {
382 0     0 0   my ($t,$args) = @_;
383 0 0         if (is_blank($args)) {
384 0           return '';
385             }
386 0           my $strs = [ map { sym_to_perl($_) } @{[ map { name($_) } @{atoms($args)} ]} ];
  0            
  0            
  0            
  0            
387 0           my $str = ajoin(',',$strs);
388 0 0         if (len($strs) == 1) {
389 0 0         if ($str eq '@args') {
390 0           return " my $str = \@_;\n";
391             }
392 0           return " my $str = shift;\n";
393             }
394 0           return " my ($str) = \@_;\n";
395             }
396            
397             sub my_to_perl {
398 0     0 0   my ($t,$args) = @_;
399 0           my ($sym,$value) = flat($args);
400 0           my $value_str = atom_to_perl($t,$value);
401 0           my $name = atom_to_perl($t,$sym);
402 0           my $indent = GetIndent($t);
403 0           return add($indent,"my $name = $value_str;");
404             }
405            
406             sub our_to_perl {
407 0     0 0   my ($t,$args) = @_;
408 0           my ($slist,$value) = flat($args);
409 0           my $names = atoms_to_perl_strs($t,value($slist));
410 0           my $slist_str = ajoin(',',$names);
411 0           my $value_str = atom_to_perl($t,$value);
412 0           my $indent = GetIndent($t);
413 0           return add($indent,"my ($slist_str) = $value_str;");
414             }
415            
416             sub const_to_perl {
417 0     0 0   my ($t,$args) = @_;
418 0           my $strs = atoms_to_perl_strs($t,$args);
419 0           my $str = ajoin(' = ',$strs);
420 0           my $indent = GetIndent($t);
421 0           return add($indent,"our $str");
422             }
423            
424             sub return_to_perl {
425 0     0 0   my ($t,$args) = @_;
426 0           my $strs = atoms_to_perl_strs($t,$args);
427 0           my $str = ajoin(',',$strs);
428 0           my $indent = GetIndent($t);
429 0           return add($indent,"return $str;");
430             }
431            
432             sub array_to_perl {
433 0     0 0   my ($t,$array) = @_;
434 0           my $atoms = atoms_to_perl_strs($t,$array);
435 0           my $atoms_str = ajoin(',',$atoms);
436 0           return "[$atoms_str]";
437             }
438            
439             sub hash_to_perl {
440 0     0 0   my ($t,$pairs) = @_;
441 0           my $strs = [];
442 0           for my $pair (@{atoms($pairs)}) {
  0            
443 0           my ($key,$value) = flat($pair);
444 0           my $key_str = str_to_perl($key);
445 0           my $value_str = atom_to_perl($t,$value);
446 0           apush($strs,add($key_str,' => ',$value_str));
447             }
448 0           my $str = ajoin(',',$strs);
449 0           return "{$str}";
450             }
451            
452             sub exists_to_perl {
453 0     0 0   my ($t,$args) = @_;
454 0           my ($map,$keys) = match($args);
455 0           my $map_str = atom_to_perl($t,$map);
456 0           my $keys_str = keys_to_perl($t,$keys);
457 0           return "exists $map_str\->$keys_str";
458             }
459            
460             sub keys_to_perl {
461 0     0 0   my ($t,$keys) = @_;
462 0           my $strs = atoms_to_perl_strs($t,$keys);
463 0           my $keys_strs = [ map { key_to_perl($_) } @{$strs} ];
  0            
  0            
464 0           return to_str($keys_strs);
465             }
466            
467             sub key_to_perl {
468 0     0 0   my $key = shift;
469 0           return "{$key}";
470             }
471            
472             sub eq_to_perl {
473 0     0 0   my ($t,$args) = @_;
474 0           my $first = first(atoms($args));
475 0           my $strs = atoms_to_perl_strs($t,$args);
476 0           my $type = GetAtomType($t,$first);
477 0 0         if ($type eq 'Str') {
478 0           return ajoin(' eq ',$strs);
479             }
480 0           return ajoin(' == ',$strs);
481             }
482            
483             sub ne_to_perl {
484 0     0 0   my ($t,$args) = @_;
485 0           my $first = first(atoms($args));
486 0           my $strs = atoms_to_perl_strs($t,$args);
487 0           my $type = GetAtomType($t,$first);
488 0 0         if ($type eq 'Str') {
489 0           return ajoin(' ne ',$strs);
490             }
491 0           return ajoin(' != ',$strs);
492             }
493            
494             sub le_to_perl {
495 0     0 0   my ($t,$args) = @_;
496 0           my $first = first(atoms($args));
497 0           my $strs = atoms_to_perl_strs($t,$args);
498 0           my $type = GetAtomType($t,$first);
499 0 0         if ($type eq 'Str') {
500 0           return ajoin(' le ',$strs);
501             }
502 0           return ajoin(' <= ',$strs);
503             }
504            
505             sub ge_to_perl {
506 0     0 0   my ($t,$args) = @_;
507 0           my $first = first(atoms($args));
508 0           my $strs = atoms_to_perl_strs($t,$args);
509 0           my $type = GetAtomType($t,$first);
510 0 0         if ($type eq 'Str') {
511 0           return ajoin(' ge ',$strs);
512             }
513 0           return ajoin(' >= ',$strs);
514             }
515            
516             sub lt_to_perl {
517 0     0 0   my ($t,$args) = @_;
518 0           my $first = first(atoms($args));
519 0           my $strs = atoms_to_perl_strs($t,$args);
520 0           my $type = GetAtomType($t,$first);
521 0 0         if ($type eq 'Str') {
522 0           return ajoin(' lt ',$strs);
523             }
524 0           return ajoin(' < ',$strs);
525             }
526            
527             sub gt_to_perl {
528 0     0 0   my ($t,$args) = @_;
529 0           my $first = first(atoms($args));
530 0           my $strs = atoms_to_perl_strs($t,$args);
531 0           my $type = GetAtomType($t,$first);
532 0 0         if ($type eq 'Str') {
533 0           return ajoin(' gt ',$strs);
534             }
535 0           return ajoin(' > ',$strs);
536             }
537            
538             sub oper_to_perl {
539 0     0 0   my ($t,$name,$args) = @_;
540 0           my $strs = atoms_to_perl_strs($t,$args);
541 0           my $indent = GetIndent($t);
542 0 0         if ($name eq 'set') {
543 0           my $str = ajoin(' = ',$strs);
544 0           return add($indent,"$str;");
545             }
546 0 0         if ($name ~~ ['-','&&','||','~~']) {
547 0           return ajoin(" $name ",$strs);
548             }
549 0           given ($name) {
550 0           when ('map') {
551 0           return map_to_perl($strs);
552             }
553 0           when ('grep') {
554 0           return grep_to_perl($strs);
555             }
556 0           default {
557 0           my $args_str = ajoin(',',$strs);
558 0           my $call_str = call_to_perl($name,$args_str);
559 0           my $call_type = GetCallType($t,$name);
560 0 0         if ($call_type eq 'Nil') {
561 0           return add($indent,"$call_str;");
562             }
563 0           return $call_str;
564             }
565             }
566             }
567            
568             sub call_to_perl {
569 0     0 0   my ($name,$str) = @_;
570 0           given ($name) {
571 0           when ('+') {
572 0           return "add($str)";
573             }
574 0           when ('say') {
575 0           return "say $str";
576             }
577 0           when ('print') {
578 0           return "print $str";
579             }
580 0           when ('trace') {
581 0           return "croak($str)";
582             }
583 0           when ('chop') {
584 0           return "Chop($str)";
585             }
586 0           when ('inc') {
587 0           return "$str++;";
588             }
589 0           when ('dec') {
590 0           return "$str --";
591             }
592 0           when ('stdin') {
593 0           return "";
594             }
595 0           when ('join') {
596 0           return "ajoin($str)";
597             }
598 0           when ('split') {
599 0           return "asplit($str)";
600             }
601 0           when ('push') {
602 0           return "apush($str)";
603             }
604 0           when ('unshift') {
605 0           return "aunshift($str)";
606             }
607 0           when ('shift') {
608 0           return "ashift($str)";
609             }
610 0           when ('nextif') {
611 0           return "next if $str";
612             }
613 0           when ('exitif') {
614 0           return "exit() if $str";
615             }
616 0           default {
617 0           $name = name_to_perl($name);
618 0           return "$name($str)";
619             }
620             }
621             }
622            
623             sub string_to_perl {
624 0     0 0   my $args = shift;
625 0           my $strs = [];
626 0           for my $name (@{atoms($args)}) {
  0            
627 0 0         if (start_with($name,'$')) {
628 0           apush($strs,name_to_perl($name));
629             }
630             else {
631 0           apush($strs,$name);
632             }
633             }
634 0           my $str = to_str($strs);
635 0           return "\"$str\"";
636             }
637            
638             sub use_to_perl {
639 0     0 0   my $args = shift;
640 0           return "use $args;";
641             }
642            
643             sub lstr_to_perl {
644 0     0 0   my $str = shift;
645 0           return "<<'EOF'\n$str\nEOF\n";
646             }
647            
648             sub str_to_perl {
649 0     0 0   my $str = shift;
650 0           return "'$str'";
651             }
652            
653             sub bool_to_perl {
654 0     0 0   my $bool = shift;
655 0 0         if ($bool eq 'true') {
656 0           return '1';
657             }
658 0           return '0';
659             }
660            
661             sub sym_to_perl {
662 0     0 0   my $name = shift;
663 0 0         if ($name eq '@args') {
664 0           return $name;
665             }
666 0           given ($name) {
667 0           when ('Int') {
668 0           return '0';
669             }
670 0           when ('Str') {
671 0           return "''";
672             }
673 0           when ('Bool') {
674 0           return '1';
675             }
676 0           when ('Strs') {
677 0           return '[]';
678             }
679 0           when ('Ints') {
680 0           return '[]';
681             }
682 0           when ('Table') {
683 0           return '{}';
684             }
685 0           when ('Tree') {
686 0           return '{}';
687             }
688 0           default {
689 0           return name_to_perl($name);
690             }
691             }
692             }
693            
694             sub name_to_perl {
695 0     0 0   my $name = shift;
696 0           my $chars = [];
697 0           for my $char (@{to_chars($name)}) {
  0            
698 0           given ($char) {
699 0           when ('-') {
700 0           apush($chars,'_');
701             }
702 0           when ('@') {
703 0           apush($chars,'$');
704             }
705 0           when ('%') {
706 0           apush($chars,'$');
707             }
708 0           default {
709 0           apush($chars,$char);
710             }
711             }
712             }
713 0           return to_str($chars);
714             }
715            
716             sub char_to_perl {
717 0     0 0   my $args = shift;
718 0           my $last_char = last_char($args);
719 0           given ($last_char) {
720 0           when ('n') {
721 0           return '"\n"';
722             }
723 0           when ('t') {
724 0           return '"\t"';
725             }
726 0           when ('r') {
727 0           return '"\r"';
728             }
729 0           when (Ep) {
730 0           return '"\\"';
731             }
732 0           when ("'") {
733 0           return '"\'"';
734             }
735 0           default {
736 0           return "'$last_char'";
737             }
738             }
739             }
740            
741             sub map_to_perl {
742 0     0 0   my $strs = shift;
743 0           my ($fn,$array) = aflat($strs);
744 0 0         if ($array eq '@args') {
745 0           return "[ map { $fn(\$_) } $array ]";
746             }
747 0           return "[ map { $fn(\$_) } \@{$array} ]";
748             }
749            
750             sub grep_to_perl {
751 0     0 0   my $strs = shift;
752 0           my ($fn,$array) = aflat($strs);
753 0           return "[ grep { $fn(\$_) } \@{$array} ]";
754             }
755             1;