File: gforth.info, Node: Top, Next: Goals, Prev: (dir), Up: (dir)
Gforth
******
This manual is for Gforth (version 0.6.2, August 25, 2003), a fast and
portable implementation of the ANS Forth language
Copyright (C) 1995, 1996, 1997, 1998, 2000, 2003 Free Software
Foundation, Inc.
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
Version 1.1 or any later version published by the Free Software
Foundation; with no Invariant Sections, with the Front-Cover texts
being "A GNU Manual," and with the Back-Cover Texts as in (a)
below. A copy of the license is included in the section entitled
"GNU Free Documentation License."
(a) The FSF's Back-Cover Text is: "You have freedom to copy and
modify this GNU Manual, like GNU software. Copies published by
the Free Software Foundation raise funds for GNU development."
* Menu:
* Goals:: About the Gforth Project
* Gforth Environment:: Starting (and exiting) Gforth
* Tutorial:: Hands-on Forth Tutorial
* Introduction:: An introduction to ANS Forth
* Words:: Forth words available in Gforth
* Error messages:: How to interpret them
* Tools:: Programming tools
* ANS conformance:: Implementation-defined options etc.
* Standard vs Extensions:: Should I use extensions?
* Model:: The abstract machine of Gforth
* Integrating Gforth:: Forth as scripting language for applications
* Emacs and Gforth:: The Gforth Mode
* Image Files:: `.fi' files contain compiled code
* Engine:: The inner interpreter and the primitives
* Cross Compiler:: The Cross Compiler
* Bugs:: How to report them
* Origin:: Authors and ancestors of Gforth
* Forth-related information:: Books and places to look on the WWW
* Licenses::
* Word Index:: An item for each Forth word
* Concept Index:: A menu covering many topics
--- The Detailed Node Listing ---
Gforth Environment
* Invoking Gforth:: Getting in
* Leaving Gforth:: Getting out
* Command-line editing::
* Environment variables:: that affect how Gforth starts up
* Gforth Files:: What gets installed and where
* Gforth in pipes::
* Startup speed:: When 35ms is not fast enough ...
Forth Tutorial
* Starting Gforth Tutorial::
* Syntax Tutorial::
* Crash Course Tutorial::
* Stack Tutorial::
* Arithmetics Tutorial::
* Stack Manipulation Tutorial::
* Using files for Forth code Tutorial::
* Comments Tutorial::
* Colon Definitions Tutorial::
* Decompilation Tutorial::
* Stack-Effect Comments Tutorial::
* Types Tutorial::
* Factoring Tutorial::
* Designing the stack effect Tutorial::
* Local Variables Tutorial::
* Conditional execution Tutorial::
* Flags and Comparisons Tutorial::
* General Loops Tutorial::
* Counted loops Tutorial::
* Recursion Tutorial::
* Leaving definitions or loops Tutorial::
* Return Stack Tutorial::
* Memory Tutorial::
* Characters and Strings Tutorial::
* Alignment Tutorial::
* Files Tutorial::
* Interpretation and Compilation Semantics and Immediacy Tutorial::
* Execution Tokens Tutorial::
* Exceptions Tutorial::
* Defining Words Tutorial::
* Arrays and Records Tutorial::
* POSTPONE Tutorial::
* Literal Tutorial::
* Advanced macros Tutorial::
* Compilation Tokens Tutorial::
* Wordlists and Search Order Tutorial::
An Introduction to ANS Forth
* Introducing the Text Interpreter::
* Stacks and Postfix notation::
* Your first definition::
* How does that work?::
* Forth is written in Forth::
* Review - elements of a Forth system::
* Where to go next::
* Exercises::
Forth Words
* Notation::
* Case insensitivity::
* Comments::
* Boolean Flags::
* Arithmetic::
* Stack Manipulation::
* Memory::
* Control Structures::
* Defining Words::
* Interpretation and Compilation Semantics::
* Tokens for Words::
* Compiling words::
* The Text Interpreter::
* The Input Stream::
* Word Lists::
* Environmental Queries::
* Files::
* Blocks::
* Other I/O::
* Locals::
* Structures::
* Object-oriented Forth::
* Programming Tools::
* Assembler and Code Words::
* Threading Words::
* Passing Commands to the OS::
* Keeping track of Time::
* Miscellaneous Words::
Arithmetic
* Single precision::
* Double precision:: Double-cell integer arithmetic
* Bitwise operations::
* Numeric comparison::
* Mixed precision:: Operations with single and double-cell integers
* Floating Point::
Stack Manipulation
* Data stack::
* Floating point stack::
* Return stack::
* Locals stack::
* Stack pointer manipulation::
Memory
* Memory model::
* Dictionary allocation::
* Heap Allocation::
* Memory Access::
* Address arithmetic::
* Memory Blocks::
Control Structures
* Selection:: IF ... ELSE ... ENDIF
* Simple Loops:: BEGIN ...
* Counted Loops:: DO
* Arbitrary control structures::
* Calls and returns::
* Exception Handling::
Defining Words
* CREATE::
* Variables:: Variables and user variables
* Constants::
* Values:: Initialised variables
* Colon Definitions::
* Anonymous Definitions:: Definitions without names
* Supplying names:: Passing definition names as strings
* User-defined Defining Words::
* Deferred words:: Allow forward references
* Aliases::
User-defined Defining Words
* CREATE..DOES> applications::
* CREATE..DOES> details::
* Advanced does> usage example::
* `Const-does>'::
Interpretation and Compilation Semantics
* Combined words::
Tokens for Words
* Execution token:: represents execution/interpretation semantics
* Compilation token:: represents compilation semantics
* Name token:: represents named words
Compiling words
* Literals:: Compiling data values
* Macros:: Compiling words
The Text Interpreter
* Input Sources::
* Number Conversion::
* Interpret/Compile states::
* Interpreter Directives::
Word Lists
* Vocabularies::
* Why use word lists?::
* Word list example::
Files
* Forth source files::
* General files::
* Search Paths::
Search Paths
* Source Search Paths::
* General Search Paths::
Other I/O
* Simple numeric output:: Predefined formats
* Formatted numeric output:: Formatted (pictured) output
* String Formats:: How Forth stores strings in memory
* Displaying characters and strings:: Other stuff
* Input:: Input
* Pipes:: How to create your own pipes
Locals
* Gforth locals::
* ANS Forth locals::
Gforth locals
* Where are locals visible by name?::
* How long do locals live?::
* Locals programming style::
* Locals implementation::
Structures
* Why explicit structure support?::
* Structure Usage::
* Structure Naming Convention::
* Structure Implementation::
* Structure Glossary::
Object-oriented Forth
* Why object-oriented programming?::
* Object-Oriented Terminology::
* Objects::
* OOF::
* Mini-OOF::
* Comparison with other object models::
The `objects.fs' model
* Properties of the Objects model::
* Basic Objects Usage::
* The Objects base class::
* Creating objects::
* Object-Oriented Programming Style::
* Class Binding::
* Method conveniences::
* Classes and Scoping::
* Dividing classes::
* Object Interfaces::
* Objects Implementation::
* Objects Glossary::
The `oof.fs' model
* Properties of the OOF model::
* Basic OOF Usage::
* The OOF base class::
* Class Declaration::
* Class Implementation::
The `mini-oof.fs' model
* Basic Mini-OOF Usage::
* Mini-OOF Example::
* Mini-OOF Implementation::
Programming Tools
* Examining::
* Forgetting words::
* Debugging:: Simple and quick.
* Assertions:: Making your programs self-checking.
* Singlestep Debugger:: Executing your program word by word.
Assembler and Code Words
* Code and ;code::
* Common Assembler:: Assembler Syntax
* Common Disassembler::
* 386 Assembler:: Deviations and special cases
* Alpha Assembler:: Deviations and special cases
* MIPS assembler:: Deviations and special cases
* Other assemblers:: How to write them
Tools
* ANS Report:: Report the words used, sorted by wordset.
ANS conformance
* The Core Words::
* The optional Block word set::
* The optional Double Number word set::
* The optional Exception word set::
* The optional Facility word set::
* The optional File-Access word set::
* The optional Floating-Point word set::
* The optional Locals word set::
* The optional Memory-Allocation word set::
* The optional Programming-Tools word set::
* The optional Search-Order word set::
The Core Words
* core-idef:: Implementation Defined Options
* core-ambcond:: Ambiguous Conditions
* core-other:: Other System Documentation
The optional Block word set
* block-idef:: Implementation Defined Options
* block-ambcond:: Ambiguous Conditions
* block-other:: Other System Documentation
The optional Double Number word set
* double-ambcond:: Ambiguous Conditions
The optional Exception word set
* exception-idef:: Implementation Defined Options
The optional Facility word set
* facility-idef:: Implementation Defined Options
* facility-ambcond:: Ambiguous Conditions
The optional File-Access word set
* file-idef:: Implementation Defined Options
* file-ambcond:: Ambiguous Conditions
The optional Floating-Point word set
* floating-idef:: Implementation Defined Options
* floating-ambcond:: Ambiguous Conditions
The optional Locals word set
* locals-idef:: Implementation Defined Options
* locals-ambcond:: Ambiguous Conditions
The optional Memory-Allocation word set
* memory-idef:: Implementation Defined Options
The optional Programming-Tools word set
* programming-idef:: Implementation Defined Options
* programming-ambcond:: Ambiguous Conditions
The optional Search-Order word set
* search-idef:: Implementation Defined Options
* search-ambcond:: Ambiguous Conditions
Emacs and Gforth
* Installing gforth.el:: Making Emacs aware of Forth.
* Emacs Tags:: Viewing the source of a word in Emacs.
* Hilighting:: Making Forth code look prettier.
* Auto-Indentation:: Customizing auto-indentation.
* Blocks Files:: Reading and writing blocks files.
Image Files
* Image Licensing Issues:: Distribution terms for images.
* Image File Background:: Why have image files?
* Non-Relocatable Image Files:: don't always work.
* Data-Relocatable Image Files:: are better.
* Fully Relocatable Image Files:: better yet.
* Stack and Dictionary Sizes:: Setting the default sizes for an image.
* Running Image Files:: `gforth -i file' or file.
* Modifying the Startup Sequence:: and turnkey applications.
Fully Relocatable Image Files
* gforthmi:: The normal way
* cross.fs:: The hard way
Engine
* Portability::
* Threading::
* Primitives::
* Performance::
Threading
* Scheduling::
* Direct or Indirect Threaded?::
* Dynamic Superinstructions::
* DOES>::
Primitives
* Automatic Generation::
* TOS Optimization::
* Produced code::
Cross Compiler
* Using the Cross Compiler::
* How the Cross Compiler Works::
Licenses
* GNU Free Documentation License:: License for copying this manual.
* Copying:: GPL (for copying this software).
File: gforth.info, Node: Goals, Next: Gforth Environment, Prev: Top, Up: Top
Goals of Gforth
***************
The goal of the Gforth Project is to develop a standard model for
ANS Forth. This can be split into several subgoals:
* Gforth should conform to the ANS Forth Standard.
* It should be a model, i.e. it should define all the
implementation-dependent things.
* It should become standard, i.e. widely accepted and used. This goal
is the most difficult one.
To achieve these goals Gforth should be
* Similar to previous models (fig-Forth, F83)
* Powerful. It should provide for all the things that are considered
necessary today and even some that are not yet considered
necessary.
* Efficient. It should not get the reputation of being exceptionally
slow.
* Free.
* Available on many machines/easy to port.
Have we achieved these goals? Gforth conforms to the ANS Forth
standard. It may be considered a model, but we have not yet documented
which parts of the model are stable and which parts we are likely to
change. It certainly has not yet become a de facto standard, but it
appears to be quite popular. It has some similarities to and some
differences from previous models. It has some powerful features, but not
yet everything that we envisioned. We certainly have achieved our
execution speed goals (*note Performance::)(1). It is free and
available on many machines.
---------- Footnotes ----------
(1) However, in 1998 the bar was raised when the major commercial
Forth vendors switched to native code compilers.
File: gforth.info, Node: Gforth Environment, Next: Tutorial, Prev: Goals, Up: Top
Gforth Environment
******************
Note: ultimately, the Gforth man page will be auto-generated from the
material in this chapter.
* Menu:
* Invoking Gforth:: Getting in
* Leaving Gforth:: Getting out
* Command-line editing::
* Environment variables:: that affect how Gforth starts up
* Gforth Files:: What gets installed and where
* Gforth in pipes::
* Startup speed:: When 35ms is not fast enough ...
For related information about the creation of images see *Note Image
Files::.
File: gforth.info, Node: Invoking Gforth, Next: Leaving Gforth, Prev: Gforth Environment, Up: Gforth Environment
Invoking Gforth
===============
Gforth is made up of two parts; an executable "engine" (named
`gforth' or `gforth-fast') and an image file. To start it, you will
usually just say `gforth' - this automatically loads the default image
file `gforth.fi'. In many other cases the default Gforth image will be
invoked like this:
gforth [file | -e forth-code] ...
This interprets the contents of the files and the Forth code in the
order they are given.
In addition to the `gforth' engine, there is also an engine called
`gforth-fast', which is faster, but gives less informative error
messages (*note Error messages::) and may catch some stack underflows
later or not at all. You should use it for debugged,
performance-critical programs.
Moreover, there is an engine called `gforth-itc', which is useful in
some backwards-compatibility situations (*note Direct or Indirect
Threaded?::).
In general, the command line looks like this:
gforth[-fast] [engine options] [image options]
The engine options must come before the rest of the command line.
They are:
`--image-file file'
`-i file'
Loads the Forth image file instead of the default `gforth.fi'
(*note Image Files::).
`--appl-image file'
Loads the image file and leaves all further command-line arguments
to the image (instead of processing them as engine options). This
is useful for building executable application images on Unix,
built with `gforthmi --application ...'.
`--path path'
`-p path'
Uses path for searching the image file and Forth source code files
instead of the default in the environment variable `GFORTHPATH' or
the path specified at installation time (e.g.,
`/usr/local/share/gforth/0.2.0:.'). A path is given as a list of
directories, separated by `:' (on Unix) or `;' (on other OSs).
`--dictionary-size size'
`-m size'
Allocate size space for the Forth dictionary space instead of
using the default specified in the image (typically 256K). The
size specification for this and subsequent options consists of an
integer and a unit (e.g., `4M'). The unit can be one of `b'
(bytes), `e' (element size, in this case Cells), `k' (kilobytes),
`M' (Megabytes), `G' (Gigabytes), and `T' (Terabytes). If no unit
is specified, `e' is used.
`--data-stack-size size'
`-d size'
Allocate size space for the data stack instead of using the
default specified in the image (typically 16K).
`--return-stack-size size'
`-r size'
Allocate size space for the return stack instead of using the
default specified in the image (typically 15K).
`--fp-stack-size size'
`-f size'
Allocate size space for the floating point stack instead of using
the default specified in the image (typically 15.5K). In this case
the unit specifier `e' refers to floating point numbers.
`--locals-stack-size size'
`-l size'
Allocate size space for the locals stack instead of using the
default specified in the image (typically 14.5K).
`--help'
`-h'
Print a message about the command-line options
`--version'
`-v'
Print version and exit
`--debug'
Print some information useful for debugging on startup.
`--offset-image'
Start the dictionary at a slightly different position than would
be used otherwise (useful for creating data-relocatable images,
*note Data-Relocatable Image Files::).
`--no-offset-im'
Start the dictionary at the normal position.
`--clear-dictionary'
Initialize all bytes in the dictionary to 0 before loading the
image (*note Data-Relocatable Image Files::).
`--die-on-signal'
Normally Gforth handles most signals (e.g., the user interrupt
SIGINT, or the segmentation violation SIGSEGV) by translating it
into a Forth `THROW'. With this option, Gforth exits if it
receives such a signal. This option is useful when the engine
and/or the image might be severely broken (such that it causes
another signal before recovering from the first); this option
avoids endless loops in such cases.
`--no-dynamic'
`--dynamic'
Disable or enable dynamic superinstructions with replication
(*note Dynamic Superinstructions::).
`--no-super'
Disable dynamic superinstructions, use just dynamic replication;
this is useful if you want to patch threaded code (*note Dynamic
Superinstructions::).
`--ss-number=N'
Use only the first N static superinstructions compiled into the
engine (default: use them all; note that only `gforth-fast' has
any). This option is useful for measuring the performance impact
of static superinstructions.
`--ss-min-codesize'
`--ss-min-ls'
`--ss-min-lsu'
`--ss-min-nexts'
Use specified metric for determining the cost of a primitive or
static superinstruction for static superinstruction selection.
`Codesize' is the native code size of the primive or static
superinstruction, `ls' is the number of loads and stores, `lsu' is
the number of loads, stores, and updates, and `nexts' is the
number of dispatches (not taking dynamic superinstructions into
account), i.e. every primitive or static superinstruction has cost
1. Default: `codesize' if you use dynamic code generation,
otherwise `nexts'.
`--ss-greedy'
This option is useful for measuring the performance impact of
static superinstructions. By default, an optimal shortest-path
algorithm is used for selecting static superinstructions. With
`--ss-greedy' this algorithm is modified to assume that anything
after the static superinstruction currently under consideration is
not combined into static superinstructions. With `--ss-min-nexts'
this produces the same result as a greedy algorithm that always
selects the longest superinstruction available at the moment.
E.g., if there are superinstructions AB and BCD, then for the
sequence A B C D the optimal algorithm will select A BCD and the
greedy algorithm will select AB C D.
`--print-metrics'
Prints some metrics used during static superinstruction selection:
`code size' is the actual size of the dynamically generated code.
`Metric codesize' is the sum of the codesize metrics as seen by
static superinstruction selection; there is a difference from `code
size', because not all primitives and static superinstructions are
compiled into dynamically generated code, and because of markers.
The other metrics correspond to the `ss-min-...' options. This
option is useful for evaluating the effects of the `--ss-...'
options.
As explained above, the image-specific command-line arguments for the
default image `gforth.fi' consist of a sequence of filenames and `-e
FORTH-CODE' options that are interpreted in the sequence in which they
are given. The `-e FORTH-CODE' or `--evaluate FORTH-CODE' option
evaluates the Forth code. This option takes only one argument; if you
want to evaluate more Forth words, you have to quote them or use `-e'
several times. To exit after processing the command line (instead of
entering interactive mode) append `-e bye' to the command line.
If you have several versions of Gforth installed, `gforth' will
invoke the version that was installed last. `gforth-version' invokes a
specific version. If your environment contains the variable
`GFORTHPATH', you may want to override it by using the `--path' option.
Not yet implemented: On startup the system first executes the system
initialization file (unless the option `--no-init-file' is given; note
that the system resulting from using this option may not be ANS Forth
conformant). Then the user initialization file `.gforth.fs' is
executed, unless the option `--no-rc' is given; this file is searched
for in `.', then in `~', then in the normal path (see above).
File: gforth.info, Node: Leaving Gforth, Next: Command-line editing, Prev: Invoking Gforth, Up: Gforth Environment
Leaving Gforth
==============
You can leave Gforth by typing `bye' or `Ctrl-d' (at the start of a
line) or (if you invoked Gforth with the `--die-on-signal' option)
`Ctrl-c'. When you leave Gforth, all of your definitions and data are
discarded. For ways of saving the state of the system before leaving
Gforth see *Note Image Files::.
`bye' - tools-ext ``bye''
Return control to the host operating system (if any).
File: gforth.info, Node: Command-line editing, Next: Environment variables, Prev: Leaving Gforth, Up: Gforth Environment
Command-line editing
====================
Gforth maintains a history file that records every line that you
type to the text interpreter. This file is preserved between sessions,
and is used to provide a command-line recall facility; if you type
`Ctrl-P' repeatedly you can recall successively older commands from
this (or previous) session(s). The full list of command-line editing
facilities is:
* `Ctrl-p' ("previous") (or up-arrow) to recall successively older
commands from the history buffer.
* `Ctrl-n' ("next") (or down-arrow) to recall successively newer
commands from the history buffer.
* `Ctrl-f' (or right-arrow) to move the cursor right,
non-destructively.
* `Ctrl-b' (or left-arrow) to move the cursor left,
non-destructively.
* `Ctrl-h' (backspace) to delete the character to the left of the
cursor, closing up the line.
* `Ctrl-k' to delete ("kill") from the cursor to the end of the line.
* `Ctrl-a' to move the cursor to the start of the line.
* `Ctrl-e' to move the cursor to the end of the line.
* <RET> (`Ctrl-m') or <LFD> (`Ctrl-j') to submit the current line.
* <TAB> to step through all possible full-word completions of the
word currently being typed.
* `Ctrl-d' on an empty line line to terminate Gforth (gracefully,
using `bye').
* `Ctrl-x' (or `Ctrl-d' on a non-empty line) to delete the character
under the cursor.
When editing, displayable characters are inserted to the left of the
cursor position; the line is always in "insert" (as opposed to
"overstrike") mode.
On Unix systems, the history file is `~/.gforth-history' by
default(1). You can find out the name and location of your history file
using:
history-file type \ Unix-class systems
history-file type \ Other systems
history-dir type
If you enter long definitions by hand, you can use a text editor to
paste them out of the history file into a Forth source file for reuse at
a later time.
Gforth never trims the size of the history file, so you should do
this periodically, if necessary.
---------- Footnotes ----------
(1) i.e. it is stored in the user's home directory.
File: gforth.info, Node: Environment variables, Next: Gforth Files, Prev: Command-line editing, Up: Gforth Environment
Environment variables
=====================
Gforth uses these environment variables:
* `GFORTHHIST' - (Unix systems only) specifies the directory in
which to open/create the history file, `.gforth-history'. Default:
`$HOME'.
* `GFORTHPATH' - specifies the path used when searching for the
gforth image file and for Forth source-code files.
* `GFORTH' - used by `gforthmi', *Note gforthmi::.
* `GFORTHD' - used by `gforthmi', *Note gforthmi::.
* `TMP', `TEMP' - (non-Unix systems only) used as a potential
location for the history file.
All the Gforth environment variables default to sensible values if
they are not set.
File: gforth.info, Node: Gforth Files, Next: Gforth in pipes, Prev: Environment variables, Up: Gforth Environment
Gforth files
============
When you install Gforth on a Unix system, it installs files in these
locations by default:
* `/usr/local/bin/gforth'
* `/usr/local/bin/gforthmi'
* `/usr/local/man/man1/gforth.1' - man page.
* `/usr/local/info' - the Info version of this manual.
* `/usr/local/lib/gforth/<version>/...' - Gforth `.fi' files.
* `/usr/local/share/gforth/<version>/TAGS' - Emacs TAGS file.
* `/usr/local/share/gforth/<version>/...' - Gforth source files.
* `.../emacs/site-lisp/gforth.el' - Emacs gforth mode.
You can select different places for installation by using
`configure' options (listed with `configure --help').
File: gforth.info, Node: Gforth in pipes, Next: Startup speed, Prev: Gforth Files, Up: Gforth Environment
Gforth in pipes
===============
Gforth can be used in pipes created elsewhere (described here). It
can also create pipes on its own (*note Pipes::).
If you pipe into Gforth, your program should read with `read-file'
or `read-line' from `stdin' (*note General files::). `Key' does not
recognize the end of input. Words like `accept' echo the input and are
therefore usually not useful for reading from a pipe. You have to
invoke the Forth program with an OS command-line option, as you have no
chance to use the Forth command line (the text interpreter would try to
interpret the pipe input).
You can output to a pipe with `type', `emit', `cr' etc.
When you write to a pipe that has been closed at the other end,
Gforth receives a SIGPIPE signal ("pipe broken"). Gforth translates
this into the exception `broken-pipe-error'. If your application does
not catch that exception, the system catches it and exits, usually
silently (unless you were working on the Forth command line; then it
prints an error message and exits). This is usually the desired
behaviour.
If you do not like this behaviour, you have to catch the exception
yourself, and react to it.
Here's an example of an invocation of Gforth that is usable in a
pipe:
gforth -e ": foo begin pad dup 10 stdin read-file throw dup while \
type repeat ; foo bye"
This example just copies the input verbatim to the output. A very
simple pipe containing this example looks like this:
cat startup.fs |
gforth -e ": foo begin pad dup 80 stdin read-file throw dup while \
type repeat ; foo bye"|
head
Pipes involving Gforth's `stderr' output do not work.
File: gforth.info, Node: Startup speed, Prev: Gforth in pipes, Up: Gforth Environment
Startup speed
=============
If Gforth is used for CGI scripts or in shell scripts, its startup
speed may become a problem. On a 300MHz 21064a under Linux-2.2.13 with
glibc-2.0.7, `gforth -e bye' takes about 24.6ms user and 11.3ms system
time.
If startup speed is a problem, you may consider the following ways to
improve it; or you may consider ways to reduce the number of startups
(for example, by using Fast-CGI).
An easy step that influences Gforth startup speed is the use of the
`--no-dynamic' option; this decreases image loading speed, but
increases compile-time and run-time.
Another step to improve startup speed is to statically link Gforth,
by building it with `XLDFLAGS=-static'. This requires more memory for
the code and will therefore slow down the first invocation, but
subsequent invocations avoid the dynamic linking overhead. Another
disadvantage is that Gforth won't profit from library upgrades. As a
result, `gforth-static -e bye' takes about 17.1ms user and 8.2ms system
time.
The next step to improve startup speed is to use a non-relocatable
image (*note Non-Relocatable Image Files::). You can create this image
with `gforth -e "savesystem gforthnr.fi bye"' and later use it with
`gforth -i gforthnr.fi ...'. This avoids the relocation overhead and a
part of the copy-on-write overhead. The disadvantage is that the
non-relocatable image does not work if the OS gives Gforth a different
address for the dictionary, for whatever reason; so you better provide a
fallback on a relocatable image. `gforth-static -i gforthnr.fi -e bye'
takes about 15.3ms user and 7.5ms system time.
The final step is to disable dictionary hashing in Gforth. Gforth
builds the hash table on startup, which takes much of the startup
overhead. You can do this by commenting out the `include hash.fs' in
`startup.fs' and everything that requires `hash.fs' (at the moment
`table.fs' and `ekey.fs') and then doing `make'. The disadvantages are
that functionality like `table' and `ekey' is missing and that text
interpretation (e.g., compiling) now takes much longer. So, you should
only use this method if there is no significant text interpretation to
perform (the script should be compiled into the image, amongst other
things). `gforth-static -i gforthnrnh.fi -e bye' takes about 2.1ms
user and 6.1ms system time.
File: gforth.info, Node: Tutorial, Next: Introduction, Prev: Gforth Environment, Up: Top
Forth Tutorial
**************
The difference of this chapter from the Introduction (*note
Introduction::) is that this tutorial is more fast-paced, should be
used while sitting in front of a computer, and covers much more
material, but does not explain how the Forth system works.
This tutorial can be used with any ANS-compliant Forth; any
Gforth-specific features are marked as such and you can skip them if you
work with another Forth. This tutorial does not explain all features of
Forth, just enough to get you started and give you some ideas about the
facilities available in Forth. Read the rest of the manual and the
standard when you are through this.
The intended way to use this tutorial is that you work through it
while sitting in front of the console, take a look at the examples and
predict what they will do, then try them out; if the outcome is not as
expected, find out why (e.g., by trying out variations of the example),
so you understand what's going on. There are also some assignments
that you should solve.
This tutorial assumes that you have programmed before and know what,
e.g., a loop is.
* Menu:
* Starting Gforth Tutorial::
* Syntax Tutorial::
* Crash Course Tutorial::
* Stack Tutorial::
* Arithmetics Tutorial::
* Stack Manipulation Tutorial::
* Using files for Forth code Tutorial::
* Comments Tutorial::
* Colon Definitions Tutorial::
* Decompilation Tutorial::
* Stack-Effect Comments Tutorial::
* Types Tutorial::
* Factoring Tutorial::
* Designing the stack effect Tutorial::
* Local Variables Tutorial::
* Conditional execution Tutorial::
* Flags and Comparisons Tutorial::
* General Loops Tutorial::
* Counted loops Tutorial::
* Recursion Tutorial::
* Leaving definitions or loops Tutorial::
* Return Stack Tutorial::
* Memory Tutorial::
* Characters and Strings Tutorial::
* Alignment Tutorial::
* Files Tutorial::
* Interpretation and Compilation Semantics and Immediacy Tutorial::
* Execution Tokens Tutorial::
* Exceptions Tutorial::
* Defining Words Tutorial::
* Arrays and Records Tutorial::
* POSTPONE Tutorial::
* Literal Tutorial::
* Advanced macros Tutorial::
* Compilation Tokens Tutorial::
* Wordlists and Search Order Tutorial::
File: gforth.info, Node: Starting Gforth Tutorial, Next: Syntax Tutorial, Prev: Tutorial, Up: Tutorial
Starting Gforth
===============
You can start Gforth by typing its name:
gforth
That puts you into interactive mode; you can leave Gforth by typing
`bye'. While in Gforth, you can edit the command line and access the
command line history with cursor keys, similar to bash.
File: gforth.info, Node: Syntax Tutorial, Next: Crash Course Tutorial, Prev: Starting Gforth Tutorial, Up: Tutorial
Syntax
======
A "word" is a sequence of arbitrary characters (expcept white
space). Words are separated by white space. E.g., each of the
following lines contains exactly one word:
word
!@#$%^&*()
1234567890
5!a
A frequent beginner's error is to leave away necessary white space,
resulting in an error like `Undefined word'; so if you see such an
error, check if you have put spaces wherever necessary.
." hello, world" \ correct
."hello, world" \ gives an "Undefined word" error
Gforth and most other Forth systems ignore differences in case (they
are case-insensitive), i.e., `word' is the same as `Word'. If your
system is case-sensitive, you may have to type all the examples given
here in upper case.
File: gforth.info, Node: Crash Course Tutorial, Next: Stack Tutorial, Prev: Syntax Tutorial, Up: Tutorial
Crash Course
============
Type
0 0 !
here execute
' catch >body 20 erase abort
' (quit) >body 20 erase
The last two examples are guaranteed to destroy parts of Gforth (and
most other systems), so you better leave Gforth afterwards (if it has
not finished by itself). On some systems you may have to kill gforth
from outside (e.g., in Unix with `kill').
Now that you know how to produce crashes (and that there's not much
to them), let's learn how to produce meaningful programs.
File: gforth.info, Node: Stack Tutorial, Next: Arithmetics Tutorial, Prev: Crash Course Tutorial, Up: Tutorial
Stack
=====
The most obvious feature of Forth is the stack. When you type in a
number, it is pushed on the stack. You can display the content of the
stack with `.s'.
1 2 .s
3 .s
`.s' displays the top-of-stack to the right, i.e., the numbers
appear in `.s' output as they appeared in the input.
You can print the top of stack element with `.'.
1 2 3 . . .
In general, words consume their stack arguments (`.s' is an
exception).
Assignment:
What does the stack contain after `5 6 7 .'?
File: gforth.info, Node: Arithmetics Tutorial, Next: Stack Manipulation Tutorial, Prev: Stack Tutorial, Up: Tutorial
Arithmetics
===========
The words `+', `-', `*', `/', and `mod' always operate on the top
two stack items:
2 2 .s
+ .s
.
2 1 - .
7 3 mod .
The operands of `-', `/', and `mod' are in the same order as in the
corresponding infix expression (this is generally the case in Forth).
Parentheses are superfluous (and not available), because the order of
the words unambiguously determines the order of evaluation and the
operands:
3 4 + 5 * .
3 4 5 * + .
Assignment:
What are the infix expressions corresponding to the Forth code
above? Write `6-7*8+9' in Forth notation(1).
To change the sign, use `negate':
2 negate .
Assignment:
Convert -(-3)*4-5 to Forth.
`/mod' performs both `/' and `mod'.
7 3 /mod . .
Reference: *Note Arithmetic::.
---------- Footnotes ----------
(1) This notation is also known as Postfix or RPN (Reverse Polish
Notation).
File: gforth.info, Node: Stack Manipulation Tutorial, Next: Using files for Forth code Tutorial, Prev: Arithmetics Tutorial, Up: Tutorial
Stack Manipulation
==================
Stack manipulation words rearrange the data on the stack.
1 .s drop .s
1 .s dup .s drop drop .s
1 2 .s over .s drop drop drop
1 2 .s swap .s drop drop
1 2 3 .s rot .s drop drop drop
These are the most important stack manipulation words. There are
also variants that manipulate twice as many stack items:
1 2 3 4 .s 2swap .s 2drop 2drop
Two more stack manipulation words are:
1 2 .s nip .s drop
1 2 .s tuck .s 2drop drop
Assignment:
Replace `nip' and `tuck' with combinations of other stack
manipulation words.
Given: How do you get:
1 2 3 3 2 1
1 2 3 1 2 3 2
1 2 3 1 2 3 3
1 2 3 1 3 3
1 2 3 2 1 3
1 2 3 4 4 3 2 1
1 2 3 1 2 3 1 2 3
1 2 3 4 1 2 3 4 1 2
1 2 3
1 2 3 1 2 3 4
1 2 3 1 3
5 dup * .
Assignment:
Write 17^3 and 17^4 in Forth, without writing `17' more than once.
Write a piece of Forth code that expects two numbers on the stack
(A and B, with B on top) and computes `(a-b)(a+1)'.
Reference: *Note Stack Manipulation::.
File: gforth.info, Node: Using files for Forth code Tutorial, Next: Comments Tutorial, Prev: Stack Manipulation Tutorial, Up: Tutorial
Using files for Forth code
==========================
While working at the Forth command line is convenient for one-line
examples and short one-off code, you probably want to store your source
code in files for convenient editing and persistence. You can use your
favourite editor (Gforth includes Emacs support, *note Emacs and
Gforth::) to create FILE.FS and use
s" FILE.FS" included
to load it into your Forth system. The file name extension I use for
Forth files is `.fs'.
You can easily start Gforth with some files loaded like this:
gforth FILE1.FS FILE2.FS
If an error occurs during loading these files, Gforth terminates,
whereas an error during `INCLUDED' within Gforth usually gives you a
Gforth command line. Starting the Forth system every time gives you a
clean start every time, without interference from the results of earlier
tries.
I often put all the tests in a file, then load the code and run the
tests with
gforth CODE.FS TESTS.FS -e bye
(often by performing this command with `C-x C-e' in Emacs). The `-e
bye' ensures that Gforth terminates afterwards so that I can restart
this command without ado.
The advantage of this approach is that the tests can be repeated
easily every time the program ist changed, making it easy to catch bugs
introduced by the change.
Reference: *Note Forth source files::.
File: gforth.info, Node: Comments Tutorial, Next: Colon Definitions Tutorial, Prev: Using files for Forth code Tutorial, Up: Tutorial
Comments
========
\ That's a comment; it ends at the end of the line
( Another comment; it ends here: ) .s
`\' and `(' are ordinary Forth words and therefore have to be
separated with white space from the following text.
\This gives an "Undefined word" error
The first `)' ends a comment started with `(', so you cannot nest
`('-comments; and you cannot comment out text containing a `)' with `(
... )'(1).
I use `\'-comments for descriptive text and for commenting out code
of one or more line; I use `('-comments for describing the stack
effect, the stack contents, or for commenting out sub-line pieces of
code.
The Emacs mode `gforth.el' (*note Emacs and Gforth::) supports these
uses by commenting out a region with `C-x \', uncommenting a region
with `C-u C-x \', and filling a `\'-commented region with `M-q'.
Reference: *Note Comments::.
---------- Footnotes ----------
(1) therefore it's a good idea to avoid `)' in word names.
File: gforth.info, Node: Colon Definitions Tutorial, Next: Decompilation Tutorial, Prev: Comments Tutorial, Up: Tutorial
Colon Definitions
=================
are similar to procedures and functions in other programming
languages.
: squared ( n -- n^2 )
dup * ;
5 squared .
7 squared .
`:' starts the colon definition; its name is `squared'. The
following comment describes its stack effect. The words `dup *' are
not executed, but compiled into the definition. `;' ends the colon
definition.
The newly-defined word can be used like any other word, including
using it in other definitions:
: cubed ( n -- n^3 )
dup squared * ;
-5 cubed .
: fourth-power ( n -- n^4 )
squared squared ;
3 fourth-power .
Assignment:
Write colon definitions for `nip', `tuck', `negate', and `/mod' in
terms of other Forth words, and check if they work (hint: test
your tests on the originals first). Don't let the
`redefined'-Messages spook you, they are just warnings.
Reference: *Note Colon Definitions::.
File: gforth.info, Node: Decompilation Tutorial, Next: Stack-Effect Comments Tutorial, Prev: Colon Definitions Tutorial, Up: Tutorial
Decompilation
=============
You can decompile colon definitions with `see':
see squared
see cubed
In Gforth `see' shows you a reconstruction of the source code from
the executable code. Informations that were present in the source, but
not in the executable code, are lost (e.g., comments).
You can also decompile the predefined words:
see .
see +
File: gforth.info, Node: Stack-Effect Comments Tutorial, Next: Types Tutorial, Prev: Decompilation Tutorial, Up: Tutorial
Stack-Effect Comments
=====================
By convention the comment after the name of a definition describes
the stack effect: The part in from of the `--' describes the state of
the stack before the execution of the definition, i.e., the parameters
that are passed into the colon definition; the part behind the `--' is
the state of the stack after the execution of the definition, i.e., the
results of the definition. The stack comment only shows the top stack
items that the definition accesses and/or changes.
You should put a correct stack effect on every definition, even if
it is just `( -- )'. You should also add some descriptive comment to
more complicated words (I usually do this in the lines following `:').
If you don't do this, your code becomes unreadable (because you have to
work through every definition before you can understand any).
Assignment:
The stack effect of `swap' can be written like this: `x1 x2 -- x2
x1'. Describe the stack effect of `-', `drop', `dup', `over',
`rot', `nip', and `tuck'. Hint: When you are done, you can
compare your stack effects to those in this manual (*note Word
Index::).
Sometimes programmers put comments at various places in colon
definitions that describe the contents of the stack at that place (stack
comments); i.e., they are like the first part of a stack-effect
comment. E.g.,
: cubed ( n -- n^3 )
dup squared ( n n^2 ) * ;
In this case the stack comment is pretty superfluous, because the
word is simple enough. If you think it would be a good idea to add
such a comment to increase readability, you should also consider
factoring the word into several simpler words (*note Factoring:
Factoring Tutorial.), which typically eliminates the need for the stack
comment; however, if you decide not to refactor it, then having such a
comment is better than not having it.
The names of the stack items in stack-effect and stack comments in
the standard, in this manual, and in many programs specify the type
through a type prefix, similar to Fortran and Hungarian notation. The
most frequent prefixes are:
`n'
signed integer
`u'
unsigned integer
`c'
character
`f'
Boolean flags, i.e. `false' or `true'.
`a-addr,a-'
Cell-aligned address
`c-addr,c-'
Char-aligned address (note that a Char may have two bytes in
Windows NT)
`xt'
Execution token, same size as Cell
`w,x'
Cell, can contain an integer or an address. It usually takes 32,
64 or 16 bits (depending on your platform and Forth system). A
cell is more commonly known as machine word, but the term _word_
already means something different in Forth.
`d'
signed double-cell integer
`ud'
unsigned double-cell integer
`r'
Float (on the FP stack)
You can find a more complete list in *Note Notation::.
Assignment:
Write stack-effect comments for all definitions you have written
up to now.
File: gforth.info, Node: Types Tutorial, Next: Factoring Tutorial, Prev: Stack-Effect Comments Tutorial, Up: Tutorial
Types
=====
In Forth the names of the operations are not overloaded; so similar
operations on different types need different names; e.g., `+' adds
integers, and you have to use `f+' to add floating-point numbers. The
following prefixes are often used for related operations on different
types:
`(none)'
signed integer
`u'
unsigned integer
`c'
character
`d'
signed double-cell integer
`ud, du'
unsigned double-cell integer
`2'
two cells (not-necessarily double-cell numbers)
`m, um'
mixed single-cell and double-cell operations
`f'
floating-point (note that in stack comments `f' represents flags,
and `r' represents FP numbers).
If there are no differences between the signed and the unsigned
variant (e.g., for `+'), there is only the prefix-less variant.
Forth does not perform type checking, neither at compile time, nor at
run time. If you use the wrong oeration, the data are interpreted
incorrectly:
-1 u.
If you have only experience with type-checked languages until now,
and have heard how important type-checking is, don't panic! In my
experience (and that of other Forthers), type errors in Forth code are
usually easy to find (once you get used to it), the increased vigilance
of the programmer tends to catch some harder errors in addition to most
type errors, and you never have to work around the type system, so in
most situations the lack of type-checking seems to be a win (projects to
add type checking to Forth have not caught on).
File: gforth.info, Node: Factoring Tutorial, Next: Designing the stack effect Tutorial, Prev: Types Tutorial, Up: Tutorial
Factoring
=========
If you try to write longer definitions, you will soon find it hard to
keep track of the stack contents. Therefore, good Forth programmers
tend to write only short definitions (e.g., three lines). The art of
finding meaningful short definitions is known as factoring (as in
factoring polynomials).
Well-factored programs offer additional advantages: smaller, more
general words, are easier to test and debug and can be reused more and
better than larger, specialized words.
So, if you run into difficulties with stack management, when writing
code, try to define meaningful factors for the word, and define the word
in terms of those. Even if a factor contains only two words, it is
often helpful.
Good factoring is not easy, and it takes some practice to get the
knack for it; but even experienced Forth programmers often don't find
the right solution right away, but only when rewriting the program.
So, if you don't come up with a good solution immediately, keep trying,
don't despair.
File: gforth.info, Node: Designing the stack effect Tutorial, Next: Local Variables Tutorial, Prev: Factoring Tutorial, Up: Tutorial
Designing the stack effect
==========================
In other languages you can use an arbitrary order of parameters for a
function; and since there is only one result, you don't have to deal
with the order of results, either.
In Forth (and other stack-based languages, e.g., PostScript) the
parameter and result order of a definition is important and should be
designed well. The general guideline is to design the stack effect such
that the word is simple to use in most cases, even if that complicates
the implementation of the word. Some concrete rules are:
* Words consume all of their parameters (e.g., `.').
* If there is a convention on the order of parameters (e.g., from
mathematics or another programming language), stick with it (e.g.,
`-').
* If one parameter usually requires only a short computation (e.g.,
it is a constant), pass it on the top of the stack. Conversely,
parameters that usually require a long sequence of code to compute
should be passed as the bottom (i.e., first) parameter. This
makes the code easier to read, because reader does not need to
keep track of the bottom item through a long sequence of code (or,
alternatively, through stack manipulations). E.g., `!' (store,
*note Memory::) expects the address on top of the stack because it
is usually simpler to compute than the stored value (often the
address is just a variable).
* Similarly, results that are usually consumed quickly should be
returned on the top of stack, whereas a result that is often used
in long computations should be passed as bottom result. E.g., the
file words like `open-file' return the error code on the top of
stack, because it is usually consumed quickly by `throw';
moreover, the error code has to be checked before doing anything
with the other results.
These rules are just general guidelines, don't lose sight of the
overall goal to make the words easy to use. E.g., if the convention
rule conflicts with the computation-length rule, you might decide in
favour of the convention if the word will be used rarely, and in favour
of the computation-length rule if the word will be used frequently
(because with frequent use the cost of breaking the computation-length
rule would be quite high, and frequent use makes it easier to remember
an unconventional order).
File: gforth.info, Node: Local Variables Tutorial, Next: Conditional execution Tutorial, Prev: Designing the stack effect Tutorial, Up: Tutorial
Local Variables
===============
You can define local variables (_locals_) in a colon definition:
: swap { a b -- b a }
b a ;
1 2 swap .s 2drop
(If your Forth system does not support this syntax, include
`compat/anslocals.fs' first).
In this example `{ a b -- b a }' is the locals definition; it takes
two cells from the stack, puts the top of stack in `b' and the next
stack element in `a'. `--' starts a comment ending with `}'. After
the locals definition, using the name of the local will push its value
on the stack. You can leave the comment part (`-- b a') away:
: swap ( x1 x2 -- x2 x1 )
{ a b } b a ;
In Gforth you can have several locals definitions, anywhere in a
colon definition; in contrast, in a standard program you can have only
one locals definition per colon definition, and that locals definition
must be outside any controll structure.
With locals you can write slightly longer definitions without running
into stack trouble. However, I recommend trying to write colon
definitions without locals for exercise purposes to help you gain the
essential factoring skills.
Assignment:
Rewrite your definitions until now with locals
Reference: *Note Locals::.
File: gforth.info, Node: Conditional execution Tutorial, Next: Flags and Comparisons Tutorial, Prev: Local Variables Tutorial, Up: Tutorial
Conditional execution
=====================
In Forth you can use control structures only inside colon
definitions. An `if'-structure looks like this:
: abs ( n1 -- +n2 )
dup 0 < if
negate
endif ;
5 abs .
-5 abs .
`if' takes a flag from the stack. If the flag is non-zero (true),
the following code is performed, otherwise execution continues after the
`endif' (or `else'). `<' compares the top two stack elements and
prioduces a flag:
1 2 < .
2 1 < .
1 1 < .
Actually the standard name for `endif' is `then'. This tutorial
presents the examples using `endif', because this is often less
confusing for people familiar with other programming languages where
`then' has a different meaning. If your system does not have `endif',
define it with
: endif postpone then ; immediate
You can optionally use an `else'-part:
: min ( n1 n2 -- n )
2dup < if
drop
else
nip
endif ;
2 3 min .
3 2 min .
Assignment:
Write `min' without `else'-part (hint: what's the definition of
`nip'?).
Reference: *Note Selection::.
File: gforth.info, Node: Flags and Comparisons Tutorial, Next: General Loops Tutorial, Prev: Conditional execution Tutorial, Up: Tutorial
Flags and Comparisons
=====================
In a false-flag all bits are clear (0 when interpreted as integer).
In a canonical true-flag all bits are set (-1 as a twos-complement
signed integer); in many contexts (e.g., `if') any non-zero value is
treated as true flag.
false .
true .
true hex u. decimal
Comparison words produce canonical flags:
1 1 = .
1 0= .
0 1 < .
0 0 < .
-1 1 u< . \ type error, u< interprets -1 as large unsigned number
-1 1 < .
Gforth supports all combinations of the prefixes `0 u d d0 du f f0'
(or none) and the comparisons `= <> < > <= >='. Only a part of these
combinations are standard (for details see the standard, *Note Numeric
comparison::, *Note Floating Point:: or *Note Word Index::).
You can use `and or xor invert' can be used as operations on
canonical flags. Actually they are bitwise operations:
1 2 and .
1 2 or .
1 3 xor .
1 invert .
You can convert a zero/non-zero flag into a canonical flag with
`0<>' (and complement it on the way with `0=').
1 0= .
1 0<> .
You can use the all-bits-set feature of canonical flags and the
bitwise operation of the Boolean operations to avoid `if's:
: foo ( n1 -- n2 )
0= if
14
else
0
endif ;
0 foo .
1 foo .
: foo ( n1 -- n2 )
0= 14 and ;
0 foo .
1 foo .
Assignment:
Write `min' without `if'.
For reference, see *Note Boolean Flags::, *Note Numeric
comparison::, and *Note Bitwise operations::.
File: gforth.info, Node: General Loops Tutorial, Next: Counted loops Tutorial, Prev: Flags and Comparisons Tutorial, Up: Tutorial
General Loops
=============
The endless loop is the most simple one:
: endless ( -- )
0 begin
dup . 1+
again ;
endless
Terminate this loop by pressing `Ctrl-C' (in Gforth). `begin' does
nothing at run-time, `again' jumps back to `begin'.
A loop with one exit at any place looks like this:
: log2 ( +n1 -- n2 )
\ logarithmus dualis of n1>0, rounded down to the next integer
assert( dup 0> )
2/ 0 begin
over 0> while
1+ swap 2/ swap
repeat
nip ;
7 log2 .
8 log2 .
At run-time `while' consumes a flag; if it is 0, execution continues
behind the `repeat'; if the flag is non-zero, execution continues
behind the `while'. `Repeat' jumps back to `begin', just like `again'.
In Forth there are many combinations/abbreviations, like `1+'.
However, `2/' is not one of them; it shifts its argument right by one
bit (arithmetic shift right):
-5 2 / .
-5 2/ .
`assert(' is no standard word, but you can get it on systems other
then Gforth by including `compat/assert.fs'. You can see what it does
by trying
0 log2 .
Here's a loop with an exit at the end:
: log2 ( +n1 -- n2 )
\ logarithmus dualis of n1>0, rounded down to the next integer
assert( dup 0 > )
-1 begin
1+ swap 2/ swap
over 0 <=
until
nip ;
`Until' consumes a flag; if it is non-zero, execution continues at
the `begin', otherwise after the `until'.
Assignment:
Write a definition for computing the greatest common divisor.
Reference: *Note Simple Loops::.
File: gforth.info, Node: Counted loops Tutorial, Next: Recursion Tutorial, Prev: General Loops Tutorial, Up: Tutorial
Counted loops
=============
: ^ ( n1 u -- n )
\ n = the uth power of u1
1 swap 0 u+do
over *
loop
nip ;
3 2 ^ .
4 3 ^ .
`U+do' (from `compat/loops.fs', if your Forth system doesn't have
it) takes two numbers of the stack `( u3 u4 -- )', and then performs
the code between `u+do' and `loop' for `u3-u4' times (or not at all, if
`u3-u4<0').
You can see the stack effect design rules at work in the stack
effect of the loop start words: Since the start value of the loop is
more frequently constant than the end value, the start value is passed
on the top-of-stack.
You can access the counter of a counted loop with `i':
: fac ( u -- u! )
1 swap 1+ 1 u+do
i *
loop ;
5 fac .
7 fac .
There is also `+do', which expects signed numbers (important for
deciding whether to enter the loop).
Assignment:
Write a definition for computing the nth Fibonacci number.
You can also use increments other than 1:
: up2 ( n1 n2 -- )
+do
i .
2 +loop ;
10 0 up2
: down2 ( n1 n2 -- )
-do
i .
2 -loop ;
0 10 down2
Reference: *Note Counted Loops::.
File: gforth.info, Node: Recursion Tutorial, Next: Leaving definitions or loops Tutorial, Prev: Counted loops Tutorial, Up: Tutorial
Recursion
=========
Usually the name of a definition is not visible in the definition;
but earlier definitions are usually visible:
1 0 / . \ "Floating-point unidentified fault" in Gforth on most platforms
: / ( n1 n2 -- n )
dup 0= if
-10 throw \ report division by zero
endif
/ \ old version
;
1 0 /
For recursive definitions you can use `recursive' (non-standard) or
`recurse':
: fac1 ( n -- n! ) recursive
dup 0> if
dup 1- fac1 *
else
drop 1
endif ;
7 fac1 .
: fac2 ( n -- n! )
dup 0> if
dup 1- recurse *
else
drop 1
endif ;
8 fac2 .
Assignment:
Write a recursive definition for computing the nth Fibonacci
number.
Reference (including indirect recursion): *Note Calls and returns::.
File: gforth.info, Node: Leaving definitions or loops Tutorial, Next: Return Stack Tutorial, Prev: Recursion Tutorial, Up: Tutorial
Leaving definitions or loops
============================
`EXIT' exits the current definition right away. For every counted
loop that is left in this way, an `UNLOOP' has to be performed before
the `EXIT':
: ...
... u+do
... if
... unloop exit
endif
...
loop
... ;
`LEAVE' leaves the innermost counted loop right away:
: ...
... u+do
... if
... leave
endif
...
loop
... ;
Reference: *Note Calls and returns::, *Note Counted Loops::.
File: gforth.info, Node: Return Stack Tutorial, Next: Memory Tutorial, Prev: Leaving definitions or loops Tutorial, Up: Tutorial
Return Stack
============
In addition to the data stack Forth also has a second stack, the
return stack; most Forth systems store the return addresses of
procedure calls there (thus its name). Programmers can also use this
stack:
: foo ( n1 n2 -- )
.s
>r .s
r@ .
>r .s
r@ .
r> .
r@ .
r> . ;
1 2 foo
`>r' takes an element from the data stack and pushes it onto the
return stack; conversely, `r>' moves an elementm from the return to the
data stack; `r@' pushes a copy of the top of the return stack on the
return stack.
Forth programmers usually use the return stack for storing data
temporarily, if using the data stack alone would be too complex, and
factoring and locals are not an option:
: 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
rot >r rot r> ;
The return address of the definition and the loop control parameters
of counted loops usually reside on the return stack, so you have to take
all items, that you have pushed on the return stack in a colon
definition or counted loop, from the return stack before the definition
or loop ends. You cannot access items that you pushed on the return
stack outside some definition or loop within the definition of loop.
If you miscount the return stack items, this usually ends in a crash:
: crash ( n -- )
>r ;
5 crash
You cannot mix using locals and using the return stack (according to
the standard; Gforth has no problem). However, they solve the same
problems, so this shouldn't be an issue.
Assignment:
Can you rewrite any of the definitions you wrote until now in a
better way using the return stack?
Reference: *Note Return stack::.
File: gforth.info, Node: Memory Tutorial, Next: Characters and Strings Tutorial, Prev: Return Stack Tutorial, Up: Tutorial
Memory
======
You can create a global variable `v' with
variable v ( -- addr )
`v' pushes the address of a cell in memory on the stack. This cell
was reserved by `variable'. You can use `!' (store) to store values
into this cell and `@' (fetch) to load the value from the stack into
memory:
v .
5 v ! .s
v @ .
You can see a raw dump of memory with `dump':
v 1 cells .s dump
`Cells ( n1 -- n2 )' gives you the number of bytes (or, more
generally, address units (aus)) that `n1 cells' occupy. You can also
reserve more memory:
create v2 20 cells allot
v2 20 cells dump
creates a word `v2' and reserves 20 uninitialized cells; the address
pushed by `v2' points to the start of these 20 cells. You can use
address arithmetic to access these cells:
3 v2 5 cells + !
v2 20 cells dump
You can reserve and initialize memory with `,':
create v3
5 , 4 , 3 , 2 , 1 ,
v3 @ .
v3 cell+ @ .
v3 2 cells + @ .
v3 5 cells dump
Assignment:
Write a definition `vsum ( addr u -- n )' that computes the sum of
`u' cells, with the first of these cells at `addr', the next one
at `addr cell+' etc.
You can also reserve memory without creating a new word:
here 10 cells allot .
here .
`Here' pushes the start address of the memory area. You should
store it somewhere, or you will have a hard time finding the memory area
again.
`Allot' manages dictionary memory. The dictionary memory contains
the system's data structures for words etc. on Gforth and most other
Forth systems. It is managed like a stack: You can free the memory that
you have just `allot'ed with
-10 cells allot
here .
Note that you cannot do this if you have created a new word in the
meantime (because then your `allot'ed memory is no longer on the top of
the dictionary "stack").
Alternatively, you can use `allocate' and `free' which allow freeing
memory in any order:
10 cells allocate throw .s
20 cells allocate throw .s
swap
free throw
free throw
The `throw's deal with errors (e.g., out of memory).
And there is also a garbage collector
(http://www.complang.tuwien.ac.at/forth/garbage-collection.zip), which
eliminates the need to `free' memory explicitly.
Reference: *Note Memory::.
File: gforth.info, Node: Characters and Strings Tutorial, Next: Alignment Tutorial, Prev: Memory Tutorial, Up: Tutorial
Characters and Strings
======================
On the stack characters take up a cell, like numbers. In memory they
have their own size (one 8-bit byte on most systems), and therefore
require their own words for memory access:
create v4
104 c, 97 c, 108 c, 108 c, 111 c,
v4 4 chars + c@ .
v4 5 chars dump
The preferred representation of strings on the stack is `addr
u-count', where `addr' is the address of the first character and
`u-count' is the number of characters in the string.
v4 5 type
You get a string constant with
s" hello, world" .s
type
Make sure you have a space between `s"' and the string; `s"' is a
normal Forth word and must be delimited with white space (try what
happens when you remove the space).
However, this interpretive use of `s"' is quite restricted: the
string exists only until the next call of `s"' (some Forth systems keep
more than one of these strings, but usually they still have a limited
lifetime).
s" hello," s" world" .s
type
type
You can also use `s"' in a definition, and the resulting strings
then live forever (well, for as long as the definition):
: foo s" hello," s" world" ;
foo .s
type
type
Assignment:
`Emit ( c -- )' types `c' as character (not a number). Implement
`type ( addr u -- )'.
Reference: *Note Memory Blocks::.
File: gforth.info, Node: Alignment Tutorial, Next: Files Tutorial, Prev: Characters and Strings Tutorial, Up: Tutorial
Alignment
=========
On many processors cells have to be aligned in memory, if you want to
access them with `@' and `!' (and even if the processor does not
require alignment, access to aligned cells is faster).
`Create' aligns `here' (i.e., the place where the next allocation
will occur, and that the `create'd word points to). Likewise, the
memory produced by `allocate' starts at an aligned address. Adding a
number of `cells' to an aligned address produces another aligned
address.
However, address arithmetic involving `char+' and `chars' can create
an address that is not cell-aligned. `Aligned ( addr -- a-addr )'
produces the next aligned address:
v3 char+ aligned .s @ .
v3 char+ .s @ .
Similarly, `align' advances `here' to the next aligned address:
create v5 97 c,
here .
align here .
1000 ,
Note that you should use aligned addresses even if your processor
does not require them, if you want your program to be portable.
Reference: *Note Address arithmetic::.
File: gforth.info, Node: Files Tutorial, Next: Interpretation and Compilation Semantics and Immediacy Tutorial, Prev: Alignment Tutorial, Up: Tutorial
Files
=====
This section gives a short introduction into how to use files inside
Forth. It's broken up into five easy steps:
1. Opened an ASCII text file for input
2. Opened a file for output
3. Read input file until string matched (or some other condition
matched)
4. Wrote some lines from input ( modified or not) to output
5. Closed the files.
Open file for input
-------------------
s" foo.in" r/o open-file throw Value fd-in
Create file for output
----------------------
s" foo.out" w/o create-file throw Value fd-out
The available file modes are r/o for read-only access, r/w for
read-write access, and w/o for write-only access. You could open both
files with r/w, too, if you like. All file words return error codes; for
most applications, it's best to pass there error codes with `throw' to
the outer error handler.
If you want words for opening and assigning, define them as follows:
0 Value fd-in
0 Value fd-out
: open-input ( addr u -- ) r/o open-file throw to fd-in ;
: open-output ( addr u -- ) w/o create-file throw to fd-out ;
Usage example:
s" foo.in" open-input
s" foo.out" open-output
Scan file for a particular line
-------------------------------
256 Constant max-line
Create line-buffer max-line 2 + allot
: scan-file ( addr u -- )
begin
line-buffer max-line fd-in read-line throw
while
>r 2dup line-buffer r> compare 0=
until
else
drop
then
2drop ;
`read-line ( addr u1 fd -- u2 flag ior )' reads up to u1 bytes into
the buffer at addr, and returns the number of bytes read, a flag that is
false when the end of file is reached, and an error code.
`compare ( addr1 u1 addr2 u2 -- n )' compares two strings and
returns zero if both strings are equal. It returns a positive number if
the first string is lexically greater, a negative if the second string
is lexically greater.
We haven't seen this loop here; it has two exits. Since the `while'
exits with the number of bytes read on the stack, we have to clean up
that separately; that's after the `else'.
Usage example:
s" The text I search is here" scan-file
Copy input to output
--------------------
: copy-file ( -- )
begin
line-buffer max-line fd-in read-line throw
while
line-buffer swap fd-out write-file throw
repeat ;
Close files
-----------
fd-in close-file throw
fd-out close-file throw
Likewise, you can put that into definitions, too:
: close-input ( -- ) fd-in close-file throw ;
: close-output ( -- ) fd-out close-file throw ;
Assignment:
How could you modify `copy-file' so that it copies until a second
line is matched? Can you write a program that extracts a section
of a text file, given the line that starts and the line that
terminates that section?
File: gforth.info, Node: Interpretation and Compilation Semantics and Immediacy Tutorial, Next: Execution Tokens Tutorial, Prev: Files Tutorial, Up: Tutorial
Interpretation and Compilation Semantics and Immediacy
======================================================
When a word is compiled, it behaves differently from being
interpreted. E.g., consider `+':
1 2 + .
: foo + ;
These two behaviours are known as compilation and interpretation
semantics. For normal words (e.g., `+'), the compilation semantics is
to append the interpretation semantics to the currently defined word
(`foo' in the example above). I.e., when `foo' is executed later, the
interpretation semantics of `+' (i.e., adding two numbers) will be
performed.
However, there are words with non-default compilation semantics,
e.g., the control-flow words like `if'. You can use `immediate' to
change the compilation semantics of the last defined word to be equal to
the interpretation semantics:
: [FOO] ( -- )
5 . ; immediate
[FOO]
: bar ( -- )
[FOO] ;
bar
see bar
Two conventions to mark words with non-default compilation semnatics
are names with brackets (more frequently used) and to write them all in
upper case (less frequently used).
In Gforth (and many other systems) you can also remove the
interpretation semantics with `compile-only' (the compilation semantics
is derived from the original interpretation semantics):
: flip ( -- )
6 . ; compile-only \ but not immediate
flip
: flop ( -- )
flip ;
flop
In this example the interpretation semantics of `flop' is equal to
the original interpretation semantics of `flip'.
The text interpreter has two states: in interpret state, it performs
the interpretation semantics of words it encounters; in compile state,
it performs the compilation semantics of these words.
Among other things, `:' switches into compile state, and `;'
switches back to interpret state. They contain the factors `]' (switch
to compile state) and `[' (switch to interpret state), that do nothing
but switch the state.
: xxx ( -- )
[ 5 . ]
;
xxx
see xxx
These brackets are also the source of the naming convention mentioned
above.
Reference: *Note Interpretation and Compilation Semantics::.
File: gforth.info, Node: Execution Tokens Tutorial, Next: Exceptions Tutorial, Prev: Interpretation and Compilation Semantics and Immediacy Tutorial, Up: Tutorial
Execution Tokens
================
`' word' gives you the execution token (XT) of a word. The XT is a
cell representing the interpretation semantics of a word. You can
execute this semantics with `execute':
' + .s
1 2 rot execute .
The XT is similar to a function pointer in C. However, parameter
passing through the stack makes it a little more flexible:
: map-array ( ... addr u xt -- ... )
\ executes xt ( ... x -- ... ) for every element of the array starting
\ at addr and containing u elements
{ xt }
cells over + swap ?do
i @ xt execute
1 cells +loop ;
create a 3 , 4 , 2 , -1 , 4 ,
a 5 ' . map-array .s
0 a 5 ' + map-array .
s" max-n" environment? drop .s
a 5 ' min map-array .
You can use map-array with the XTs of words that consume one element
more than they produce. In theory you can also use it with other XTs,
but the stack effect then depends on the size of the array, which is
hard to understand.
Since XTs are cell-sized, you can store them in memory and manipulate
them on the stack like other cells. You can also compile the XT into a
word with `compile,':
: foo1 ( n1 n2 -- n )
[ ' + compile, ] ;
see foo
This is non-standard, because `compile,' has no compilation
semantics in the standard, but it works in good Forth systems. For the
broken ones, use
: [compile,] compile, ; immediate
: foo1 ( n1 n2 -- n )
[ ' + ] [compile,] ;
see foo
`'' is a word with default compilation semantics; it parses the next
word when its interpretation semantics are executed, not during
compilation:
: foo ( -- xt )
' ;
see foo
: bar ( ... "word" -- ... )
' execute ;
see bar
1 2 bar + .
You often want to parse a word during compilation and compile its XT
so it will be pushed on the stack at run-time. `[']' does this:
: xt-+ ( -- xt )
['] + ;
see xt-+
1 2 xt-+ execute .
Many programmers tend to see `'' and the word it parses as one unit,
and expect it to behave like `[']' when compiled, and are confused by
the actual behaviour. If you are, just remember that the Forth system
just takes `'' as one unit and has no idea that it is a parsing word
(attempts to convenience programmers in this issue have usually
resulted in even worse pitfalls, see `State'-smartness--Why it is evil
and How to Exorcise it
(http://www.complang.tuwien.ac.at/papers/ertl98.ps.gz)).
Note that the state of the interpreter does not come into play when
creating and executing XTs. I.e., even when you execute `'' in compile
state, it still gives you the interpretation semantics. And whatever
that state is, `execute' performs the semantics represented by the XT
(i.e., for XTs produced with `'' the interpretation semantics).
Reference: *Note Tokens for Words::.
File: gforth.info, Node: Exceptions Tutorial, Next: Defining Words Tutorial, Prev: Execution Tokens Tutorial, Up: Tutorial
Exceptions
==========
`throw ( n -- )' causes an exception unless n is zero.
100 throw .s
0 throw .s
`catch ( ... xt -- ... n )' behaves similar to `execute', but it
catches exceptions and pushes the number of the exception on the stack
(or 0, if the xt executed without exception). If there was an
exception, the stacks have the same depth as when entering `catch':
.s
3 0 ' / catch .s
3 2 ' / catch .s
Assignment:
Try the same with `execute' instead of `catch'.
`Throw' always jumps to the dynamically next enclosing `catch', even
if it has to leave several call levels to achieve this:
: foo 100 throw ;
: foo1 foo ." after foo" ;
: bar ['] foo1 catch ;
bar .
It is often important to restore a value upon leaving a definition,
even if the definition is left through an exception. You can ensure
this like this:
: ...
save-x
['] word-changing-x catch ( ... n )
restore-x
( ... n ) throw ;
Gforth provides an alternative syntax in addition to `catch': `try
... recover ... endtry'. If the code between `try' and `recover' has
an exception, the stack depths are restored, the exception number is
pushed on the stack, and the code between `recover' and `endtry' is
performed. E.g., the definition for `catch' is
: catch ( x1 .. xn xt -- y1 .. ym 0 / z1 .. zn error ) \ exception
try
execute 0
recover
nip
endtry ;
The equivalent to the restoration code above is
: ...
save-x
try
word-changing-x 0
recover endtry
restore-x
throw ;
This works if `word-changing-x' does not change the stack depth,
otherwise you should add some code between `recover' and `endtry' to
balance the stack.
Reference: *Note Exception Handling::.
File: gforth.info, Node: Defining Words Tutorial, Next: Arrays and Records Tutorial, Prev: Exceptions Tutorial, Up: Tutorial
Defining Words
==============
`:', `create', and `variable' are definition words: They define
other words. `Constant' is another definition word:
5 constant foo
foo .
You can also use the prefixes `2' (double-cell) and `f' (floating
point) with `variable' and `constant'.
You can also define your own defining words. E.g.:
: variable ( "name" -- )
create 0 , ;
You can also define defining words that create words that do
something other than just producing their address:
: constant ( n "name" -- )
create ,
does> ( -- n )
( addr ) @ ;
5 constant foo
foo .
The definition of `constant' above ends at the `does>'; i.e.,
`does>' replaces `;', but it also does something else: It changes the
last defined word such that it pushes the address of the body of the
word and then performs the code after the `does>' whenever it is called.
In the example above, `constant' uses `,' to store 5 into the body
of `foo'. When `foo' executes, it pushes the address of the body onto
the stack, then (in the code after the `does>') fetches the 5 from
there.
The stack comment near the `does>' reflects the stack effect of the
defined word, not the stack effect of the code after the `does>' (the
difference is that the code expects the address of the body that the
stack comment does not show).
You can use these definition words to do factoring in cases that
involve (other) definition words. E.g., a field offset is always added
to an address. Instead of defining
2 cells constant offset-field1
and using this like
( addr ) offset-field1 +
you can define a definition word
: simple-field ( n "name" -- )
create ,
does> ( n1 -- n1+n )
( addr ) @ + ;
Definition and use of field offsets now look like this:
2 cells simple-field field1
create mystruct 4 cells allot
mystruct .s field1 .s drop
If you want to do something with the word without performing the code
after the `does>', you can access the body of a `create'd word with
`>body ( xt -- addr )':
: value ( n "name" -- )
create ,
does> ( -- n1 )
@ ;
: to ( n "name" -- )
' >body ! ;
5 value foo
foo .
7 to foo
foo .
Assignment:
Define `defer ( "name" -- )', which creates a word that stores an
XT (at the start the XT of `abort'), and upon execution `execute's
the XT. Define `is ( xt "name" -- )' that stores `xt' into
`name', a word defined with `defer'. Indirect recursion is one
application of `defer'.
Reference: *Note User-defined Defining Words::.
File: gforth.info, Node: Arrays and Records Tutorial, Next: POSTPONE Tutorial, Prev: Defining Words Tutorial, Up: Tutorial
Arrays and Records
==================
Forth has no standard words for defining data structures such as
arrays and records (structs in C terminology), but you can build them
yourself based on address arithmetic. You can also define words for
defining arrays and records (*note Defining Words: Defining Words
Tutorial.).
One of the first projects a Forth newcomer sets out upon when
learning about defining words is an array defining word (possibly for
n-dimensional arrays). Go ahead and do it, I did it, too; you will
learn something from it. However, don't be disappointed when you later
learn that you have little use for these words (inappropriate use would
be even worse). I have not yet found a set of useful array words yet;
the needs are just too diverse, and named, global arrays (the result of
naive use of defining words) are often not flexible enough (e.g.,
consider how to pass them as parameters). Another such project is a set
of words to help dealing with strings.
On the other hand, there is a useful set of record words, and it has
been defined in `compat/struct.fs'; these words are predefined in
Gforth. They are explained in depth elsewhere in this manual (see
*note Structures::). The `simple-field' example above is simplified
variant of fields in this package.
File: gforth.info, Node: POSTPONE Tutorial, Next: Literal Tutorial, Prev: Arrays and Records Tutorial, Up: Tutorial
`POSTPONE'
==========
You can compile the compilation semantics (instead of compiling the
interpretation semantics) of a word with `POSTPONE':
: MY-+ ( Compilation: -- ; Run-time of compiled code: n1 n2 -- n )
POSTPONE + ; immediate
: foo ( n1 n2 -- n )
MY-+ ;
1 2 foo .
see foo
During the definition of `foo' the text interpreter performs the
compilation semantics of `MY-+', which performs the compilation
semantics of `+', i.e., it compiles `+' into `foo'.
This example also displays separate stack comments for the
compilation semantics and for the stack effect of the compiled code.
For words with default compilation semantics these stack effects are
usually not displayed; the stack effect of the compilation semantics is
always `( -- )' for these words, the stack effect for the compiled code
is the stack effect of the interpretation semantics.
Note that the state of the interpreter does not come into play when
performing the compilation semantics in this way. You can also perform
it interpretively, e.g.:
: foo2 ( n1 n2 -- n )
[ MY-+ ] ;
1 2 foo .
see foo
However, there are some broken Forth systems where this does not
always work, and therefore this practice was been declared non-standard
in 1999.
Here is another example for using `POSTPONE':
: MY-- ( Compilation: -- ; Run-time of compiled code: n1 n2 -- n )
POSTPONE negate POSTPONE + ; immediate compile-only
: bar ( n1 n2 -- n )
MY-- ;
2 1 bar .
see bar
You can define `ENDIF' in this way:
: ENDIF ( Compilation: orig -- )
POSTPONE then ; immediate
Assignment:
Write `MY-2DUP' that has compilation semantics equivalent to
`2dup', but compiles `over over'.
File: gforth.info, Node: Literal Tutorial, Next: Advanced macros Tutorial, Prev: POSTPONE Tutorial, Up: Tutorial
`Literal'
=========
You cannot `POSTPONE' numbers:
: [FOO] POSTPONE 500 ; immediate
Instead, you can use `LITERAL (compilation: n --; run-time: -- n )':
: [FOO] ( compilation: --; run-time: -- n )
500 POSTPONE literal ; immediate
: flip [FOO] ;
flip .
see flip
`LITERAL' consumes a number at compile-time (when it's compilation
semantics are executed) and pushes it at run-time (when the code it
compiled is executed). A frequent use of `LITERAL' is to compile a
number computed at compile time into the current word:
: bar ( -- n )
[ 2 2 + ] literal ;
see bar
Assignment:
Write `]L' which allows writing the example above as `: bar ( -- n
) [ 2 2 + ]L ;'
File: gforth.info, Node: Advanced macros Tutorial, Next: Compilation Tokens Tutorial, Prev: Literal Tutorial, Up: Tutorial
Advanced macros
===============
Reconsider `map-array' from *Note Execution Tokens: Execution Tokens
Tutorial. It frequently performs `execute', a relatively expensive
operation in some Forth implementations. You can use `compile,' and
`POSTPONE' to eliminate these `execute's and produce a word that
contains the word to be performed directly:
: compile-map-array ( compilation: xt -- ; run-time: ... addr u -- ... )
\ at run-time, execute xt ( ... x -- ... ) for each element of the
\ array beginning at addr and containing u elements
{ xt }
POSTPONE cells POSTPONE over POSTPONE + POSTPONE swap POSTPONE ?do
POSTPONE i POSTPONE @ xt compile,
1 cells POSTPONE literal POSTPONE +loop ;
: sum-array ( addr u -- n )
0 rot rot [ ' + compile-map-array ] ;
see sum-array
a 5 sum-array .
You can use the full power of Forth for generating the code; here's
an example where the code is generated in a loop:
: compile-vmul-step ( compilation: n --; run-time: n1 addr1 -- n2 addr2 )
\ n2=n1+(addr1)*n, addr2=addr1+cell
POSTPONE tuck POSTPONE @
POSTPONE literal POSTPONE * POSTPONE +
POSTPONE swap POSTPONE cell+ ;
: compile-vmul ( compilation: addr1 u -- ; run-time: addr2 -- n )
\ n=v1*v2 (inner product), where the v_i are represented as addr_i u
0 postpone literal postpone swap
[ ' compile-vmul-step compile-map-array ]
postpone drop ;
see compile-vmul
: a-vmul ( addr -- n )
\ n=a*v, where v is a vector that's as long as a and starts at addr
[ a 5 compile-vmul ] ;
see a-vmul
a a-vmul .
This example uses `compile-map-array' to show off, but you could
also use `map-array' instead (try it now!).
You can use this technique for efficient multiplication of large
matrices. In matrix multiplication, you multiply every line of one
matrix with every column of the other matrix. You can generate the code
for one line once, and use it for every column. The only downside of
this technique is that it is cumbersome to recover the memory consumed
by the generated code when you are done (and in more complicated cases
it is not possible portably).
File: gforth.info, Node: Compilation Tokens Tutorial, Next: Wordlists and Search Order Tutorial, Prev: Advanced macros Tutorial, Up: Tutorial
Compilation Tokens
==================
This section is Gforth-specific. You can skip it.
`' word compile,' compiles the interpretation semantics. For words
with default compilation semantics this is the same as performing the
compilation semantics. To represent the compilation semantics of other
words (e.g., words like `if' that have no interpretation semantics),
Gforth has the concept of a compilation token (CT, consisting of two
cells), and words `comp'' and `[comp']'. You can perform the
compilation semantics represented by a CT with `execute':
: foo2 ( n1 n2 -- n )
[ comp' + execute ] ;
see foo
You can compile the compilation semantics represented by a CT with
`postpone,':
: foo3 ( -- )
[ comp' + postpone, ] ;
see foo3
`[ comp' word postpone, ]' is equivalent to `POSTPONE word'.
`comp'' is particularly useful for words that have no interpretation
semantics:
' if
comp' if .s 2drop
Reference: *Note Tokens for Words::.
File: gforth.info, Node: Wordlists and Search Order Tutorial, Prev: Compilation Tokens Tutorial, Up: Tutorial
Wordlists and Search Order
==========================
The dictionary is not just a memory area that allows you to allocate
memory with `allot', it also contains the Forth words, arranged in
several wordlists. When searching for a word in a wordlist,
conceptually you start searching at the youngest and proceed towards
older words (in reality most systems nowadays use hash-tables); i.e., if
you define a word with the same name as an older word, the new word
shadows the older word.
Which wordlists are searched in which order is determined by the
search order. You can display the search order with `order'. It
displays first the search order, starting with the wordlist searched
first, then it displays the wordlist that will contain newly defined
words.
You can create a new, empty wordlist with `wordlist ( -- wid )':
wordlist constant mywords
`Set-current ( wid -- )' sets the wordlist that will contain newly
defined words (the _current_ wordlist):
mywords set-current
order
Gforth does not display a name for the wordlist in `mywords' because
this wordlist was created anonymously with `wordlist'.
You can get the current wordlist with `get-current ( -- wid)'. If
you want to put something into a specific wordlist without overall
effect on the current wordlist, this typically looks like this:
get-current mywords set-current ( wid )
create someword
( wid ) set-current
You can write the search order with `set-order ( wid1 .. widn n --
)' and read it with `get-order ( -- wid1 .. widn n )'. The first
searched wordlist is topmost.
get-order mywords swap 1+ set-order
order
Yes, the order of wordlists in the output of `order' is reversed
from stack comments and the output of `.s' and thus unintuitive.
Assignment:
Define `>order ( wid -- )' with adds `wid' as first searched
wordlist to the search order. Define `previous ( -- )', which
removes the first searched wordlist from the search order.
Experiment with boundary conditions (you will see some crashes or
situations that are hard or impossible to leave).
The search order is a powerful foundation for providing features
similar to Modula-2 modules and C++ namespaces. However, trying to
modularize programs in this way has disadvantages for debugging and
reuse/factoring that overcome the advantages in my experience (I don't
do huge projects, though). These disadvantages are not so clear in
other languages/programming environments, because these languages are
not so strong in debugging and reuse.
Reference: *Note Word Lists::.
File: gforth.info, Node: Introduction, Next: Words, Prev: Tutorial, Up: Top
An Introduction to ANS Forth
****************************
The difference of this chapter from the Tutorial (*note Tutorial::)
is that it is slower-paced in its examples, but uses them to dive deep
into explaining Forth internals (not covered by the Tutorial). Apart
from that, this chapter covers far less material. It is suitable for
reading without using a computer.
The primary purpose of this manual is to document Gforth. However,
since Forth is not a widely-known language and there is a lack of
up-to-date teaching material, it seems worthwhile to provide some
introductory material. For other sources of Forth-related information,
see *Note Forth-related information::.
The examples in this section should work on any ANS Forth; the
output shown was produced using Gforth. Each example attempts to
reproduce the exact output that Gforth produces. If you try out the
examples (and you should), what you should type is shown `like this'
and Gforth's response is shown `like this'. The single exception is
that, where the example shows <RET> it means that you should press the
"carriage return" key. Unfortunately, some output formats for this
manual cannot show the difference between `this' and `this' which will
make trying out the examples harder (but not impossible).
Forth is an unusual language. It provides an interactive development
environment which includes both an interpreter and compiler. Forth
programming style encourages you to break a problem down into many
small fragments ("factoring"), and then to develop and test each
fragment interactively. Forth advocates assert that breaking the
edit-compile-test cycle used by conventional programming languages can
lead to great productivity improvements.
* Menu:
* Introducing the Text Interpreter::
* Stacks and Postfix notation::
* Your first definition::
* How does that work?::
* Forth is written in Forth::
* Review - elements of a Forth system::
* Where to go next::
* Exercises::
File: gforth.info, Node: Introducing the Text Interpreter, Next: Stacks and Postfix notation, Prev: Introduction, Up: Introduction
Introducing the Text Interpreter
================================
When you invoke the Forth image, you will see a startup banner
printed and nothing else (if you have Gforth installed on your system,
try invoking it now, by typing `gforth<RET>'). Forth is now running its
command line interpreter, which is called the "Text Interpreter" (also
known as the "Outer Interpreter"). (You will learn a lot about the
text interpreter as you read through this chapter, for more detail
*note The Text Interpreter::).
Although it's not obvious, Forth is actually waiting for your input.
Type a number and press the <RET> key:
45<RET> ok
Rather than give you a prompt to invite you to input something, the
text interpreter prints a status message after it has processed a line
of input. The status message in this case ("` ok'" followed by
carriage-return) indicates that the text interpreter was able to process
all of your input successfully. Now type something illegal:
qwer341<RET>
:1: Undefined word
qwer341
^^^^^^^
$400D2BA8 Bounce
$400DBDA8 no.extensions
The exact text, other than the "Undefined word" may differ slightly
on your system, but the effect is the same; when the text interpreter
detects an error, it discards any remaining text on a line, resets
certain internal state and prints an error message. For a detailed
description of error messages see *Note Error messages::.
The text interpreter waits for you to press carriage-return, and then
processes your input line. Starting at the beginning of the line, it
breaks the line into groups of characters separated by spaces. For each
group of characters in turn, it makes two attempts to do something:
* It tries to treat it as a command. It does this by searching a
"name dictionary". If the group of characters matches an entry in
the name dictionary, the name dictionary provides the text
interpreter with information that allows the text interpreter
perform some actions. In Forth jargon, we say that the group of
characters names a "word", that the dictionary search returns an
"execution token (xt)" corresponding to the "definition" of the
word, and that the text interpreter executes the xt. Often, the
terms "word" and "definition" are used interchangeably.
* If the text interpreter fails to find a match in the name
dictionary, it tries to treat the group of characters as a number
in the current number base (when you start up Forth, the current
number base is base 10). If the group of characters legitimately
represents a number, the text interpreter pushes the number onto a
stack (we'll learn more about that in the next section).
If the text interpreter is unable to do either of these things with
any group of characters, it discards the group of characters and the
rest of the line, then prints an error message. If the text interpreter
reaches the end of the line without error, it prints the status message
"` ok'" followed by carriage-return.
This is the simplest command we can give to the text interpreter:
<RET> ok
The text interpreter did everything we asked it to do (nothing)
without an error, so it said that everything is "` ok'". Try a slightly
longer command:
12 dup fred dup<RET>
:1: Undefined word
12 dup fred dup
^^^^
$400D2BA8 Bounce
$400DBDA8 no.extensions
When you press the carriage-return key, the text interpreter starts
to work its way along the line:
* When it gets to the space after the `2', it takes the group of
characters `12' and looks them up in the name dictionary(1). There
is no match for this group of characters in the name dictionary,
so it tries to treat them as a number. It is able to do this
successfully, so it puts the number, 12, "on the stack" (whatever
that means).
* The text interpreter resumes scanning the line and gets the next
group of characters, `dup'. It looks it up in the name dictionary
and (you'll have to take my word for this) finds it, and executes
the word `dup' (whatever that means).
* Once again, the text interpreter resumes scanning the line and
gets the group of characters `fred'. It looks them up in the name
dictionary, but can't find them. It tries to treat them as a
number, but they don't represent any legal number.
At this point, the text interpreter gives up and prints an error
message. The error message shows exactly how far the text interpreter
got in processing the line. In particular, it shows that the text
interpreter made no attempt to do anything with the final character
group, `dup', even though we have good reason to believe that the text
interpreter would have no problem looking that word up and executing it
a second time.
---------- Footnotes ----------
(1) We can't tell if it found them or not, but assume for now that
it did not
File: gforth.info, Node: Stacks and Postfix notation, Next: Your first definition, Prev: Introducing the Text Interpreter, Up: Introduction
Stacks, postfix notation and parameter passing
==============================================
In procedural programming languages (like C and Pascal), the
building-block of programs is the "function" or "procedure". These
functions or procedures are called with "explicit parameters". For
example, in C we might write:
total = total + new_volume(length,height,depth);
where new_volume is a function-call to another piece of code, and total,
length, height and depth are all variables. length, height and depth are
parameters to the function-call.
In Forth, the equivalent of the function or procedure is the
"definition" and parameters are implicitly passed between definitions
using a shared stack that is visible to the programmer. Although Forth
does support variables, the existence of the stack means that they are
used far less often than in most other programming languages. When the
text interpreter encounters a number, it will place ("push") it on the
stack. There are several stacks (the actual number is
implementation-dependent ...) and the particular stack used for any
operation is implied unambiguously by the operation being performed.
The stack used for all integer operations is called the "data stack"
and, since this is the stack used most commonly, references to "the
data stack" are often abbreviated to "the stack".
The stacks have a last-in, first-out (LIFO) organisation. If you
type:
1 2 3<RET> ok
Then this instructs the text interpreter to placed three numbers on
the (data) stack. An analogy for the behaviour of the stack is to take a
pack of playing cards and deal out the ace (1), 2 and 3 into a pile on
the table. The 3 was the last card onto the pile ("last-in") and if you
take a card off the pile then, unless you're prepared to fiddle a bit,
the card that you take off will be the 3 ("first-out"). The number that
will be first-out of the stack is called the "top of stack", which is
often abbreviated to "TOS".
To understand how parameters are passed in Forth, consider the
behaviour of the definition `+' (pronounced "plus"). You will not be
surprised to learn that this definition performs addition. More
precisely, it adds two number together and produces a result. Where does
it get the two numbers from? It takes the top two numbers off the
stack. Where does it place the result? On the stack. You can act-out the
behaviour of `+' with your playing cards like this:
* Pick up two cards from the stack on the table
* Stare at them intently and ask yourself "what is the sum of these
two numbers"
* Decide that the answer is 5
* Shuffle the two cards back into the pack and find a 5
* Put a 5 on the remaining ace that's on the table.
If you don't have a pack of cards handy but you do have Forth
running, you can use the definition `.s' to show the current state of
the stack, without affecting the stack. Type:
clearstack 1 2 3<RET> ok
.s<RET> <3> 1 2 3 ok
The text interpreter looks up the word `clearstack' and executes it;
it tidies up the stack and removes any entries that may have been left
on it by earlier examples. The text interpreter pushes each of the
three numbers in turn onto the stack. Finally, the text interpreter
looks up the word `.s' and executes it. The effect of executing `.s' is
to print the "<3>" (the total number of items on the stack) followed by
a list of all the items on the stack; the item on the far right-hand
side is the TOS.
You can now type:
+ .s<RET> <2> 1 5 ok
which is correct; there are now 2 items on the stack and the result of
the addition is 5.
If you're playing with cards, try doing a second addition: pick up
the two cards, work out that their sum is 6, shuffle them into the pack,
look for a 6 and place that on the table. You now have just one item on
the stack. What happens if you try to do a third addition? Pick up the
first card, pick up the second card - ah! There is no second card. This
is called a "stack underflow" and consitutes an error. If you try to do
the same thing with Forth it often reports an error (probably a Stack
Underflow or an Invalid Memory Address error).
The opposite situation to a stack underflow is a "stack overflow",
which simply accepts that there is a finite amount of storage space
reserved for the stack. To stretch the playing card analogy, if you had
enough packs of cards and you piled the cards up on the table, you would
eventually be unable to add another card; you'd hit the ceiling. Gforth
allows you to set the maximum size of the stacks. In general, the only
time that you will get a stack overflow is because a definition has a
bug in it and is generating data on the stack uncontrollably.
There's one final use for the playing card analogy. If you model your
stack using a pack of playing cards, the maximum number of items on
your stack will be 52 (I assume you didn't use the Joker). The maximum
value of any item on the stack is 13 (the King). In fact, the only
possible numbers are positive integer numbers 1 through 13; you can't
have (for example) 0 or 27 or 3.52 or -2. If you change the way you
think about some of the cards, you can accommodate different numbers.
For example, you could think of the Jack as representing 0, the Queen
as representing -1 and the King as representing -2. Your range remains
unchanged (you can still only represent a total of 13 numbers) but the
numbers that you can represent are -2 through 10.
In that analogy, the limit was the amount of information that a
single stack entry could hold, and Forth has a similar limit. In Forth,
the size of a stack entry is called a "cell". The actual size of a cell
is implementation dependent and affects the maximum value that a stack
entry can hold. A Standard Forth provides a cell size of at least
16-bits, and most desktop systems use a cell size of 32-bits.
Forth does not do any type checking for you, so you are free to
manipulate and combine stack items in any way you wish. A convenient way
of treating stack items is as 2's complement signed integers, and that
is what Standard words like `+' do. Therefore you can type:
-5 12 + .s<RET> <1> 7 ok
If you use numbers and definitions like `+' in order to turn Forth
into a great big pocket calculator, you will realise that it's rather
different from a normal calculator. Rather than typing 2 + 3 = you had
to type 2 3 + (ignore the fact that you had to use `.s' to see the
result). The terminology used to describe this difference is to say that
your calculator uses "Infix Notation" (parameters and operators are
mixed) whilst Forth uses "Postfix Notation" (parameters and operators
are separate), also called "Reverse Polish Notation".
Whilst postfix notation might look confusing to begin with, it has
several important advantages:
* it is unambiguous
* it is more concise
* it fits naturally with a stack-based system
To examine these claims in more detail, consider these sums:
6 + 5 * 4 =
4 * 5 + 6 =
If you're just learning maths or your maths is very rusty, you will
probably come up with the answer 44 for the first and 26 for the
second. If you are a bit of a whizz at maths you will remember the
convention that multiplication takes precendence over addition, and
you'd come up with the answer 26 both times. To explain the answer 26
to someone who got the answer 44, you'd probably rewrite the first sum
like this:
6 + (5 * 4) =
If what you really wanted was to perform the addition before the
multiplication, you would have to use parentheses to force it.
If you did the first two sums on a pocket calculator you would
probably get the right answers, unless you were very cautious and
entered them using these keystroke sequences:
6 + 5 = * 4 = 4 * 5 = + 6 =
Postfix notation is unambiguous because the order that the operators
are applied is always explicit; that also means that parentheses are
never required. The operators are active (the act of quoting the
operator makes the operation occur) which removes the need for "=".
The sum 6 + 5 * 4 can be written (in postfix notation) in two
equivalent ways:
6 5 4 * + or:
5 4 * 6 +
An important thing that you should notice about this notation is that
the order of the numbers does not change; if you want to subtract 2
from 10 you type `10 2 -'.
The reason that Forth uses postfix notation is very simple to
explain: it makes the implementation extremely simple, and it follows
naturally from using the stack as a mechanism for passing parameters.
Another way of thinking about this is to realise that all Forth
definitions are active; they execute as they are encountered by the text
interpreter. The result of this is that the syntax of Forth is trivially
simple.
File: gforth.info, Node: Your first definition, Next: How does that work?, Prev: Stacks and Postfix notation, Up: Introduction
Your first Forth definition
===========================
Until now, the examples we've seen have been trivial; we've just been
using Forth as a bigger-than-pocket calculator. Also, each calculation
we've shown has been a "one-off" - to repeat it we'd need to type it in
again(1) In this section we'll see how to add new words to Forth's
vocabulary.
The easiest way to create a new word is to use a "colon definition".
We'll define a few and try them out before worrying too much about how
they work. Try typing in these examples; be careful to copy the spaces
accurately:
: add-two 2 + . ;
: greet ." Hello and welcome" ;
: demo 5 add-two ;
Now try them out:
greet<RET> Hello and welcome ok
greet greet<RET> Hello and welcomeHello and welcome ok
4 add-two<RET> 6 ok
demo<RET> 7 ok
9 greet demo add-two<RET> Hello and welcome7 11 ok
The first new thing that we've introduced here is the pair of words
`:' and `;'. These are used to start and terminate a new definition,
respectively. The first word after the `:' is the name for the new
definition.
As you can see from the examples, a definition is built up of words
that have already been defined; Forth makes no distinction between
definitions that existed when you started the system up, and those that
you define yourself.
The examples also introduce the words `.' (dot), `."' (dot-quote)
and `dup' (dewp). Dot takes the value from the top of the stack and
displays it. It's like `.s' except that it only displays the top item
of the stack and it is destructive; after it has executed, the number
is no longer on the stack. There is always one space printed after the
number, and no spaces before it. Dot-quote defines a string (a sequence
of characters) that will be printed when the word is executed. The
string can contain any printable characters except `"'. A `"' has a
special function; it is not a Forth word but it acts as a delimiter
(the way that delimiters work is described in the next section).
Finally, `dup' duplicates the value at the top of the stack. Try typing
`5 dup .s' to see what it does.
We already know that the text interpreter searches through the
dictionary to locate names. If you've followed the examples earlier, you
will already have a definition called `add-two'. Lets try modifying it
by typing in a new definition:
: add-two dup . ." + 2 =" 2 + . ;<RET> redefined add-two ok
Forth recognised that we were defining a word that already exists,
and printed a message to warn us of that fact. Let's try out the new
definition:
9 add-two<RET> 9 + 2 =11 ok
All that we've actually done here, though, is to create a new
definition, with a particular name. The fact that there was already a
definition with the same name did not make any difference to the way
that the new definition was created (except that Forth printed a warning
message). The old definition of add-two still exists (try `demo' again
to see that this is true). Any new definition will use the new
definition of `add-two', but old definitions continue to use the
version that already existed at the time that they were `compiled'.
Before you go on to the next section, try defining and redefining
some words of your own.
---------- Footnotes ----------
(1) That's not quite true. If you press the up-arrow key on your
keyboard you should be able to scroll back to any earlier command, edit
it and re-enter it.
File: gforth.info, Node: How does that work?, Next: Forth is written in Forth, Prev: Your first definition, Up: Introduction
How does that work?
===================
Now we're going to take another look at the definition of `add-two'
from the previous section. From our knowledge of the way that the text
interpreter works, we would have expected this result when we tried to
define `add-two':
: add-two 2 + . ;<RET>
^^^^^^^
Error: Undefined word
The reason that this didn't happen is bound up in the way that `:'
works. The word `:' does two special things. The first special thing
that it does prevents the text interpreter from ever seeing the
characters `add-two'. The text interpreter uses a variable called `>IN'
(pronounced "to-in") to keep track of where it is in the input line.
When it encounters the word `:' it behaves in exactly the same way as
it does for any other word; it looks it up in the name dictionary,
finds its xt and executes it. When `:' executes, it looks at the input
buffer, finds the word `add-two' and advances the value of `>IN' to
point past it. It then does some other stuff associated with creating
the new definition (including creating an entry for `add-two' in the
name dictionary). When the execution of `:' completes, control returns
to the text interpreter, which is oblivious to the fact that it has
been tricked into ignoring part of the input line.
Words like `:' - words that advance the value of `>IN' and so
prevent the text interpreter from acting on the whole of the input line
- are called "parsing words".
The second special thing that `:' does is change the value of a
variable called `state', which affects the way that the text
interpreter behaves. When Gforth starts up, `state' has the value 0,
and the text interpreter is said to be "interpreting". During a colon
definition (started with `:'), `state' is set to -1 and the text
interpreter is said to be "compiling".
In this example, the text interpreter is compiling when it processes
the string "`2 + . ;'". It still breaks the string down into character
sequences in the same way. However, instead of pushing the number `2'
onto the stack, it lays down ("compiles") some magic into the
definition of `add-two' that will make the number `2' get pushed onto
the stack when `add-two' is "executed". Similarly, the behaviours of
`+' and `.' are also compiled into the definition.
One category of words don't get compiled. These so-called "immediate
words" get executed (performed now) regardless of whether the text
interpreter is interpreting or compiling. The word `;' is an immediate
word. Rather than being compiled into the definition, it executes. Its
effect is to terminate the current definition, which includes changing
the value of `state' back to 0.
When you execute `add-two', it has a "run-time effect" that is
exactly the same as if you had typed `2 + . <RET>' outside of a
definition.
In Forth, every word or number can be described in terms of two
properties:
* Its "interpretation semantics" describe how it will behave when the
text interpreter encounters it in "interpret" state. The
interpretation semantics of a word are represented by an "execution
token".
* Its "compilation semantics" describe how it will behave when the
text interpreter encounters it in "compile" state. The compilation
semantics of a word are represented in an implementation-dependent
way; Gforth uses a "compilation token".
Numbers are always treated in a fixed way:
* When the number is "interpreted", its behaviour is to push the
number onto the stack.
* When the number is "compiled", a piece of code is appended to the
current definition that pushes the number when it runs. (In other
words, the compilation semantics of a number are to postpone its
interpretation semantics until the run-time of the definition that
it is being compiled into.)
Words don't behave in such a regular way, but most have default
semantics which means that they behave like this:
* The "interpretation semantics" of the word are to do something
useful.
* The "compilation semantics" of the word are to append its
"interpretation semantics" to the current definition (so that its
run-time behaviour is to do something useful).
The actual behaviour of any particular word can be controlled by
using the words `immediate' and `compile-only' when the word is
defined. These words set flags in the name dictionary entry of the most
recently defined word, and these flags are retrieved by the text
interpreter when it finds the word in the name dictionary.
A word that is marked as "immediate" has compilation semantics that
are identical to its interpretation semantics. In other words, it
behaves like this:
* The "interpretation semantics" of the word are to do something
useful.
* The "compilation semantics" of the word are to do something useful
(and actually the same thing); i.e., it is executed during
compilation.
Marking a word as "compile-only" prohibits the text interpreter from
performing the interpretation semantics of the word directly; an attempt
to do so will generate an error. It is never necessary to use
`compile-only' (and it is not even part of ANS Forth, though it is
provided by many implementations) but it is good etiquette to apply it
to a word that will not behave correctly (and might have unexpected
side-effects) in interpret state. For example, it is only legal to use
the conditional word `IF' within a definition. If you forget this and
try to use it elsewhere, the fact that (in Gforth) it is marked as
`compile-only' allows the text interpreter to generate a helpful error
message rather than subjecting you to the consequences of your folly.
This example shows the difference between an immediate and a
non-immediate word:
: show-state state @ . ;
: show-state-now show-state ; immediate
: word1 show-state ;
: word2 show-state-now ;
The word `immediate' after the definition of `show-state-now' makes
that word an immediate word. These definitions introduce a new word:
`@' (pronounced "fetch"). This word fetches the value of a variable,
and leaves it on the stack. Therefore, the behaviour of `show-state' is
to print a number that represents the current value of `state'.
When you execute `word1', it prints the number 0, indicating that
the system is interpreting. When the text interpreter compiled the
definition of `word1', it encountered `show-state' whose compilation
semantics are to append its interpretation semantics to the current
definition. When you execute `word1', it performs the interpretation
semantics of `show-state'. At the time that `word1' (and therefore
`show-state') are executed, the system is interpreting.
When you pressed <RET> after entering the definition of `word2', you
should have seen the number -1 printed, followed by "` ok'". When the
text interpreter compiled the definition of `word2', it encountered
`show-state-now', an immediate word, whose compilation semantics are
therefore to perform its interpretation semantics. It is executed
straight away (even before the text interpreter has moved on to process
another group of characters; the `;' in this example). The effect of
executing it are to display the value of `state' at the time that the
definition of `word2' is being defined. Printing -1 demonstrates that
the system is compiling at this time. If you execute `word2' it does
nothing at all.
Before leaving the subject of immediate words, consider the
behaviour of `."' in the definition of `greet', in the previous
section. This word is both a parsing word and an immediate word. Notice
that there is a space between `."' and the start of the text `Hello and
welcome', but that there is no space between the last letter of
`welcome' and the `"' character. The reason for this is that `."' is a
Forth word; it must have a space after it so that the text interpreter
can identify it. The `"' is not a Forth word; it is a "delimiter". The
examples earlier show that, when the string is displayed, there is
neither a space before the `H' nor after the `e'. Since `."' is an
immediate word, it executes at the time that `greet' is defined. When
it executes, its behaviour is to search forward in the input line
looking for the delimiter. When it finds the delimiter, it updates
`>IN' to point past the delimiter. It also compiles some magic code
into the definition of `greet'; the xt of a run-time routine that
prints a text string. It compiles the string `Hello and welcome' into
memory so that it is available to be printed later. When the text
interpreter gains control, the next word it finds in the input stream
is `;' and so it terminates the definition of `greet'.
File: gforth.info, Node: Forth is written in Forth, Next: Review - elements of a Forth system, Prev: How does that work?, Up: Introduction
Forth is written in Forth
=========================
When you start up a Forth compiler, a large number of definitions
already exist. In Forth, you develop a new application using bottom-up
programming techniques to create new definitions that are defined in
terms of existing definitions. As you create each definition you can
test and debug it interactively.
If you have tried out the examples in this section, you will probably
have typed them in by hand; when you leave Gforth, your definitions will
be lost. You can avoid this by using a text editor to enter Forth source
code into a file, and then loading code from the file using `include'
(*note Forth source files::). A Forth source file is processed by the
text interpreter, just as though you had typed it in by hand(1).
Gforth also supports the traditional Forth alternative to using text
files for program entry (*note Blocks::).
In common with many, if not most, Forth compilers, most of Gforth is
actually written in Forth. All of the `.fs' files in the installation
directory(2) are Forth source files, which you can study to see
examples of Forth programming.
Gforth maintains a history file that records every line that you
type to the text interpreter. This file is preserved between sessions,
and is used to provide a command-line recall facility. If you enter long
definitions by hand, you can use a text editor to paste them out of the
history file into a Forth source file for reuse at a later time (for
more information *note Command-line editing::).
---------- Footnotes ----------
(1) Actually, there are some subtle differences - see *Note The Text
Interpreter::.
(2) For example, `/usr/local/share/gforth...'
File: gforth.info, Node: Review - elements of a Forth system, Next: Where to go next, Prev: Forth is written in Forth, Up: Introduction
Review - elements of a Forth system
===================================
To summarise this chapter:
* Forth programs use "factoring" to break a problem down into small
fragments called "words" or "definitions".
* Forth program development is an interactive process.
* The main command loop that accepts input, and controls both
interpretation and compilation, is called the "text interpreter"
(also known as the "outer interpreter").
* Forth has a very simple syntax, consisting of words and numbers
separated by spaces or carriage-return characters. Any additional
syntax is imposed by "parsing words".
* Forth uses a stack to pass parameters between words. As a result,
it uses postfix notation.
* To use a word that has previously been defined, the text
interpreter searches for the word in the "name dictionary".
* Words have "interpretation semantics" and "compilation semantics".
* The text interpreter uses the value of `state' to select between
the use of the "interpretation semantics" and the "compilation
semantics" of a word that it encounters.
* The relationship between the "interpretation semantics" and
"compilation semantics" for a word depend upon the way in which
the word was defined (for example, whether it is an "immediate"
word).
* Forth definitions can be implemented in Forth (called "high-level
definitions") or in some other way (usually a lower-level language
and as a result often called "low-level definitions", "code
definitions" or "primitives").
* Many Forth systems are implemented mainly in Forth.
File: gforth.info, Node: Where to go next, Next: Exercises, Prev: Review - elements of a Forth system, Up: Introduction
Where To Go Next
================
Amazing as it may seem, if you have read (and understood) this far,
you know almost all the fundamentals about the inner workings of a Forth
system. You certainly know enough to be able to read and understand the
rest of this manual and the ANS Forth document, to learn more about the
facilities that Forth in general and Gforth in particular provide. Even
scarier, you know almost enough to implement your own Forth system.
However, that's not a good idea just yet... better to try writing some
programs in Gforth.
Forth has such a rich vocabulary that it can be hard to know where to
start in learning it. This section suggests a few sets of words that are
enough to write small but useful programs. Use the word index in this
document to learn more about each word, then try it out and try to write
small definitions using it. Start by experimenting with these words:
* Arithmetic: `+ - * / /MOD */ ABS INVERT'
* Comparison: `MIN MAX ='
* Logic: `AND OR XOR NOT'
* Stack manipulation: `DUP DROP SWAP OVER'
* Loops and decisions: `IF ELSE ENDIF ?DO I LOOP'
* Input/Output: `. ." EMIT CR KEY'
* Defining words: `: ; CREATE'
* Memory allocation words: `ALLOT ,'
* Tools: `SEE WORDS .S MARKER'
When you have mastered those, go on to:
* More defining words: `VARIABLE CONSTANT VALUE TO CREATE DOES>'
* Memory access: `@ !'
When you have mastered these, there's nothing for it but to read
through the whole of this manual and find out what you've missed.
File: gforth.info, Node: Exercises, Prev: Where to go next, Up: Introduction
Exercises
=========
TODO: provide a set of programming excercises linked into the stuff
done already and into other sections of the manual. Provide solutions
to all the exercises in a .fs file in the distribution.
File: gforth.info, Node: Words, Next: Error messages, Prev: Introduction, Up: Top
Forth Words
***********
* Menu:
* Notation::
* Case insensitivity::
* Comments::
* Boolean Flags::
* Arithmetic::
* Stack Manipulation::
* Memory::
* Control Structures::
* Defining Words::
* Interpretation and Compilation Semantics::
* Tokens for Words::
* Compiling words::
* The Text Interpreter::
* The Input Stream::
* Word Lists::
* Environmental Queries::
* Files::
* Blocks::
* Other I/O::
* Locals::
* Structures::
* Object-oriented Forth::
* Programming Tools::
* Assembler and Code Words::
* Threading Words::
* Passing Commands to the OS::
* Keeping track of Time::
* Miscellaneous Words::
File: gforth.info, Node: Notation, Next: Case insensitivity, Prev: Words, Up: Words
Notation
========
The Forth words are described in this section in the glossary
notation that has become a de-facto standard for Forth texts:
word Stack effect wordset pronunciation
Description
WORD
The name of the word.
STACK EFFECT
The stack effect is written in the notation `before -- after',
where before and after describe the top of stack entries before
and after the execution of the word. The rest of the stack is not
touched by the word. The top of stack is rightmost, i.e., a stack
sequence is written as it is typed in. Note that Gforth uses a
separate floating point stack, but a unified stack notation. Also,
return stack effects are not shown in stack effect, but in
Description. The name of a stack item describes the type and/or
the function of the item. See below for a discussion of the types.
All words have two stack effects: A compile-time stack effect and a
run-time stack effect. The compile-time stack-effect of most words
is - . If the compile-time stack-effect of a word deviates from
this standard behaviour, or the word does other unusual things at
compile time, both stack effects are shown; otherwise only the
run-time stack effect is shown.
PRONUNCIATION
How the word is pronounced.
WORDSET
The ANS Forth standard is divided into several word sets. A
standard system need not support all of them. Therefore, in
theory, the fewer word sets your program uses the more portable it
will be. However, we suspect that most ANS Forth systems on
personal machines will feature all word sets. Words that are not
defined in ANS Forth have `gforth' or `gforth-internal' as word
set. `gforth' describes words that will work in future releases of
Gforth; `gforth-internal' words are more volatile. Environmental
query strings are also displayed like words; you can recognize
them by the `environment' in the word set field.
DESCRIPTION
A description of the behaviour of the word.
The type of a stack item is specified by the character(s) the name
starts with:
`f'
Boolean flags, i.e. `false' or `true'.
`c'
Char
`w'
Cell, can contain an integer or an address
`n'
signed integer
`u'
unsigned integer
`d'
double sized signed integer
`ud'
double sized unsigned integer
`r'
Float (on the FP stack)
`a-'
Cell-aligned address
`c-'
Char-aligned address (note that a Char may have two bytes in
Windows NT)
`f-'
Float-aligned address
`df-'
Address aligned for IEEE double precision float
`sf-'
Address aligned for IEEE single precision float
`xt'
Execution token, same size as Cell
`wid'
Word list ID, same size as Cell
`ior, wior'
I/O result code, cell-sized. In Gforth, you can `throw' iors.
`f83name'
Pointer to a name structure
`"'
string in the input stream (not on the stack). The terminating
character is a blank by default. If it is not a blank, it is shown
in `<>' quotes.
File: gforth.info, Node: Case insensitivity, Next: Comments, Prev: Notation, Up: Words
Case insensitivity
==================
Gforth is case-insensitive; you can enter definitions and invoke
Standa