File Coverage

blib/lib/Blatte/Syntax.pm
Criterion Covered Total %
statement 221 254 87.0
branch 20 26 76.9
condition n/a
subroutine 65 73 89.0
pod 0 2 0.0
total 306 355 86.2


line stmt bran cond sub pod time code
1 12     12   71 use strict;
  12         22  
  12         80953  
2              
3             package Blatte::Syntax;
4              
5             sub transform {
6 343     343 0 511 my($obj, $column) = @_;
7 343 50       738 return $obj unless ref($obj);
8 343         985 $obj->transform($column);
9             }
10              
11             sub make_sub {
12 5     5 0 39 my($params, $exprs, $column) = @_;
13              
14 5         11 my @positional;
15             my @named;
16 0         0 my $rest;
17              
18 5         11 foreach my $param (@$params) {
19 8 100       68 if ($param->isa('Blatte::Syntax::Param::Positional')) {
    100          
    50          
20 5         15 push(@positional, $param->name());
21             } elsif ($param->isa('Blatte::Syntax::Param::Named')) {
22 2         7 push(@named, $param->name());
23             } elsif ($param->isa('Blatte::Syntax::Param::Rest')) {
24 1         5 $rest = $param->name();
25             }
26             }
27              
28 5         19 my $indent = (' ' x $column);
29              
30 5         16 my $result = "sub {\n";
31 5         14 $result .= sprintf("%s my \$_named = shift;\n", $indent);
32 5 100       16 if (@positional) {
33 5         20 $result .= sprintf("%s my(%s) = map {\n",
34             $indent,
35             join(sprintf(",\n%s ", $indent),
36 4         13 map { sprintf('$%s', $_) } @positional));
37 4         11 $result .= sprintf("%s &Blatte::unwrapws(\$_);\n",
38             $indent);
39 4         15 $result .= sprintf("%s } splice(\@_, 0, %d);\n",
40             $indent,
41             scalar(@positional));
42             }
43 5         13 foreach my $named (@named) {
44 2         7 $result .= sprintf("%s my \$%s = \$_named->{%s};\n",
45             $indent, $named, $named);
46             }
47 5 100       22 if (defined($rest)) {
48 1         4 $result .= sprintf("%s my \$%s = [\@_];\n", $indent, $rest);
49             }
50 5         14 $result .= sprintf("%s %s;\n",
51             $indent,
52             join(sprintf(";\n%s ", $indent),
53 5         16 map { &Blatte::Syntax::transform($_, $column + 2) } @$exprs));
54 5         15 $result .= sprintf("%s}", $indent);
55              
56 5         48 $result;
57             }
58              
59             ############################################################
60              
61             package Blatte::Syntax::List;
62              
63             sub new {
64 35     35   59 my $type = shift;
65 35         167 bless [@_], $type;
66             }
67              
68             sub transform {
69 35     35   57 my($self, $column) = @_;
70              
71 35 100       564 return '[]' unless @$self;
72              
73 31         40 my @exprs;
74             my @assignments;
75              
76 31         68 foreach my $subexpr (@$self) {
77 100 100       1277 if (UNIVERSAL::isa($subexpr, 'Blatte::Syntax::Assignment')) {
78 2         5 push(@assignments, $subexpr);
79             } else {
80 98         205 push(@exprs, $subexpr);
81             }
82             }
83              
84 31         60 my $first = shift(@exprs);
85              
86 31         79 my $indent = (' ' x $column);
87 31         96 my $result = "do {\n";
88 31         356 $result .= sprintf("%s my \$_first = %s;\n",
89             $indent,
90             &Blatte::Syntax::transform($first, $column + 15));
91 67         194 $result .= sprintf("%s my \@_rest = (%s);\n",
92             $indent,
93             join(sprintf(",\n%s ", $indent),
94             map {
95 31         2241 my $result =
96             sprintf("&Blatte::wrapws('%s',\n",
97             &Blatte::wsof($_));
98 67         385 $result .=
99             sprintf("%s%s%s%s)",
100             $indent,
101             (' ' x 15),
102             (' ' x 16),
103             &Blatte::Syntax::transform($_,
104             $column + 31));
105 67         303 $result;
106             } @exprs));
107 31         95 $result .= sprintf("%s if (ref(\$_first) eq 'CODE') {\n", $indent);
108 2         7 $result .= sprintf("%s &\$_first({%s}",
109             $indent,
110             join(sprintf(",\n%s ", $indent),
111             map {
112 31         118 sprintf('%s => %s',
113             $_->name(),
114             &Blatte::Syntax::transform($_->expr(),
115             $column + 16));
116             } @assignments));
117 31 50       98 if (@exprs) {
118 31         189 $result .= sprintf(",\n%s &Blatte::unwrapws(\$_rest[0])",
119             $indent);
120 31 100       105 if (@exprs > 1) {
121 20         58 $result .= sprintf(",\n%s \@_rest[1 .. \$#_rest]",
122             $indent);
123             }
124             }
125 31         58 $result .= ");\n";
126 31         531 $result .= sprintf("%s } else {\n", $indent);
127 31         70 $result .= sprintf("%s [\$_first, \@_rest];\n", $indent);
128 31         69 $result .= sprintf("%s }\n", $indent);
129 31         59 $result .= sprintf("%s}", $indent);
130              
131 31         378 $result;
132             }
133              
134             ############################################################
135              
136             package Blatte::Syntax::Assignment;
137              
138             sub new {
139 2     2   4 my($type, $name, $expr) = @_;
140 2         10 bless [$name, $expr], $type;
141             }
142              
143 2     2   105 sub name { $_[0]->[0] }
144 2     2   7 sub expr { $_[0]->[1] }
145              
146             ############################################################
147              
148             package Blatte::Syntax::VarRef;
149              
150             sub new {
151 42     42   83 my($type, $name) = @_;
152 42         261 bless \$name, $type;
153             }
154              
155 42     42   49 sub name { $ {$_[0]} }
  42         402  
