3 ms·
I must say, implementing Forth in almost any high-level language, even C, can be awkward and almost antithetical. A "high-level" Forth implementation often mere
by anyfoo 1y ago
I must say, implementing Forth in almost any high-level language, even C, can be awkward and almost antithetical. A "high-level" Forth implementation often merely presents a Forth-compatible runtime, which runs the risk of missing what makes Forth so unique and useful. (The author actually seems to understand this: "The first implementation I tried is stubbornly different. Can we just make a pure interpreter?")
That's because of two main reasons. First, Forth relies heavily on passing control to the next word, instead of calling word implementations as subroutines. This is difficult to do correctly, and dynamically, in C. I suppose you could get by with computed gotos, but...
Secondly, Forth and assembly (or more generally any lower-level instruction/register view of what it's running on) go hand in hand. Forth words may carry their own assembly implementation within them, or they may be partially assembly.
Without those two things, you don't really have a Forth system, just a Forth interpreter. And you cannot define new primitive words, or words with very custom compilation semantics, from within Forth itself.
And therein also lies Forth's strength. It is very easily on-the-fly expandable, and it can even bootstrap itself. It is a great tool for machine-level exploration: Do complex low-level things with a lot less boilerplate.
The author mentions that this second attempt is a "hacker level" implementation, but short of reading the source code does not seem to go into any detail what that means exactly, and how it's implemented?
- johnecheck 1y agoAh, but which assembly? If you just roll a simple VM in the host language, your instruction set becomes the assembly Forth integrates so well with. I'm assuming that's what they did in their C implementation.
- anyfoo 1y agoTrue! I don't think that's what happening, though. At a quick glance, the primitive words seem to be directly implemented in C: https://github.com/eliben/goforth/blob/3949fe0cc52131fdcae0e38ac5f6aee596056d3b/ctil/builtins.c#L106 https://github.com/eliben/goforth/blob/3949fe0cc52131fdcae0e... So it looks like this one kind of sits in between. It has primitive words implemented in C, but a dictionary accessible by Forth. The interpreter loop however seems to be implemented in C as well, not Forth.
- johnecheck 1y agoI remember when I realized just how little host language code was needed to bootstrap a Forth. Before that I was making the same mistake. OP, I strongly recommend the book Threaded Interpreted Languages [1]. I had to read chapter 2 several times before it clicked (short and dense), but it's an excellent resource. [1] https://archive.org/details/R.G.LoeligerThreadedInterpretiveLanguagesTheirDesignAndImplementationByteBooks1981 https://archive.org/details/R.G.LoeligerThreadedInterpretive...
- pjmlp 1y agoI agree, Lisp and Forth share this beauty of needing only a handfull of Assembly written primitives, and then the whole world can be bootstraped out of them.