File Coverage

blib/lib/Java/JVM/Classfile/Perl.pm
Criterion Covered Total %
statement 9 144 6.2
branch 0 80 0.0
condition 0 9 0.0
subroutine 3 7 42.8
pod 0 4 0.0
total 12 244 4.9


line stmt bran cond sub pod time code
1             package Java::JVM::Classfile::Perl;
2              
3 1     1   3046 use strict;
  1         2  
  1         41  
4 1     1   6 use vars qw($VERSION @ISA);
  1         2  
  1         50  
5 1     1   689 use Java::JVM::Classfile;
  1         4  
  1         2632  
6              
7             $VERSION = '0.16';
8              
9             sub new {
10 0     0 0   my $class = shift;
11 0           my $filename = shift;
12 0           my $self = {};
13              
14 0           my $c = Java::JVM::Classfile->new($filename);
15 0           $self->{_class} = $c;
16 0           bless $self, $class;
17 0           return $self;
18             }
19              
20             sub as_perl {
21 0     0 0   my $self = shift;
22 0           my $c = $self->{_class};
23 0           my $code;
24 0           my @cpool = @{$c->constant_pool};
  0            
25              
26 0           $code .= q|
27             package java::io::PrintStream;
28             sub new {
29             my $class = shift;
30             my $self = {};
31             return bless $self, $class;
32             }
33             sub print {
34             my $self = shift;
35             print shift();
36             }
37             sub println {
38             my $self = shift;
39             my $arg = shift;
40             print $arg if defined $arg;
41             print "\n";
42             }
43              
44             package java::lang::Integer;
45             sub parseInt {
46             my($class, $s) = @_;
47             return $s + 0;
48             }
49              
50             package java::lang::System;
51             sub out {
52             return java::io::PrintStream->new();
53             }
54              
55             package java::lang::String;
56             sub new {
57             my $class = shift;
58             my $self = {};
59             $self->{value} = "";
60             return bless $self, $class;
61             }
62              
63             sub valueOf {
64             my $class = shift;
65             return $_[0];
66             }
67              
68             package java::lang::StringBuffer;
69             sub new {
70             my $class = shift;
71             my $self = {};
72             $self->{value} = "";
73             return bless $self, $class;
74             }
75             sub append {
76             my $self = shift;
77             my $text = shift;
78             $self->{value} .= $text;
79             return $self;
80             }
81             sub toString {
82             my $self = shift;
83             return $self->{value};
84             }
85             |;
86              
87 0           $code .= "\npackage " . $c->class . ";\n";
88              
89 0           $code .= "no warnings 'recursion';\n";
90              
91 0 0         die "Subclasses not supported!" if $c->superclass ne "java/lang/Object";
92              
93 0           foreach my $method (@{$c->methods}) {
  0            
94 0 0         next if $method->name eq '';
95 0           $code .= "\nsub " . $method->name . " {\n";
96              
97 0           $code .= "my \@stack;\n";
98 0           $code .= "my \$class = shift();\n";
99 0           $code .= "my \@locals = \@_;\n";
100 0           $code .= "my(\$o, \$p, \$return, \@in);\n";
101 0           $code .= "my \@params;\n";
102             # $code .= qq|print "locals ";\n|;
103             # $code .= qq|print join("# ", \@\$locals[0]) . "\\n";\n|;
104 0           foreach my $att (@{$method->attributes}) {
  0            
105 0           my $name = $att->name;
106 0           my $value = $att->value;
107 0 0         next unless $name eq 'Code';
108 0           foreach my $instruction (@{$value->code}) {
  0            
109 0           my $label = $instruction->label;
110 0           my $op = $instruction->op;
111 0           my @args = @{$instruction->args};
  0            
112 0 0         $code .= "$label:\n" if defined $label;
113 0           my $javacode = "\t$op\t" . (join ", ", @{$instruction->args});
  0            
114 0           $code .= "# $javacode\n";
115             # $code .= qq|print "\@stack / code = $javacode\\n";\n|;
116 0 0 0       if ($op eq 'getstatic') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
117 0           my $class = $args[0];
118 0           $class =~ s|/|::|g;
119 0           my $field = $args[1];
120 0           $code .= "push \@stack, $class->$field;\n";
121             } elsif ($op eq 'new') {
122 0           my $class = $args[0];
123 0           $class =~ s|/|::|g;
124 0           $code .= "push \@stack, $class->new();\n";
125             } elsif ($op eq 'invokevirtual') {
126 0           my $class = $args[0];
127 0           $class =~ s|/|::|g;
128 0           my $method = $args[1];
129 0           my $signature = $args[2];
130 0           $code .= $self->invokevirtual_code($class, $method, $signature);
131             } elsif ($op eq 'invokestatic') {
132 0           my $class = $args[0];
133 0           $class =~ s|/|::|g;
134 0           my $method = $args[1];
135 0           my $signature = $args[2];
136 0           my($in, $out) = $signature =~ /^\((.*?)\)(.*?)$/;
137 0           $code .= $self->invokestatic_code($class, $method, $signature);
138             } elsif ($op eq 'invokespecial') {
139 0           $code .= "pop \@stack;\n";
140             } elsif ($op eq 'ldc') {
141 0           my $arg = $args[0];
142 0           $code .= "push \@stack, '$arg';\n";
143             } elsif ($op eq 'ldc2_w') {
144 0           my $arg = $args[0] << 8 | $args[1]; # See JVM specs
145 0           $code .= "push \@stack, ".$cpool[$arg]->values->[0].";\n";
146 0           $code .= "push \@stack, 'FAKE VALUE FOR LONG';\n";
147             } elsif ($op eq 'bipush' or $op eq 'sipush') {
148 0           my $arg = $args[0];
149 0           $code .= "push \@stack, $arg;\n";
150             } elsif ($op eq 'return') {
151 0           $code .= "return;\n";
152             } elsif ($op =~ /^[fldai]return$/) {
153 0           $code .= "return pop(\@stack);\n";
154             } elsif ($op =~ /^[li]const_(\d)/) {
155 0           $code .= "push \@stack, $1;\n";
156             } elsif ($op =~ /^[fai]store_(\d)/) {
157 0           $code .= "\$locals[$1] = pop \@stack;\n";
158             } elsif ($op =~ /^[ld]store_(\d)/) {
159 0           $code .= "pop \@stack;\n";
160 0           $code .= "\$locals[$1] = pop \@stack;\n";
161             } elsif ($op =~ /^[fai]store/) {
162 0           my $i = $args[0];
163 0           $code .= "\$locals[$i] = pop \@stack;\n";
164             } elsif ($op =~ /^[ld]store/) {
165 0           my $i = $args[0];
166 0           $code .= "\$locals[$i] = pop \@stack;\n";
167 0           $code .= "pop \@stack;\n";
168             } elsif ($op =~ /[fai]load_(\d)/) {
169 0           $code .= "push \@stack, \$locals[$1];\n";
170             } elsif ($op =~ /[ld]load_(\d)/) {
171 0           $code .= "push \@stack, \$locals[$1];\n";
172 0           $code .= "push \@stack, 'FAKE VALUE FOR LONGS';\n";
173             } elsif ($op =~ /^[fai]load$/) {
174 0           my $i = $args[0];
175 0           $code .= "push \@stack, \$locals[$i];\n";
176             } elsif ($op =~ /^[ld]load$/) {
177 0           my $i = $args[0];
178 0           $code .= "push \@stack, \$locals[$i];\n";
179 0           $code .= "push \@stack, 'FAKE VALUE FOR LONGS';\n";
180             } elsif ($op eq 'goto') {
181 0           my $label = $args[0];
182 0           $code .= "goto $label;\n";
183             } elsif ($op eq 'dup') {
184 0           $code .= "push \@stack, \$stack[-1];\n";
185             } elsif ($op =~ /^[fi]add$/) {
186 0           $code .= "push \@stack, (pop \@stack) + (pop \@stack);\n";
187             } elsif ($op =~ /^[ld]add$/) {
188 0           $code .= qq|pop \@stack;
189             \$o = pop \@stack;
190             pop \@stack;
191             \$o += pop \@stack;
192             push \@stack, \$o;\n|;
193             } elsif ($op =~ /^[fldi]sub/) {
194 0           $code .= "push \@stack, - (pop \@stack) + (pop \@stack);\n";
195             } elsif ($op =~ /^[fldi]mul/) {
196 0           $code .= "push \@stack, (pop \@stack) * (pop \@stack);\n";
197             } elsif ($op eq 'aaload') {
198 0           $code .= qq|\$o = pop \@stack;
199             my \$array = pop \@stack;
200             push \@stack, \$array->[\$o];\n|;
201             } elsif ($op eq 'iinc') {
202 0           my $i = $args[0];
203 0           my $n = $args[1];
204 0           $code .= "\$locals[$i] += $n;\n";
205             } elsif ($op eq 'if_icmplt') {
206 0           my $label = $args[0];
207 0           $code .= "goto $label if (pop \@stack) > (pop \@stack);\n";
208             } elsif ($op eq 'if_icmpge') {
209 0           my $label = $args[0];
210 0           $code .= "goto $label if (pop \@stack) <= (pop \@stack);\n";
211             } elsif ($op eq 'ifne') {
212 0           my $label = $args[0];
213 0           $code .= "goto $label if (pop \@stack);\n";
214             } else {
215 0           $code .= "# ?\n";
216             }
217             }
218             }
219 0           $code .= "}\n\n";
220             }
221             # $code .= qq|print join(", ", \@ARGV) . "\\n";\n|;
222 0           $code .= $c->class . "->main([\@ARGV]);\n";
223 0           return $code;
224             }
225              
226             # Invoking static methods
227             sub invokestatic_code {
228 0     0 0   my $self = shift;
229 0           my ($class, $method, $signature) = @_;
230              
231 0           my ($code, $incount, $doubles);
232 0           my($in, $out) = $signature =~ /^\((.*?)\)(.*?)$/;
233              
234 0           $in =~ s/L[^;]*;/L/g;
235 0           $incount = () = $in =~ /[FIL]/g;
236 0           $doubles = () = $in =~ /[JD]/g;
237 0           $incount += 2*$doubles;
238 0 0 0       $out = "" if defined($out) && $out eq 'V';
239 0 0         if ($in) {
240 0           $code .= qq|\@params = splice(\@stack,-$incount);
241             \$return = $class->$method(\@params); # $in / $out\n|;
242             } else {
243 0           $code .= "\$return = $class->$method(); # $in / $out\n";
244             }
245 0 0         $code .= "push \@stack, \$return;\n" if $out;
246            
247 0           return $code;
248             }
249              
250             # Invoking virtual methods
251             sub invokevirtual_code {
252 0     0 0   my $self = shift;
253 0           my ($class, $method, $signature) = @_;
254              
255 0           my ($code, $incount, $doubles);
256 0           my($in, $out) = $signature =~ /^\((.*?)\)(.*?)$/;
257 0           $in =~ s/L[^;]*;/L/g;
258 0           $incount = () = $in =~ /[FIL]/g;
259 0           $doubles = () = $in =~ /[JD]/g;
260 0           $incount += 2*$doubles;
261 0 0 0       $out = "" if defined($out) && $out eq 'V';
262              
263 0 0         if ($in) {
264 0           $code .= qq|\@params = splice(\@stack,-$incount);
265             \$p = pop \@stack;
266             \$return = \$p->$method(\@params); # $in / $out\n|;
267             } else {
268 0           $code .= "\$return = (pop \@stack)->$method(); # $in / $out\n";
269             }
270 0 0         $code .= "push \@stack, \$return;\n" if $out;
271              
272 0           return $code;
273             }
274              
275             1;