Early Interpreters Smalltalk “Blue Book” (esp. Par...
# linking-together
g
Early Interpreters Smalltalk “Blue Book” (esp. Part Four) http://stephane.ducasse.free.fr/FreeBooks/BlueBook/Bluebook.pdf Tiny Basic (including tiny basic virtual machine) https://archive.org/details/dr_dobbs_journal_vol_01/page/n5/mode/2up Frits van der Wateren Lisp (Lisp 1.5) (esp. LISP.TXT) https://github.com/guitarvydas/frits-van-der-wateren-lisp SmallC (strictly not an interpreter, but a compiler (I learned about compilers from this code)) https://archive.org/details/dr_dobbs_journal_vol_05_201803/page/n189/mode/2up, https://github.com/trcwm/smallc_v1
📚 1
b
Nice! I'll add Forth "Programming a Problem-Oriented Language": https://www.forth.org/POL.pdf on which I wanted to write for a while. The book is largely unedited early notes, later published as-is for historic interest. Well structured, but I think parts will be hard to follow for people who don't know Forth? Either way, chapters 3 and 4 talking of the structure of dictionary entries could benefit from diagrams (beyond those included on p.140) => the site https://www.bradrodriguez.com/papers/moving1.htm is the clearest intro I've seen. (I think the book describes what is now known as the "indirect threaded" variant.) • I loved the modest opening
I'm not sure why you're reading this book.  It's taken me a while to discover why I'm writing it.
😂 and constrained focus
Let me warn you now that I'll be talking about programs that will fit comfortably in 4K words of core.
• I expected the book to be "Forth is a cool language, build your apps in it"; instead it was "make your native app extensible—and interactively controllable—by embedding an interpreter" 😮 ◦ Moore says
I'm going to tell you how to write a program. It is a specific program; that is, a program with a specific structure and capabilities.
— the book describes a pattern, an architecture, but those terms hadn't entered programming then yet. • Chapter 4: I love how already then (by ~1970) Moore understood the importance of being able to mint new callables at run time 👏. He does it by each word combining pointer to native code + parameters field. (https://www.bradrodriguez.com/papers/moving3.htm goes into deep details on this) ◦ Compare this to C much later insisting on parameter-less function pointers as the default callable thing, which can only be minted at compile time => having to pass void* parameters through APIs all around, which I think was part of the reason people jumped on C++... This is not quite fair comparison —C wants to be the low-level language in which you implement higher-level stuff— yet I wish we had skipped that detour... • Chapter 7 is an interesting peek into the gone world of language-level multiuser time sharing. It was much easier than full-scale OS with native programs that are free to crash... afaik early BASIC systems started out that way too. (chicken-and-egg: time-sharing enabled multiple interactive users, but there was not much to do interactively before timesharing made it affordable! interpreter REPLs were one of the first use cases.)
g
I will be interested in your thoughts on these issues. thoughts on modern renamings: • threaded code == continuation passing (sans parameters) • Forth == concatenative programming • no named parameters == de Bruijn indexing • postscript is but a flexible app written in a Forth-like manner • my first exposure to time-sharing, aka “multi-tasking” was ch. 10 of Holt’s book Concurrent Euclid, The UNIX System and Tunis (less than a page of pdp-11 code) • we’ve (Torlisp members) created a new discord aimed at demonstrating how to build tiny Forth-ish ideas using modern programming languages, everyone welcome: https://discord.gg/sKTdyBdK7A
b
Forth's EDIT: concatenative langs' separate return stack is the clearest mental picture I've seen for continuations. https://www.nsl.com/k/xy/xy.htm and

https://youtu.be/R3MNcA2dpts?si=N9HU5N_IXffUP8zn

double down on that theme. I'm not sure i'd say it == "threaded code", for me that's just the (two variants of) the memory IR forth compiles to. But the concatenative style, enabled by the separate arg/result stack, does nicely blur the line between explicit "continuation passing" vs. it just implicitly waiting there. I'd love to see how some less LIFO continuations - e.g. promises and iterators - look like in a 2-stack model. Those get harder in Forth without GC. Maybe i should play with Factor.
dup
= de Bruijn 0,
over
= de Bruijn 1, yeah. But de Bruijn indexes came from lambda calculus where you have clear "bound" vs. "free variables".
Copy code
def make_greeter(greeting='Hello, '):
    def greeter(name): return greeting + name
    return greeter
so in the inner function
name
is locally bound, index 0, but
greeting
is comes from the closure, index 1. Forth is looser, every function gets the whole stack and tends to touch some portion of it:
Copy code
: g ( greeting name -- greeting sentence ) over swap concat ;
"Hello, " ( pushed onto stack )
...
"Paul" g
it's a blurrier distinction whether you view it as 1-argument function peeking at "free context" or 2-argument function 'binding" both...
👀 1
What the book makes me appreciate more is how Forth sticking close to the metal is not just a language choice, but a pragmatic FFI choice for interfacing 1:1 to native code. PostScript and Factor have GC, lists and maps. We know now how to expose C to managed languages - Python & Lua highly focused on that - but it does require more glue. In that sense, Forth is an outlier among concatenative languages! 🤯 It's the only REPL where you do raw malloc, memcpy & pointers. Even strings are hard.
👍 1
g
Forth has 2 stacks /AND/ access to the input stream /AND/ the notion of "immediate words".
...
Just about every popular programming language (including Scheme, Racket, Clojure) have inadvertently discarded such aspects of programming by over-emphasizing production engineering and disregarding iterative design.
...
Program Design and Engineering