File Coverage

blib/lib/Mylisp/ToGo.pm
Criterion Covered Total %
statement 14 483 2.9
branch 0 38 0.0
condition n/a
subroutine 5 52 9.6
pod 0 47 0.0
total 19 620 3.0


line stmt bran cond sub pod time code
1             package Mylisp::ToGo;
2              
3 1     1   14 use 5.012;
  1         2  
4 1     1   4 no warnings 'experimental';
  1         2  
  1         24  
5              
6 1     1   5 use Exporter;
  1         1  
  1         71  
7             our @ISA = qw(Exporter);
8             our @EXPORT =
9             qw(ast_to_go atoms_to_go join_go_exprs atoms_to_gos atom_to_go not_to_go oper_to_go call_to_go substr_to_go push_to_go unshift_to_go shift_to_go my_to_go const_to_go our_to_go slist_to_go array_to_go package_to_go use_to_go ns_to_go func_to_go name_args_to_go arg_to_go return_expr_to_go for_to_go iter_to_go while_to_go if_to_go elif_to_go else_to_go cond_expr_to_go given_to_go when_to_go then_to_go aindex_to_go struct_to_go field_to_go lstr_to_go str_to_go string_to_go clean_go_string return_to_go name_to_go sym_to_go type_to_go type_declare_to_go char_to_go);
10              
11 1     1   5 use Spp::Builtin;
  1         2  
  1         185  
12 1     1   6 use Spp::Tools;
  1         4  
  1         2916  
13 0     0 0   sub ast_to_go { my $ast = shift; return atoms_to_go($ast) }
  0            
