Oxcart

From Esolang
Jump to navigation Jump to search

Oxcart is a continuation-passing concatenative language created by Chris Pressey in 2019. It is "purely concatenative" in the sense of Wagon, Equipage, and Carriage: there are no nested blocks and no names, the program is just one long string of symbols.

Program structure

In most concatenative languages, each symbol represents a function of one argument, and concatenating symbols represents composing one-argument functions in the conventional fashion. Like Wagon, Oxcart deviates from this slightly: each symbol represents a function as it would be written in continuation-passing style (CPS), i.e. a function of two arguments, where the first argument is the program state and the second argument is a continuation (which is a function which takes a program state and is not considered to return). Such CPS functions can be thought of as being typically written like:

f(x, κ) = (let y = something(x) in κ(y))

In the sequel we sometimes refer to κ as the "current continuation" of such a CPS function.

In Oxcart these CPS functions are composed by a rule of "continuation-passing style function composition", which is defined as

(f ⊛ g)(x, κ) = f(x, λs. g(s, κ))

The identity function for this sort of composition is

ι(x, κ) = κ(x)

A program state in Oxcart is a tape of unbounded stacks of elements; each element may be either a machine integer or a continuation. The tape, as usual, has a tape head indicating which location of the tape is active; the stack at that location is referred to as the "current stack". Tape cells are in fact numbered. All stacks are initially empty, and the tape is initially at position 0. The initial continuation is one that, when continued, simply terminates the program (perhaps dumping out the program state that was passed to it before doing so, for the sake of convenience).

Primitives

Oxcart provides fourteen built-in operations which can be composed to form Oxcart programs. Note that Oxcart is not a minimal language; some of these operations are redundant and could be removed.

Symbol Description
0 Push a 0 onto the current stack and continue as normal.
^ Pop an integer from the current stack, increment it, push it back on the current stack, and continue as normal.
v Pop an integer from the current stack, decrement it, push it back on the current stack, and continue as normal.
: Duplicate the top element on the current stack, and continue as normal.
$ Pop the top element on the current stack, discard it, and continue as normal.
\ Swap the top two elements of the current stack, and continue as normal.
< Move one cell left (negative direction) on the tape, and continue as normal. (After this, the current stack will refer to a different stack.)
> Move one cell right (positive direction) on the tape, and continue as normal.
( Pop a value from the current stack, move one cell left on the tape, push the value on the (new) current stack, and continue as normal.
) Pop a value from the current stack, move one cell right on the tape, push the value on the (new) current stack, and continue as normal.
' Pop a number A, then a value B, from the current stack. Set the tape position absolutely to A (where 0 = the position the tape started at at the beginning of the program.) Then push B onto the (possibly different now) current stack and continue as normal.
Y Pop a value A, then a value B, from the current stack. If A is zero, add B to the tape position (negative values go left, positive values go right), otherwise do nothing in particular. Then continue as normal.
S Push the current continuation onto the current stack and continue as normal.
% Pop a value A, then a value B, from the current stack. If A is non-zero, and B is a continuation, then discard the current continuation and continue B instead; otherwise continue as normal.

Whitespace is also allowed; it corresponds to the CPS identity function, i.e. it has no effect on the resulting program.

In the above descriptions, "continue as normal" means to continue the current continuation.

Examples

Infinite loop

S:0^%

"Repeat...until" loop

<0^^^^^^^^^^>S:<:v:)%

Counts down from 10 to 0, pushing each value onto stack -1.

External links