Running Forth Unikernels

Forth has been called lots of things and it was something that I figured we could easily unikernelize so I dove into it. I think it's safe to say I've never written any production Forth nor do I see myself doing so but having said that - let's begin!

Like Go (the game, not the language) Forth is considered easy to learn but difficult to master.

It's commonly used on hardware that doesn't have the notion of an operating system as we view them as. Hhrm... kinda reminds me of something.

Forth is an interesting usecase for unikernels because unikernels being minimalistic by nature fit right in and Forth has been traditionally deployed on devices that are resource constrained.

For instance it's used on the comet lander Philae and has been ran in environments that hold a whopping 16k of memory and that includes everything. So that makes it a good fit for providing backwards support for 'legacy' apps of which you'd be surprised how much still exists but it also is something to look forward to for the future for "beyond edge" applications. Having said that, out of all the unikernel implementations out there, if you are going for size OPS doesn't produce the most minimalistic ones but they are still much smaller than say a typical linux.

Some interesting but by no means complete Forth properties:

  • no errors
  • no files
  • no operating systems
  • no syntax

It has this interesting lispy property where you can start crafting your own language inside the interepter as you are typing it.

As an old HP48G+ calculator owner before the TIs took over Forth also embraces postfix notation. If you've never learned to do math this way you are missing out. Most of us are used to doing math via infix:

eg: A + B

However there are many different ways of expressing this.

We can express it via prefix notation:

+ A B

We can express it via infix notation:

A + B

Or we can express it via postfix notation:

A B +

Of course you don't need to choose between the (better) HP48G+ and the TI89 to understand this concept. Chances are you've already been quizzed about this in various interview settings. Stacks? Queues made out of stacks? How about those pre-order/post-order tree traversals?

Anyways enough about postfix notation - what does this mean for forth unikernels? It sounds like a great fit is what it means!

Enough of the pep talk - let's code!

If you're new to the dev section here you'll want to download OPS from https://ops.city. OPS is a simple tool written in Go that will transform any ELF binary into a unikernel instantly. It also has the concept of 'packages' which are rough analogues to debian packages that allow you to install pre-built software. That's what we are going to do here when we write your first Forth unikernel right now.

First - put this into hi.fth:

.( Hello World!) CR
bye

Great - now let's run it - using ops when can go ahead and download the gforth package, create a unikernel and run it.

➜  fth  ops pkg load gforth_0.7.3 -a hi.fth
Extracting /Users/eyberg/.ops/packages/gforth_0.7.3.tar.gz to
/Users/eyberg/.ops/.staging/gforth_0.7.3
/Users/eyberg/.ops/.staging/gforth_0.7.3/package.manifest
[gforth hi.fth]
booting /Users/eyberg/.ops/images/gforth.img ...
assigned: 10.0.2.15
Hello World!
exit status 1
However, hello worlds don't show you what's interesting about this language - let's look at an example of Pascal's Triangle that I stole from Rosetta Code:

➜  fth  cat pascals.fth
: pascals
  cr dup 0
  ?do
     1 over 1- i - 2* spaces i 1+ 0 ?do dup 4 .r j i - * i 1+ / loop cr
drop
  loop drop
;

10 pascals
bye
Now let's run it:

➜  fth  ops pkg load gforth_0.7.3 -a pascals.fth
Extracting /Users/eyberg/.ops/packages/gforth_0.7.3.tar.gz to
/Users/eyberg/.ops/.staging/gforth_0.7.3
/Users/eyberg/.ops/.staging/gforth_0.7.3/package.manifest
[gforth pascals.fth]
booting /Users/eyberg/.ops/images/gforth.img ...
assigned: 10.0.2.15

                     1
                   1   1
                 1   2   1
               1   3   3   1
             1   4   6   4   1
           1   5  10  10   5   1
         1   6  15  20  15   6   1
       1   7  21  35  35  21   7   1
     1   8  28  56  70  56  28   8   1
   1   9  36  84 126 126  84  36   9   1
exit status 1

Interesting! Also interesting - you can see right now my toy programs are still clocking in at around 8 megabytes:

-rw-r--r--  1 eyberg  staff   7.4M Mar 27 15:13
/Users/eyberg/.ops/images/gforth.img

...and if you're new to this blog - that's an entire disk image - you can take that and go boot it on AWS or GCloud and run it.

Happy Hacking!

Deploy Your First Open Source Unikernel In Seconds

Get Started Now.