
Forth: The Hacker’s Language - mpweiher
http://hackaday.com/2017/01/27/forth-the-hackers-language/
======
rwmj
This is a how-to-write-a-FORTH tutorial that I wrote a few years ago. It's
particularly nice that you get to see how various control structures are
implemented, like IF, CASE and even comments!

Part 1:
[http://git.annexia.org/?p=jonesforth.git;a=blob;f=jonesforth...](http://git.annexia.org/?p=jonesforth.git;a=blob;f=jonesforth.S)

Part 2:
[http://git.annexia.org/?p=jonesforth.git;a=blob;f=jonesforth...](http://git.annexia.org/?p=jonesforth.git;a=blob;f=jonesforth.f)

(github mirror:
[https://github.com/AlexandreAbreu/jonesforth/blob/master/jon...](https://github.com/AlexandreAbreu/jonesforth/blob/master/jonesforth.S)
[https://github.com/AlexandreAbreu/jonesforth/blob/master/jon...](https://github.com/AlexandreAbreu/jonesforth/blob/master/jonesforth.f))

Previous HN comments:
[https://news.ycombinator.com/item?id=10187248](https://news.ycombinator.com/item?id=10187248)

~~~
rsaarelm
Working through Jones Forth got me up to speed on both understanding how Forth
works and getting my hands dirty with some practical assembly coding.

Once I got a better idea of Forth, I also realized that Jones stays in
assembly for rather long. He builds up the entire interpreter from raw
assembly words, because you need the interpreter to start parsing textual
Forth source. But you if you could somehow write Forth before the interpreter
is put together, it would be quite natural to switch to Forth much earlier.
And it turns out you can do that. Jones even defines the `defword` macro. But
for some reason he makes very little use of it. Rewriting most of the code
leading up to INTERPRET using defword was a fun exercise.

The next step would've been making the whole system bootstrapping by rewriting
the assembler in Forth, but x86 machine code generation is hairy enough that I
bailed out at this point.

~~~
rwmj
All fair points. I was reading over it again today thinking that it would have
been better to write more of it in FORTH. At the time I was prematurely
optimizing I think.

~~~
i336_
Have you ever considered a revisit?

------
shortsightedsid
I'm a embedded software dev and write code all day in C. Sure enough forth
comes up in conversations once in a while as does other ideas like Python, JS,
Lua etc..

Of all the alternatives to C, Forth is the only one which groks hardware. This
is particularly important for embedded development. Any realistic alternative
to C must understand interrupts, memory mapped registers etc.. Forth is the
only one in which this is possible. Every other example I've seen always uses
C for "low-level" access or a libraries. If you need to do that, then you
won't win over embedded devs like me. It's much easier to write good embedded
C code (no mallocs etc) than having to debug FFI.

Having said all that, my mind doesn't understand Forth. I'm too used to seeing
code in C or even assembly to fully understand Forth. Nevertheless things like
[https://github.com/jeelabs/mecrisp-
stellaris](https://github.com/jeelabs/mecrisp-stellaris) are really cool and
are a realistic alternative to C.

~~~
pjmlp
> Forth is the only one in which this is possible. Every other example I've
> seen always uses C for "low-level" access or a libraries. If you need to do
> that, then you won't win over embedded devs like me.

Not really.

[https://www.mikroe.com/mikrobasic/](https://www.mikroe.com/mikrobasic/)

[https://www.mikroe.com/mikropascal/](https://www.mikroe.com/mikropascal/)

[http://www.astrobe.com/default.htm](http://www.astrobe.com/default.htm)

[http://www.adacore.com/gnatpro/embedded](http://www.adacore.com/gnatpro/embedded)

[http://www.ptc.com/developer-tools/apexada](http://www.ptc.com/developer-
tools/apexada)

[http://www.ghs.com/products/ada_optimizing_compilers.html](http://www.ghs.com/products/ada_optimizing_compilers.html)

Zero lines of C.

~~~
qwertyuiop924
Is there any reason he would have heard of those? They're all pretty fringe,
arguably moreso than Forth, for some of them.

Some of these do look neat: I've had an interest in both Ada and Oberon,
although I haven't been able to get over the verbosity and unpleasant syntax
of either (it's not COBOL, or anything, but it's not nice).

OTOH, I am immediately suspicious of any product that claims it's professional
and also has BASIC in the name...

~~~
jnbiche
Ada is not fringe. It's used by many large companies, although less and less
these for new projects these days. There are some huge Ada codebases being
maintained in industry, particularly in the aviation industry.

~~~
qwertyuiop924
The same can be said of Lisp and Forth. Would you call them fringe?

------
qwertyuiop924
Forth is really neat. It's a rare langauge that has the same abilities as C to
deal with hardware, but is a higher level language than assembly, and isn't C.
Most languages in common use today have reached a level of abstraction where
direct hardware interaction is either impossible or discouraged.

Also, my time with Lisp has taught me that interactive environments are A Good
Thing, and Forth is exceedingly interactive, and has better native
introspection than many Lisps (when your guts are strewn across the floor,
it's hard to hide them).

But for all that is good about it, Forth does have its problems: depending on
how well your problem maps to the stack, Forth can be exceedingly painful.

A discussion of Forth's flaws, of course, would not be complete without a link
to Yossi Kreinin's now-famous post on the subject: [http://yosefk.com/blog/my-
history-with-forth-stack-machines....](http://yosefk.com/blog/my-history-with-
forth-stack-machines.html)

------
pmoriarty
I really, really wanted to like Forth. I love learning new languages and
different paradigms from those I know already. The fact that Forth was really
tiny and yet very powerful and could do meta-programming in a Lisp-like way
(though I hadn't yet learned Lisp at the time to fully appreciate what this
meant) was also very attractive.

Unfortunately, learning Forth was a real let down. Forth turned out to be way
too much of a write-only language for me, with lots of convoluted, hard to
understand code. The Forth community preaches simplicity and using short,
clear, well documented words (functions). But the reality, at least in most of
the open source Forth code I've seen was the opposite, with long, convoluted,
poorly documented words being the rule rather than the exception. I've been
told that commercial Forth code is a lot better in these respects, but I
haven't verified that.

I've also heard even Forth fans tell me that the whole point of Forth is to
write yourself something more pleasant than Forth to work in as quickly as
possible. Since I don't have an interest or need to write programming
languages myself, I'd just rather start with something more pleasant from the
beginning, and skip the painful stage of having to work with Forth.

In very resource constrained environments where your only alternative to
assembly is Forth, Forth might be the best choice. But since I don't do most
of my programming in such environments, I really don't see the point of using
Forth at all.

Finally, after learning Forth, I went on to learn Lisp and then Scheme, and
fell in love. Those (especially Scheme) really were super clear and easy to
both write and read, and felt far more powerful and not at all painful. I felt
far more productive in them, and would now far rather use a tiny Scheme or
even Lisp on a resource constrained system, if at all possible.

~~~
JBiserkov
Have you looked at Clojure? It's a modern Lisp that feels _designed_ to be
simple, yet powerful. It works on the JVM/.NET/JavaScript platforms, so it's
reach is almost universal.

[https://clojure.org/](https://clojure.org/)

[https://clojurescript.org/](https://clojurescript.org/)

------
s-macke
One of the most complex games Starflight of the 80th's is written in Forth. I
had a lot of fun decompiling it.

[https://github.com/s-macke/starflight-
reverse](https://github.com/s-macke/starflight-reverse)

It turns out to be very portable because the assembler code is only about
1000-2000 lines. The rest is implemented in Forth itself. They use indirect
threading to produce very dense code. They kept even most of the debugging
symbols inside the code and kept the forth interpreter itself in the code.

~~~
dzdt
At one point 10ish years ago the starflight source code was posted online by
one of the authors, but it went back down pretty quickly. Someone might have a
copy though. A few of the files are on archive.org, but not the main body.

[http://web.archive.org/web/20030214111810/http://www.sonic.n...](http://web.archive.org/web/20030214111810/http://www.sonic.net/~sage/sf/Development/TheMakingOfStarflight.htm)

~~~
s-macke
Thanks for posting the link. I found the archive a few month ago and
downloaded the few documents that were left. The table here

[https://github.com/s-macke/starflight-
reverse/blob/master/sr...](https://github.com/s-macke/starflight-
reverse/blob/master/src/global.c#L7)

is based on these documents and I filled some gaps of the symbol table. To
start the game they used the word "LET-THERE-BE-STARFLIGHT", in the binary you
see only part of it: "LET-TH".

I wish this "someone" would provide a full copy of the archive :)

------
eggy
I like Factor, but staying small and innovative, I really like what Charles
Childers has done with Retroforth. He has implemented a newer version running
on a smaller VM Nga (the older was Ngaro) called Retro 12 [1]. Very cool
stuff.

    
    
      [1]  http://forthworks.com/retro/

------
agumonkey
I quite like Forth. It feels like a blend of lisp and apl. And even ml if you
squint a bit at it as an applicative as composition system.

People on reddit seems to hint at the fact that Forth people stay under the
radar because it allow them to design and solve problems in better ways.

I wonder how true it is ..

~~~
vanderZwan
The more likely culprit is this:

> _But Forth is also like a high-wire act; if C gives you enough rope to hang
> yourself, Forth is a flamethrower crawling with cobras. There is no type
> checking, no scope, and no separation of data and code. You can do horrible
> things like redefine 2 as a function that will return seven, and forever
> after your math won’t work. (But why would you?) You can easily jump off
> into bad sections of memory and crash the system. You will develop a good
> mental model of what data is on the stack at any given time, or you will
> suffer. If you want a compiler to worry about code safety for you, go see
> Rust, Ada, or Java. You will not find it here. Forth is about simplicity and
> flexibility._

When it comes to working on a large project in a team, I suspect Forth doesn't
scale.

Think of why Go works so well for Google: it's designed for code bases that
are maintained by many people. And almost every design decision that was made
for that goes against the spirit of Forth.

It's too flexible; you can change anything about the system so any Forth code
ends up deeply personal, and specific to the current task. It's a language for
individual artisans, which is another reason why it works well in the embedded
space. But it's not hard to see how it all goes up in flames when you're in a
large team.

~~~
snarfy
> Forth code ends up deeply personal, and specific to the current task.

That's the point though. You create a domain specific language using Forth and
solve your domain specific problems with it.

~~~
coldtea
Yes, but create "other programmers don't understand my DSL" problem.

DSLs come at a cost.

~~~
qwertyuiop924
...And Forth's DSL's are worse than most, by virtue of having minimal syntax,
and being bound by the stack. So it's not just the Lisp problem again: it's
actually worse.

------
macintux
Ever since I missed Chuck Moore's talk at Strange Loop a few years ago, I've
been wanting to watch it. By all accounts it's quite good.

[https://www.infoq.com/presentations/power-144-chip](https://www.infoq.com/presentations/power-144-chip)

Glad this piece popped up, time to finally watch it.

------
vram22
Just saw recently that the classic FORTH tutorial is available online:

Starting FORTH — Online Edition:

[https://www.forth.com/starting-forth/](https://www.forth.com/starting-forth/)

I had read it and played around with FORTH on a microcomputer some years ago.
Fun language.

Thinking FORTH, a more advanced book, also by Leo Brodie, is also linked to
from the above URL.

~~~
microtherion
Amazing book. This is what got me started in implementing my own FORTH in the
early 1980s.

~~~
vram22
Cool.

------
usernam
Things you can do with forth, from the forth author:

[http://www.greenarraychips.com/](http://www.greenarraychips.com/)

which is actually a truly message-passing based arch with 144 clockless
"cpus". Each cpu is actually so limited that forth is one of the few languages
that makes programming this tricky platform viable.

~~~
qwertyuiop924
As multiple people have pointed out, GreenArray chips are basically TIS-100
IRL, but in Forth. Right down to the quirky design.

~~~
usernam
Never heard of TIS-100 (you mean
[http://www.zachtronics.com/tis-100/](http://www.zachtronics.com/tis-100/) ?)

~~~
falcolas
Worth playing; if you enjoy programming challenges within limited
environments, you would be hard pressed to find better games than the
Zachtronics set of games.

~~~
usernam
If I had time to spare, I'd actually order the development board. The
architecture is unique and fascinating.

~~~
qwertyuiop924
...What dev board? The GreenArrays one?

------
mpweiher
I came to Forth-like languages via PostScript, which has the advantage of a
huge built-in graphics library. It very naturally introduces concepts like
higher order operations, code as data and data as code.

~~~
qwertyuiop924
Can you reccomend any books on PS?

~~~
protomyth
reference manual:
[https://www.adobe.com/products/postscript/pdfs/PLRM.pdf](https://www.adobe.com/products/postscript/pdfs/PLRM.pdf)

tutorial and cookbook (blue book): [https://www-
cdf.fnal.gov/offline/PostScript/BLUEBOOK.PDF](https://www-
cdf.fnal.gov/offline/PostScript/BLUEBOOK.PDF)

language program design (green book): [https://www-
cdf.fnal.gov/offline/PostScript/GREENBK.PDF](https://www-
cdf.fnal.gov/offline/PostScript/GREENBK.PDF)

------
throwaway7645
There is a decent amount of Forth publications out there, but nothing that
really takes you from A->Z in building your own Forth based off of Assembly or
C. JonesForth helped me conceptually understand parts of Forth, but there is a
lot missing there for me to be able to start from scratch. I would pay $ for a
real book in the vein of "Land of Lisp" that shows you how to build a Forth
compiler/editor and how to extend it...the pros/cons of different design
decisions like direct/indirect threading.

~~~
tzs
You might find R. G. Loeliger's book "Threaded Interpretive Languages: Their
Design and Implementation" [1] interesting. Here's a review [2]. The comments
on that review list some online resources that might also be useful.

It's long out of print, but used copies are cheap, and scans are readily
findable on the net.

I wrote a comment a while back outlining how to do a FORTH-like language from
scratch by starting with a simple calculator and expanding it, writing in C
with optional assembly optimizations. This was aimed at people who have less
knowledge of FORTH-like systems than you do, I think, but if you are curious
here it is [3].

[1] [https://www.amazon.com/Threaded-Interpretive-Languages-
Desig...](https://www.amazon.com/Threaded-Interpretive-Languages-Design-
Implementation/dp/007038360X)

[2] [http://www.retroprogramming.com/2010/03/threaded-
interpretiv...](http://www.retroprogramming.com/2010/03/threaded-interpretive-
languages-by-r-g.html)

[3]
[https://news.ycombinator.com/item?id=13082825](https://news.ycombinator.com/item?id=13082825)

~~~
throwaway7645
Thank you!

------
stewbrew
While forth can be quite elegant at times and I have fond memories of using
Mops, I wish modern forth dialects were statically type checked.

~~~
vanderZwan
You probably want to look at Kitten, by John Purdy:

[http://kittenlang.org/](http://kittenlang.org/)

[https://docs.google.com/presentation/d/1SJQGow_fnMSt5PsMgESu...](https://docs.google.com/presentation/d/1SJQGow_fnMSt5PsMgESumKhqlcnIQoFK_wQPkxpwWKU/edit#slide=id.p)

Some discussion on linked slides:
[https://www.reddit.com/r/concatenative/comments/4bj4lu/slide...](https://www.reddit.com/r/concatenative/comments/4bj4lu/slides_from_a_talk_i_gave_yesterday_about_kitten/)

------
dwarman
FORTH variation #1,000,001: I took John Walkers' AtLast as a core, and
extended it in several directions, some I believe quite significant. My use
case for FORTH has been as a live debugger that lets me interact with a
running Real Time system, an environment where breakpoints are not very useful
(except in crashes) because they only allow for post-mortem examination, but a
RT system needs to be watched while it is runnung to more quickly discern
pathologies.

Extensions that saved me the most agony:

1: Use of stack frame comments to actually define local variables and enforce
the in - out stack transform. While at this I also added the comment string to
the word definition in an additional help link. Thus:

[:] do_it ( in1 in2 -- out : return in1 * in2 * 2 ) local lv : lv_helper 2 * ;
in1 @ in2 @ * lv_helper out ! [;]

> help do_it in1 in2 -- out : return in1 * in2 > 3 6 do_it . 36 >

Note the [:] and [;] redefs for compiler words, had to do this to accommodate
nesting, locals, stack frames, while not compromising regular FORTH.

all variables are local in scope to the containing word. Defining variables
inside ditto. Had words for listing contents of these too.

I later extended this to include nested word definitions, dynamically
allocated variables, and stack frames that will unwind these on execution
error. Gone were stack frame size errors, a missed dup or drop no longer
fatal, indeed dup and drop not really necessary any more.

2: Structured data debugging aides: a few words and a C header parser allowed
me to dump or modify readable contaents of application structs, and to call
into application functions.

3: along the same lines of nested definitions, I was able to associate sub-
dictionaries with graphical views along their heirarchy. This was a later
addition, applied to VNOS. Lots of little things became manageable with this
paradigm. In particular, allowed me to do a scoped local console (as a debug
object instantated in a View), and to insert message overrides into the VNOS
messaging mechanism, effectively adding what turned out to be a really
powerful scripting system. Done as an object too - current version includes
Perl 5 and Lua (almost ready).

And yes, concurrency is a concern, and being sure not to call non-re-entrant
(errant:) functions, but hey, ypu'd likely be surprised at how good a pattern
recognizer ther Human Brain is here.

Over-all, I think I used this system with a good half-dozen different CPU
architectures and their OS's, also in the high level VNOS GUI (originally put
my FORTH into it for debugging purposes, but that was rapidly out-grown).

------
kazinator
Forth is a hacker's language only when we take a narrow definition of "hacker"
as someone who cares about making a device field-programmable in the easiest,
smallest way that doesn't completely suck, and can somehow get things to work
without caring what the code looks like or whether anyone understands it,
including the same hacker seventeen months later.

~~~
yjftsjthsd-h
One might even say that the language is a bit of a hack. :)

------
vertebrate
Why do you think some of the so-called hacker languages were pretty popular at
a time (perl, lisp), and not the others (forth, apl?)

~~~
pjmlp
There was no Internet and knowledge was shared via magazines and computer
clubs.

Forth was quite popular in Europe thanks to Jupiter Ace and ZX Spectrum
extensions.

[https://en.wikipedia.org/wiki/Jupiter_Ace](https://en.wikipedia.org/wiki/Jupiter_Ace)

[http://www.worldofspectrum.org/infoseekid.cgi?id=0008717](http://www.worldofspectrum.org/infoseekid.cgi?id=0008717)

~~~
qwertyuiop924
That's true. And APL and its children is _still_ quite popular in finance.

By the way, I found a rather neat page about building a Jupiter ACE:
[http://searle.hostei.com/grant/JupiterAce/JupiterAce.html](http://searle.hostei.com/grant/JupiterAce/JupiterAce.html)

~~~
mhd
Mentioning APL in this context makes me picture an 8 bit home computer with an
APL interpreter. I mean, the C64 had all kinds of weird symbols on its
keyboard, too. And the magazines would save quite some pages for their source
code listing compared to BASIC...

~~~
qwertyuiop924
According to Wikipedia, the first implementation of APL on a micro was on the
8008, in '73\. It wasn't very good, but it did run...

Later ('77), TIS APL ran on Z80 systems, and was aparently quite a bit better,
although it wasn't a full implementation.

But I'm just quoting Wikipedia at this point, so look it up yourself.

------
jlg23
Amen.

And it is dead simple to implement. I did it in common lisp 3 years ago for an
IRC-bot - a lazy Sunday afternoon and 50 lines of code later I was done.

I would not want to write code in Forth on a regular basis, but reading (and
making an effort to really understand it) definitely made me a better
programmer.

~~~
qwertyuiop924
Given, there are a lot of languages that you can implement reasonably easily
in CL...

------
mcgwiz
The main reason I fell in love with the HP 48 calculator series was the RPL
programming language, which could be described as the pragmatic lovechild of
Forth and Lisp - think Forth with higher-order functions.

------
BillBohan
My first program was written in FORTRAN IV and it compiled and ran in the
summer of 1967. After that, I learned APL, Z80 assembly, and BASIC.

The August 1980 issue of BYTE magazine was all about FORTH. I read it cover to
cover, then sent to the Forth Interest Group for a copy of the implementation
guide and the 8080A listing of Forth.

I typed it all in, including comments but changed the 8080A mnemonics to Z80
mnemonics. After the typos were corrected and the I/O routines modified to run
under TRSDOS it ran as advertised. Then I optimized the code for Z80 which
made it both smaller and faster.

My job then took me from Tandy's manufacturing plant to the R&D department
where I wrote assembly code for another product but continued to work on Forth
as a side project. Management said that they would be willing to release it as
a product if I could get a signed statement declaring Fig-Forth to be in the
public domain. I tried repeatedly to get people at the Forth Interest Group to
sign but was never successful. This is the reason Radio Shack never released
Forth, though many people in R&D used my code internally. They especially
liked the ease of number base conversion.

From Tandy, I went to an industrial equipment manufacturer where I wrote a lot
of assembly for embedded applications. I ported CP/M to run on TRS-80 model
12. The need arose to read input from a graphics tablet via serial, process
the input and output a bitmap. My estimate on the length of time it would take
to write this for the CP/M machine extended past the deadline.

I combined my Forth code with the drivers for the Model 12. The boot procedure
for Model 12's consists of reading 26 128-Byte sectors from Track 0, Side 0
into memory and jumping to the loaded code. I changed to format of the
remaining tracks (both sides) to 9 1K sectors and a 256 byte sector (double
density). My boot code prompted to press the F1 or F2 key, then read all the
256 byte sectors on side 0 or side 1 (depending on F1/F2) into memory. I added
a FSAVE word which wrote memory to the 256 byte sectors. I had a Forth
operating system. I wrote the code for the application in Forth, performed the
necessary scanning and conversion and output the desired bitmap with time to
spare.

I highly recommend learning assembly for at least one processor. Without it,
you can only know about Forth, you don't really know Forth. I understand how
directly threaded code (DTC) works but I prefer the indirectly threaded code
(ITC) model of Fig-Forth as it seems more elegant to me.

I still have an x86 machine running Windows XP which will run the 16-bit code
but it will not run on my Windows 7 system. I am looking at ciforth [1] which
is a 32-bit implementation. I intend to get it running under Windows 7.

Forth is a really good system for a command line environment. As far as
readability goes, the code itself has such high information content that it is
difficult. It is up to the programmer to add abundant comments which make
reading the code unnecessary in most cases.

I'll conclude with a Forth joke:

: Decompose ROT ROT ROT ;