14              
15             sub atoms_to_go {
16 0     0 0   my $atoms = shift;
17 0           my $strs = atoms_to_gos($atoms);
18 0           return join_go_exprs($strs);
19             }
20              
21             sub join_go_exprs {
22 0     0 0   my $exprs = shift;
23 0           my $strs = [];
24 0           my $count = 0;
25 0           for my $expr (@{ atoms($exprs) }) {
  0            
26 0           $count++;
27 0 0         if ($count == 1) { push @{$strs}, $expr; }
  0            
  0            
28             else {
29 0 0         if (not(start_with($expr, 'else'))) {
30 0           push @{$strs}, ';';
  0            
31             }
32 0           push @{$strs}, $expr;
  0            
33             }
34             }
35 0           return join '', @{$strs};
  0            
36             }
37              
38             sub atoms_to_gos {
39 0     0 0   my $atoms = shift;
40 0           return estr([map { atom_to_go($_) } @{ atoms($atoms) }]);
  0            
  0            
41             }
42              
43             sub atom_to_go {
44 0     0 0   my $atom = shift;
45 0           my ($name, $args) = flat($atom);
46 0           given ($name) {
47 0           when ('package') { return package_to_go($args) }
  0            
48 0           when ('use') { return use_to_go($args) }
  0            
49 0           when ('func') { return func_to_go($args) }
  0            
50 0           when ('given') { return given_to_go($args) }
  0            
51 0           when ('for') { return for_to_go($args) }
  0            
52 0           when ('while') { return while_to_go($args) }
  0            
53 0           when ('if') { return if_to_go($args) }
  0            
54 0           when ('elif') { return elif_to_go($args) }
  0            
55 0           when ('else') { return else_to_go($args) }
  0            
56 0           when ('given') { return given_to_go($args) }
  0            
57 0           when ('when') { return when_to_go($args) }
  0            
58 0           when ('then') { return then_to_go($args) }
  0            
59 0           when ('return') { return return_to_go($args) }
  0            
60 0           when ('my') { return my_to_go($args) }
  0            
61 0           when ('our') { return our_to_go($args) }
  0            
62 0           when ('const') { return const_to_go($args) }
  0            
63 0           when ('not') { return not_to_go($args) }
  0            
64 0           when ('Aindex') { return aindex_to_go($args) }
  0            
65 0           when ('Sym') { return sym_to_go($args) }
  0            
66 0           when ('Hash') { return struct_to_go($args) }
  0            
67 0           when ('Lstr') { return lstr_to_go($args) }
  0            
68 0           when ('Str') { return str_to_go($args) }
  0            
69 0           when ('Char') { return char_to_go($args) }
  0            
70 0           when ('String') { return string_to_go($args) }
  0            
71 0           when ('Array') { return array_to_go($args) }
  0            
72 0           when ('Type') { return $args }
  0            
73 0           when ('Int') { return $args }
  0            
74 0           when ('Bool') { return $args }
  0            
75 0           when ('end') { return ' ' }
  0            
76 0           default {
77 0           my $strs = atoms_to_gos($args);
78 0           return oper_to_go($name, $strs)
79             }
80             }
81             }
82              
83             sub not_to_go {
84 0     0 0   my $args = shift;
85 0           my $str = atoms_to_go($args);
86 0           return "!$str";
87             }
88              
89             sub oper_to_go {
90 0     0 0   my ($name, $strs) = @_;
91 0           given ($name) {
92 0           when ('gt') { return ejoin($strs, '>') }
  0            
93 0           when ('ge') { return ejoin($strs, '>=') }
  0            
94 0           when ('lt') { return ejoin($strs, '<') }
  0            
95 0           when ('eq') { return ejoin($strs, '==') }
  0            
96 0           when ('le') { return ejoin($strs, '<=') }
  0            
97 0           when ('ne') { return ejoin($strs, '!=') }
  0            
98 0           when ('add') { return ejoin($strs, '+') }
  0            
99 0           when ('=') { return ejoin($strs, '=') }
  0            
100 0           when ('+') { return ejoin($strs, '+') }
  0            
101 0           when ('-') { return ejoin($strs, '-') }
  0            
102 0           when ('==') { return ejoin($strs, '==') }
  0            
103 0           when ('>=') { return ejoin($strs, '>=') }
  0            
104 0           when ('!=') { return ejoin($strs, '!=') }
  0            
105 0           when ('>') { return ejoin($strs, '>') }
  0            
106 0           when ('<') { return ejoin($strs, '<') }
  0            
107 0           when ('<=') { return ejoin($strs, '<=') }
  0            
108 0           when ('&&') { return ejoin($strs, '&&') }
  0            
109 0           when ('||') { return ejoin($strs, '||') }
  0            
110 0           when ('push') { return push_to_go($strs) }
  0            
111 0           when ('unshift') { return unshift_to_go($strs) }
  0            
112 0           default { return call_to_go($name, $strs) }
  0            
113             }
114             }
115              
116             sub call_to_go {
117 0     0 0   my ($name, $strs) = @_;
118 0           my $str = ejoin($strs, ',');
119 0           given ($name) {
120 0           when ('~~') { return "IsIn($str)" }
  0            
121 0           when ('>>') { return "Eunshift($str)" }
  0            
122 0           when ('<<') { return "Epush($str)" }
  0            
123 0           when ('><') { return "Eappend($str)" }
  0            
124 0           when ('shift') { return shift_to_go($str) }
  0            
125 0           when ('Cursor') { return "&Cursor$str" }
  0            
126 0           when ('Lint') { return "&Lint$str" }
  0            
127 0           when ('Hash') { return "Hash$str" }
  0            
128 0           when ('exitif') { return "if $str { Exit() }" }
  0            
129 0           when ('nextif') { return "if $str { continue }" }
  0            
130 0           when ('inc') { return "$str += 1" }
  0            
131 0           when ('dec') { return "$str -= 1" }
  0            
132 0           when ('croak') { return "panic($str)" }
  0            
133 0           when ('substr') { return substr_to_go($strs) }
  0            
134 0           default {
135 0           $name = sym_to_go($name);
136 0           return "$name($str)"
137             }
138             }
139             }
140              
141             sub substr_to_go {
142 0     0 0   my $strs = shift;
143 0 0         if (elen($strs) == 2) {
144 0           my ($name, $from) = flat($strs);
145 0           return "$name\[$from:]";
146             }
147 0 0         if (elen($strs) == 3) {
148 0           my ($name, $rest) = match($strs);
149 0           my ($from, $to) = flat($rest);
150 0 0         if ($to eq '1') { return "$name\[$from]" }
  0            
151 0           return "$name\[$from:len($name)$to]";
152             }
153             }
154              
155             sub push_to_go {
156 0     0 0   my $strs = shift;
157 0           my ($array, $elem) = flat($strs);
158 0           return "$array = append($array, $elem)";
159             }
160              
161             sub unshift_to_go {
162 0     0 0   my $strs = shift;
163 0           my ($array, $elem) = flat($strs);
164 0           return "$array = append(Array{$elem}, $array...)";
165             }
166              
167             sub shift_to_go {
168 0     0 0   my $str = shift;
169 0           return "$str = $str\[1:]";
170             }
171              
172             sub my_to_go {
173 0     0 0   my $args = shift;
174 0           my $strs = atoms_to_gos($args);
175 0           my ($sym, $value) = flat($strs);
176 0 0         if (is_type($value)) {
177 0           my $value_str = type_to_go($value);
178 0           return "var $sym $value";
179             }
180 0           return "$sym := $value";
181             }
182              
183             sub const_to_go {
184 0     0 0   my $args = shift;
185 0           my $strs = atoms_to_gos($args);
186 0           my ($sym, $value) = flat($strs);
187 0           return "const $sym = $value";
188             }
189              
190             sub our_to_go {
191 0     0 0   my $args = shift;
192 0           my ($slist, $value) = flat($args);
193 0           my $slist_str = slist_to_go(value($slist));
194 0           my $value_str = atom_to_go($value);
195 0           return "$slist_str := $value_str";
196             }
197              
198             sub slist_to_go {
199 0     0 0   my $syms = shift;
200 0           my $names = atoms_to_gos($syms);
201 0           return ejoin($names, ',');
202             }
203              
204             sub array_to_go {
205 0     0 0   my $args = shift;
206 0           my $strs = atoms_to_gos($args);
207 0           my $str = ejoin($strs, ',');
208 0           return "Array{$str}";
209             }
210              
211             sub package_to_go {
212 0     0 0   my $ns = shift;
213 0           my $name = ns_to_go($ns);
214 0           return "package $name";
215             }
216              
217             sub use_to_go {
218 0     0 0   my $ns = shift;
219 0           my $names = [split '::', $ns];
220 0           my $name = join '/', @{$names};
  0            
221 0           return "import . \"$name\"";
222             }
223              
224             sub ns_to_go {
225 0     0 0   my $ns = shift;
226 0           return tail([split '::', $ns]);
227             }
228              
229             sub func_to_go {
230 0     0 0   my $args = shift;
231 0           my ($name_args, $rest) = match($args);
232 0           my ($return, $exprs) = match($rest);
233 0           my $args_str = name_args_to_go($name_args);
234 0           my $return_str = return_expr_to_go($return);
235 0           my $exprs_str = atoms_to_go($exprs);
236 0           return "func $args_str $return_str { $exprs_str }";
237             }
238              
239             sub name_args_to_go {
240 0     0 0   my $name_args = shift;
241 0           my ($name, $args) = flat($name_args);
242             my $args_str = join ',',
243 0           @{ [map { arg_to_go($_) } @{ atoms($args) }] };
  0            
  0            
  0            
244 0           $name = sym_to_go($name);
245 0           return "$name($args_str)";
246             }
247              
248             sub arg_to_go {
249 0     0 0   my $arg = shift;
250 0           my ($name, $type) = flat($arg);
251 0           my $name_str = name_to_go($name);
252 0           my $type_str = type_declare_to_go($type);
253 0           return "$name_str $type_str";
254             }
255              
256             sub return_expr_to_go {
257 0     0 0   my $expr = shift;
258 0           my $args = value($expr);
259 0           my $types = [map { value($_) } @{ atoms($args) }];
  0            
  0            
260 0           my $go_types = [map { type_declare_to_go($_) } @{$types}];
  0            
  0            
261 0           my $str = join ',', @{$go_types};
  0            
262 0 0         if (len($types) == 1) { return $str }
  0            
263 0           return "($str)";
264             }
265              
266             sub for_to_go {
267 0     0 0   my $args = shift;
268 0           my ($iter_atom, $exprs) = match($args);
269 0           my $iter_str = iter_to_go($iter_atom);
270 0           my $exprs_str = atoms_to_go($exprs);
271 0           return "for $iter_str $exprs_str }";
272             }
273              
274             sub iter_to_go {
275 0     0 0   my $atom = shift;
276 0           my ($loop_name, $iter_atom) = flat($atom);
277 0           my $loop = sym_to_go($loop_name);
278 0           my $iter = atom_to_go($iter_atom);
279 0 0         if (is_sym($iter_atom)) {
280 0           my $char = first_char(value($iter_atom));
281 0           given ($char) {
282 0           when ('$') {
283 0           return "_, c := range $iter { $loop := string(c);"
284             }
285 0           when ('%') { return "$loop, _ := range $iter { " }
  0            
286 0           default { return "_, $loop := range $iter { " }
  0            
287             }
288             }
289 0           return "_, $loop := range $iter { ";
290             }
291              
292             sub while_to_go {
293 0     0 0   my $args = shift;
294 0           my ($guide_atom, $exprs) = match($args);
295 0           my $guide_str = atom_to_go($guide_atom);
296 0           my $exprs_str = atoms_to_go($exprs);
297 0           return "for $guide_str { $exprs_str }";
298             }
299              
300             sub if_to_go {
301 0     0 0   my $args = shift;
302 0           my $args_str = cond_expr_to_go($args);
303 0           return "if $args_str";
304             }
305              
306             sub elif_to_go {
307 0     0 0   my $args = shift;
308 0           my $args_str = cond_expr_to_go($args);
309 0           return "else if $args_str";
310             }
311              
312             sub else_to_go {
313 0     0 0   my $args = shift;
314 0           my $args_str = atoms_to_go($args);
315 0           return "else { $args_str }";
316             }
317              
318             sub cond_expr_to_go {
319 0     0 0   my $args = shift;
320 0           my ($cond_atom, $exprs) = match($args);
321 0           my $cond_str = atom_to_go($cond_atom);
322 0           my $exprs_str = atoms_to_go($exprs);
323 0           return "$cond_str { $exprs_str }";
324             }
325              
326             sub given_to_go {
327 0     0 0   my $args = shift;
328 0           my $str = cond_expr_to_go($args);
329 0           return "switch $str";
330             }
331              
332             sub when_to_go {
333 0     0 0   my $args = shift;
334 0           my ($cond_atom, $exprs) = match($args);
335 0           my $cond_str = atom_to_go($cond_atom);
336 0           my $exprs_str = atoms_to_go($exprs);
337 0           return "case $cond_str: $exprs_str";
338             }
339              
340             sub then_to_go {
341 0     0 0   my $args = shift;
342 0           my $args_str = atoms_to_go($args);
343 0           return "default: $args_str";
344             }
345              
346             sub aindex_to_go {
347 0     0 0   my $args = shift;
348 0           my $strs = atoms_to_gos($args);
349 0           my ($sym, $indexs) = match($strs);
350 0           my $index_str = ejoin($indexs, '][');
351 0           return "$sym\[$index_str]";
352             }
353              
354             sub struct_to_go {
355 0     0 0   my $pairs = shift;
356 0           my $strs = [];
357 0           for my $pair (@{ atoms($pairs) }) {
  0            
358 0           my ($name, $args) = flat($pair);
359 0 0         if ($name eq 'Pair') {
360 0           push @{$strs}, field_to_go($args);
  0            
361             }
362             }
363 0           my $str = join ', ', @{$strs};
  0            
364 0           return "{ $str }";
365             }
366              
367             sub field_to_go {
368 0     0 0   my $pair = shift;
369 0           my ($key, $value) = flat($pair);
370 0           my $key_str = value($key);
371 0           my $value_str = atom_to_go($value);
372 0           return "$key_str: $value_str";
373             }
374 0     0 0   sub lstr_to_go { my $args = shift; return "`$args`" }
  0            
