File Coverage

blib/lib/Language/l33t.pm
Criterion Covered Total %
statement 76 91 83.5
branch 11 28 39.2
condition 6 6 100.0
subroutine 22 25 88.0
pod 1 1 100.0
total 116 151 76.8


line stmt bran cond sub pod time code
1             package Language::l33t;
2             our $AUTHORITY = 'cpan:YANICK';
3             # ABSTRACT: a l33t interpreter
4             $Language::l33t::VERSION = '1.0.1';
5 3     3   56887 use 5.20.0;
  3         7  
6              
7 3     3   12 use strict;
  3         3  
  3         104  
8 3     3   12 use warnings;
  3         4  
  3         83  
9              
10 3     3   1622 use Moo;
  3         36778  
  3         14  
11 3     3   5292 use MooX::HandlesVia;
  3         24544  
  3         16  
12 3     3   1881 use MooseX::MungeHas 'is_rw';
  3         10357  
  3         28  
13              
14 3     3   1996 use Carp;
  3         4  
  3         162  
15              
16 3     3   2133 use Moose::Util::TypeConstraints;
  3         736683  
  3         34  
17              
18 3     3   6826 use IO::Socket::INET;
  3         57308  
  3         23  
19              
20 3     3   3091 use experimental 'signatures';
  3         8698  
  3         15  
21              
22             with 'Language::l33t::Operators';
23              
24 3     3   2381 use Types::Standard qw/ Int ArrayRef /;
  3         164635  
  3         30  
25 3     3   2264 use Type::Tiny;
  3         6  
  3         2298  
