[HN Gopher] My history with Forth and stack machines (2010)
       ___________________________________________________________________
        
       My history with Forth and stack machines (2010)
        
       Author : homebrewer
       Score  : 109 points
       Date   : 2024-12-28 16:34 UTC (1 days ago)
        
 (HTM) web link (yosefk.com)
 (TXT) w3m dump (yosefk.com)
        
       | DonHopkins wrote:
       | I just posted some historical info about Chuck Moore's work for
       | HOMER and Associates on a real time visual mixing console that
       | produced many music videos that ran endlessly on MTV back when
       | they actually played music videos, and special effects for
       | blockbuster films like RoboCop and Total Recall to the discussion
       | about abstractions:
       | 
       | https://news.ycombinator.com/item?id=42532404
        
       | mud_dauber wrote:
       | I got a taste for this years ago at Harris Semi. Grokking their
       | RTX microcontrollers was a ton of fun. (Not so much for
       | customers, who'd never seen such a thing.)
        
       | romforth wrote:
       | I have ported Forth to a dozen small microcontrollers and my
       | experience writing much of the bootstrap code in Forth tells me
       | that you are better off coding Forth in a "vertical" style (ie
       | one word per line with stack picture comments), rather than the
       | terse "horizontal" code of "everything on one line" that many of
       | the folks using Forth (including @yosefk, the author) seem to
       | prefer.
       | 
       | Given how close Forth is to assembly (seen from an implementer's
       | point of view) it makes sense to write Forth in a "vertical"
       | style which reflects the "vertical" style in which assembly code
       | is written. This has the advantage that the "stack picture
       | comments" on each line of code can stand in for Hoare triplets so
       | that the code and its - I'll call it - "proof" can be written
       | hand in hand at the same time.
       | 
       | This is how all of the Forth code that I've written in
       | https://github.com/romforth/romforth is structured.
       | 
       | It does make the code appear less compact though so you are not
       | going to win any code golf prizes.
        
         | Lerc wrote:
         | Is there any editor/IDE support for stack state visualisation?
         | 
         | A text display with an auto pretty printed view would serve
         | people who like both code styles well.
         | 
         | A newline per stack reducing operation with the next line
         | indented by stack depth would make it close to your style and
         | could be quite automatic.
        
           | romforth wrote:
           | Something like an automated proof assistant to help annotate
           | the stack while coding would be awesome, but I'm not aware of
           | any.
           | 
           | These might be famous last words, but if switching between
           | compile/interpret modes is ignored, I think it shouldn't be
           | too hard to implement it though.
        
             | nxobject wrote:
             | I do that's the rub with any language that works with
             | procedural macroexpansion: it's conceptually hard to make
             | diagnostics correspond one-to-one with original syntax. I
             | think it might be especially hard with Common Lisp-style
             | reader macros (i.e. procedures triggered at the parsing
             | stage when a character is read in the input stream).
        
           | cess11 wrote:
           | Adjacent rather than a Forth, but take a look at Factor.
           | 
           | https://factorcode.org/
        
             | 7thaccount wrote:
             | Also 8th. I find the free version fun to play with as a
             | modern desktop forth with built-in support for things like
             | databases, odbc, json, matrices...etc. The commercial
             | aspect won't be most people's cup of tea of course, but I
             | still think it's neat and 8th is probably the most
             | approachable way to write a desktop app with forth.
             | 
             | https://8th-dev.com/
             | 
             | https://8th-dev.com/manual.html
        
         | volemo wrote:
         | We removed explicit arguments from the language so you can
         | write comments with arguments after every function call. :D
        
       | nxobject wrote:
       | I'll agree with a lot of his critiques, but one of his small ones
       | that surprisingly echoed a lot of frustration was the dictum to
       | prefer small definitions.
       | 
       | > Quoting Chuck Moore:
       | 
       | > Forth is highly factored code. I don't know anything else to
       | say except that Forth is definitions. If you have a lot of small
       | definitions you are writing Forth. In order to write a lot of
       | small definitions you have to have a stack.
       | 
       | It seemed like apologetics and a making a virtue out of
       | necessity, given the fact that I don't have the capability to do
       | stack acrobatics in my head live. The only way to be able to read
       | a function in my head, without taking a pencil to paper _was_
       | small functions. But I found that clashed with the ways some
       | algorithms and procedures naturally expressed themselves in
       | longer multi-step style, and actually ending up being more
       | verbose and tangled with multiple top-level definitions.
       | 
       | It turns out that local variables that compile to C-style
       | indirect (SP + i) accesses are only mildly more expensive than
       | stack acrobatics, but still gave the flexibility of Forth-style
       | metaprogramming. [1]
       | 
       | Ultimately, the author's points about the "Forth philosophy" but
       | not Forth-the-language itself (and extremely spare code) ring
       | true to me.
       | 
       | Given my limitations, life is too short to work to have as
       | minimalist an implementation as you'd like, and to desire to have
       | a interactive development environment in <128k. For me, it's hard
       | enough to implement the "subject" that I'm programming
       | algorithmically/data-driven-ly/amortizing-computation-ly
       | efficiently.
       | 
       | [1] https://www.novabbs.com/devel/article-
       | flat.php?id=26347&grou...
        
         | nalsirety wrote:
         | It's easier to approach Forth as assembly-like than C-like.
         | 
         | That is, why are you factoring the code to use the stack when
         | you have globals?
         | 
         | (Mumble mumble structured program, recursion, reuse)
         | 
         | If you move towards a global-first approach(which is what Chuck
         | Moore seems to have moved towards, from anecdote), what changes
         | is that you can substitute the word defining the variable for
         | another word, later down the line, that adds the context,
         | indirection and error handling you need. The mechanism can be
         | added without changing how the word is being used, and you can
         | still write a divide-and-conquer kind of algorithm in this way,
         | it's just more classically imperative in style, with more
         | setting of mutable global temporaries and every byte of
         | bookkeeping directly accounted for.
         | 
         | Part of the minimalist freedom in Forth is that it is agnostic
         | to whether you're using the stack or the dictionary. If you
         | want the word to be unambiguously about a particular space in
         | memory it makes sense to define it first in terms of "it
         | accesses this static location" instead of "it consumes three
         | things on the stack and shuffles them around and indirects one
         | to a memory location and adds the other two", because that
         | inclines all the words to be about the stack. Take the
         | primitive approach - the one that maps well to assembly - first
         | and see how far it goes. You stay in control of how you're
         | extending the language that way. C preempts that because the
         | compiler hides the stack manipulation, so the semantics of the
         | function will default towards locals, and then further
         | extension is guided around fitting it into that.
         | 
         | (And it's true that the compiler gets you to an answer faster,
         | and black-boxes the interface, so you can use code without
         | reading code - and that is coming at the expense of precision
         | around details like this. Forth is probably not the right way,
         | if it's Conway's law that you're up against.)
        
           | rep_lodsb wrote:
           | In most assembly languages, accessing local variables on the
           | stack is easy, plus you have multiple registers for temporary
           | data. Forth feels extremely limiting compared to that.
           | 
           | On an architecture without those features, like the 6502,
           | Forth _may_ be a good idea, and possibly faster than C - but
           | only if it 's compiled to machine code with some peephole
           | optimizations, so that e.g. "123 MY-VAR C!" translates into
           | "LDA #123 ; STA MY-VAR", instead of a naive implementation
           | where the address and constant would first be pushed onto the
           | stack.
           | 
           | And any more complicated optimizations would probably require
           | first "decompiling" the Forth code back into a higher level
           | of abstraction. It's practically the same as assembler macros
           | otherwise.
           | 
           |  _edit:_ fixed order of operands. I originally wrote  "MY-VAR
           | 123 C!", but then remembered that the address to store to has
           | to be on top of stack. IMHO, infix notation is less
           | confusing, and writing a recursive-descent parser to handle
           | it isn't that hard compared to everything else in
           | implementing a compiler. And of course in an infix language,
           | "123 := MYVAR" would be a syntax error, instead of storing
           | (the low byte of) the address of MYVAR into memory location
           | 123.
        
           | nxobject wrote:
           | I appreciate your nudge towards thinking in a global-style
           | manner - it does remind me of the style that early Macs and
           | PCs wrote their software in, with memory and all lifetime
           | data accounted for before the algorithms. (Maybe instead of
           | the structured programming "Algorithms and Data Structures"
           | (Wirth) approach, it's "Data Structures and Algorithms".)
        
       | vok wrote:
       | I think that "Good Forth programmers arrange things so that they
       | flow on the stack" has analogs in other languages. For example,
       | arranging things in J so that short tacit expressions naturally
       | provide the functions you need.
        
       | abrax3141 wrote:
       | You want to be truly amazed, check out Newell's IPL-V, which is a
       | machine language for a stack machine, developed in the 1950s and
       | used to implement the first AIs. It had every idea n Lisp except
       | the parens.
        
       | codr7 wrote:
       | I feel like Forth will always have a place in embedded contexts.
       | And it's a good language to start with when learning how to write
       | interpreters/compilers.
       | 
       | The second you start building higher level apps in Forth, you
       | lose most of its advantages from my experience.
       | 
       | While usable as an in-app scripting language, I would pick Lisp
       | any day.
        
         | vdupras wrote:
         | The opinion that Forth doesn't climb the abstraction ladder
         | well is popular, but I'd be tempted to qualify it as a
         | misconception.
         | 
         | My own attempt[1] at a Forth that climbs that ladder is, I
         | think, a good counter example. In my opinion, its HAL compares
         | favorably to, for example, SBCL's native code compiler. Its
         | almost-C compiler compares favorably to, I think, Tiny CC.
         | 
         | This misconception stems, I think, from the fact that you can
         | very well reap the rewards of Forth in a low level environment
         | without needing to "think in Forth". For example, by mastering
         | immediate mechanics.
         | 
         | Someone who hasn't invested the effort to twist their mind to
         | Forth-think will, yes, end up having troubles climbing the
         | abstraction ladder.
         | 
         | This is not unlike, I think, "macro heavy" lisp, which many
         | lispers actively avoid. But at the same time, much of lisp's
         | power comes from it.
         | 
         | [1]: http://duskos.org/
        
           | codr7 wrote:
           | It's not so much tools as convenient abstractions I feel are
           | missing. Nice, but an OS is about as low level as they come.
        
       | hlehmann wrote:
       | I had a job in 1982 or so that involved programming in Forth. It
       | kinda made sense at the time to my young impressionable self, and
       | one of the old timers thought it was ideal for what we were
       | working on at the time. It all ran on a single thread; I don't
       | even recall it having interrupts. I can't imagine using it for
       | anything practical today.
        
       | veltas wrote:
       | I appreciate Yossi's plain honesty in this article, and it's a
       | fun and interesting read; I've read it before.
       | 
       | I can relate to, but not endorse, designing a CPU and dialect for
       | an interesting language you've never properly used. This turned
       | out to be very painful, and Yossi argues convincingly that it is
       | essentially not practical to use Forth at all, debating Jeff
       | Fox's position. However, there is some evidence[1] that Forth
       | actually might be practical, and it certainly seemed to have a
       | niche in the 80's.
       | 
       | Yossi made some errors I've seen among new Forth programmers. A
       | lot of people, before writing real programs, think Forth is like
       | lisp from another universe. They visualise Forth primarily as a
       | sort-of functional, concatenative, highly refactor-focused
       | language. They likewise tend to throw out all the normal Forth
       | defining words and use Forth as 'lisp without parentheses'. They
       | try and put all their data on the stack, 'point-free', rather
       | than using variables. And often their projects eventually devolve
       | into C envy, every line with stack comments and equivalent C code
       | to help, as shown in the article.
       | 
       | But go look at real, working, classic Forth code, of which there
       | is much, and you'll see that there is a prevailing style that's
       | easy to read and not actually that 'smart', or 'academic'. No
       | more than 1-2 stack items need to be mentally 'juggled' for 99%
       | of code, lots of variables and buffers are used whenever it's
       | easier. Yes the classic variables are 'global', but it doesn't
       | matter if the relevant code isn't recursing or touched in
       | interrupts, and is only used by a cluster of related words. Newer
       | Forths do have local variables, in spite of Jeff Fox's
       | disapproval!
       | 
       | The classic code I'm talking about matches what I think Jeff Fox
       | is trying to coerce you towards. Ultimately I disagree with
       | Yossi's views because I think if he had actually tried to
       | implement what Jeff Fox proposes, and got some practice first on
       | a more realistic project, he would have had a much better shot.
       | It's impressive how well the project turned out in spite of the
       | approach, and how Yossi wrote a backend for his architecture in a
       | week: a testament to both his skills and LLVM's design; but it's
       | worth reflecting as engineers how arrogant (yet relatable) it is
       | to make a CPU and compiler for a language you've never properly
       | used.
       | 
       | [1]
       | https://www.hardware-x.com/article/S2468-0672(22)00025-6/ful...
        
       | OldGuyInTheClub wrote:
       | I have read this article many times, usually whenever I look at
       | Forth for whatever reason. As a non-computer scientist I learn a
       | little about language design every time I look at it. But,I can
       | never figure out what the author actually thinks about Forth. It
       | seems like he is interested by it and sometimes amazed by it but
       | has concerns and ultimately decides it is not for him. I could be
       | way off on multiple axes though.
        
         | matheusmoreira wrote:
         | He thinks he's not smart enough for it.
         | 
         | He describes the good Forth programmers as people who are so
         | smart they can focus on nothing but the problem. To such
         | people, programming languages, operating systems, libraries,
         | even the chips that run all this stuff, they are all non-
         | problems, to be reduced or eliminated. And to do that, it
         | requires that the mind be able to compensate for all the
         | comfort all of those layers would have afforded.
         | 
         | > Why pay this cost? _[The cost of adding junk you don 't
         | actually need]_
         | 
         | > Because I don't do algorithms, other people do, so I have to
         | trust them and respect their judgment to a large extent.
         | 
         | > Because you need superhuman abilities to work without layers.
         | 
         | > The Forth way of focusing on just the problem you need to
         | solve seems to more or less require that the same person or a
         | very tightly united group focus on all three of these things,
         | and pick the right algorithms, the right computer architecture,
         | the right language, the right word size, etc.
         | 
         | > I don't know how to make this work.
         | 
         | > having people being able to do what at least 3 people in
         | their respective areas normally do, and concentrating on those
         | 3 things at the same time
         | 
         | > Doing the cross-layer global optimization.
         | 
         | A sufficiently smart person is capable of analyzing and
         | optimizing the problem from the requirements all the way to the
         | literal chip running the software. They come up with custom
         | unconventional algorithms and implement weird chips with 18 bit
         | words.
         | 
         | These are people who are smart enough to modify standard
         | engineering equations. Those things weren't sacred to them,
         | they understood them to the point they felt confident enough to
         | change them in such a way that they could be efficiently
         | implemented in some weirdly minimal custom chips[1]. And this
         | somehow yielded more efficient algorithms which were easy to
         | implement in Forth.
         | 
         | I share their enthusiasm for minimalism and eliminating the
         | dependencies and the "junk". It always ends with me learning
         | everything I can about the junk and doing it myself, maybe even
         | reimagining it, hopefully better and smaller this time. I can
         | only hope to one day be half as smart as some of these folks
         | seem to be, though. Every time I try to get into hardware, I
         | discover my limits.
         | 
         | [1]: The Yamaha DX7 is an example. People understood things and
         | reframed the problems until the solution fit the available
         | resources. They needed a sine wave...
         | 
         | https://www.righto.com/2021/12/yamaha-dx7-reverse-engineerin...
         | 
         | > multiplying the sine wave by the envelope level yields the
         | output
         | 
         | > However, fast multiplication required too much hardware in
         | the 1980s, so the DX7 uses a mathematical shortcut: adding
         | logarithms is equivalent to multiplying the values.
         | 
         | > The obvious problem is that computing logarithms is harder
         | than multiplying, but the trick is to store the (negated)
         | logarithm of the sine wave in the lookup table (below) instead
         | of the sine wave.
         | 
         | > This provides the logarithm for free.
         | 
         | > The implementation takes advantage of the symmetry of the
         | sine wave so only a quarter-wave needs to be stored.
        
           | OldGuyInTheClub wrote:
           | Thanks for clarifying! In that case, he and I have the same
           | "problem" although at very different levels. I've written in
           | other posts about Forth and Lisp that I would very much like
           | to get over the hump of changing how I think about problems.
           | Unfortunately, I have never been able to do it.
           | 
           | There are times where I see how Moore and McCarthy are using
           | a language to define itself. I can sort-of understand how
           | Moore creates a custom language in Forth to tackle something.
           | But, damned if I can explain it or apply that to even a toy
           | problem. I am thankful that there are people out there who
           | can think differently.
        
           | nxobject wrote:
           | That being said, I wonder whether those applications tend to
           | be embedded or devices, that lend to "first, you must invent
           | the world" style thinking (which is good!)
           | 
           | The last task I was doing on a side project was making sure
           | some bidirectional content accessible by a screen reader,
           | which was the ultimate task of relying on other people's
           | work.
           | 
           | Ultimately, I can't imagine having to think through in an
           | integrated matter all of the layers that power this TTS -
           | from the Unicode parsing, through the NN models to the sound
           | synthesis, all the way to dealing with sound output.
        
       | GlenTheMachine wrote:
       | I desperately wish I had been introduced to Forth when I was
       | learning assembly circa 1984 on my Commodore. Would have changed
       | my life.
        
         | SoftTalker wrote:
         | I had Forth for my TI/99-4A but at age 14 I lacked the
         | background and context to be able to understand it or a mentor
         | to get me started. I took a couple of stabs at it but the book
         | I was using was just over my head, when all I had for
         | comparison was programming I had done in BASIC. No internet in
         | those days of course.
        
           | osullivj wrote:
           | I got hold of the FIG UK 808O listing, and ported to Z80 to
           | run on my Camputers Lynx.
        
       | PaulHoule wrote:
       | Stack machines are a place where hardware goes to die. We have
       | this book at my Uni library
       | 
       | https://www.amazon.com/Stack-Computers-Wave-Philip-Koopman/d...
       | 
       | but in 1989 these were not a new wave at all, but another CPU
       | without a future like the Lisp machines.
        
       ___________________________________________________________________
       (page generated 2024-12-29 23:02 UTC)