Forth compiler in one literate x86 assembly file
annexia.org
annexia.org
This is what I long for: simple self-contained bootstrapping systems that can be eventually used to build anything. These days it seems that all we have is that "anything" and we'll just glue the pieces together without ever understading how everything works.
That's what got me started in computers anyway: to understand how _everything_ works.
Something I did recently is a source-to-source compiler as a series of function calls, e.g.:
1 2 +
may translate to
stack.push(1); stack.push(2); add();
in an Algol-type language. You don't get niceties like a "real" namespace or interactivity with this approach, but if the function calls are inlined, the only performance overhead comes from usage of the data stack - making it a good candidate for "glue code" that doesn't need to be dynamic. It's basically "Forth-like macro-assembler" at this level.
For things like runtime mutability, interrupt-and-continue behavior, and interactivity, another strategy is to build an interpreter loop where each word is a list or array of data containing two types - values and function calls. Lots of features become possible - even easy - once you do that.
Since I started experimenting with stack languages I've been trending towards this approach: build a Forth-type API on top of whatever language is best for the task. Then build the app in the Forth. On the one hand you can say "ah, but that's not necessary," but on the other, it focuses your energies around setting up the plumbing well, so that the final solution is small and easy to extend. And that's always a good outcome.
You use the primitives to define other words in order to achieve your desired effects.
It is a stack-based language.
Forth programs tend to be extremely small, typical usage is in embedded control applications, though there have been much larger programs written in Forth. Forth was invented by Chuck Moore, he is still active:
It definitely is a language that is worth learning, if only because it will subtly change your point-of-view.
If you're really interested you might want to read this book:
If you wrote a lisp where evaluation went left-to-right instead of right-to-left and where the operators took fixed numbers of arguments (so you could drop the parentheses), you would have an unconventional but recognizable dialect of forth.
http://en.wikipedia.org/wiki/SECD_machine is an interesting example of something between lisp, forth, and traditional assembly.
Syntax is of course the most obvious `backward' thing. Conceptually Lisp moves you away from the machine and closer to math, Forth stays way closer. Forth does not (normally) include a garbage collector. Naming variables is discouraged. Forth is almost untyped, Lisp is strongly-dynamically typed.
Bootstrapping a forth-like system on your own is a great exercise; it'll teach you a lot about writing minimal systems. The _Threaded Interpretive Languages_ book is a good read, too.
My personal belief (after seeing many forth-based projects fail) is that it's a terrible language for scaling to real systems and even medium-size teams, but it's got some great ideas. The trouble comes when you do stuff like trying to treat that toy driver ("hey, i just wrote a disk driver in eight lines of forth!") as something that is ready for production. Also, a sea of invented operators like "^!" does not help, though arguably this is more developer discipline than a fault of the language.
[[[pats forth on the head. nice language, now go play]]]