r5004@merlin: jquelin | 2007-05-24 15:50:38 +0200
[inline-befunge.git] / Befunge.pm
blobf778c07c560f25d223818eb0d821ae1b2ee73dd0
1 # $Id$
3 # Copyright (c) 2002 Jerome Quelin <jquelin@cpan.org>
4 # All rights reserved.
6 # This program is free software; you can redistribute it and/or
7 # modify it under the same terms as Perl itself.
10 package Inline::Befunge;
12 =head1 NAME
14 Inline::Befunge - write Perl subs in Befunge
17 =head1 SYNOPSIS
19 use Inline "Befunge";
21 print "9 + 16 = ", add(9, 16), "\n";
22 print "9 - 16 = ", subtract(9, 16),"\n";
24 __END__
25 __Befunge__
26 ;:add; +q
28 ;:subtract; -q
31 =head1 DESCRIPTION
33 The C<Inline::Befunge> module allows you to put Befunge source code
34 directly "inline" in a Perl script or module.
36 This allows you to write cool stuff with all the power of Befunge!
39 =head1 USING Inline::Befunge
41 Using C<Inline::Befunge> will seem very similar to using a another
42 Inline language, thanks to Inline's consistent look and feel.
44 This section will explain how to use C<Inline::Befunge>.
46 For more details on C<Inline>, see C<perldoc Inline>.
49 =head2 Feeding Inline with your code
51 The recommended way of using Inline is the following:
53 use Inline Befunge;
55 ...
57 __END__
58 __Befunge__
60 Befunge source code goes here.
62 But there are much more ways to use Inline. You'll find them in
63 C<perldoc Inline>.
66 =head2 Defining functions
68 As a befunge fan, you know that Befunge does not support named
69 subroutines. So, I introduced a little hack (thank goes to Sean
70 O'Rourke) in order for Inline to work: each subroutine definition
71 should be prepended with a comment C<;:subname;> (notice the colon
72 prepended).
74 You'll notice how smart it is, since it's enclosed in comments, and
75 therefore the overall meaning of the code isn't changed.
77 You can define your subroutines in any of the four cardinal directions,
78 and the subroutine velocity will be the velocity defined by the
79 comment. That is, if you define a subroutine in a vertical comment
80 from bottom to top, when called, the subroutine will start with a
81 velocity of (0,-1).
83 You can add comments after the subname. Thus, C<;:foo - a foo
84 subroutine;> defines a new subroutine C<foo>.
86 So, here's a valid example:
88 use Inline "Befunge";
90 hello();
92 __END__
93 __Befunge__
94 ;:hello - print a msg;<q_,#! #:<"Hello world!"a
98 a q - ;tcartsbus:;
102 + ;not a valid func def;
106 In this example, I defined three functions: C<hello()>, C<add()> and
107 C<substract>, and you can call them from within perl as if they were
108 valid perl functions. The fourth comment C<;not a valid func def;>
109 isn't a valid function definition since it lacks a colon C<:> just
110 after the C<;>.
113 =head2 Passing arguments
115 In order to write useful functions, one should be able to pass
116 arguments. This is possible, and one will find the arguments on the
117 TOSS of the interpreter: this means the stack may not be empty at the
118 beginning of the run. If you're a purist, then you may ignore this and
119 call your functions without arguments, and the stack will be empty.
121 Strings are pushed as 0gnirts.
123 B</!\> Remember, Befunge works with a stack: the first argument will
124 be the first pushed, ie, the deeper in the stack.
126 For example, when calling an inlined Befunge function like this:
127 C<foo( 'bar', 7, 'baz' );>, then the stack will be (bottom->top): C<(0
128 114 97 98 7 0 122 97 98)>.
131 =head2 Return values
133 Furthermore, one can return some values from the befunge
134 subroutines... how exciting!
136 To do so, the Befunge semantics have been a little adapted:
138 =over 4
140 =item o
142 when an Instruction Pointer reaches a C<q> instruction, one cell will
143 be popped from its stack and will be returned. This works like a
144 scalar return.
146 =item o
148 when an Instruction Pointer reaches a C<@> instruction, it will be
149 killed (just as in traditional Befunge). But when the B<last> IP
150 reaches a C<@>, then the sub is exited and will return the whole stack
151 of the IP that just died. This works like a list return.
153 B</!\> Be careful, that you will return a list of integer values. You
154 are to decide what to do with those values (especially, you are to
155 convert back to characters with the C<chr> perl builtin function and
156 join the chars if you're waiting for a string!).
158 =back
161 =head2 Supported options
163 C<Inline::Befunge> supports a DEBUG option, to follow the IP(s) as
164 they are running on the funge-space.
166 Use the following to activate it:
168 use Inline( Befunge => 'DATA',
169 DEBUG => 1 );
172 __END__
173 __Befunge__
175 Enter you befunge code here.
178 =cut
180 # A little anal retention ;-)
181 use strict;
182 use warnings;
184 # Modules we relied upon.
185 use Carp; # This module can't explode :o)
186 require Inline; # use Inline forbidden.
187 use Language::Befunge;
189 # Inheritance.
190 use base qw! Inline !;
192 # Public variables of the module.
193 our $VERSION = '0.04';
196 =head1 PUBLIC METHODS
198 =head2 register( )
200 Register as an Inline Language Support Module.
202 =cut
203 sub register {
204 return
205 { language => 'Befunge',
206 aliases => [ 'befunge', 'BEFUNGE', 'bf', 'BF' ],
207 type => 'interpreted',
208 suffix => 'bf',
212 =head2 validate( )
214 Check the params for the Befunge interpreter. Currently no options are
215 supported.
217 =cut
218 sub validate {
219 my $self = shift;
221 # Initializes funcs.
222 $self->{ILSM}{DEBUG} = 0;
224 while(@_ >= 2) {
225 my ($key, $value) = (shift, shift);
226 $key eq "DEBUG" and $self->{ILSM}{DEBUG} = $value, next;
227 croak "Unsupported option found: '$key'.";
232 =head2 build( )
234 Register the Befunge as a valid Inline extension.
236 =cut
237 sub build {
238 my $self = shift;
239 # The magic incantations to register.
240 my $path = $self->{API}{install_lib}."/auto/".$self->{API}{modpname};
241 $self->mkpath($path) unless -d $path;
242 my $file = $self->{API}{location};
243 open FOO_OBJ, "> $file" or croak "Can't open $file for output\n$!";
244 print FOO_OBJ $self->{API}{code};
245 close FOO_OBJ;
249 =head2 load( )
251 This function actually fetches the Befunge code. It first splits it to
252 find the functions.
254 =cut
255 sub load {
256 # Fetch object and package.
257 my $self = shift;
258 my $pkg = $self->{API}{pkg} || 'main';
260 # Fetch code and create the interpreter.
261 my $code = $self->{API}{code};
262 my $bef = $self->{ILSM}{bef} = new Language::Befunge;
263 $bef->store_code( $code );
264 $bef->DEBUG( $self->{ILSM}{DEBUG} );
266 # Parse the code.
267 # Each subroutine should be:
268 # ;:subname1; < @ ,,,,"foo"a
269 # ;:subname2;
270 # etc.
271 my $funcs = $bef->torus->labels_lookup;
272 $self->{ILSM}{funcs} = join " ", sort keys %$funcs;
274 foreach my $subname ( keys %$funcs ) {
275 no strict 'refs';
276 *{"${pkg}::$subname"} =
277 sub {
278 # Cosmetics.
279 $bef->debug( "\n-= SUBROUTINE $subname =-\n" );
280 $bef->file( "Inline-$subname" );
282 # Create the first Instruction Pointer.
283 my $ip = new Language::Befunge::IP;
285 # Move the IP at the beginning of the function.
286 $ip->curx( $funcs->{$subname}[0] );
287 $ip->cury( $funcs->{$subname}[1] );
288 $ip->dx( $funcs->{$subname}[2] );
289 $ip->dy( $funcs->{$subname}[3] );
291 # Fill the stack with arguments.
292 $ip->spush_args( @_ );
294 # Initialize the interpreter.
295 $bef->ips( [ $ip ] );
296 $bef->kcounter(-1);
297 $bef->retval(0);
299 # Loop as long as there are IPs.
300 $bef->next_tick while scalar @{ $bef->ips };
302 # Return the exit code and the TOSS.
303 return $bef->lastip->end eq '@' ?
304 @{ $bef->lastip->toss } # return the TOSS.
305 : $bef->retval; # return exit code.
312 =head2 info( )
314 Return a small report about the Befunge code.
316 =cut
317 sub info {
318 my $self = shift;
319 my $text = <<'END';
320 The following functions have been defined via Inline::Befunge:
321 $self->{ILSM}{funcs}
323 return $text;
328 __END__
330 =head1 AUTHOR
332 Jerome Quelin, E<lt>jquelin@cpan.orgE<gt>
335 =head1 ACKNOWLEDGEMENTS
337 I would like to thank:
339 =over 4
341 =item o
343 Brian Ingerson, for writing the incredibly cool C<Inline> module, and
344 giving the world's programmers enough rope to hang themselves many
345 times over.
347 =item o
349 Chris Pressey, creator of Befunge, who gave a whole new dimension to
350 both coding and obfuscating.
352 =item o
354 Sean O'Rourke E<lt>seano@alumni.rice.eduE<gt> for his incredible cool
355 idea on defining labels in Befunge code.
357 =back
360 =head1 COPYRIGHT
362 This program is free software; you can redistribute it and/or modify
363 it under the same terms as Perl itself.
366 =head1 SEE ALSO
368 =over 4
370 =item L<perl>
372 =item L<Inline>
374 =item L<Language::Befunge>
376 =back
378 =cut