File Coverage

blib/lib/R/Writer.pm
Criterion Covered Total %
statement 38 39 97.4
branch 2 2 100.0
condition n/a
subroutine 12 13 92.3
pod n/a
total 52 54 96.3


line stmt bran cond sub pod time code
1             # $Id: /mirror/coderepos/lang/perl/R-Writer/trunk/lib/R/Writer.pm 43085 2008-03-01T12:28:42.888222Z daisuke $
2              
3             package R::Writer;
4 6     6   140297 use strict;
  6         15  
  6         230  
5 6     6   32 use warnings;
  6         14  
  6         176  
6 6     6   161 use 5.008;
  6         18  
  6         258  
7 6     6   29 use base qw(Class::Accessor::Fast);
  6         26  
  6         17920  
8 6     6   32373 use R::Writer::Call;
  6         16  
  6         67  
9 6     6   3869 use R::Writer::Encoder;
  6         21  
  6         196  
10 6     6   3636 use R::Writer::Range;
  6         15  
  6         47  
11 6     6   4632 use R::Writer::Var;
  6         17  
  6         44  
12              
13             __PACKAGE__->mk_accessors($_) for qw(encoder statements);
14              
15             our $VERSION = '0.00001';
16 6         101 use Sub::Exporter -setup => {
17             exports => [ 'R' ]
18 6     6   7278 };
  6         93288  
19              
20 0     0   0 sub R { return __PACKAGE__->new(@_) }
21              
22             sub new
23             {
24 5     5   105 my $class = shift;
25 5         55 my $self = $class->SUPER::new({
26             encoder => R::Writer::Encoder->new,
27             @_,
28             statements => [],
29             delimiter => undef,
30             });
31 5         74 return $self;
32             }
33              
34 2     2   6 sub __push_statement { push @{ $_[0]->statements }, $_[1]; }
  2         476  
35              
36             # Call is a statement to call functions
37             sub call
38             {
39 3     3   19 my ($self, $function, @args) = @_;
40              
41             # If this is the end of the call chain, then push the
42             # statement. Otherwise, return it
43 3         10 my $end_of_call_chain = ! defined wantarray;
44 3         31 my $call = R::Writer::Call->new(
45             call => $function,
46             args => [@args],
47             end_of_call_chain => $end_of_call_chain,
48             );
49              
50 3 100       43 if ($end_of_call_chain) {
51 2         10 $self->__push_statement( $call );
52             }
53 1         5 return $call;
54             }
55              
56             BEGIN
57             {
58             foreach my $method qw(c expression) {
59             eval sprintf(<<' EOSUB', $method, $method);
60             sub %s {
61             my $self = shift;
62             return R::Writer::Call->new(
63             call => '%s',
64             args => [ @_ ],
65             );
66             }
67             EOSUB
68             die if $@;
69             }
70             }
71              
72             sub var
73             {
74             my ($self, $var, $value) = @_;
75              
76             my $obj = R::Writer::Var->new($var, $value, $self);
77             $self->__push_statement($obj);
78             return $obj;
79             }
80              
81             sub range
82             {
83             my ($self, $start, $end) = @_;
84             my $obj = R::Writer::Range->new($start, $end);
85             $obj;
86             }
87              
88             # Turn myself into a string
89             sub as_string
90             {
91             my $self = shift;
92             my $ret = "";
93              
94             for my $s (@{$self->{statements}}) {
95             my $delimiter = defined $s->{delimiter} ? $s->{delimiter} : ";";
96             if (my $c = $s->{code}) {
97             $ret .= $c;
98             }
99             else {
100             $ret .= $s->as_string($self);
101             }
102             $ret .= $delimiter unless $ret =~ /$delimiter\s*$/s;
103             $ret .= "\n";
104             }
105             return $ret;
106             }
107              
108             # Turn arbitrary objects to string
109             sub __obj_as_string
110             {
111             my ($self, $obj) = @_;
112              
113             my $ref = ref($obj);
114              
115             if ($ref eq 'CODE') {
116             return $self->__obj_as_string($obj->());
117             }
118             elsif ($ref =~ /^R::Writer/) {
119             return $obj->as_string($self);
120             }
121             elsif ($ref eq "SCALAR") {
122             return $$obj
123             }
124             elsif ($ref eq 'ARRAY') {
125             my @ret = map {
126             $self->__obj_as_string($_)
127             } @$obj;
128              
129             return "[" . join(",", @ret) . "]";
130             }
131             elsif ($ref eq 'HASH') {
132             my %ret;
133             while (my ($k, $v) = each %$obj) {
134             $ret{$k} = $self->__obj_as_string($v)
135             }
136             return "{" . join (",", map { $self->encoder->encode($_) . ":" . $ret{$_} } keys %ret) . "}";
137             }
138             else {
139             return $self->encoder->encode($obj)
140             }
141             }
142              
143             sub save
144             {
145             my ($self, $file) = @_;
146              
147             my $fh;
148             my $close = 1;
149             my $ref = ref $file;
150              
151             if ($ref && ( $ref eq 'GLOB' || eval { $file->can('print') } )) {
152             $close = 0;
153             $fh = $file;
154             } else {
155             open($fh, '>', $file) or die "Failed to open $file for writing: $!";
156             }
157             print $fh $self->as_string;
158             close($fh) if $close;
159             }
160              
161             sub reset { shift->statements([]) }
162              
163             1;
164              
165             __END__