How to be an Irredeemable Nerd and Look Good Doing It
In a previous post, I talked a bit about my endeavour to build
myself a lil' Lisp: PebbLisp. It's a project I work off and on depending on my
motivation. Recently, I was pretty bored with it, and found myself looking for
a new project. Having read a bit about Forth, I thought it wouldn't be too hard
to try implementing it. Plus, this would be a great opportunity do some
practice with Rust.
If you're not familiar with Forth, it's a weird little interpreted language
built around a stack. Passing in a number will add it to the top of the stack,
passing in a function will (usually) do something with numbers on the stack.
For example, what happens when you run the following?
2 3 + .
First, `2` and `3` are added to the stack. Then, `+` pops the top two items off
the stack, and adds them. Then it pushes the result back onto the stack.
Finally, the `.` pops the top item off of the stack, and prints it out:
5
You can also compile functions that add some of these elements, and the
language can become surprisingly expressive:
: feet 12 * ;
So, I figured "hey, looks simple enough", and got to work. Got basic parsing
going, got the stack pretty functional, added a few functions, whoo. Rust
turned out to be a great choice. Expressive, safe, and with built-in testing.
Good stuff. Almost too good. I'd started looking at PebbLisp again. Could I
write an interpreted language using my own interpreted language? Forth is
pretty simple, conceptually. How hard could it be?
Actually, it hasn't been the unholy mess that I was expecting. Yes, my PebbLisp
is severely lacking (there was no way to take user input before?). No, it has
nothing anything even remotely resembling a formal language definition (I've
operated on the "this seems to make sense" principle). With some tweaks though,
it has kind of worked!
My to-be-named Forth (Forbble? PLForth? PebForListhble?) is incredibly
buggy, and pretty tedious even when it does work, but it sort of kind of does!
: yards feet 3 * ;
5 feet .
\ This prints 60 (5 feet in inches)
8 yards .
\ This prints 288 (6 yards in inches)
5 yards 2 feet + .
\ This prints 204 (5 yards + 2 feet)
$ "feet" 12 * "END"
So, for reasons I've yet to suss out:
$ "yards" 36 * "END"
5 "yards" 2 "feet" +
.
\ This prints 204