https://github.com/eliben/goforth
Forth implementations in Go and C
https://github.com/eliben/goforth
c compiler forth go interpreter stack-based-language
Last synced: 4 months ago
JSON representation
Forth implementations in Go and C
- Host: GitHub
- URL: https://github.com/eliben/goforth
- Owner: eliben
- License: unlicense
- Created: 2025-06-21T12:41:30.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2025-08-22T17:20:23.000Z (5 months ago)
- Last Synced: 2025-08-31T00:04:56.806Z (4 months ago)
- Topics: c, compiler, forth, go, interpreter, stack-based-language
- Language: C
- Homepage:
- Size: 208 KB
- Stars: 14
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# goforth
----
This repository contains two implementations of the
[Forth programming language](https://en.wikipedia.org/wiki/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: Go implementation of Forth
`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: lower-level C implementation
`ctil` (stands for "C [Thread Interpretive Language](https://wiki.c2.com/?ThreadedInterpretiveLanguage)")
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](http://git.annexia.org/?p=jonesforth.git)
implementation, though some things work differently (I tried to stick closer to standard
Forth).
## Testing
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`.