File Coverage

blib/lib/Language/l33t.pm
Criterion Covered Total %
statement 8 10 80.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 12 14 85.7


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