File Coverage

blib/lib/Language/l33t.pm
Criterion Covered Total %
statement 72 85 84.7
branch 3 4 75.0
condition 6 6 100.0
subroutine 22 25 88.0
pod 1 1 100.0
total 104 121 85.9


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.1.0';
5 3     3   514934 use 5.20.0;
  3         14  
6              
7 3     3   38 use strict;
  3         9  
  3         92  
8 3     3   16 use warnings;
  3         5  
  3         187  
9              
10 3     3   2183 use Moo;
  3         29167  
  3         17  
11 3     3   7189 use MooX::HandlesVia;
  3         46519  
  3         23  
12 3     3   2447 use MooseX::MungeHas 'is_rw';
  3         22358  
  3         25  
13              
14 3     3   3474 use Carp;
  3         6  
  3         259  
15              
16 3     3   2366 use Moose::Util::TypeConstraints;
  3         1094322  
  3         12219  
17              
18 3     3   9637 use IO::Socket::INET;
  3         117314  
  3         30  
19              
20 3     3   4191 use experimental 'signatures';
  3         12452  
  3         55  
21              
22             with 'Language::l33t::Operators';
23              
24 3     3   3360 use Types::Standard qw/ Int ArrayRef /;
  3         483961  
  3         43  
25 3     3   12859 use Type::Tiny;
  3         12  
  3         3555  
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   109 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     23   175 sub _build__memory($self) {
  23         27  
  23         26  
66 23         320 my @memory = ( map ( { my $s = 0;
  305         550  
67 305         1286 $s += $& while /\d/g;
68 305         654 $s % $self->byte_size
69             } split ' ', $self->source ), 0 );
70              
71              
72 23 100       175 die "F00l! teh c0d3 1s b1g3R th4n teh m3m0ry!!1!\n"
73             if $self->memory_max_size < @memory;
74              
75 21         81 $self->mem_ptr( $#memory );
76 21         402 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 1 0 sub reset($self) {
  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     477   804 sub _iterate($self) {
  477         804  
  477         801  
122 477         11493 my $op_id = $self->memory_cell( $self->op_ptr );
123            
124 477 50       50865 if ( $self->debug ) {
125 3     3   122 no warnings qw/ uninitialized /;
  3         11  
  3         1336  
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         4681 return $self->opcode( $op_id );
134             }
135              
136             sub _incr_op_ptr {
137 1088   100 1088   64249 $_[0]->op_ptr( $_[0]->op_ptr + ( $_[1] || 1 ) );
138             }
139              
140             sub _incr_mem_ptr {
141 104     104   9112 my ( $self, $increment ) = @_;
142 104   100     250 $increment ||= 1;
143 104         689 $self->mem_ptr( ( $self->mem_ptr + $increment ) % $self->byte_size );
144             }
145              
146             sub _incr_mem {
147 127     127   11212 my ( $self, $increment ) = @_;
148 3     3   29 no warnings qw/ uninitialized /;
  3         8  
  3         1133  
149 127         3066 $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 sub _set_current_mem ($self, $value ) {
  0         0  
  0         0  
  0         0  
155 0         0 return $self->memory_set( $self->mem_ptr => $value );
156             }
157              
158              
159 111     111   174 sub _get_current_mem($self) {
  111         166  
  111         170  
160 111         2750 return $self->memory_cell( $self->mem_ptr );
161             }
162              
163 573     573   24094 sub _current_op($self) {
  573         996  
  573         904  
164 573   100     13226 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.1.0
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) 2026, 2008 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