egranata / krakatau

Krakatau: a stack based virtual machine
Apache License 2.0
12 stars 0 forks source link
cpp17 functional functional-programming stack virtual-machine

Welcome to Krakatau

Build License

Krakatau is a stack-based virtual machine.

It amins to be minimal, fast, orthogonal and easy to program - albeit with permutations of the ordering of those.

Krakatau is based upon the notion of immutable values and a stack.

Values

A value is an immutable box that contains one specific kind of datum.

Values can be of one of the following types:

The stack

The Krakatau VM currently has a single stack on which values can be pushed and popped.

Executing blocks and mutating the stack is the way to perform a computation in the VM.

Blocks

Blocks are the equivalent to functions in the Krakatau language. A block is a sequence of operations, which are by default executed in order from first to last. There are control flow operations that allow to restart execution of a block or skip the remainder of a block.

Blocks take arguments off the stack. As a convenience, one can define slots as part of a block, which are then automatically popped off the stack, and labeled for each execution of a block.

Blocks can be given names and inserted in the value store, or defined at the point of use.

Value store

Krakatau can load programs from a textual language, as well as from a serialized binary format.

Both formats work by describing a series of named values (e.g. main of type block) and putting these in a storage separate from the stack: the value store. Instructions exist to add and fetch values from this storage area. By convention, a program begins by looking for a block named main in the store and executing it.

For example, this is a valid Krakatau program:

value compute block slots $a,$b,$c {
  loadslot $a
  loadslot $b
  add
  loadslot $c
  mul
}

value main block {
  push number 5
  dup
  push number 4
  load compute
  exec
}

It is roughly equivalent to the C++ program

#include <stdio.h>
#include <inttypes.h>

uint64_t compute(uint64_t a, uint64_t b, uint64_t c) {
  return (a+b)*c;
}

int main() {
  printf("%" PRIu64 "\n", compute(4, 5, 5));
  return 0;
}

This is a very simple example, but more interesting programs are possible, and blocks can be nested at arbitrary levels of depth, including recursion.

How to get started

To build Krakatau, you need cmake, lex, and a C++17 compiler (clang and gcc are supported).

build$ cmake ..
[...]
-- Build files have been written to: /home/egranata/krakatau/build
$ make -j
[...]
build$ ls
assembler  CMakeCache.txt  cmake_install.cmake  googletest-download  lexer.cpp  libstuff.so  runner
bin        CMakeFiles      googletest-build     googletest-src       lib        Makefile     tests

The build process generates a series of targets:

Once a build is complete, run tests to check for any issues:

build$ ./tests
[...]
[==========] 299 tests from 63 test suites ran. (12 ms total)
[  PASSED  ] 299 tests.

Join the conversation

To get involved with the Krakatau project,

In all cases, enjoy this project but please know that Krakatau is not an officially supported Google product.