26              
27             my $l33tByteSize = Type::Tiny->new(
28             name => 'L33tByteSize',
29             parent => Int,
30             constraint => sub { $_ > 10 },
31             message => sub { "Byt3 s1z3 must be at l34st 11, n00b!" }
32             );
33              
34 12     12   1074 has debug => sub { 0 };
35              
36             has code => ();
37              
38             has source => (
39             predicate => 1,
40             clearer => 1,
41             trigger => sub($self,@) {
42             $self->_clear_memory;
43             $self->_memory;
44             },
45             );
46              
47             has byte_size => ( is => 'ro', isa => $l33tByteSize, default => 256 );
48              
49             has _memory => (
50             writer => '_set_memory',
51             predicate => '_has_memory',
52             clearer => '_clear_memory',
53             isa => ArrayRef[Int],
54             lazy => 1,
55             builder => 1,
56             handles_via => 'Array',
57             handles => {
58             memory => 'elements',
59             set_memory_cell => 'set',
60             memory_size => 'count',
61             memory_cell => 'get',
62             },
63             );
64              
65 23 50   23   2315 sub _build__memory($self) {
  23 50       49  
  23         26  
  23         20  
66 23         365 my @memory = ( map ( { my $s = 0;
  305         1519  
67 305         1448 $s += $& while /\d/g;
68 305         583 $s % $self->byte_size
69             } split ' ', $self->source ), 0 );
70              
71              
72 23 100       142 die "F00l! teh c0d3 1s b1g3R th4n teh m3m0ry!!1!\n"
73             if $self->memory_max_size < @memory;
74              
75 21         65 $self->mem_ptr( $#memory );
76 21         432 return [ @memory ];
77             }
78              
79             has memory_max_size => (
80             is => 'ro',
81             default => 64 * 1024,
82             );
83              
84             has mem_ptr => ();
85              
86             has op_ptr => (
87             isa => Int,
88             default => 0,
89             );
90              
91             after _clear_memory => sub($self) {
92             $self->op_ptr(0);
93             $self->mem_ptr(0);
94             };
95              
96 0 0   0 1 0 sub reset($self) {
  0 0       0  
  0         0  
  0         0  
97 0         0 $self->_clear_memory;
98 0         0 $self->memory;
99             }
100              
101              
102 0     0   0 has stdout => sub { return \*STDOUT; };
103             has stdin => ();
104             has socket => ();
105              
106             before run => sub($self,@) {
107             die "L0L!!1!1!! n0 l33t pr0gr4m l04d3d, sUxX0r!\n"
108             unless $self->_has_memory;
109             };
110              
111             sub run ( $self, $nbr_iterations = -1 ) {
112            
113             while ( $self->_iterate ) {
114             $nbr_iterations-- if $nbr_iterations != -1;
115             return 1 unless $nbr_iterations;
116             }
117              
118             return 0;
119             }
120              
121 477 50   477   1216 sub _iterate($self) {
  477 50       1071  
  477         638  
  477         550  
122 477         12705 my $op_id = $self->memory_cell( $self->op_ptr );
123            
124 477 50       55075 if ( $self->debug ) {
125 3     3   18 no warnings qw/ uninitialized /;
  3         5  
  3         746  
126 0         0 warn "memory: ", join( ':', $self->memory ), "\n";
127 0         0 warn "op_ptr: $self->op_ptr, ",
128             "mem_ptr: $self->mem_ptr, ",
129             "op: $op_id, ",
130             "mem: ", $self->_get_current_mem, "\n";
131             }
132              
133 477         4994 return $self->opcode( $op_id );
134             }
135              
136             sub _incr_op_ptr {
137 1088   100 1088   69191 $_[0]->op_ptr( $_[0]->op_ptr + ( $_[1] || 1 ) );
138             }
139              
140             sub _incr_mem_ptr {
141 104     104   9081 my ( $self, $increment ) = @_;
142 104   100     390 $increment ||= 1;
143 104         590 $self->mem_ptr( ( $self->mem_ptr + $increment ) % $self->byte_size );
144             }
145              
146             sub _incr_mem {
147 127     127   10769 my ( $self, $increment ) = @_;
148 3     3   15 no warnings qw/ uninitialized /;
  3         4  
  3         680  
149 127         3272 $self->set_memory_cell( $self->mem_ptr =>
150             ( $self->memory_cell( $self->mem_ptr ) + $increment ) %
151             $self->byte_size );
152             }
153              
154 0 0   0   0 sub _set_current_mem ($self, $value ) {
  0 0       0  
  0         0  
  0         0  
  0         0  
155 0         0 return $self->memory_set( $self->mem_ptr => $value );
156             }
157              
158              
159 111 50   111   292 sub _get_current_mem($self) {
  111 50       240  
  111         142  
  111         125  
160 111         3058 return $self->memory_cell( $self->mem_ptr );
161             }
162              
163 573 50   573   25447 sub _current_op($self) {
  573 50       1485  
  573         860  
  573         771  
164 573   100     15133 return $self->memory_cell( $self->op_ptr ) || 0;
165             }
166              
167             'End of Language::l33t';
168              
169             __END__
170              
171             =pod
172              
173             =encoding UTF-8
174              
175             =head1 NAME
176              
177             Language::l33t - a l33t interpreter
178              
179             =head1 VERSION
180              
181             version 1.0.1
182              
183             =head1 SYNOPSIS
184              
185             use Language::l33t;
186              
187             my $interpreter = Language::l33t->new;
188             $interpreter->set_source( 'Ph34r my l33t sk1llz' );
189             $interpreter->run;
190              
191             =head1 DESCRIPTION
192              
193             Language::l33t is a Perl interpreter of the l33t language created by
194             Stephen McGreal and Alex Mole. For the specifications of l33t, refer
195             to L<Language::l33t::Specifications>.
196              
197             =head1 METHODS
198              
199             =head2 new( %options )
200              
201             Creates a new interpreter. The options that can be passed to the function are:
202              
203             =over
204              
205             =item debug => $flag
206              
207             If $flag is set to true, the interpreter will print debugging information
208             as it does its thing.
209              
210             =item stdin => $io
211              
212             Ties the stdin of the interpreter to the given object.
213              
214             =item stdout => $io
215              
216             Ties the stdout of the interpreter to the given object.
217              
218             E.g.:
219              
220             my $output;
221             open my $fh_output, '>', \$output;
222              
223             my $l33t = Language::l33t->new( stdout => $fh_output );
224              
225             $l33t->set_source( $code );
226             $l33t->run;
227              
228             print "l33t output: $output";
229              
230             =item memory_max_size => $bytes
231              
232             The size of the block of memory available to interpreter. By default set to
233             64K (as the specs recomment).
234              
235             =item byte_size => $size
236              
237             The size of a byte in the memory used by the interpreter. Defaults to
238             256 (so a memory byte can hold a value going from 0 to 255).
239              
240             =back
241              
242             =head2 source( $l33tcode )
243              
244             Loads and "compiles" the string $l33tcode. If one program was already loaded,
245             it is clobbered by the newcomer.
246              
247             =head2 run( [ $nbr_iterations ] )
248              
249             Runs the loaded program. If $nbr_iterations is given, interupts the program
250             after this number of iterations even if it hasn't terminated. Returns 0 in
251             case the program terminated by evaluating an END, 1 if it finished by reaching
252             $nbr_iterations.
253              
254             =head2 reset
255              
256             Reset the interpreter to its initial setting. Code is
257             recompiled, and pointers reset to their initial values.
258              
259             E.g.
260              
261             my $l33t = Language::l33t->new();
262             $l33t->load( $code );
263             $l33t->run;
264              
265             # to run the same code a second time
266             $l33t->reset;
267             $l33t->run;
268              
269             =head2 memory
270              
271             Returns the memory of the interpreter in its current state as an array.
272              
273             =head1 DIAGNOSTICS
274              
275             =over
276              
277             =item F00l! teh c0d3 1s b1g3R th4n teh m3m0ry!!1!
278              
279             You tried to load a program that is too big to fit in
280             the memory. Note that at compile time, one byte is reserved
281             for the memory buffer, so the program's size must be less than
282             the memory size minus one byte.
283              
284             =item Byt3 s1z3 must be at l34st 11, n00b!
285              
286             The I<byte_size> argument of I<new()> was less than 11.
287             The byte size of an interpreter must be at least 11 (to
288             accomodate for the opcodes).
289              
290             =item L0L!!1!1!! n0 l33t pr0gr4m l04d3d, sUxX0r!
291              
292             run() called before any program was load()ed.
293              
294             =back
295              
296             =head1 SEE ALSO
297              
298             L<Language::l33t::Specifications>
299              
300             =head1 THANKS
301              
302             It goes without saying, special thanks go
303             to Stephen McGreal and Alex Mole for inventing l33t.
304             They are teh rOxX0rs.
305              
306             =head1 AUTHOR
307              
308             Yanick Champoux <yanick@cpan.org>
309              
310             =head1 COPYRIGHT AND LICENSE
311              
312             This software is copyright (c) 2006 by Yanick Champoux.
313              
314             This is free software; you can redistribute it and/or modify it under
315             the same terms as the Perl 5 programming language system itself.
316              
317             =cut