StackStacks


 * Not to be confused with Stackstack.

StackStacks is an esoteric programming language designed and implemeted by User:Oj742 in 2014, taking inspiration from Forth. It doesn't store any data (excluding two flags); instead, all stacks contain stacks within themselves, so that a theoretically unlimited level of recursion can be reached.

It is likely that if you read this article in it's entirety, you will become sick of the word stack.

Overview
The stacks in StackStacks don't hold data, but instead hold other stacks. There are four variables in the language:
 * The root stack, the first stack from which all other stacks are made within.
 * The working stack, which is actually just a pointer to a stack. All instructions are local to the working stack.
 * The FAIL flag, which is set whenever a failable instruction is executed; 0 if the instruction succeeded, and 1 if it fails.
 * The TEST flag, which is used by conditional branching instructions.

Since there needs to be some data for i/o, stacks can be translated into data and vice versa. Translation is as follows:
 * Stack -> Data : The size of the stack becomes the value of the data (an integer/character/boolean).
 * Data -> Stack : Create a stack with x empty stacks inside of it, where x is the value of the data (integer/character/boolean).

At the beginning of execution, the working stack is set to the root stack; you can think of the stacks like directories in a file system. You can move the working stack up, to its parent, or down, to its head.

StackStacks uses functions, in a similar way to C (though without any parameters). Functions are declared by a name outside any code block, followed by a code block. Execution begins at the function called 'main'. Code blocks are also similar to those in C.

Comments are made like this: /* a comment */ While inline comments are made like this: //a comment

Examples
Note that these examples don't really take advantage of StackStacks 'stacks within stacks'.

Hello World
main {   'Hello World!\n' outa //'"Hello World!\n" outs' is also viable }

Cat
main {   geta outa //As with hello world, 'gets outs' would also work }

99 bottles of beer
main {	1 99 { @bottles "of beer on the wall, " outs @bottles "of beer.\n" outs @takedown dup not not test swap ?skip not dup test swap ?loop } }	bottles {	dup 1 eq test ?do { //one bottle "1 bottle " } ?skip { dup 0 eq test ?do { //zero bottles "No more bottles " } ?skip { //more than one bottle dup outi " bottles " } } outs //output } takedown {	dup 0 neq test ?skip { "Go to the store, buy some more, 99 bottles " outs } ?do { "Take one down, pass it around, " outs dec dup //take one down @bottles } "of beer on the wall.\n\n" outs }

Quine
main {	"main" cdup outs endl 123 outc endl 9 outc 34 pack 0 34 pack cat outs endl 1 "cdup outs endl 123 outc endl 9 outc 34 pack 0 34 pack cat outs endl 1" "swap { 9 outc -cycle dup test dec cycle cdup ?do { outs endl 9 outc 34 pack 0 34 pack cat outs } ?skip { 34 pack 0 34 pack cat outs endl 9 outc outs } endl ?loop 125 outc endl }" swap { 9 outc -cycle dup test dec cycle cdup ?do { outs endl 9 outc 34 pack 0 34 pack cat outs } ?skip { 34 pack 0 34 pack cat outs endl 9 outc outs } endl ?loop 125 outc endl } }

Truth-machine
 main {       geta dup '0' eq test ?do outc ?exit '1' eq test ?do { 1 outi ?loop } }

Turing completeness
Reduction from Brainfuck. If you start the program with main { 0 0 0 and end it with } then the following reduction is true:

External resources
Oj742's (Crude) Interpreter