
Running Forth Unikernels - eyberg
https://nanovms.com/dev/tutorials/running-forth-unikernels
======
mjevans
It really depends on your Forth environment. The language is a great one for
bootstrapping an operating environment since a small blob can define basic
routines and building blocks for more complicated operations.

The language is a dynamic synthesis of incremental compiler and Basic
Input/Output System where more generic and cross implementation concepts can
be added or re-defined.

[https://en.wikipedia.org/wiki/Forth_(programming_language)](https://en.wikipedia.org/wiki/Forth_\(programming_language\))

Skimming this I don't see any actual reference to a standard method for
accessing a filesystem, I suppose in cases where a filesystem is relevant
there'd either need to be a driver for that written in native forth, or a host
operating system which could be called via a syscall of somekind.

I expect Forth to be used in different contexts, but mostly in this order:
extremely low level (high performance in L1 cache execution), early boot (a
slower / read only FS driver is fine), or toy / experiment / prototyping
(syscalls might be good enough). Anything else can probably afford to be
written in a more easily maintained language.

One benefit of the early boot context is that, in theory, a minimal
compatibility standard could be written and one 'interpreted' (hooks on to the
definitions of functions already in the context stack) driver could function
on vastly different hardware as long as it didn't actually use native
assembly.

~~~
peteri
Historically Forth was block orientated (1024 bytes)

[https://www.forth.com/starting-forth/3-forth-editor-
blocks-b...](https://www.forth.com/starting-forth/3-forth-editor-blocks-
buffer/)

When I implemented this in a home rolled Forth on the Apple //e under Prodos
(mid eighties) I used the Apple sparse file with random IO as block orientated
drive. The Starting Forth link suggests that's a common mechanism. I suspect a
lot of micro Forths just hit the disk directly.

------
protomyth
As much as I love Forth, I am a bit troubled by the list in the article:

Some interesting but by no means complete Forth properties:

    
    
        no errors
        no files
        no operating systems
        no syntax
    

uhm... Forth does have errors like Stack Underflow. When I programmed in Forth
we did have the notion of files. It most certainly does have a syntax also.

~~~
mruts
People talk about forth having no syntax the same way people talk about lisp
having no syntax: not entirely correctly. Of course, every textual
representation of anything has a syntax, but when people talk about something
not having a syntax what they really mean is that the syntax is uniform: there
is only one global (uniform) syntax.

~~~
madhadron
> there is only one global (uniform) syntax.

Not quite. You have access to the reader in Forth, and it's quite typical to
write a word that takes over for the reader for some time and then hands back
to the usual reader. Julian Noble used this to implement a subset of FORTRAN
for computational physics (more convenient than postfix for doing that) and to
make state machine transition tables into code. Sadly, he is no longer with
us.

Common Lisp also provides access to the reader, so you can do the same trick,
but it's not a ubiquitous thing to do the way it is in Forth.

------
0815test
If you're going to run an interpreter as a unikernel, arguably you should pick
a typed assembly language and use that to enforce desirable properties about
the assemblies you're running (e.g. protection domains). FORTH doesn't really
make these things feasible so I find that choice quite puzzling.

~~~
geon
The project seems to be just for personal amusement.

------
DogestFogey
Implementing a Forth is a great incremental process, all you need is a
processor with stacks, registers, and RAM. Words are just lists of addresses.
Once you have the base execution routines, e.g. DOCOL, NEXT etc., implementing
the rest of the interpreter is easy. It can even be done on a calculator or
in-game computer![1]

[1]
[http://github.com/siraben/r216-forth](http://github.com/siraben/r216-forth)

------
emeraldd
It would have been very nice to see comments with stack diagrams in the code
examples. FORTH code without them becomes very hard to understand in very
short order.

------
convolvatron
building a bootable image from an executable sounds..pretty convenient(?)

how is this different from docker?

~~~
Someone
Let’s say you run a database in a Docker image. That image will run at least
two processes: a kernel and a database server. Whenever the database server
wants to call code in the kernel, a task switch is needed.

In a unikernel, that overhead is removed by having only a single address
space. You can see it as taking the full source of the kernel and the database
server, linking it into a single executable, and stripping _everything_ you
don’t need, including everything the kernel would need if it supported
multiple processes.

Is that a good idea? Not if the service you’re running wants to be multi-
process, not if you trust your kernel code more than the code of the service
you run on top of it, and not if you want the ability to look inside your
containers (e.g. by ssh-ing into it)

What you do get in exchange is smaller containers (does anybody know why the
image in this example is so enormous? I expected something that easily fits in
64 kB), a smaller attack surface, and faster boot times.

(See also
[https://en.m.wikipedia.org/wiki/Unikernel](https://en.m.wikipedia.org/wiki/Unikernel))

~~~
muricula
Hold on here, kernels do not run as a separate process. And there is no task
switch, just a privilege level switch.

A kernel may or may not exist in a separate address space depending on
hardware and software features (e.g. the arm split paging regime or the
meltdown mitigations). It's just that the kernel memory is not accessible to
userspace code.

