This repository contains two implementations of the Forth programming language.
The first is just called goforth
and lives in the root directory of this
repository. The second is called ctil
and lives in the ctil
directory.
goforth
is implemented in Go and takes an unusual approach to Forth. It acts
as a source-level interpreter. There is no intermediate representation of
the program - the source string is interpreted directly. When a word definition
is encountered, goforth
links it to the offset in the input string where
the word is defined, and when this word is called the interpreter just
processes its string definition word by word.
This is an interesting experiment but clearly not the best way to implement
Forth; in addition to the performance implications, it makes implementing things
like loops quite difficult (having to carefully keep track of nested constructs
like IF
to enable proper LEAVE
), and it's hard to support Forth's famous
self-extension mechanisms - for example, implementing IF...THEN...ELSE
in
Forth itself using lower-level primitives.
To run goforth
on a piece of Forth code, simply execute:
$ go run . < testdata/fizzbuzz.4th
... or ...
$ go build
$ ./goforth < testdata/fizzbuzz.4th
There are many small Forth programs in the testdata
directory that can serve
as examples to run and play with.
ctil
(stands for "C Thread Interpretive Language")
is a C implementation of Forth. It takes a much more traditional
Forth implementation approach, where the Forth code is actually compiled into
linked dictionary entries, and word invocations are replaced with the addresses
of the dictionary entries for these words.
ctil
still deviates from the Forth convention of Assembly language
implementations, but it should be able to support pretty much everything.
As an example, take a look at ctil/prelude.4th
- it contains implementations
of the variable
word, IF...THEN...ELSE
conditions and BEGIN...REPEAT
loops in Forth itself.
To run ctil
on a piece of Forth code, first build ctil
. A Makefile is
included - ctil
has no external dependencies other than a standard C compiler.
$ cd ctil
$ make
To run realistic Forth programs, the "prelude" has to be included first - it's
an implementation of several Forth primitives in Forth itself. If you're still
in the ctil
directory, run:
$ ./ctil -i prelude.4th < ../testdata/fizzbuzz.4th
The design of ctil
is inspired by the jonesforth
implementation, though some things work differently (I tried to stick closer to standard
Forth).
goforth has an extensive automated test harness. Each test consists of a file
in the testdata
directory that contains some Forth code and the expected
output from that code. The test harness runs the Forth code using each
interpreter and compares the output with what's expected.
Both interpreters are tested using a Go test harness; goforth_test.go
tests
the Go implementation, and ctil_test.go
tests the C implementation. Since the
C implementation supports more features, some test files in testdata
are
prefixed by ctil-
and are run only for ctil
.