No description, website, or topics provided.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Insignificance is our existence / Hear the litany of life's persistance.

-- Bolt Thrower, "The IVth Crusade"


Ivth is a minimal language reminiscent of FORTH. The goal is to make the initial language footprint as minimal as possible in the spirit of a Turing Tarpit. However the language should be rich enough that it can be bootstrapped into an actually useful language (going against the spirit of most tarpits).


Ivth is stack-based. There is a data stack which holds 32-bit integers, as well as a traditional call stack. All program instructions and all program data consist of words, which are continguous bytes of "not-whitespace".

Thus, there are a few simple ways to write hello world:

72 .c 69 .c 76 .c 76 .c 79 .c 32 .c 87 .c 79 .c 82 .c 76 .c 68 .c 10 .c
: # .c ; 10 68 76 82 79 87 32 79 76 76 69 72 # # # # # # # # # # #
0 10 68 76 82 79 87 32 79 76 76 69 72 dup 0br 4 .c 0 0br -7 drop

Interpretation and Compilation

Like FORTH, the Ivth interpreter has two modes. It is either interpreting or compiling. While interpreting each word is executed as soon as it is seen. In compiling mode (used to define new words) only "fast" words ("immediate" in FORTH) are executed.

Currently only : and ; are fast. Until some of the problems with the interpretation model are overcome it's not clear that writing other fast words is very useful--if not, we can remove the distinction of these two modes and possible get ride of the ; word as well.

Built-in Words

There are currently 9 built-in words, although once Ivth is finished this number should be much smaller. They are currently:

  • (* Used to start a comment (can be removed).
  • copy Put s1 copies of s2 on the stack.
  • alt Rotate the top s1 entries of the stack left.
  • 0br If s1 is zero, add the next word to the current word pointer.
  • nor Return bitwise-nor of s1 and s2
  • + Return the sum of s1 and s2
  • .c Print the character value of s1
  • : Start defining a new word. : ; End the definition of a new word.

Since 1 of the 9 can already be removed, the goal will be to reduce the remaining 8. It would be nice to define more primitive parsing manipulation words to bootstrap (*, :, and ; but that might require too much machinery in the interpreter.

If we gave up on boostrapping, we could remove : and ; thus getting rid of two more operators. Thus, of the 11 current operators only 6 may be necessary.


The 0br word is ugly. Partially this is becuase the current design reads a word ahead (like it does in FORTH) rather than reading the address from the data stack.

A deeper problem is that we're not using memory addresses, 0br can't behave like a goto. This is unfortunate because it makes defining words like if or higher-level loop constructs very difficult or impossible (since br0 inside a word definition can only jump through that word's stack frame).

These problems are definitely solvable, and they don't impact Turing completeness. They just prevent bootstrapping a reasonable control flow.


It might be nice to move to numeric addressing, to support more control flow. We'd need to introduce something like FORTH's return stack but we'd be able to simplify some other things.

It would be nice for the interpreter loop itself to be written in IVTH. Again, if we moved more of the interpreter state into addressed variables we could access interpreter state directly in Ivth.