An approach to the Joy Programming Language.

Rabbit-vm is essentially a Joy programming language implementation.

Joy is a functional programming language which is not based on the application of functions to arguments but on the composition of functions. Function composition is done by concatenation.

This is called concatenative, tacit or point-free programming or if you prefer say straight away: pointless programming!

See Joy-at-wikipedia or An informal tutorial on Joy.

System Requirements

Rabbit-vm runs on x86-64 Linux.

It is written in FASM assembly code, using the 64 bit instruction set and system calls of Linux on Intel or AMD processor. (elf64)

  • FASM is needed to compile Rabbit-vm. Development on Linux happens on FASM 1.73.06 flatassembler.
  • rlwrap or something similar is very helpful when working in a repl.

There are no other dependencies, system requirements or libs to link to.


There is no further install process. Download, find a place, unpack or git clone and cd.

    git clone https://bitbucket.org/sts-q/rabbit-vm

Compile a new rabbit-vm and check with:

./rabbit-run -mo
./rabbit  -v

>>> Rabbit-vm  2018-December fasm compiled-on: Linux x86_64 29.11.2018 15:38:23

Does it work?

The following is a short transscript of commands to rabbit and what it's output should look like. Type <enter> on an empty line to leave rabbit-repl.

bash> ./rabbit 3 4 + iprint lf

The rabbit binary reads the commandline, calculates 3+4 and prints the result 7 to screen, followed by a linefeed.

bash> ./rr ddw rotate
rotate {a b c -- c b a}<commandline> 1
(swap swapd swap )

The rr bash script invokes rabbit binary with commands to read rabbit source files. stdlib defines ddw, which prints out the definition of the following word. Rotate in this case, which is defined as swap swapd swap and was first time seen by vm in the commandline, line 1.

bash> ./rr dda Random
Random.boolean      {-- b // maybe true, maybe false, who knows...}
Random.get          {l -- l x  // get x blind out of bag l, return bag (without x) and x}
Random.init         {i --  // init random numbers}
Random.next         {-- i  // return next random number}
Random.ppt          {i -- b  // i parts per thousand are true}
Random.roll         {i -- i  // return 0 <= random number < i}
Random.shuffle      {l -- l  // shuffle l}

dda prints the interface of a module, Random in this case. rabbit source files are loaded and operational.

bash> ./rrr
rabbit> 3 4 +
 !  7   
rabbit>  ddw rotate
rotate {a b c -- c b a} stdlib 51
(swap swapd swap)
rabbit>   <enter>

rrr invokes the rabbit repl. Now, ddw rotate says rotate was first seen in stdlib, line 51.

Rabbit-vm loads rabbit source files, defines new words and accepts commands from it's repl. Ok.

bash> ./rrnb Play.2048

Use the cursor keys to play the game. Quit with q. rrnb sets the terminal to nonblocking mode. All keys are passed to rabbit without terminal intervention. Warning: if rabbit fails to exit, Ctrl-C is passed as well instead of terminating the running rabbit. If that happens you will have to kill the rabbit by hand....;) In case the cursor disappeared say 'rr Xterm.cursor-show'.

bash> grep GNU LICENSE | rrp ' ( "GNU"findseq )map ' | sort

rrp reads from stdin and pipes to stdout.


At sts-q.bitbucket.io can be found an Introduction to Rabbit-vm.

There is no introduction or tutorial into the programming language defined on top of Rabbit-vm in prelib.rabbit and stdlib.rabbit, so far.

Rabbit is all about introspection. Start a repl, say 'help' and try the examples. say Play.flappy-bird ;)

Or look into src/stdlib.rabbit to see how rabbit programs look like.

asm/rabbit_atomsadd.asm            # documents all words build into Rabbit-vm

src/stdlib.rabbit                  # defines and documents additional words

./rr help                          # prints a list of get-help-commands

./rabbit-run --contents src        # print contents of files in rabbit source directory

./rabbit-run --contents fasm       # print contents of rabbit-vm assembler sources

Comparison with Joy

description Joy Rabbit-vm
execution model functions from stack to stack yes
function composition by concatenation yes
data == list == quotation == program == stack yes
strick evaluation yes yes
partial evaluation no no
functional claims to be pure functional define at runtime
source parsing [[atom 1 "string"]] ((atom 1"string'in'"{docstring}))
data types integer list symbol float string set integer list symbol
build in language sqr == dup * ; no
look ahead like XY no limited: hiccup ` ^ if j
push back like XY no no
branching [ test ][ if-true ][ if-false ]ifte test if( if-true )( if-false )
looping constructs recursive combinators circular lists
local variables no upstack or redefining definitions
[ f g ] dip ( f g )dip
[ f ] dip ^f
[ f ] first `f


;   Rabbit-vm   An approach to the Joy Programming Language.
;   GNU GENERAL PUBLIC LICENSE, Version 3.0, http://www.gnu.org/licenses/
;   https://bitbucket.org/sts-q/rabbit-vm
;   Copyright (C) 2018 2019 Heiko Kuhrt
;   Heiko.Kuhrt `( at )` yahoo.de


Send email to Heiko.Kuhrt ( at ) yahoo.de

This version of Rabbit-vm, rabbit-vm-asm-x86-64 was first published at 18. January 2018.

This version of Rabbit-vm, rabbit-vm-fasm-x86-64 was first published at 29. November 2018.


  • very limited support for arrays
  • no floats
  • 16 bytes per list item, character strings are stored as lists.
  • Just and only ASCII characters.
  • File.read does only read a complete file at once.
  • no dynamic memory allocation
  • many more

Bugs and ToDo

  • There is no load stack: errors found in scratch.rabbit are reported wrong.
  • Sys.cmd: "grep GNU LICENSE" Sys.cmd works, 'grep "GNU" LICENSE' Sys.cmd not.