Pictogenesis: Stack Machine

Okay, enough with register machines. Let’s make something new. This time, a stack based machine!

Rather than keeping it’s memory in a series of memory cells, there will be a single stack of values. All functions can pop values from the top of the stack or push them back on. I will add the ability to read the X/Y value and directly write R/G/B, but you can’t write to the former or read from the latter, so you can’t use them as registers. Let’s see what that looks like!

The first thing I want to do is add a handful of new instructions that don’t really make as much sense in the register machine, but do in a stack context:

const stackInstructions = instructions.concat([
  // Functions to read/write X/Y/R/G/B (also on the stack)
  {name: "readX", function: function() { return this.x;}},
  {name: "readY", function: function() { return this.y;}},
  {name: "writeR", function: function(v) { this.r = v; }},
  {name: "writeG", function: function(v) { this.g = v; }},
  {name: "writeB", function: function(v) { this.b = v; }},

  // Duplicate the top element of the stack
  {
    name: "dup",
    function: function(x) {
      this.stack.push(x);
      this.stack.push(x);
    }
  },
]);

Here I’m actually getting a bit more tricky. I can’t use the () => ... syntax, because this behaves differently than when using the function syntax (even with apply). Specifically, with an arrow function, this is still set to the context the function was defined in. But now, I can actually pass this in and mess with variables on that object:

var result = command.function.apply(this, args);

Doing this, I’m passing the this of the run function into the function() in the instructions object as this. That’s one of the things that Javascript both does well and can really bite if you get too fancy (which I’m often guilty of).

That’s most of it, so let’s check out the demo!

Unfortunately, about the coolest image I got in my testing was this:

Since most of the stack functions pop two variables, they are almost always grabbing 0 (when the stack is empty) and breaking things. So it goes. It was still interesting to write up.

I think next I’ll work on transpiling this (like I did for registers). And then on to some other type of function! S-expressions? Neural networks? Who knows!