
Stack-Oriented Programming - azhenley
https://en.wikipedia.org/wiki/Stack-oriented_programming
======
jandrese
The old RoboWar game on the Mac featured a stack oriented language for
programming your battle robots. It was a great introduction to RPN and
thinking about the stack.

One of the interesting aspects of the game was the way the CPU was limited to
a very small number of instructions per tick. At most you would get 50. So if
you had a complex task that had to be executed in one tick, like filling the
screen with bullets before your robot shut down due to lack of power, the way
to do it was to preload all of the arguments onto the stack, wait for the tick
to turn over, then call all of the functions at once. Basically allowing you
to bank processing time for the turn you needed it.

~~~
skocznymroczny
In CoreWars, which used assembly-like language to create programs fighting
each other, one of the most powerful strategies was to inject a SPL
instruction (basically fork) into an enemy program, preferably jumping to the
SPL instruction itself. As a result, the enemy program would quickly be split
into 64 processes (usual maximum number), so the actual logic would be running
at 1/64 speed, bogged down by the dummy processes.

~~~
flir
If you could successfully do that, why wouldn't you just bomb a DAT in
instead?

~~~
brazzy
Because the opponent could already be running multiple processes - killing one
would only speed up the others.

The programs that uses the SPL-bomb tactic usually tried to catch all the
enemy processes (slowed down to uselessness by the SPL-bomb) in the same place
before finishing them off with a DAT.

~~~
flir
I see. I don't think the original version of CoreWars had multiple program
counters? Got to admit it's been a while.

~~~
brazzy
You're right, the version described in the original article in the Scientific
American did not have the SPL instruction, but the first "Core Wars Standard"
proposal in 1988 introduced it.

