File Coverage

blib/lib/Blatte/Builtins.pm
Criterion Covered Total %
statement 13 13 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 18 100.0


line stmt bran cond sub pod time code
1             package Blatte::Builtins;
2              
3 12     12   95564 use strict;
  12         33  
  12         1245  
4              
5             BEGIN {
6 12     12   548 @Blatte::Builtins::builtins = qw($acall $add $ameth $append $apply
7             $aref $aset $concat $defined
8             $divide $streq $flatten $foreach
9             $funcall $numge $numgt $hashdel $hashkeys
10             $hashp $hashref $hashset $hashtest
11             $int $lc $lcfirst $numle $length $list
12             $listp $numlt $match $max $min $mkhash
13             $multiply $not $numeq $pop $push
14             $random $require $use $scall $shift
15             $smeth $split $sprintf $strge
16             $strgt $strle $strlt $subseq $subst
17             $substr $subtract $uc $ucfirst
18             $unshift);
19             }
20              
21 12     12   67 use vars (qw(@ISA @EXPORT), @Blatte::Builtins::builtins);
  12         29  
  12         7386  
22              
23 12     12   75 use Exporter;
  12         36  
  12         1011  
24              
25             @ISA = qw(Exporter);
26              
27             @EXPORT = @Blatte::Builtins::builtins;
28              
29 12     12   211 use Blatte qw(traverse true unwrapws flatten);
  12         20  
  12         67306  
