File Coverage

blib/lib/Inline/SMITH.pm
Criterion Covered Total %
statement 14 149 9.4
branch 2 82 2.4
condition 0 6 0.0
subroutine 4 11 36.3
pod 1 8 12.5
total 21 256 8.2


line stmt bran cond sub pod time code
1             package Inline::SMITH;
2              
3             $VERSION = '0.03';
4             require Inline;
5             @ISA = qw(Inline);
6 1     1   10169 use strict;
  1         2  
  1         29  
7 1     1   5 use Carp;
  1         1  
  1         2306  
8              
9             sub register {
10             return {
11 0     0 0 0 language => 'SMITH',
12             aliases => ['Smith', 'smith'],
13             type => 'interpreted',
14             suffix => 'smt',
15             };
16             }
17              
18             sub usage_config {
19 0     0 0 0 my $key = shift;
20 0         0 "'$key' is not a valid config option for Inline::SMITH\n";
21             }
22              
23 1     1 0 32 sub validate {
24             }
25              
26             sub build {
27 0     0 0 0 my $o = shift;
28 0         0 my $code = $o->{API}{code};
29 0         0 my $pattern = $o->{ILSM}{PATTERN};
30 0         0 $code = smith_load($code);
31             {
32 0         0 package Inline::SMITH::Loader;
33 0         0 eval $code;
34             }
35 0 0       0 croak "Brainfuck build failed:\n$@" if $@;
36 0         0 my $path = "$o->{API}{install_lib}/auto/$o->{API}{modpname}";
37 0         0 my $obj = $o->{API}{location};
38 0 0       0 $o->mkpath($path) unless -d $path;
39 0 0       0 open FOO_OBJ, "> $obj" or croak "Can't open $obj for output\n$!";
40 0         0 print FOO_OBJ $code;
41 0         0 close \*FOO_OBJ;
42             }
43              
44             sub load {
45 1     1 0 4 my $o = shift;
46 1         8 my $obj = $o->{API}{location};
47 1 50       65 open FOO_OBJ, "< $obj" or croak "Can't open $obj for output\n$!";
48 1         28 my $code = join '', ;
49 1         14 close \*FOO_OBJ;
50 1     0   71 eval "package $o->{API}{pkg};\n$code";
  0            
51 1 50       8 croak "Unable to load Foo module $obj:\n$@" if $@;
52             }
53              
54             sub info {
55 0     0 1   my $o = shift;
56             }
57              
58              
59             sub smith_load {
60 0     0 0   my ($code) = @_;
61 0           my $out = "";
62              
63 0           while($code =~ m/function(\s+)([a-z0-9_]+)(\s*){{(.*?)}}/isg){
64 0           my $func_name = $2;
65 0           my $func_code = $4;
66             # print "loaded function $func_name\n";
67 0           $func_code =~ s/\|/\\|/g;
68 0           $out .= "sub $func_name { return Inline::SMITH::smith_run(q|$func_code|, \$_[0]); }\n";
69             }
70              
71 0           return $out;
72             }
73              
74             sub smith_run {
75 0     0 0   my ($code, $data) = @_;
76              
77 0           my $buffer = "";
78 0           my @data;
79             my $input_callback;
80 0           my $output_callback;
81 0           my $echo = 1;
82              
83 0 0         if (ref $data eq 'HASH'){
84 0 0         @data = split(//, ${$data}{input}) if ${$data}{input};
  0            
  0            
85 0   0       $input_callback = ${$data}{input_callback} || 0;
86 0   0       $output_callback = ${$data}{output_callback} || 0;
87 0   0       $echo = ${$data}{echo} || 0;
88             }else{
89 0           @data = split(//, $data);
90             }
91              
92 0           my $mem = [];
93 0           my $reg = [];
94 0           my $debug = 0;
95 0           my $cont = 0;
96 0           my $quiet = 0;
97 0           my $pause = 0;
98 0           my ($ggg, $hhh);
99              
100             #
101             # load the code into $mem
102             #
103              
104 0           my @lines = split(/\r?\n/, $code);
105 0           my $line = '';
106 0           my $i = 0;
107 0           for $line(@lines){
108 0 0         $line = $' if $line =~ /^\s*/;
109 0 0         $line = $` if $line =~ /\s*$/;
110 0           $line =~ s/\s*;.*?$//;
111 0           $line =~ s/\*/$i/ge;
  0            
112 0 0         if ($line =~ /^\S+/){
113 0           my $reps = 1;
114 0           my $j;
115 0 0         if ($line =~ /^REP\s*(\d+)\s*/){
116 0           $line = $';
117 0           $reps = $1;
118             }
119 0           for($j = 0; $j < $reps; $j++){
120 0           $mem->[$i] = $line;
121             # print "Load $i = $mem->[$i]\n" if $showload;
122 0           $i++;
123             }
124             }
125             }
126              
127             #
128             # run the code
129             #
130              
131 0           my $pc = 0;
132 0           while($mem->[$pc] ne 'STOP') {
133              
134 0 0         if ($mem->[$pc] =~ /^MOV\s*R(\d+)\s*,\s*\#?(\d+)$/) { # MOV reg, imm
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
135 0           $reg->[$1] = $2;
136             } elsif ($mem->[$pc] =~ /^MOV\s*R(\d+)\s*,\s*R(\d+)$/) { # MOV reg, reg
137 0           $reg->[$1] = $reg->[$2];
138             } elsif ($mem->[$pc] =~ /^MOV\s*R\[R(\d+)\]\s*,\s*R(\d+)$/) { # MOV [reg], reg
139 0           $reg->[$reg->[$1]] = $reg->[$2];
140             } elsif ($mem->[$pc] =~ /^MOV\s*R(\d+)\s*,\s*R\[R(\d+)\]$/) { # MOV reg, [reg]
141 0           $reg->[$1] = $reg->[$reg->[$2]];
142             } elsif ($mem->[$pc] =~ /^MOV\s*R\[R(\d+)\]\s*,\s*\"(.*?)\"$/) { # MOV [reg], "string"
143 0           my $i = $reg->[$1];
144 0           my $s = $2;
145 0           while($i < ($reg->[$1] + length($s))) {
146 0           $reg->[$i] = ord(substr($s, ($i-$reg->[$1]), 1));
147 0           $i++;
148             }
149             } elsif ($mem->[$pc] =~ /^MOV\s*R(\d+)\s*,\s*PC$/) { # MOV reg, PC
150 0           $reg->[$1] = $pc;
151             } elsif ($mem->[$pc] =~ /^MOV\s*TTY\s*,\s*R(\d+)$/) { # MOV TTY, reg
152 0 0         print chr($reg->[$1]) if $echo;
153 0           $buffer .= chr($reg->[$1]);
154 0 0         &{$output_callback}(chr($reg->[$1])) if $output_callback;
  0            
155             } elsif ($mem->[$pc] =~ /^MOV\s*TTY\s*,\s*R\[R(\d+)\]$/) { # MOV TTY, [reg]
156 0 0         print chr($reg->[$reg->[$1]]) if $echo;
157 0           $buffer .= chr($reg->[$reg->[$1]]);
158 0 0         &{$output_callback}(chr($reg->[$reg->[$1]])) if $output_callback;
  0            
159             } elsif ($mem->[$pc] =~ /^MOV\s*R(\d+)\s*,\s*TTY$/) { # MOV reg, TTY
160 0 0         $reg->[$1] = ($input_callback)?&{$input_callback}:shift @data;
  0            
161 0 0         if ($reg->[$1]) {
162 0           $reg->[$1] = ord($reg->[$1]);
163             } else {
164 0           $reg->[$1] = 0;
165             }
166             } elsif ($mem->[$pc] =~ /^MOV\s*R\[R(\d+)\]\s*,\s*TTY$/) { # MOV [reg], TTY
167 0 0         $reg->[$reg->[$1]] = ($input_callback)?&{$input_callback}:shift @data;
  0            
168 0 0         if ($reg->[$reg->[$1]]) {
169 0           $reg->[$reg->[$1]] = ord($reg->[$reg->[$1]]);
170             } else {
171 0           $reg->[$reg->[$1]] = 0;
172             }
173             } elsif ($mem->[$pc] =~ /^SUB\s*R(\d+)\s*,\s*\#?(\d+)$/) { # SUB reg, imm
174 0           $reg->[$1] -= $2;
175             } elsif ($mem->[$pc] =~ /^SUB\s*R(\d+)\s*,\s*R(\d+)$/) { # SUB reg, reg
176 0           $reg->[$1] -= $reg->[$2];
177             } elsif ($mem->[$pc] =~ /^MUL\s*R(\d+)\s*,\s*\#?(\d+)$/) { # MUL reg, imm
178 0           $reg->[$1] *= $2;
179             } elsif ($mem->[$pc] =~ /^MUL\s*R(\d+)\s*,\s*R(\d+)$/) { # MUL reg, reg
180 0           $reg->[$1] *= $reg->[$2];
181             } elsif ($mem->[$pc] =~ /^NOT\s*R(\d+)$/) { # NOT reg
182 0 0         if($reg->[$1] != 0) {
183 0           $reg->[$1] = 0;
184             } else {
185 0           $reg->[$1] = 1;
186             }
187             } elsif ($mem->[$pc] =~ /^COR\s*([-+]\d+)\s*,\s*([-+]\d+)\s*,\s*R(\d+)\s*$/) { # COR imm, imm, reg
188 0           my $dst = 0+$pc+$1;
189 0           my $src = 0+$pc+$2;
190 0           my $lrg = 0+$3;
191 0           my $i;
192             {
193 0           for ($i = 0; $i < $reg->[$lrg]; $i++) {
  0            
194 0           $mem->[$dst+$i] = $mem->[$src+$i];
195 0           $ggg = $dst + $i;
196 0           $hhh = $src + $i;
197             }
198             }
199             } elsif ($mem->[$pc] =~ /^COR\s*([-+]\d+)\s*,\s*R(\d+)\s*,\s*R(\d+)\s*$/) { # COR imm, reg, reg
200 0           my $dst = 0+$pc+$1;
201 0           my $src = 0+$pc+$reg->[$2];
202 0           my $lrg = 0+$3;
203 0           my $i;
204             {
205 0           for ($i = 0; $i < $reg->[$lrg]; $i++) {
  0            
206 0           $mem->[$dst+$i] = $mem->[$src+$i];
207 0           $ggg = $dst + $i;
208 0           $hhh = $src + $i;
209             }
210             }
211             } elsif ($mem->[$pc] =~ /^BLA\s*([-+]\d+)\s*,\s*(\w+)\s*,\s*R(\d+)\s*$/) { # BLA imm, OPC, reg
212 0           my $dst = 0+$pc+$1;
213 0           my $src = $2;
214 0           my $lrg = 0+$3;
215 0           my $i;
216             {
217 0           for ($i = 0; $i < $reg->[$lrg]; $i++) {
  0            
218 0           $mem->[$dst+$i] = $src;
219 0           $ggg = $dst + $i;
220             }
221             }
222             } elsif ($mem->[$pc] =~ /^NOP$/) { # NOP
223             # Nothing happens here.
224             } else {
225 0           print "Invalid instruction $mem->[$pc]!\n";
226 0 0         $pc = $#{$mem} + 1 if not $cont;
  0            
227             }
228 0           $pc++;
229 0 0         $mem->[$pc] = 'STOP' if $pc > $#{$mem};
  0            
230             }
231              
232             #
233             # we're done
234             #
235              
236 0           return $buffer;
237             }
238              
239             1;
240              
241             __END__