File under: Development, Throff

blog/ Internal Actions

How do functions work in the Throff engine?

Everything in Throff is a function. So understanding how they work is the key to understanding throff. This article started as a my notes on how to re-implement throff for a new platform.

Throff works by treating each word in the program as a function. In order to do this, each word has a default "action", provided by a function.

The default function is to take one element from the code stack, and push it onto the data stack, unchanged. The data stack is the "argument" stack, so this means that the TOKEN will be an argument to the next function.

In fact, this is not quite true. Before moving the TOKEN from code stack to data stack, throff looks up the TOKEN in the current namespace. If throff can find the TOKEN in the current namespace, then the result of that lookup is fetched and pushed onto the codestack (and if you make the mistake of binding a token to itself, throff will go into an infinite loop).

Basic functions

Below is a list of every basic NATIVE function that the interpreter provides. The list is short, because throff is simple.

All the functions take a throff interpreter state, and return a new interpreter state, and internally they are all called 'stepper functions', because internally the code looks like

state2 = step(state1)

The functions are named after what they do, kind of.

TOKEN(default) looks up this token in the current namespace. If the TOKEN is bound to a value(it's a variable name), that value is pushed onto the codestack, where it will be activated on the next step. Otherwise, the TOKEN will be pushed onto the datastack, possibly with an error about an unknown variable.

NULLSTEP Does nothing

BUILDMODE or ']' Buildmode sets the engine into build function mode. In this mode, all TOKENs are moved onto the data stack until a matching '[' is found. Nested [ ] are allowed.

BUILDFUNC or '[' BUILDFUNC travels down the data stack, moving each TOKEN into an array, until it finds a matching ']'. Nested [ ] are allowed. When buildfunc finds the matching ']', it creates a function from the array, by adding a namespace and setting its action function to the INTERPRETED function. Unfortunately this has to be hard coded into the engine. I plan to have a way to add more "function close" markers, so that people can define their own functions.

INTERPRETED All user functions have this. It pushes each TOKEN from its array onto the codestack. These tokens will be looked up and activated like normal. Because of this, there is no "return" or end-of-function marker. When all the TOKENs from the function have been used up, the throff continues down the code stack, which holds the rest of the calling function. This gives us tail calls for free.

NATIVE All the builtin throff functions. These include functions to open/close files, print to the screen, and so on.