NAME
Language::Befunge - a Befunge-98 interpreter.
SYNOPSIS
use Language::Befunge;
my $interp = new Language::Befunge( "program.bf" );
$interp->run_code( "param", 7, "foo" );
Or, one can write directly:
my $interp = new Language::Befunge;
$interp->store_code( <<'END_OF_CODE' );
< @,,,,"foo"a
END_OF_CODE
$interp->run_code;
DESCRIPTION
Enter the realm of topological languages!
This module implements the Funge-98 specifications on a 2D field (also called Befunge). In particular, be aware that this is not a Trefunge implementation (3D).
This Befunge-98 interpreters assumes the stack and Funge-Space cells of this implementation are 32 bits signed integers (I hope your os understand those integers). This means that the torus (or Cartesian Lahey-Space topology to be more precise) looks like the following:
32-bit Befunge-98
=================
^
|-2,147,483,648
|
| x
<-----------+----------->
-2,147,483,648 | 2,147,483,647
|
y|2,147,483,647
v
This implementation is meant to work on unix-like systems, because this interpreters only handle the character which ordinal value is 10 (also known as \n) as an End-Of-Line chars. In particular, no warranty is made neither for Microsoft systems (\r\n) nor for Macs (\r).
This module also implements the Concurrent Funge semantics.
CONSTRUCTOR
new( [filename] )
Create a new Befunge interpreter. If a filename is provided, then read and store the content of the file in the cartesian Lahey space topology of the interpreter.
ACCESSORS
All the following accessors are autoloaded.
file( [filename] )
Get or set the filename of the script.
params( [arrayref] )
Get or set the parameters of the script.
retval( [retval] )
Get or set the current return value of the interpreter.
kcounter( [kcounter] )
Get or set the kcounter (ie, the number of times the next instruction will be repeated).
DEBUG( boolean )
Set wether the interpreter should output debug messages.
curip( IPref )
Get or set the current Instruction Pointer processed.
ips( [arrayref] )
Get or set the current set of IPs travelling in the Lahey space.
newips( [arrayref] )
Get or set the set of IPs that will travel in the Lahey space after the current tick.
torus( )
Get the Lahey space object.
PUBLIC METHODS
Utilities
- move_curip( [regex] )
-
Move the current IP according to its delta on the LaheySpace topology.
If a regex ( a
qr//
object ) is specified, then IP will move as long as the pointed character match the supplied regex.Example: given the code
;foobar;
(assuming the IP points on the first;
) and the regexqr/[^;]/
, the IP will move in order to point on ther
. - abort( reason )
-
Abort the interpreter with the given reason, as well as the current file and coordinate of the offending instruction.
- debug( LIST )
-
Issue a warning if the interpreter has DEBUG enabled.
Code and Data Storage
- read_file( filename )
-
Read a file (given as argument) and store its code.
Side effect: clear the previous code.
- store_code( code )
-
Store the given code in the Lahey space.
Side effect: clear the previous code.
Run methods
- run_code( [params] )
-
Run the current code. That is, create a new Instruction Pointer and move it around the code.
Return the exit code of the program.
- next_tick( )
-
Finish the current tick and stop just before the next tick.
- process_ip( )
-
Process the current ip.
INSTRUCTION IMPLEMENTATIONS
Numbers
Strings
Mathematical operations
- op_math_addition( )
- op_math_substraction( )
- op_math_multiplication( )
- op_math_division( )
- op_math_remainder( )
Direction changing
- op_dir_go_east( )
- op_dir_go_west( )
- op_dir_go_north( )
- op_dir_go_south( )
- op_dir_go_away( )
- op_dir_turn_left( )
-
Turning left, like a car (the specs speak about a bicycle, but perl is _so_ fast that we can speak about cars ;) ).
- op_dir_turn_right( )
-
Turning right, like a car (the specs speak about a bicycle, but perl is _so_ fast that we can speak about cars ;) ).
- op_dir_reverse( )
- op_dir_set_delta( )
-
Hmm, the user seems to know where he wants to go. Let's trust him/her.
Decision making
Flow control
- op_flow_space( )
-
A serie of spaces is to be treated as one NO-OP.
- op_flow_no_op( )
- op_flow_comments( )
-
Bypass comments in one tick.
- op_flow_trampoline( )
- op_flow_jump_to( )
- op_flow_repeat( )
- op_flow_kill_thread( )
- op_flow_quit( )
Stack manipulation
Stack stack manipulation
Funge-space storage
Standard Input/Output
- op_stdio_out_num( )
- op_stdio_out_ascii( )
- op_stdio_in_num( )
- op_stdio_in_ascii( )
- op_stdio_in_file( )
- op_stdio_out_file( )
- op_stdio_sys_exec( )
System info retrieval
Concurrent Funge
Library semantics
TODO
- o
-
Write standard libraries.
BUGS
Although this module comes with a full set of tests, maybe there are subtle bugs - or maybe even I misinterpreted the Funge-98 specs. Please report them to me.
There are some bugs anyway, but they come from the specs:
- o
-
About the 18th cell pushed by the
y
instruction: Funge specs just tell to push onto the stack the size of the stacks, but nothing is said about how user will retrieve the number of stacks. - o
-
About the load semantics. Once a library is loaded, the interpreter is to put onto the TOSS the fingerprint of the just-loaded library. But nothing is said if the fingerprint is bigger than the maximum cell width (here, 4 bytes). This means that libraries can't have a name bigger than
0x80000000
, ie, more than four letters with the first one smaller thanP
(chr(80)
).Since perl is not so rigid, one can build libraries with more than four letters, but perl will issue a warning about non-portability of numbers greater than
0xffffffff
.
AUTHOR
Jerome Quelin, <jquelin@cpan.org>
COPYRIGHT
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.