Forth DSL example

Forth is a language, like Lisp, that has a certain fascination for me. I’ve tried Forth a few times, but have always gone back to other languages. Recently I tried creating a Forth myself as a learning exercise: ultimc [1]. It compiles on Linux, Windows (theoretically), and under the Ultibo [2] unikernel for a bare metal Raspberry Pi Forth.

Creating my own Forth has taught me a lot about the language, and really made me understand the way it works. In this post, I am going to peer a little under the hood to show that Forth, like Lisp, has a secret sauce that you just don’t get with most other languages. Maybe it will excite you a little as to the unique possibilities of Forth.

Recently I came across some Forth code [3] that was as follows:


Notice how there’s a lot boilerplate code there: “0 constant:”, “1 constant:”, etc. Wouldn’t it be nice to write something like:


and have Forth “do the right thing”. Well, let’s see …

Here’s the code, written in gforth:
variable enum \ the current enumerated value, starting at 0
: enum++ enum @ dup 1+ enum ! ; \ increment enum, leaving the original enum value on the stack
: >enum nextname enum++ constant ; \ Given a name, set it to the value of enum as a constant
: enum1 parse-word dup if >enum 0 else 2drop 1 then ; \ scan the input buffer, and call >enum if legit
: enum: begin enum1 until ; \ keep going until the input buffer is exhausted

Just 5 lines of code, although admittedly it did take me a lot of time to figure out. The code needs a little elaboration.

PARSE-WORD and NEXTNAME act a little bit like CREATE, except that PARSE-WORD gets the next word from the input buffer, and NEXTNAME creates a word from the input buffer.

Now, if we’re at the end of the buffer PARSE-WORD returns a zero length string. This is what ENUM1 checks for. It only calls >ENUM if the string has at least 1 character. What it returns on the stack is the value 0 to signify success, and 1 to signify failure.

ENUM: then just loops around until the value 0 appears on the stack, implying that the input buffer is exhausted.

Let’s test it, using more condensed names:

enum: foo bar baz

And check our handiwork:

foo . bar . baz . \ outputs: 0 1 2

Can your language do that?


About mcturra2000

Computer programmer living in Scotland.
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s