Arthur J. O'Dwyer

Funge-98 Complete Reference

Funge-Space

Funge-Space is an N-dimensional lattice. At each lattice point, we have a Funge-Space cell, which can hold an integer value.

IPs

An executing Funge program has one or more IPs, which are the "execution threads" of the program. Each IP has associated with it the following components:

IP modes

An executing IP can be in any of several orthogonal modes. Standard Funge-98 provides only stringmode, toggled by the " instruction. The standard MODE extension provides the other modes in the following table. Listed alongside each mode is a "flag bit" associated with that mode by the haunted M instruction used by our Dynafing fingerprint specification:

IP Modes
stringmode [standard]0x0001
hovermode [MODE]0x0002
invertmode [MODE]0x0004
queuemode [MODE]0x0008
switchmode [MODE]0x0010
absolute mode [FNGR]0x0020
roll mode [FNGR]0x0040
swap mode [FNGR]0x0080

Stack-Stacks

Each executing IP controls its own stack-stack. A stack-stack is simply a LIFO stack whose elements are themselves LIFO stacks of Funge-Space values. (The top element of the stack-stack is called the top-of-stack stack, or TOSS. The stack under that stack is called the second-on-stack stack, or SOSS.) However, certain standard extensions require that the stack-stack be able to perform the following operations as well:

Fingerprints and Mini-Funges

Fingerprints are Funge-98's way of extending the core language. There are two types of fingerprints: tame fingerprints, which do not change the behavior of the interpreter and can be easily expressed through the Dynafing mechanism explained below; and feral fingerprints, which are generally built into the interpreter itself and can radically alter the way the interpreter operates.

Each executing IP has a LIFO stack of fingerprints which it has previously loaded into memory. These fingerprints overload the instructions A to Z with special behaviors, and can also affect the very operation of the interpreter itself. A complete list of known fingerprints follows, with short descriptions and originators' handprints:

Print Description Origin Instructions
BASEI/O for numbers in other bases RCSU BHINO
CPLIComplex integers RCSU ADMOSV
DIRFDirectory functions RCSU CMR
EVAREnvironment variables RCSU GNPV
FILEFile I/O functions RCSU CGLOPRSW
FIXPSome useful math functions RCSU ABCDIJNOPQRSTUVX
FNGRFingerprint management RCSU ABCDFKNORSTX
FPDPDouble precision floating point RCSU ABCDEFGHIKLMNPQRSTVXY
FPSPSingle precision floating point RCSU ABCDEFGHIKLMNPQRSTVXY
FRTHSome common Forth commands RCSU DLOPR
HRTIHigh resolution timer interface Cats-Eye EGMST
IMAPInstruction remap RCSU CMO
INDVPointer functions RCSU GPVW
JSTRString handling RC/Funge GP
MODEStandard modes Cats-Eye HIQS
MODUModulo arithmetic Cats-Eye MUR
NCRSncurses interface RC/Funge BCEGIKMNPRSU
NULLNull Cats-Eye ABCDEFGHIJKLMNOPQRSTUVWXYZ
ORTHOrthogonal easement Cats-Eye AEGOPSVWXYZ
PERLGeneric Perl interface Cats-Eye EIS
REFCReferenced cells Cats-Eye RD
ROMARoman numerals Cats-Eye CDILMVX
SGNLSignal handling RC/Funge HKMRXY
STRNString functions RCSU ACDFGILMNPRSV
SUBRSubroutine extension RCSU CJR
TERMTerminal extension RCSU CDGHLSU
TOYSStandard Toys Cats-Eye ABCDEFGHIJKLMNOPQRSTUVWXYZ
TURTTurtle graphics Cats-Eye ABCDEFHILNPQRTU
WINDWindows interface RCSU BCDEIKLMOPRSTW

See Jesse van Herk's RCFunge specifications for more detailed descriptions of most of the above fingerprints. The rest can be found at Chris Pressey's Befunge-98 library site.

When an IP encounters a ( instruction, it pops from the stack a counted string such as 4 "ROMA", and uses that to construct a fingerprint identifier: in this case, 0x524F4D41 for the ROMA extension. The interpreter then checks its internal list of fingerprints to see whether the named fingerprint is a built-in extension. If so, it works its magic; but if not, the interpreter then checks the directory ./fingerprints for a fingerprint implementation file with one of the names ROMA.df or 0x524F4D41.df. If no such file can be found, then the fingerprint is rejected as "unimplemented" (and the ( instruction acts as if it were an r instruction instead).

Suppose we have found a Dynafing implementation file for the ROMA fingerprint. The next step is to overload each of the instructions (in the range A to Z) defined by the new fingerprint. Un-overloaded instructions retain their old semantics. To do the overloading, we look in the file for blocks of the form

=M
52*::**@
The = character introduces a new definition for the instruction M. The new definition is that whenever the current IP executes an M instruction, it is to act as if it had instead executed the whole Funge program 52*::**@. Practically speaking, we make an actual dynamic copy of the entire fingerprint implementation file: a Mini-Funge. When the IP encounters an M instruction, we suspend execution of the current IP, and create a "ghost" IP inside the space of the Mini-Funge, below the =M line, heading east. All Mini-Funges have dimension 2; that is, they are Befunges, regardless of the dimension of the haunted IP's program. (This means that the instructions h, l, and m act like r within Mini-Funges.) The ghost IP executes until it reaches an @ instruction, at which point control is returned to the original, haunted IP, and the ghost IP is terminated.

See the Dynafing specs for more information on the possible interactions between ghost and haunted IPs.

When the IP encounters a ) instruction, it pops a counted-string fingerprint identifier and performs a "reverse overloading" of that fingerprint; that is, it loads the fingerprint into a new Mini-Funge and then proceeds to systematically de-overload each of the instructions which it would normally be overloading with new semantics.

The Dynafing system allows the programmer to create "false" overloads for the instructions @ and t. The overloaded @ instruction will be called whenever the haunted IP is about to die via @ or q. The overloaded t instruction will be called whenever the haunted IP is about to be split by a t instruction.

Each new ghost IP comes into the Mini-Funge world without any loaded fingerprints, no matter what the haunted IP might have loaded. Not even the current fingerprint is loaded; that is, when ROMA overloads the M instruction, it cannot use the definition CX* unless the ghost IP first loads ROMA itself! Thus

=I
1@
=V
5@
=X
a@
=L
a5*@
=C
0{"AMOR"4(XX*01-u)0}@
=D
0{"AMOR"4(CV*01-u)0}@
=M
0{"AMOR"4(CX*01-u)0}@
would be a perfectly correct, although rather obfuscated, Dynafing implementation of the ROMA fingerprint!
This page was last updated    13 August 2004
All original code, images and documentation on this page are freely distributable. Please keep them that way.