File Coverage

blib/lib/Acme/Ook.pm
Criterion Covered Total %
statement 45 53 84.9
branch 7 14 50.0
condition 6 11 54.5
subroutine 10 12 83.3
pod 4 4 100.0
total 72 94 76.6


line stmt bran cond sub pod time code
1             package Acme::Ook;
2              
3 2     2   7172 use strict;
  2         4  
  2         95  
4 2     2   13 use vars qw($VERSION);
  2         3  
  2         251  
5             $VERSION = '0.11';
6              
7             my %Ook = (
8             '.' => {'?' => '$Ook++;',
9             '.' => '$Ook[$Ook]++;',
10             '!' => '$Ook[$Ook]=read(STDIN,$Ook[$Ook],1)?ord$Ook[$Ook]:0;'},
11             '?' => {'.' => '$Ook--;',
12             '!' => '}'},
13             '!' => {'!' => '$Ook[$Ook]--;',
14             '.' => 'print chr$Ook[$Ook];',
15             '?' => 'while($Ook[$Ook]){',
16             }
17             );
18              
19             BEGIN {
20 2     2   10 no strict 'refs';
  2         7  
  2         198  
21 2 0   2   8 *{'O?'} = sub { @_ ? $Ook{$_[0]} : %Ook };
  2     0   11  
  0         0  
22 2     0   6 *{'O!'} = sub { $Ook{$_[0]} = $_[1] };
  2         1478  
  0         0  
23             }
24              
25             sub optimise {
26             # Coalesce sequences of increments or decrements
27 2     2 1 5 my $prog = $_[1];
28             # print "Before '$prog'\n";
29 2         8 foreach my $thing ('$Ook', '$Ook[$Ook]') {
30 4         8 foreach my $op ('+', '-') {
31 8         22 my $left = length "$thing$op$op;";
32 8         214 $prog =~ s{((?:\Q$thing$op$op\E;){2,})}
  50         469  
33             {"$thing$op=".(length ($1)/$left).';'}ges;
34             }
35             }
36             # print "After '$prog'\n";
37 2         423 return $prog;
38             }
39              
40             sub _compile {
41 54     54   54 shift;
42 54         71 chomp $_[0];
43 54 50 100     205 $_[0] =~ s/\s*(Ook(.)\s*Ook(.)\s*|(\#.*)|\S.*)/$;=$Ook{$2||@@}{$3||''};$;?$;:defined$4?"$4\n":die"OOK? $_[1]:$_[2] '$1'\n"/eg;
  343 100 66     1465  
  343         1755  
44 54         289 return $_[0];
45             }
46              
47             sub compile {
48 2     2 1 4 my $self = shift;
49 2         6 my $prog;
50 2 50 33     21 $prog .= $self->_compile($$self, "(new)", 0) if defined $$self && length $$self;
51 2 50       8 if (@_) {
52 2         11 local *OOK;
53 2         9 while (@_) {
54 2         3 my $code = shift;
55 2 50       8 if (ref $code eq 'IO::Handle') {
56 0         0 while (<$code>) {
57 0         0 $prog .= $self->_compile($_, $code, $.);
58             }
59 0         0 close(OOK);
60             } else {
61 2 50       127 if (open(OOK, $code)) {
62 2         59 while () {
63 54         133 $prog .= $self->_compile($_, $code, $.);
64             }
65 2         36 close(OOK);
66             } else {
67 0         0 die "OOK! $code: $!\n";
68             }
69             }
70             }
71             } else {
72 0         0 while () {
73 0         0 $prog .= $self->_compile($_, "(stdin)", $.);
74             }
75             }
76 2         19 return '{my($Ook,@Ook);local$^W = 0;BEGIN{eval{require bytes;bytes::import()}}' . $prog . '}';
77             }
78              
79             sub Ook {
80 2     2 1 5 eval $_[0]->optimise(&compile);
  2     2   17  
  2         11  
  2         25  
81             }
82              
83             sub new {
84 2     2 1 196 my $class = shift;
85 2   33     25 bless \$_[0], ref $class || $class;
86             }
87              
88             1;
89             __END__