375 0     0 0   sub str_to_go { my $str = shift; return "`$str`" }
  0            
376              
377             sub string_to_go {
378 0     0 0   my $args = shift;
379 0           my $chars = [];
380 0           my $syms = [];
381 0           for my $atom (@{ atoms($args) }) {
  0            
382 0 0         if (is_sym($atom)) {
383 0           push @{$chars}, '%s';
  0            
384 0           push @{$syms}, atom_to_go($atom);
  0            
385             }
386 0           else { push @{$chars}, value($atom); }
  0            
387             }
388 0           my $str_expr = join '', @{$chars};
  0            
389 0           my $format = clean_go_string($str_expr);
390 0 0         if (len($syms) > 0) {
391 0           my $syms_str = join ',', @{$syms};
  0            
392 0           return "Sprintf(\"$format\", $syms_str)";
393             }
394 0           return "\"$format\"";
395             }
396              
397             sub clean_go_string {
398 0     0 0   my $str = shift;
399 0           my $chars = [];
400 0           my $mode = 0;
401 0           for my $char (split '', $str) {
402 0 0         if ($mode == 0) {
403 0 0         if ($char eq '\\') { $mode = 1 }
  0            
404 0           else { push @{$chars}, $char; }
  0            
405             }
406             else {
407 0           given ($char) {
408 0           when ('n') { return '\n' }
  0            
409 0           when ('r') { return '\r' }
  0            
410 0           when ('t') { return '\t' }
  0            
411 0           when ('"') { return '\"' }
  0            
412 0           when ("\\") { return '\\' }
  0            
413 0           default { return $char }
  0            
414             }
415 0           $mode == 0;
416             }
417             }
418 0           return join '', @{$chars};
  0            
419             }
420              
421             sub return_to_go {
422 0     0 0   my $args = shift;
423 0           my $strs = [map { atom_to_go($_) } @{ atoms($args) }];
  0            
  0            
424 0           my $str = join ',', @{$strs};
  0            
425 0           return "return $str";
426             }
427              
428             sub name_to_go {
429 0     0 0   my $name = shift;
430 0           my $chars = [];
431 0           for my $char (split '', $name) {
432 0 0         if (is_alpha($char)) { push @{$chars}, $char; }
  0            
  0            
433 0           else { push @{$chars}, '_'; }
  0            
434             }
435 0           return join '', @{$chars};
  0            
436             }
437              
438             sub sym_to_go {
439 0     0 0   my $name = shift;
440 0           my $first_char = first_char($name);
441 0 0         if ($first_char ~~ ['$', '@', '%']) {
442 0           return name_to_go($name);
443             }
444 0 0         if ($name ~~ ['len', 'append']) { return $name }
  0            
445 0           my $chars = [];
446 0           my $mode = 0;
447 0           for my $char (split '', $name) {
448 0 0         next if $char eq '$';
449 0 0         if ($mode == 0) {
450 0           $mode = 1;
451 0           push @{$chars}, uc($char);
  0            
452             }
453             else {
454 0 0         if ($char eq '-') { $mode = 0 }
  0            
455 0           else { push @{$chars}, $char; }
  0            
456             }
457             }
458 0           return join '', @{$chars};
  0            
459             }
460              
461             sub type_to_go {
462 0     0 0   my $str = shift;
463 0           given ($str) {
464 0           when ('Str') { return 'string' }
  0            
465 0           when ('Int') { return 'int' }
  0            
466 0           when ('Bool') { return 'bool' }
  0            
467 0           when ('Array') { return 'Array' }
  0            
468 0           when ('Ints') { return '[]int{}' }
  0            
469 0           when ('Hash') { return 'Hash{}' }
  0            
470 0           when ('Table') { return 'Table{}' }
  0            
471 0           default { error("unknown type: |$str| to go") }
  0            
472             }
473 0           return True;
474             }
475              
476             sub type_declare_to_go {
477 0     0 0   my $str = shift;
478 0           given ($str) {
479 0           when ('Str') { return 'string' }
  0            
480 0           when ('Str+') { return '...string' }
  0            
481 0           when ('Str?') { return 'string' }
  0            
482 0           when ('Int') { return 'int' }
  0            
483 0           when ('Bool') { return 'Bool' }
  0            
484 0           when ('Array') { return '[]string' }
  0            
485 0           when ('Ints') { return '[]int' }
  0            
486 0           when ('Hash') { return 'map[string]string' }
  0            
487 0           when ('Cursor') { return '*Cursor' }
  0            
488 0           when ('Lint') { return '*Lint' }
  0            
489 0           default { error("unknown type: |$str| declare") }
  0            
490             }
491 0           return True;
492             }
493              
494             sub char_to_go {
495 0     0 0   my $args = shift;
496 0           my $last_char = last_char($args);
497 0           given ($last_char) {
498 0           when ('n') { return '"\n"' }
  0            
499 0           when ('t') { return '"\t"' }
  0            
500 0           when ('r') { return '"\r"' }
  0            
501 0           when ("\\") { return '"\\\\"' }
  0            
502 0           when ("'") { return '"\'"' }
  0            
503 0           default { return "'$last_char'" }
  0            
504             }
505             }
506             1;