Ff
A Simple Forth System for Linux on i386 and ARM CPUs
Install / Use
/learn @8l/FfREADME
ff - A Simple FORTH System
Introduction
This is ff, an implementation of the Forth programming language for 32-bit
CPUs on Linux and Plan 9. ff is indirect-threaded and currently available for
x86 and ARM processors. It is kept intentionally simple to reduce size and
complexity to a minimum. Floating-point math and double-precision numbers are
not supported and only very limited I/O facilities are provided. On the other
hand, the machine-code portion is small and it should be very easy to port ff
to other architectures.
Installation
ff is available in pre-compiled, binary form and requires no additional
libraries, so it is not necessary to build it to get going.
The following files are included in the distribution:
ff-i386 x86 executable
ff-arm ARM executable
ff-i386-plan9 x86 executable for Plan 9
README This file
ff-i386.s Assembler sources for x86 (NASM syntax)
ff-arm.s Assembler sources for ARM (GAS syntax)
primitives.s Primitive dictionary
words-nasm.s Bootstrapping core dictionary (NASM syntax)
words-gas.s Bootstrapping core dictionary (GAS syntax)
core.f Core dictionary sources
meta.f Meta-compiler sources
meta-install.f Meta-compiler installation
elf.f Meta-compiler (elf binary generation)
cross.f Meta-compiler (Plan 9 a.out binary generation)
stuff.f Miscellaneous words
blocks.f Block- and buffer words
ed.f Block-editor sources
robots.f A simple game
forth Tcl/Tk frontend
x-i386.f Settings for cross-compilation to x86
x-arm.f Settings for cross-compilation to ARM
x-i386-plan9.f Settings for cross-compilation to x86 on Plan 9
In case you want to build ff-* yourself you will need an assembler -
[NASM][1] for the x86 version and [GNU as][2] for ARM, the latter being usually
available on an ARM-based linux with development tools installed. ARM ff can
also easily be cross-assembled from a non-ARM Linux system.
The necessary build-commands look like this:
nasm -f elf ff-i386.s -o ff-i386.o
ld ff-i386.o -o ff-i386 # add "-m elf_i386" on an x86_64 system
Or, for an ARM based system:
as ff-arm.s -o ff-arm.o
ld ff-arm.o -o ff-arm
Note that this creates only a minimal Forth system, sufficient to run the metacompiler. To generate or re-generate a complete binary, start the initial executable and enter:
include meta.f
include elf.f
include meta-install.f
include core.f
<ARCH> msave ff
bye
where <ARCH> should be either i386 or arm, depending on the system this
is running on.
On Plan 9, re-compilation is slightly different:
include meta.f
include a.out.f
include meta-install.f
include core.f
msave ff
bye
The C library (libc) is not used, ff directly invokes Linux or Plan 9
system-calls.
Cross-compilation is similar, but needs an additional file with hard-coded
addresses, together with binaries containing the target-specific machine code
of the kernel in the boot directory. So, assuming ff-arm is available as
boot/ff-arm:
include meta.f
0 target-endianness \ if target and host have different byte-order
\ 0 = big, 1 = little
include elf.f
include x-arm.f \ or "include x-i386.f"
include meta-install.f
include core.f
arm msave ff \ or "i386 msave ff"
bye
Again, replace elf.f with a.out.f and drop the argument to msave on
Plan 9. Note that ARM/Plan 9 is currently not supported.
Porting to other platforms should be straightforward, since the assembler
portion is quite small. Porting the system to embedded systems should also
don't present any problems - just add or remove primitive words in ff-*.s as
necessary and metacompile.
Some additional files and scripts for building and cross-compilation are
avaialble in the [ff development repository][5].
Usage
ff reads Forth commands from stdin, interpreting words as they are parsed. A
subset of the [Forth ANSI standard][3] is supported, see below for a
description of all words that are available.
All input is parsed case-sensitively, and the base dictionary contains lowercase words.
If one or more command-line arguments are given, then the first argument is
loaded as an image-file (using bload.)
The forth script implements a simple text-based front-end for ff, and is
written in Tcl/Tk. It provides a very basic terminal and implements basic
text-editing functionality. It defaults to invoking a binary named ff which
should be in the PATH (if it isn't copy or symlink the ff-* binary for your
architecture)
Command-line options that the forth script accepts:
-background COLORNAME select background color
-foreground COLORNAME select foreground color
-fontname FONTNAME select font
-fontsize FONTSIZE select fontsize
-execute FILENAME load Tcl source from FILENAME at startup
-ff FILENAME run FILENAME instead of the default "ff"
-cd DIRECTORY change working directory to DIRECTORY
-init STRING Forth code to be executed on startup
-image FILENAME Load image-file on startup (uses "-init")
Output from ff is appended to any text in the window. The character ^L
(ASCII 12) is handled specially and clears the window.
RETURN will send the current selection to the Forth interpreter, or the
current line if no text is currently selected. Pressing the Insert key will
enter hold mode, which means RETURN will just insert a newline, without
executing any code. Pressing Insert again will send all text beginning from
the location where Insert was first pressed up to the current cursor position
and disable hold mode.
Pressing the right mouse button on a word in the window will execute the Forth
statement command <word>. command is a deferred word defined in stuff.f
that can be used to implement a poor man's menu system by just right-clicking
words in the window.
Pressing Escape terminates the Forth interpreter, pressing it again exits
the front-end.
The function keys can be bound to text that is either inserted at the current
position, or (if it ends with a newline) immediately executed. To bind a key to
a particular sequence, select the text you want to bind and press Control-F<n>,
where F<n> is the function key you want to change.
Control-Up and Control-Down move the currently shown screen, when the
block and editor extensions are loaded.
If a file called .forth exists in the HOME directory, it is loaded before
startup and can be used to customize the front-end. Study the source code for
forth to learn more about it.
If the Forth system crashes, the background color turns to black and a message
is printed. Press RETURN to restart.
Unicode support
Partial UTF-8 support is provided: emit, char and [char] encode and
decode UTF-8 sequences correctly. key does not. The front-end allows entering
unicode code-points using the Delete key, which accepts either a hexadecimal
code-point or a named character. The latter can be defined in your ~/.forth
file by adding a definition for the snippets variable, holding lists of
2-element lists:
set snippets {
{alpha "\u03b1"}
...
}
Builtin words
-
Standard words (ANS)
Defined in the core system:
!##><##s'(*++!+loop,-..".r//mod0<0<>0=0>1+1-2*2/2drop2dup:;<<#<>=>>body>in>r?do?dup@[['][char]\]abortabort"absacceptagainalignalignedallotandbasebeginblblkc!c,c@cell+cellscharclearclose-filecmovecmove>compareconstantcountcrcreatedecimaldeferdepthdodropdupelseemiteraseexecuteexitfalsefillfindhherehexholdiifimmediateincludeincludedinvertisjkeylistliteralloadlooplshiftmaxminmodnegatenipoffonopen-fileoroverpadpagepickquitr/or/wr>r@read-filerecurserefillrepeatreposition-fileresetrestore-inputrotrshifts"save-inputscrsearchsignsliteralspacespacesstatestringswapthentibtruetucktypeu.u.runloopuntilunusedvariablew/owhilewithinwordwrite-filexordoes>currentDefined in the source files
stuff.fandblocks.f:2@2!2>r2r>?-trailing.s:noname/stringalsoblockbufferbuffer:casecontextcurrentdefinitionsdumpempty-buffersendcaseendofforgetforthlistloadmarkerofonlyorderpostponepreviousscrthruupdatevocabularywords -
Notes:
-
whileis only allowed once inside abegin/repeatconstruct. -
<#,#,#sand#>only handle single-precision numbers. -
There are no "state-smart" words.
is,."ands"are intended to be used inside colon definitions.
-
-
Non-standard core words
2nip ( x y -- y )Drops the 2nd item on the stack.
<builds ( | <word> -- )Compile-time part of
<builds ... does>pair. In other Forth systemscreateis normally used for this.>limit ( -- a )Variable holding the end-index in the text-input-buffer (TIB).
?stack ( -- )Aborts on stack-underflow.
`(.)