30              
31             ## Data types
32              
33             $foreach = sub {
34             my $fn = &unwrapws($_[1]);
35             my @result = map { &$fn({}, &unwrapws($_)) } @{&unwrapws($_[2])};
36             \@result;
37             };
38              
39             $length = sub {
40             my $obj = &unwrapws($_[1]);
41             if (ref($obj) eq 'ARRAY') { # xxx UNIVERSAL::isa ?
42             return scalar(@$obj);
43             }
44             length($obj);
45             };
46              
47             $listp = sub {
48             ref(&unwrapws($_[1])) eq 'ARRAY'; # xxx UNIVERSAL::isa ?
49             };
50              
51             $list = sub {
52             if (@_ > 1) {
53             [&unwrapws($_[1]), @_[2..$#_]];
54             } else {
55             [];
56             }
57             };
58              
59             $subseq = sub {
60             my($list, $start) = (&unwrapws($_[1]), &unwrapws($_[2]));
61             if ($start < 0) {
62             $start += @$list;
63             }
64             my $len;
65             if (@_ > 3) {
66             $len = &unwrapws($_[3]);
67             } else {
68             $len = @$list - $start;
69             }
70             [@$list[$start .. $start + $len]];
71             };
72              
73             $not = sub {
74             !&true(&unwrapws($_[1]));
75             };
76              
77             $defined = sub {
78             defined(&unwrapws($_[1]));
79             };
80              
81             ## Array references
82              
83             $aref = sub {
84             &unwrapws($_[1])->[&unwrapws($_[2])];
85             };
86              
87             $aset = sub {
88             &unwrapws($_[1])->[&unwrapws($_[2])] = $_[3];
89             };
90              
91             $push = sub {
92             my $list = &unwrapws($_[1]);
93             push(@$list, @_[2..$#_]);
94             $list;
95             };
96              
97             $pop = sub {
98             pop(@{&unwrapws($_[1])});
99             };
100              
101             $unshift = sub {
102             my $list = &unwrapws($_[1]);
103             unshift(@$list, @_[2..$#_]);
104             $list;
105             };
106              
107             $shift = sub {
108             shift(@{&unwrapws($_[1])});
109             };
110              
111             $append = sub {
112             my $result = [];
113             foreach my $l (@_[1..$#_]) {
114             push(@$result, @$l);
115             }
116             $result;
117             };
118              
119             ## Hash references
120              
121             $hashp = sub {
122             ref(&unwrapws($_[1])) eq 'HASH'; # xxx UNIVERSAL::isa ?
123             };
124              
125             $mkhash = sub {
126             my $result = {};
127             for (my $i = 1; $i <= $#_; $i += 2) {
128             $result->{&unwrapws($_[$i])} = $_[$i + 1];
129             }
130             $result;
131             };
132              
133             $hashref = sub {
134             &unwrapws($_[1])->{&unwrapws($_[2])};
135             };
136              
137             $hashset = sub {
138             &unwrapws($_[1])->{&unwrapws($_[2])} = $_[3];
139             };
140              
141             $hashdel = sub {
142             delete &unwrapws($_[1])->{&unwrapws($_[2])};
143             };
144              
145             $hashtest = sub {
146             exists &unwrapws($_[1])->{&unwrapws($_[2])};
147             };
148              
149             $hashkeys = sub {
150             my @result = keys %{&unwrapws($_[1])};
151             \@result;
152             };
153              
154             ## Perl function-calling interface
155              
156             $acall = sub {
157             my $name = &unwrapws($_[1]);
158             my @result = &$name(@_[2..$#_]);
159             \@result;
160             };
161              
162             $scall = sub {
163             my $name = &unwrapws($_[1]);
164             scalar(&$name(@_[2..$#_]));
165             };
166              
167             ## Perl object interface
168              
169             $ameth = sub {
170             my $obj = &unwrapws($_[1]);
171             my $meth = &unwrapws($_[2]);
172             my @result = $obj->$meth(@_[3..$#_]);
173             \@result;
174             };
175              
176             $smeth = sub {
177             my $obj = &unwrapws($_[1]);
178             my $meth = &unwrapws($_[2]);
179             scalar($obj->$meth(@_[3..$#_]));
180             };
181              
182             ## Arithmetic
183              
184             $add = sub {
185             my $result = 0;
186             foreach my $num (@_[1..$#_]) {
187             $result += &unwrapws($num);
188             }
189             $result;
190             };
191              
192             $multiply = sub {
193             my $result = 1;
194             foreach my $num (@_[1..$#_]) {
195             $result *= &unwrapws($num);
196             }
197             $result;
198             };
199              
200             $subtract = sub {
201             my $result = &unwrapws($_[1]);
202             if (@_ > 2) {
203             foreach my $num (@_[2..$#_]) {
204             $result -= &unwrapws($num);
205             }
206             } else {
207             $result = -$result;
208             }
209             $result;
210             };
211              
212             $divide = sub {
213             my $result = &unwrapws($_[1]);
214             if (@_ > 2) {
215             foreach my $num (@_[2..$#_]) {
216             $result /= &unwrapws($num);
217             }
218             } else {
219             $result = 1.0 / $result;
220             }
221             $result;
222             };
223              
224             ## Lisp-like primitives
225              
226             $funcall = sub {
227             my $sub = &unwrapws($_[1]);
228             &$sub($_[0], @_[2..$#_]);
229             };
230              
231             $apply = sub {
232             my $sub = &unwrapws($_[1]);
233             my @args = @_[2 .. ($#_ - 1)];
234             if (@_ > 2) {
235             my $last = $_[$#_];
236             my $last_unwrapped = &unwrapws($last);
237             if (ref($last_unwrapped) eq 'ARRAY') { # xxx UNIVERSAL::isa ?
238             push(@args, @$last_unwrapped);
239             } else {
240             push(@args, $last);
241             }
242             }
243             &$sub($_[0], @args);
244             };
245              
246             ## Strings
247              
248             $flatten = sub {
249             my $result = '';
250              
251             foreach my $obj (@_[1..$#_]) {
252             $result .= &flatten($obj);
253             }
254              
255             $result;
256             };
257              
258             $uc = sub {
259             uc(&unwrapws($_[1]));
260             };
261              
262             $lc = sub {
263             lc(&unwrapws($_[1]));
264             };
265              
266             $ucfirst = sub {
267             ucfirst(&unwrapws($_[1]));
268             };
269              
270             $lcfirst = sub {
271             lcfirst(&unwrapws($_[1]));
272             };
273              
274             $concat = sub {
275             my $result;
276             foreach my $str (@_[1..$#_]) {
277             $result .= &unwrapws($str);
278             }
279             $result;
280             };
281              
282             $substr = sub {
283             my $str = &unwrapws($_[1]);
284             my $start = &unwrapws($_[2]);
285             if ($#_ == 2) {
286             return substr($str, $start);
287             }
288             my $len = &unwrapws($_[3]);
289             if ($#_ == 3) {
290             return substr($str, $start, $len);
291             }
292             substr($str, $start, $len, &unwrapws($_[4]));
293             };
294              
295             $sprintf = sub {
296             my $fmt = &unwrapws($_[1]);
297             sprintf($fmt, map { &unwrapws($_) } @_[2 .. $#_]);
298             };
299              
300             $streq = sub {
301             my $first = &unwrapws($_[1]);
302             for (my $i = 2; $i <= $#_; ++$i) {
303             if ($first ne &unwrapws($_[$i])) {
304             return undef;
305             }
306             }
307             1;
308             };
309              
310             $strlt = sub {
311             my $n = &unwrapws($_[1]);
312             foreach my $m (@_[2..$#_]) {
313             $m = &unwrapws($m);
314             return undef unless $n lt $m;
315             $n = $m;
316             }
317             1;
318             };
319              
320             $strle = sub {
321             my $n = &unwrapws($_[1]);
322             foreach my $m (@_[2..$#_]) {
323             $m = &unwrapws($m);
324             return undef unless $n le $m;
325             $n = $m;
326             }
327             1;
328             };
329              
330             $strgt = sub {
331             my $n = &unwrapws($_[1]);
332             foreach my $m (@_[2..$#_]) {
333             $m = &unwrapws($m);
334             return undef unless $n gt $m;
335             $n = $m;
336             }
337             1;
338             };
339              
340             $strge = sub {
341             my $n = &unwrapws($_[1]);
342             foreach my $m (@_[2..$#_]) {
343             $m = &unwrapws($m);
344             return undef unless $n ge $m;
345             $n = $m;
346             }
347             1;
348             };
349              
350             ## Numbers
351              
352             $random = sub {
353             if ($#_ == 0) {
354             return rand(1);
355             }
356             rand(&unwrapws($_[1]));
357             };
358              
359             $int = sub {
360             int(&unwrapws($_[$#_]));
361             };
362              
363             $numeq = sub {
364             my $first = &unwrapws($_[1]);
365             for (my $i = 2; $i <= $#_; ++$i) {
366             if ($first != &unwrapws($_[$i])) {
367             return undef;
368             }
369             }
370             1;
371             };
372              
373             $max = sub {
374             my $result = &unwrapws($_[1]);
375             for (my $i = 2; $i <= $#_; ++$i) {
376             my $n = &unwrapws($_[$i]);
377             $result = $n if $n > $result;
378             }
379             $result;
380             };
381              
382             $min = sub {
383             my $result = &unwrapws($_[1]);
384             for (my $i = 2; $i <= $#_; ++$i) {
385             my $n = &unwrapws($_[$i]);
386             $result = $n if $n < $result;
387             }
388             $result;
389             };
390              
391             $numlt = sub {
392             my $n = &unwrapws($_[1]);
393             foreach my $m (@_[2..$#_]) {
394             $m = &unwrapws($m);
395             return undef unless $n < $m;
396             $n = $m;
397             }
398             1;
399             };
400              
401             $numle = sub {
402             my $n = &unwrapws($_[1]);
403             foreach my $m (@_[2..$#_]) {
404             $m = &unwrapws($m);
405             return undef unless $n <= $m;
406             $n = $m;
407             }
408             1;
409             };
410              
411             $numgt = sub {
412             my $n = &unwrapws($_[1]);
413             foreach my $m (@_[2..$#_]) {
414             $m = &unwrapws($m);
415             return undef unless $n > $m;
416             $n = $m;
417             }
418             1;
419             };
420              
421             $numge = sub {
422             my $n = &unwrapws($_[1]);
423             foreach my $m (@_[2..$#_]) {
424             $m = &unwrapws($m);
425             return undef unless $n >= $m;
426             $n = $m;
427             }
428             1;
429             };
430              
431             ## Perl modules
432              
433             $require = sub {
434             require &unwrapws($_[1]);
435             };
436              
437             $use = sub {
438             shift;
439             eval sprintf('use %s', &flatten(\@_, ''));
440             };
441              
442             ## Regular expressions
443              
444             $match = sub {
445             my $flags = $_[0]->{flags};
446             my $str = &unwrapws($_[1]);
447             my $regex = &unwrapws($_[2]);
448             my @result = eval("\$str =~ /\$regex/$flags");
449             \@result;
450             };
451              
452             $subst = sub {
453             my $flags = $_[0]->{flags};
454             my $str = &unwrapws($_[1]);
455             my $regex = &unwrapws($_[2]);
456             my $replacement = &unwrapws($_[3]);
457             eval("\$str =~ s/\$regex/\$replacement/$flags");
458             $str;
459             };
460              
461             $split = sub {
462             my $flags = $_[0]->{flags};
463             my $str = &unwrapws($_[1]);
464             my $regex = &unwrapws($_[2]);
465             if ($#_ == 2) {
466             my @result = eval("split(/\$regex/$flags, \$str)");
467             return \@result;
468             }
469             my $limit = &unwrapws($_[3]);
470             my @result = eval("split(/\$regex/$flags, \$str, \$limit)");
471             \@result;
472             };
473              
474             1;
475              
476             __END__