You can see the different versions collected here:
[https://corewar.co.uk/standards/](https://corewar.co.uk/standards/)

------
n4r9
I went through a basic Forth tutorial [0] a couple of years ago and really
enjoyed the process. It gets you to the point of building a real game of
"snake", although it slightly glosses over the actual canvas interface.

[0]
[https://skilldrick.github.io/easyforth/](https://skilldrick.github.io/easyforth/)

~~~
int_19h
The really interesting thing about Forth is just how minimalistic a bare-metal
Forth implementation can be - not even an interpreter, but literally a few
words handcoded in machine code, and the rest built from there (and then
possibly optimized with more machine code, _if_ you need that).

Given the ease with which Forth can be ported to other platforms and
architectures, I often wonder why there's no C-to-Forth translator - it seems
like it would be just about the easiest way to bootstrap things.

~~~
pjmlp
Bare metal like on the Ace.:)

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

[http://jupiter-ace.co.uk/](http://jupiter-ace.co.uk/)

------
xiphias2
Bitcoin also uses stack oriented language, and the interpreter is actually
very short and simple:

[https://en.bitcoin.it/wiki/Script](https://en.bitcoin.it/wiki/Script)

[https://github.com/bitcoin/bitcoin/blob/master/src/script/sc...](https://github.com/bitcoin/bitcoin/blob/master/src/script/script.cpp)

~~~
triska
Yes! Stack-based abstract machines are often used because they allow compact
code that is very easy to create and interpret.

As another example, Pascal p-code (UCSD p-code) is also stack-based:

[https://en.wikipedia.org/wiki/P-code_machine](https://en.wikipedia.org/wiki/P-code_machine)

The Java Virtual Machine (JVM) also uses an operand stack:

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

~~~
jacobush
That P-code was not (quite!) portable between computers, was a lost
opportunity. How cool it would have been.

------
souprock
Oddly, that article doesn't link to the most interesting modern use. It's for
security exploits. People have built compilers that output a binary that
consists largely of return addresses that point into the middle of normal
functions.

[https://en.wikipedia.org/wiki/Return-
oriented_programming](https://en.wikipedia.org/wiki/Return-
oriented_programming)

~~~
9214
This deserves a bit of clarification: ROP is an application of threaded code
technique. Conventional Forth (proto-father of stack-based/concatenative
languages, alongside with Joy) is based on indirect-threaded code (ITC), so
the connection between ROP and stack-based programming is rather indirect (pun
intended).

For anyone interested, Book by Loeliger [1] and "Moving Forth" series [2] are
essential readings on this topic.

[1]:
[https://archive.org/details/R.G.LoeligerThreadedInterpretive...](https://archive.org/details/R.G.LoeligerThreadedInterpretiveLanguagesTheirDesignAndImplementationByteBooks1981)

[2]:
[https://www.bradrodriguez.com/papers/](https://www.bradrodriguez.com/papers/)

------
munk-a
I'm a bit confused why "using postfix notation" is considered a programming
paradigm - I'm semi-fond of post-fix notation (it is the second best notation
after prefix after all) but[1] it's incredibly trivial to convert between
prefix and postfix notation and most programming language expressions use
prefix already - it's just the infix ones that are a bit weird... Allllso,
expressing if statements without any infix notation is sort of terrible, I've
never seen an option to do it that isn't incredibly misleading or confusable.

A core question, though, is why? Is tab-oriented programming have a wikipedia
page where programs are written predominantly using tab stops instead of
spaces? It's honestly a very similar sort of distinction to make.

1\. I'm trying not to stray too far into all turing complete languages are
turing complete and thus difference is meaningless land.

~~~
triska
As I see it, the key characteristic of stack-oriented programming is not that
it "uses postfix notation".

Rather, the key characteristic is that there is an important _implicit_
feature available, namely _the stack_ (or, as for example in the case of
PostScript, _several_ stacks), by which arguments can be passed along.

As a consequence, you get a form of _compositionality_ of language elements
that is not available in languages that lack this feature: A language element
may consume, change and create entities on the stack, and the next language
element can pick them up _implicitly_.

This often allows very concise and elegant code, and can also be interpreted
very efficiently.

~~~
munk-a
That's quite helpful, it may be a lack of in-depth reading of the page but the
persistence and implicit passing of computation between operations is helpful
to understand the differentiation. In more classic procedural languages you'll
usually have a function stack that is being pushed and popped two but actual
program values are handled using entirely arbitrarily loaded references that
get juggled around as needed for computation - does stack programming often
have a similar concept to frame popping when an issue with I/O or something
similar is encountered or do we just get a panic that aborts computation?

~~~
triska
To get a glimpse of stack-oriented programming, I really like and recommend
_PostScript_ , because this also automatically introduces you to a widely used
programming language with important practical applications, and it's also
great fun to learn.

So, for instance, let's elicit an error using Ghostscript, a freely available
and efficient PostScript interpreter:

    
    
        $ gs
        GPL Ghostscript 9.27 (2019-04-04)
        ...
    

At the "GS>" prompt, I now define "f" via:

    
    
        /f { /hello g } def
    

Note that "f" refers to "g", which is not yet defined.

Therefore, when I then invoke "f" via:

    
    
        GS>f
    

I get an error:

    
    
        Error: /undefined in g
    

And importantly, the stack is _retained_ , so I can inspect it at this point,
interactively, using for example "pstack":

    
    
        GS<1>pstack
        /hello
    

This shows that /hello is still on the stack. From there, we can resume in
various ways, for example by _clearing_ the stack (with "clear"), by
redefining and reinvoking "f" etc.

~~~
haolez
Is PostScript used beyond page description? I'm really curious :)

~~~
pedrow
I recently saw an announcement[0] of a Z-machine in Postscript. The Z-machine
is a runtime for text adventure games. Also posted on HN[1] but no comments
were made.

[0]: [https://groups.google.com/d/msg/rec.arts.int-
fiction/HNtntxC...](https://groups.google.com/d/msg/rec.arts.int-
fiction/HNtntxCpcHA/IB0EiadzDgAJ)

[1]:
[https://news.ycombinator.com/item?id=21367412](https://news.ycombinator.com/item?id=21367412)

~~~
zzo38computer
Yes; I wrote that program, and the Usenet message and the message on HN (which
mentions the message ID for the Usenet message). If you have comments about
it, I suggest writing a follow-up message on Usenet.

PostScript is a real programming language and can be used for many things
(especially graphics). I also wrote a JSON parser in PostScript (see message
<1567977875.bystand@zzo38computer.org> on comp.lang.postscript), and then
someone else post their JSON parser in PostScript too.

I think PostScript isn't such a good protocol or document format, but it is
good as a programming language. It is what I might use if I want to make a
diagram (but unfortunately Ghostscript cannot produce SVG output; it can
output PDF though, as well as many raster formats).

~~~
haolez
Nice! Thanks for answering! Would you choose PostScript over Forth as a
general purpose language?

~~~
zzo38computer
I think it would depend on what I am trying to make; there are advantages and
disadvantages to each. In the case of the JSON parser, I think it is helpful
that PostScript has data structures (such as arrays and dictionaries) and
arbitrarily typed values like JavaScript and many other scripting languages
have. In the case of Z-machine, Forth would probably do as well as PostScript
(or probably Forth would do better, actually).

Someone was unsure how useful would be the JSON parser I wrote in PostScript,
but if you want to print some diagram based on data in JSON format, then it
can be helpful.

(I could implement Z-machine in Forth too if I wanted to do, but I have not
done so yet because I have other things to do; I don't know if I might do so
in future or not. I could implement Z-machine in any programming language with
byte arrays, including assembly language (I started but haven't finished one
in 6502).)

------
punkbrwstr
The stack-oriented approach can also be used within modern languages to
realize the benefits of simplicity and code-reusablility. I created a python
package for data analysis that treats a data frame like a stack of columns and
lets you manipulate columns using postfix operators:
[https://github.com/punkbrwstr/pynto](https://github.com/punkbrwstr/pynto)

~~~
reedwolf
Wow, this looks really interesting. Was there any particular reason you
decided on this approach?

~~~
heavenlyblue
How is that more interesting than simple .modify_column(params)?

~~~
punkbrwstr
You definitely could do a similar column-level functional approach that way,
but I think the simple syntax of the stack-oriented approach makes it easier
to read and catch errors. The code would be a lot longer that way.

------
joncp
This makes me miss my HP 28S calculator from the 80s. What a beautiful machine
that was.

~~~
smabie
I loved my HP-50g, allowed my to program all day long while stuck in stupid
high school classes. RPL is a nice little language, a bit hard to read after a
break though. And the fact that HP calculators throw away all whitespace and
indention after saving a program certainly doesn't help.

------
zzo38computer
I have used Forth, PostScript, dc, and other stack-based prorgamming. However,
mostly in PostScript code I have not seen the Forth-like notation for the
stack effect, although I do use that in my own PostScript programming, because
I think it is better than the notation Adobe uses.

Some virtual machine instruction sets (such as Glulx and Z-machine code) still
require instruction operands but allow some or all of them to be optionally
specified as stack operands. This allows you to have both stack and a
register-like programming.

------
pipingdog
A Brainfuck tape can be thought of as two stacks and a register. ‘<‘ or move-
left becomes push the register onto the right stack and pop the left stack
into the register.

------
tombert
Can someone who knows more about Forth clarify this for me: what "level" is
something like Forth? Is it higher or lower-level than something like C?

The reason I'm confused is that I see Forth in a lot of areas that look like
they're typically for "C and lower", but looking at the syntax, Forth looks
like a high-level language.

~~~
astrobe_
Neither.

 _I recall that the first thing that jumped out at me was that Chuck 's code
didn't have all those layers that my code had. There was the abstracted code
on top and the hardware drivers on the bottom and very little in between.
There was not a clear distinction in style at various levels as in my code
where there were always someone else's code layered under mine that I could
not or dared not change. Chuck's code looked abstracted and high level right
from the bottom, the top used almost as many primitives as the bottom code._
[1]

The confusion seems to come from the idea that a piece of code _has to be_
either "abstract" all the way or "close to the metal" all the way. Why should
it be? If you need to flip a bit in a peripheral between a call to some
filesystem function and a call to memory page management function, just do it
directly, don't invent a pseudo-high-level function just for that. Bare metal
ain't dirty.

[1]
[http://www.ultratechnology.com/levels.htm](http://www.ultratechnology.com/levels.htm)

~~~
pjc50
> Bare metal ain't dirty.

No, but it's not as solid as it sounds. What happens when version 2 of the
hardware appears, and moves the bit to a different register?

~~~
pjmlp
The same thing when a new OS release break some API call.

~~~
pjc50
.. which they do far less often than hardware changes. You have a reasonable
chance of running a 25-year-old Win32 program or 20-year-old statically linked
ELF Linux program.

------
virtuous_signal
I recently wrote an accepted answer on cs.stackexchange about how to implement
sorting on a stack machine:
[https://cs.stackexchange.com/questions/117949/stack-
permutat...](https://cs.stackexchange.com/questions/117949/stack-permutation-
algorithm/117975#117975)

The asker isolated the question well, so I had no idea what Forth or stack
machines are. Still it's a nice exercise to to implement common algorithms
with a restricted set of moves.

------
quintenk
Fun to see this, I just finished implementing a stack-based language of my own
design this weekend.

The language is called UnoScript, inspired by the UNO card game. UNO has a
natural stack built-in (thinking of the draw and discard piles) so there's a
really natural connection. Link here if you're curious:
[https://github.com/berlinquin/UnoScript](https://github.com/berlinquin/UnoScript)

------
raxxorrax
There are stack based languages that have an intrinsic elegance. For example:

[https://esolangs.org/wiki/Pancake_Stack](https://esolangs.org/wiki/Pancake_Stack)

And remember to Eat all of the pancakes!

An interpreter can be written rather quickly (compared to any productive
program in the respective language) and it is interesting how much you can
actually achieve with such primitive tools.

------
wodenokoto
Is Human Resource Machine [1] basically also a stack oriented programming
game, or am I confusing the physical stacks of paper you order the little guy
to move around with computer stacks?

[1]
[https://tomorrowcorporation.com/humanresourcemachine](https://tomorrowcorporation.com/humanresourcemachine)

------
mzs
8087 had an 8 level stack
[https://en.wikipedia.org/wiki/Intel_8087#Registers](https://en.wikipedia.org/wiki/Intel_8087#Registers)

~~~
enriquto
> 8087 had an 8 level stack

Why "had"? The x87 instructions are alive and well in modern intel processors.
You can also generate code for them (for example, if you use "long double" in
C) with all major compilers.

------
marviel
Just saw this in your class this morning!

------
pagutierrezn
I expected this to be a joke about Stack(Overflow)-Oriented Programming

------
stinos
I read this title and thought, hmm is this another name for 'lock-in' or
similar? You know like pick a stack of tools and then only use those, to the
point you can hardly do anything at all without them. (which isn't necessarily
bad, if it allow you to get things done fast and good)

On topic: always good to read up on less common programming principles just
to, erm, avoid lock-in

~~~
rckoepke
I believe that's called resume oriented development.

------
empressplay
May the Forth Be With You! :)

~~~
CarlRJ
FORTH LOVE IF HONK THEN