156              
157             sub transform {
158 42     42   64 my($self, $column) = @_;
159 42         166 sprintf('$%s', $self->name());
160             }
161              
162             ############################################################
163              
164             package Blatte::Syntax::Literal;
165              
166             sub new {
167 95     95   230 my($type, $str) = @_;
168 95         15291 bless \$str, $type;
169             }
170              
171 95     95   107 sub str { $ {$_[0]} }
  95         586  
172              
173             sub transform {
174 95     95   410 my($self, $column) = @_;
175 95         197 my $str = $self->str();
176 95         246 $str =~ s/([\\\'])/\\$1/g;
177 95         1032 sprintf("'%s'", $str);
178             }
179              
180             ############################################################
181              
182             package Blatte::Syntax::DefineVar;
183              
184             sub new {
185 3     3   7 my($type, $name, $expr) = @_;
186 3         15 bless [$name, $expr], $type;
187             }
188              
189 6     6   182 sub name { $_[0]->[0] }
190 3     3   15 sub expr { $_[0]->[1] }
191              
192             sub transform {
193 3     3   5 my($self, $column) = @_;
194              
195 3         10 my $indent = (' ' x $column);
196              
197 3         11 my $result = "do {\n";
198 3         11 $result .= sprintf("%s use vars '\$%s';\n", $indent, $self->name());
199 3         12 $result .= sprintf("%s \$%s = %s;\n",
200             $indent,
201             $self->name(),
202             &Blatte::Syntax::transform($self->expr(), $column + 4));
203 3         10 $result .= sprintf("%s [];\n", $indent);
204 3         7 $result .= sprintf("%s}", $indent);
205              
206 3         25 $result;
207             }
208              
209             ############################################################
210              
211             package Blatte::Syntax::DefineFn;
212              
213             sub new {
214 4     4   11 my($type, $name, $params, $exprs) = @_;
215 4         20 bless [$name, $params, $exprs], $type;
216             }
217              
218 8     8   49 sub name { $_[0]->[0] }
219 4     4   18 sub params { $_[0]->[1] }
220 4     4   16 sub exprs { $_[0]->[2] }
221              
222             sub transform {
223 4     4   16 my($self, $column) = @_;
224              
225 4         13 my $indent = (' ' x $column);
226              
227 4         7 my $result = "do {\n";
228 4         15 $result .= sprintf("%s use vars '\$%s';\n", $indent, $self->name());
229 4         12 $result .= sprintf("%s \$%s = %s;\n",
230             $indent,
231             $self->name(),
232             &Blatte::Syntax::make_sub($self->params(),
233             $self->exprs(),
234             $column + 4));
235 4         14 $result .= sprintf("%s [];\n", $indent);
236 4         9 $result .= sprintf("%s}", $indent);
237              
238 4         122 $result;
239             }
240              
241             ############################################################
242              
243             package Blatte::Syntax::SetVar;
244              
245             sub new {
246 1     1   2 my($type, $name, $expr) = @_;
247 1         4 bless [$name, $expr], $type;
248             }
249              
250 1     1   7 sub name { $_[0]->[0] }
251 1     1   3 sub expr { $_[0]->[1] }
252              
253             sub transform {
254 1     1   2 my($self, $column) = @_;
255              
256 1         3 sprintf("\$%s = %s",
257             $self->name(),
258             &Blatte::Syntax::transform($self->expr(), $column + 2));
259             }
260              
261             ############################################################
262              
263             package Blatte::Syntax::Lambda;
264              
265             sub new {
266 1     1   2 my($type, $params, $exprs) = @_;
267 1         4 bless [$params, $exprs], $type;
268             }
269              
270 1     1   7 sub params { $_[0]->[0] }
271 1     1   4 sub exprs { $_[0]->[1] }
272              
273             sub transform {
274 1     1   6 my($self, $column) = @_;
275 1         3 &Blatte::Syntax::make_sub($self->params(), $self->exprs(), $column);
276             }
277              
278             ############################################################
279              
280             package Blatte::Syntax::Param::Positional;
281              
282             sub new {
283 5     5   11 my($type, $name) = @_;
284 5         23 bless \$name, $type;
285             }
286              
287             sub name {
288 5     5   5 $ {$_[0]};
  5         16  
289             }
290              
291             ############################################################
292              
293             package Blatte::Syntax::Param::Named;
294              
295             sub new {
296 2     2   4 my($type, $name) = @_;
297 2         11 bless \$name, $type;
298             }
299              
300             sub name {
301 2     2   3 $ {$_[0]};
  2         9  
302             }
303              
304             ############################################################
305              
306             package Blatte::Syntax::Param::Rest;
307              
308             sub new {
309 1     1   3 my($type, $name) = @_;
310 1         4 bless \$name, $type;
311             }
312              
313             sub name {
314 1     1   2 $ {$_[0]};
  1         7  
315             }
316              
317             ############################################################
318              
319             package Blatte::Syntax::Let;
320              
321             sub new {
322 4     4   8 my($type, $clauses, $exprs) = @_;
323 4         19 bless [$clauses, $exprs], $type;
324             }
325              
326 8     8   11 sub clauses { @{$_[0]->[0]} }
  8         830  
327 4     4   8 sub exprs { @{$_[0]->[1]} }
  4         92  
328              
329             sub transform {
330 4     4   7 my($self, $column) = @_;
331              
332 4         19 my $indent = (' ' x $column);
333              
334 4         17 my $result = "do {\n";
335 5         56 $result .= sprintf("%s my(%s) =\n",
336             $indent,
337             join(sprintf(",\n%s ", $indent),
338             map {
339 4         22 sprintf('$%s', $_->name());
340             } $self->clauses()));
341 5         17 $result .= sprintf("%s (%s);\n",
342             $indent,
343             join(sprintf(",\n%s ", $indent),
344             map {
345 4         19 sprintf('(%s)',
346             &Blatte::Syntax::transform($_->expr(),
347             $column + 6));
348             } $self->clauses()));
349 4         24 $result .= sprintf("%s %s;\n",
350             $indent,
351             join(sprintf(";\n%s ", $indent),
352             map {
353 4         23 &Blatte::Syntax::transform($_, $column + 2);
354             } $self->exprs()));
355 4         16 $result .= sprintf("%s}", $indent);
356              
357 4         52 $result;
358             }
359              
360             ############################################################
361              
362             package Blatte::Syntax::LetStar;
363              
364             sub new {
365 2     2   6 my($type, $clauses, $exprs) = @_;
366 2         10 bless [$clauses, $exprs], $type;
367             }
368              
369 2     2   3 sub clauses { @{$_[0]->[0]} }
  2         22  
370 2     2   5 sub exprs { @{$_[0]->[1]} }
  2         10  
371              
372             sub transform {
373 2     2   5 my($self, $column) = @_;
374              
375 2         9 my $indent = (' ' x $column);
376              
377 2         5 my $result = "do {\n";
378 4         15 $result .= sprintf("%s %s;\n",
379             $indent,
380             join(sprintf(";\n%s ", $indent),
381             map {
382 2         26 sprintf('my $%s = %s;',
383             $_->name(),
384             &Blatte::Syntax::transform($_->expr(),
385             $column + 7));
386             } $self->clauses()));
387 2         6 $result .= sprintf("%s %s;\n",
388             $indent,
389             join(sprintf(";\n%s ", $indent),
390             map {
391 2         16 &Blatte::Syntax::transform($_, $column + 2);
392             } $self->exprs()));
393 2         8 $result .= sprintf("%s}", $indent);
394              
395 2         20 $result;
396             }
397              
398             ############################################################
399              
400             package Blatte::Syntax::Letrec;
401              
402             sub new {
403 0     0   0 my($type, $clauses, $exprs) = @_;
404 0         0 bless [$clauses, $exprs], $type;
405             }
406              
407 0     0   0 sub clauses { @{$_[0]->[0]} }
  0         0  
408 0     0   0 sub exprs { @{$_[0]->[1]} }
  0         0  
409              
410             sub transform {
411 0     0   0 my($self, $column) = @_;
412              
413 0         0 my $indent = (' ' x $column);
414              
415 0         0 my $result = "do {\n";
416 0         0 $result .= sprintf("%s my(%s);\n",
417             $indent,
418             join(sprintf(",\n%s ", $indent),
419             map {
420 0         0 sprintf('$%s', $_->name());
421             } $self->clauses()));
422 0         0 $result .= sprintf("%s %s;\n",
423             $indent,
424             join(sprintf(";\n%s ", $indent),
425             map {
426 0         0 sprintf('$%s = %s;',
427             $_->name(),
428             &Blatte::Syntax::transform($_->expr(),
429             $column + 4));
430             } $self->clauses()));
431 0         0 $result .= sprintf("%s %s;\n",
432             $indent,
433             join(sprintf(";\n%s ", $indent),
434             map {
435 0         0 &Blatte::Syntax::transform($_, $column + 2);
436             } $self->exprs()));
437 0         0 $result .= sprintf("%s}", $indent);
438              
439 0         0 $result;
440             }
441              
442             ############################################################
443              
444             package Blatte::Syntax::LetClause;
445              
446             sub new {
447 9     9   16 my($type, $name, $expr) = @_;
448 9         50 bless [$name, $expr], $type;
449             }
450              
451 9     9   65 sub name { $_[0]->[0] }
452 9     9   37 sub expr { $_[0]->[1] }
453              
454             ############################################################
455              
456             package Blatte::Syntax::If;
457              
458             sub new {
459 2     2   6 my($type, $test, $consequent, @alternates) = @_;
460 2         11 bless [$test, $consequent, @alternates], $type;
461             }
462              
463 2     2   16 sub test { $_[0]->[0] }
464 2     2   6 sub consequent { $_[0]->[1] }
465 4     4   5 sub alternates { @{$_[0]}[2 .. $#{$_[0]}] }
  4         18  
  4         8  
466              
467             sub transform {
468 2     2   4 my($self, $column) = @_;
469              
470 2         6 my $indent = (' ' x $column);
471              
472 2         3 my $result = "do {\n";
473 2         21 $result .= sprintf("%s if (&Blatte::true(%s)) {\n",
474             $indent,
475             &Blatte::Syntax::transform($self->test(),
476             $column + 20));
477 2         9 $result .= sprintf("%s %s;\n",
478             $indent,
479             &Blatte::Syntax::transform($self->consequent(),
480             $column + 4));
481 2         6 $result .= sprintf("%s } else {\n",
482             $indent);
483 2         5 $result .= sprintf("%s %s;\n",
484             $indent,
485             ($self->alternates() ?
486             join(sprintf(";\n%s ", $indent),
487             map {
488 2 50       7 &Blatte::Syntax::transform($_, $column + 4);
489             } $self->alternates()) :
490             'undef'));
491 2         8 $result .= sprintf("%s }\n", $indent);
492 2         3 $result .= sprintf("%s}", $indent);
493              
494 2         22 $result;
495             }
496              
497             ############################################################
498              
499             package Blatte::Syntax::Cond;
500              
501             sub new {
502 2     2   4 my $type = shift;
503 2         9 bless [@_], $type;
504             }
505              
506 2     2   3 sub clauses { @{$_[0]} }
  2         10  
507              
508             sub transform {
509 2     2   4 my($self, $column) = @_;
510              
511 2         5 my $indent = (' ' x $column);
512              
513 2         4 my $result = "do {\n";
514              
515 2         5 my @clauses = $self->clauses();
516 2         6 my $first_clause = shift(@clauses);
517              
518 2         5 $result .= sprintf("%s if (&Blatte::true(%s)) {\n",
519             $indent,
520             &Blatte::Syntax::transform($first_clause->test(),
521             $column + 20));
522 2         5 $result .= sprintf("%s %s;\n",
523             $indent,
524             ($first_clause->actions() ?
525             join(sprintf(";\n%s ", $indent),
526             $indent,
527             map {
528 2 50       7 &Blatte::Syntax::transform($_, $column + 4);
529             } $first_clause->actions()) :
530             'undef'));
531 2         5 foreach my $clause (@clauses) {
532 5         11 $result .= sprintf("%s } elsif (&Blatte::true(%s)) {\n",
533             $indent,
534             &Blatte::Syntax::transform($clause->test(),
535             $column + 25));
536 5         12 $result .= sprintf("%s %s;\n",
537             $indent,
538             ($clause->actions() ?
539             join(sprintf(";\n%s ", $indent),
540             $indent,
541             map {
542 5 50       14 &Blatte::Syntax::transform($_, $column + 4);
543             } $clause->actions()) :
544             'undef'));
545             }
546 2         8 $result .= sprintf("%s }\n", $indent);
547 2         4 $result .= sprintf("%s}", $indent);
548              
549 2         32 $result;
550             }
551              
552             ############################################################
553              
554             package Blatte::Syntax::CondClause;
555              
556             sub new {
557 7     7   15 my($type, $test, @actions) = @_;
558 7         107 bless [$test, @actions], $type;
559             }
560              
561 7     7   27 sub test { $_[0]->[0] }
562 14     14   20 sub actions { @{$_[0]}[1 .. $#{$_[0]}] }
  14         52  
  14         25  
563              
564             ############################################################
565              
566             package Blatte::Syntax::While;
567              
568             sub new {
569 0     0   0 my($type, $test, @exprs) = @_;
570 0         0 bless [$test, @exprs], $type;
571             }
572              
573 0     0   0 sub test { $_[0]->[0] }
574 0     0   0 sub exprs { @{$_[0]}[1 .. $#{$_[0]}] }
  0         0  
  0         0  
575              
576             sub transform {
577 0     0   0 my($self, $column) = @_;
578              
579 0         0 my $indent = (' ' x $column);
580              
581 0         0 my $result = "do {\n";
582 0         0 $result .= sprintf("%s while (&Blatte::true(%s)) {\n",
583             $indent,
584             &Blatte::Syntax::transform($self->test(), $column + 23));
585 0         0 $result .= sprintf("%s %s;\n",
586             $indent,
587             join(sprintf(";\n%s ",
588             map {
589 0         0 &Blatte::Syntax::transform($_,
590             $column + 4);
591             } $self->exprs())));
592 0         0 $result .= sprintf("%s }\n", $indent);
593 0         0 $result .= sprintf("%s}", $indent);
594              
595 0         0 $result;
596             }
597              
598             ############################################################
599              
600             package Blatte::Syntax::And;
601              
602             sub new {
603 1     1   2 my $type = shift;
604 1         4 bless [@_], $type;
605             }
606              
607 1     1   1 sub exprs { @{$_[0]} }
  1         7  
608              
609             sub transform {
610 1     1   2 my($self, $column) = @_;
611              
612 1         3 my $indent = (' ' x $column);
613              
614 3         8 sprintf('(%s)',
615             join(sprintf("\n%s && ", $indent),
616             map {
617 1         5 sprintf('&Blatte::true(%s)',
618             &Blatte::Syntax::transform($_, $column + 18));
619             } $self->exprs()));
620             }
621              
622             ############################################################
623              
624             package Blatte::Syntax::Or;
625              
626             sub new {
627 2     2   4 my $type = shift;
628 2         7 bless [@_], $type;
629             }
630              
631 2     2   2 sub exprs { @{$_[0]} }
  2         9  
632              
633             sub transform {
634 2     2   4 my($self, $column) = @_;
635              
636 2         6 my $indent = (' ' x $column);
637              
638 4         11 sprintf('(%s)',
639             join(sprintf("\n%s || ", $indent),
640             map {
641 2         11 sprintf('&Blatte::true(%s)',
642             &Blatte::Syntax::transform($_, $column + 18));
643             } $self->exprs()));
644             }
645              
646             1;
647              
648             __END__