The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

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.

DEBUG( boolean )

Set wether the interpreter should output debug messages.

curip( [IPref] )

Get or set the current Instruction Pointer processed.

lastip( [IPref] )

Get or set the last Instruction Pointer (when @ or q instructions are encountered).

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 regex qr/[^;]/, the IP will move in order to point on the r.

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

op_num_push_number( )

Push the current number onto the TOSS.

Strings

op_str_enter_string_mode( )
op_str_fetch_char( )
op_str_store_char( )

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

op_decis_neg( )
op_decis_gt( )
op_decis_horiz_if( )
op_decis_vert_if( )
op_decis_cmp( )

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

op_stack_pop( )
op_stack_duplicate( )
op_stack_swap( )
op_stack_clear( )

Stack stack manipulation

op_block_open( )
op_block_close( )
op_bloc_transfer( )

Funge-space storage

op_store_get( )
op_store_put( )

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

op_sys_info( )

Concurrent Funge

op_spawn_ip( )

Library semantics

op_lib_load( )
op_lib_unload( )

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 than P (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>

Development is discussed on <language-befunge@mongueurs.net>

ACKNOWLEDGEMENTS

I would like to thank Chris Pressey, creator of Befunge, who gave a whole new dimension to both coding and obfuscating.

COPYRIGHT

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO

perl
http://www.catseye.mb.ca/esoteric/befunge/
http://dufflebunk.iwarp.com/JSFunge/spec98.html