Funge-Space is an N-dimensional lattice. At each lattice point, we have a Funge-Space cell, which can hold an integer value.
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:
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
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 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:
Description Origin Instructions BASE I/O for numbers in other bases RCSU BHINO CPLI Complex integers RCSU ADMOSV DIRF Directory functions RCSU CMR EVAR Environment variables RCSU GNPV FILE File I/O functions RCSU CGLOPRSW FIXP Some useful math functions RCSU ABCDIJNOPQRSTUVX FNGR Fingerprint management RCSU ABCDFKNORSTX FPDP Double precision floating point RCSU ABCDEFGHIKLMNPQRSTVXY FPSP Single precision floating point RCSU ABCDEFGHIKLMNPQRSTVXY FRTH Some common Forth commands RCSU DLOPR HRTI High resolution timer interface Cats-Eye EGMST IMAP Instruction remap RCSU CMO INDV Pointer functions RCSU GPVW JSTR String handling RC/Funge GP MODE Standard modes Cats-Eye HIQS MODU Modulo arithmetic Cats-Eye MUR NCRS ncurses interface RC/Funge BCEGIKMNPRSU NULL Null Cats-Eye ABCDEFGHIJKLMNOPQRSTUVWXYZ ORTH Orthogonal easement Cats-Eye AEGOPSVWXYZ PERL Generic Perl interface Cats-Eye EIS REFC Referenced cells Cats-Eye RD ROMA Roman numerals Cats-Eye CDILMVX SGNL Signal handling RC/Funge HKMRXY STRN String functions RCSU ACDFGILMNPRSV SUBR Subroutine extension RCSU CJR TERM Terminal extension RCSU CDGHLSU TOYS Standard Toys Cats-Eye ABCDEFGHIJKLMNOPQRSTUVWXYZ TURT Turtle graphics Cats-Eye ABCDEFHILNPQRTU WIND Windows 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
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.=M 52*::**@
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
would be a perfectly correct, although rather obfuscated, Dynafing implementation of the ROMA fingerprint!=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}@