r7434@merlin: jquelin | 2007-10-24 15:19:50 +0200
[inline-befunge.git] / lib / Inline / Befunge.pm
blobf3fd7a3ff4b78aed65ecc0a2de8a7eb5dfc0080a
2 # This file is part of Inline::Befunge.
3 # Copyright (c) 2001-2007 Jerome Quelin, all rights reserved.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the same terms as Perl itself.
10 package Inline::Befunge;
12 use strict;
13 use warnings;
15 use Carp;
16 use Language::Befunge;
17 require Inline; # use Inline forbidden.
18 our @ISA = qw! Inline !; # not "use base" (use will take precedence over require)
19 our $VERSION = '1.0.0';
22 sub register {
23 return
24 { language => 'Befunge',
25 aliases => [ 'befunge', 'BEFUNGE', 'bef', 'BEF' ],
26 type => 'interpreted',
27 suffix => 'bef',
31 sub validate {
32 my $self = shift;
34 # Initializes funcs.
35 $self->{ILSM}{DEBUG} = 0;
37 while(@_ >= 2) {
38 my ($key, $value) = (shift, shift);
39 $key eq "DEBUG" and $self->{ILSM}{DEBUG} = $value, next;
40 croak "Unsupported option found: '$key'.";
45 sub build {
46 my $self = shift;
47 # The magic incantations to register.
48 my $path = $self->{API}{install_lib}."/auto/".$self->{API}{modpname};
49 $self->mkpath($path) unless -d $path;
50 my $file = $self->{API}{location};
51 open FOO_OBJ, "> $file" or croak "Can't open $file for output\n$!";
52 print FOO_OBJ $self->{API}{code};
53 close FOO_OBJ;
57 sub load {
58 # Fetch object and package.
59 my $self = shift;
60 my $pkg = $self->{API}{pkg} || 'main';
62 # Fetch code and create the interpreter.
63 my $code = $self->{API}{code};
64 my $bef = $self->{ILSM}{bef} = Language::Befunge->new;
65 $bef->store_code( $code );
66 $bef->set_DEBUG( $self->{ILSM}{DEBUG} );
68 # Parse the code.
69 # Each subroutine should be:
70 # ;:subname1; < @ ,,,,"foo"a
71 # ;:subname2;
72 # etc.
73 my $funcs = $bef->get_torus->labels_lookup;
74 $self->{ILSM}{funcs} = join " ", sort keys %$funcs;
76 foreach my $subname ( keys %$funcs ) {
77 no strict 'refs';
78 *{"${pkg}::$subname"} =
79 sub {
80 # Cosmetics.
81 $bef->debug( "\n-= SUBROUTINE $subname =-\n" );
82 $bef->set_file( "Inline-$subname" );
84 # Create the first Instruction Pointer.
85 my $ip = Language::Befunge::IP->new ;
87 # Move the IP at the beginning of the function.
88 my $pos = Language::Befunge::Vector->new( 2,
89 $funcs->{$subname}[0],
90 $funcs->{$subname}[1],
92 $ip->set_position($pos);
93 my $delta = Language::Befunge::Vector->new( 2,
94 $funcs->{$subname}[2],
95 $funcs->{$subname}[3],
97 $ip->set_delta($delta);
99 # Fill the stack with arguments.
100 $ip->spush_args( @_ );
102 # Initialize the interpreter.
103 $bef->set_ips( [ $ip ] );
104 #$bef->set_kcounter(-1);
105 $bef->set_retval(0);
107 # Loop as long as there are IPs.
108 $bef->next_tick while scalar @{ $bef->get_ips };
110 # Return the exit code and the TOSS.
111 # return $bef->lastip->end eq '@' ?
112 # @{ $bef->lastip->toss } # return the TOSS.
113 # : $bef->retval; # return exit code.
114 return $bef->get_retval; # quick'n'dirty bugfix
121 sub info {
122 my $self = shift;
123 my $text = <<'END';
124 The following functions have been defined via Inline::Befunge:
125 $self->{ILSM}{funcs}
127 return $text;
132 __END__
135 =head1 NAME
137 Inline::Befunge - write Perl subs in Befunge
140 =head1 SYNOPSIS
142 use Inline "Befunge";
144 print "9 + 16 = ", add(9, 16), "\n";
145 print "9 - 16 = ", subtract(9, 16),"\n";
147 __END__
148 __Befunge__
149 ;:add; +q
151 ;:subtract; -q
154 =head1 DESCRIPTION
156 The C<Inline::Befunge> module allows you to put Befunge source code
157 directly "inline" in a Perl script or module.
159 This allows you to write cool stuff with all the power of Befunge!
162 =head1 USING Inline::Befunge
164 Using C<Inline::Befunge> will seem very similar to using a another
165 Inline language, thanks to Inline's consistent look and feel.
167 This section will explain how to use C<Inline::Befunge>.
169 For more details on C<Inline>, see C<perldoc Inline>.
172 =head2 Feeding Inline with your code
174 The recommended way of using Inline is the following:
176 use Inline Befunge;
180 __END__
181 __Befunge__
183 Befunge source code goes here.
185 But there are much more ways to use Inline. You'll find them in
186 C<perldoc Inline>.
189 =head2 Defining functions
191 As a befunge fan, you know that Befunge does not support named
192 subroutines. So, I introduced a little hack (thank goes to Sean
193 O'Rourke) in order for Inline to work: each subroutine definition
194 should be prepended with a comment C<;:subname;> (notice the colon
195 prepended).
197 You'll notice how smart it is, since it's enclosed in comments, and
198 therefore the overall meaning of the code isn't changed.
200 You can define your subroutines in any of the four cardinal directions,
201 and the subroutine velocity will be the velocity defined by the
202 comment. That is, if you define a subroutine in a vertical comment
203 from bottom to top, when called, the subroutine will start with a
204 velocity of (0,-1).
206 You can add comments after the subname. Thus, C<;:foo - a foo
207 subroutine;> defines a new subroutine C<foo>.
209 So, here's a valid example:
211 use Inline "Befunge";
213 hello();
215 __END__
216 __Befunge__
217 ;:hello - print a msg;<q_,#! #:<"Hello world!"a
221 a q - ;tcartsbus:;
225 + ;not a valid func def;
229 In this example, I defined three functions: C<hello()>, C<add()> and
230 C<substract>, and you can call them from within perl as if they were
231 valid perl functions. The fourth comment C<;not a valid func def;>
232 isn't a valid function definition since it lacks a colon C<:> just
233 after the C<;>.
236 =head2 Passing arguments
238 In order to write useful functions, one should be able to pass
239 arguments. This is possible, and one will find the arguments on the
240 TOSS of the interpreter: this means the stack may not be empty at the
241 beginning of the run. If you're a purist, then you may ignore this and
242 call your functions without arguments, and the stack will be empty.
244 Strings are pushed as 0gnirts.
246 B</!\> Remember, Befunge works with a stack: the first argument will
247 be the first pushed, ie, the deeper in the stack.
249 For example, when calling an inlined Befunge function like this:
250 C<foo( 'bar', 7, 'baz' );>, then the stack will be (bottom->top): C<(0
251 114 97 98 7 0 122 97 98)>.
254 =head2 Return values
256 Furthermore, one can return some values from the befunge
257 subroutines... how exciting!
259 To do so, the Befunge semantics have been a little adapted:
261 =over 4
263 =item o
265 when an Instruction Pointer reaches a C<q> instruction, one cell will
266 be popped from its stack and will be returned. This works like a
267 scalar return.
269 =item o
271 when an Instruction Pointer reaches a C<@> instruction, it will be
272 killed (just as in traditional Befunge). But when the B<last> IP
273 reaches a C<@>, then the sub is exited and will return the whole stack
274 of the IP that just died. This works like a list return.
276 B</!\> Be careful, that you will return a list of integer values. You
277 are to decide what to do with those values (especially, you are to
278 convert back to characters with the C<chr> perl builtin function and
279 join the chars if you're waiting for a string!).
281 =back
284 =head2 Supported options
286 C<Inline::Befunge> supports a DEBUG option, to follow the IP(s) as
287 they are running on the funge-space.
289 Use the following to activate it:
291 use Inline( Befunge => 'DATA',
292 DEBUG => 1 );
295 __END__
296 __Befunge__
298 Enter you befunge code here.
301 =head1 PUBLIC METHODS
303 =head2 register( )
305 Register as an Inline Language Support Module.
308 =head2 validate( )
310 Check the params for the Befunge interpreter. Currently no options are
311 supported.
314 =head2 build( )
316 Register the Befunge as a valid Inline extension.
319 =head2 load( )
321 This function actually fetches the Befunge code. It first splits it to
322 find the functions.
325 =head2 info( )
327 Return a small report about the Befunge code.
330 =head1 SEE ALSO
332 =over 4
334 =item L<perl>
336 =item L<Inline>
338 =item L<Language::Befunge>
340 =back
343 =head1 ACKNOWLEDGEMENTS
345 I would like to thank:
347 =over 4
349 =item o
351 Brian Ingerson, for writing the incredibly cool C<Inline> module, and
352 giving the world's programmers enough rope to hang themselves many
353 times over.
355 =item o
357 Chris Pressey, creator of Befunge, who gave a whole new dimension to
358 both coding and obfuscating.
360 =item o
362 Sean O'Rourke E<lt>seano@alumni.rice.eduE<gt> for his incredible cool
363 idea on defining labels in Befunge code.
365 =back
368 =head1 AUTHOR
370 Jerome Quelin, C<< <jquelin at cpan.org> >>
373 =head1 COPYRIGHT AND LICENCE
375 Copyright (c) 2001-2007 Jerome Quelin, all rights reserved.
377 This program is free software; you can redistribute it and/or modify
378 it under the same terms as Perl itself.
381 =cut