The background of Stacked
The last couple of weeks I've been playing around with creating a stack-based programming language - modelled after FORTH and PostScript. The result is the Stacked programming language, which I present here in this post.
It all started when I casually mentioned to a college, that one, due to the simplistic nature of the FORTH environment, probably would be able to implement a functioning FORTH interpreter in a day or so.
A saturday some weeks later, I started writing what evolved into the Stacked programming language. (The hypothesis was proven true, as I had a functioning Stacked interpreter up an running after just a few hours. Mostly because of the extremely simple syntax of, and as a result, parser for, FORTH-like languages.)
The language I did end up implementing/designing do not conform to any standard version of FORTH. In actuality, I would say that, the Stacked language have more in common with PostScript than it has with FORTH.
The main purpose for me to creating Stacked was to have fun and to think about different types of programming languages.
Some words about the syntax
The parsing/tokenizing scheme of Stacked differ from that of FORTH. In Stacked, strings are enclosed between ', like 'this'. Identifiers can either be multi-character alpha-numeric words (dup, stack, execute_debug, ...) or single-character non-alpha-numeric words (+, {, \, ...). White-spaces is only needed for marking token limits if both tokens are numbers or multi-character words. Single character words can be placed beside any other token without any whitespace in between.
Introduction through examples
Hello World!
Lets start with the old trusty Hello World! example.
'Hello World!' .
Hello World!
As Stacked is a stack-based language, the stack is a central concept, used by functions for receiving parameters and for outputting results.
So, what is happening here? First, the string 'Hello World!' is pushed to the stack. Then the function . is called, popping the upper element from the stack and outputting it.
Basic arithmetic
As you can see from the Hello World! example, the operator (.) comes after the parameter ('Hello World!'). This is a common trait among stack-based programming languages, as it plays well with stacks. You formal language aficionados will know this as reverse Polish notation.
Now, lets take a look at this example.
10 5 * .
To read Stacked code, begin from the left and read to the right. Literals (strings, numbers, ...) will be put on the stack, and identifiers (procedures, operators, ...) will be executed. In this case, first 10 and then 5 is pushed to the stack. Then the multiplication operator * is executed, popping the two upper elements from the stack, multiplying them and pushing the result (50) on the stack. Then, . is executed, popping the uppermost element from the stack, and outputting it. Pretty straightforward actually, isn't it.
Stack manipulation
4 dup * .
First 4 is pushed to the stack. Then the dup operator is called, pushing a copy (duplicate) of the uppermost element of the stack, to the stack. The * operator multiplies the two fours from the stack, and pushes the result 16 to the stack. Lastly, the . operator pops the 16 from the stack and outputs it.
Global name binding
It is possible to bind values to global names. This feature can be used to create globally accessible values.
\pi 3.141592653589793 ;

@pi .
The ; operator binds a value (3.141592653589793) to a name (pi). The @ operator can be used to push a named value to the stack. The \ operator is used to keep the name pi from being executed, and instead simply pushed to the stack.
Please note that the \ and @ operators operate on the identifier to the right of the operator.
Sometimes you want to have a collection of things, a list. In Stacked this is called a sequence.
{2 'A string' 5}
Curly brackets are used to denote the beginning and end of a sequence.
Executing sequences
In Stacked, sequences of items can both be used as a data structure (a list), or as something that resembles procedures in other languages.
\hello {'Hello!'.}; 

In this example, first the name hello is bound to the sequence by the mean of the ; operator. Then the hello sequence is executed.
Passing values to and from sequence calls
Parameters are passed to sequence calls by putting them on the stack. Which aso can be used by sequences to pass return values.
\squared {dup *}; 

5 squared .
First we bind the sequence to the global name squared by the ; operator. The we put 5 on the stack, calls the sequence, and output the uppermost element of the stack (pushed there by the * operator in the sequence) through the . operator.
{1 'string' {'A sequence'} \something} serialize .
{1 'string' {'A sequence'} \ something}
The serialize function transforms the uppermost element of the stack into its string representation.
Inspecting the stack
Sometimes, especially while debugging, one want to see the content of the stack.
2 3
{10 2 3}
{10 5}
The stack function pushes the entire content of the stack as a sequence to the stack. The : operator pops and serializes the uppermost element of the stack, and outputs the result.
The conditional operator
true 'TRUE' 'FALSE' ? .

false 'TRUE' 'FALSE' ? .
The conditional operator, ?, works in a similar way as the ?: operator in many other programming languages. It pops three element from the stack. If the first is true the second element is pushed back to the stack, else the third element is pushed to the stack.
The execute operator
5 {dup*.}!

'6 dup *'! .
The ! operator executes the uppermost element of the stack. If this element is a sequence it will simply execute the sequence. If the element is a string the operator will execute the content of the string as Stacked source code.
Local named values
\a 'GLOBAL';
{@a. \a 'LOCAL', @a.}! 
The , operator binds values to local names - bounded to the scope of a called sequence. When getting a named value by the use of the @ operator, local names have higher priority than global names.
Bulk local named value binding
The main hassle, as a human, in using a stack based language, is to mangle the stack content - to put the parameters in the right order before a call. To make this a bit more hassle free in Stacked, one can use bulk binding of local names.
\t { {a b}#
'a: ' @a + 
' - b: ' @b + 

'A' 55 t   
a: 55 - b: A
The # operator pops a sequence of identifiers, and binds local names given through those identifiers to the top elements of the stack.
The ? and ! operators can used together fill the function of the if-else-endif construct in other languages.
\is_positive {{n}#
@n 0 gt 
{@n ' is positive'+.} 
{@n ' is NOT positive'+.}

-5 is_positive
0 is_positive
7 is_positive

-5 is NOT positive
0 is NOT positive
7 is positive
The sequence in the example above could be rewritten more compactly as:
{dup 0 gt ' is' ' is NOT'?+' positive'+.}
But that would just be me trying to show off.
A more involved example
Putting the stuff we talked about so far together.
\fibonacci {{n}# 
~'Calculate the n-th fibonacci number. (n -- fib)'
@n 2 lte
{@n 1 - fibonacci @n 2 - fibonacci +}

1 fibonacci.
2 fibonacci.
3 fibonacci.
4 fibonacci. 
5 fibonacci.
This defines the sequence fibonacci, which when called, calculates the n-th fibonacci number. The ~ operator lets one define a description for a sequence.
Getting help
Sometimes you want to get information about a function.
\dup help.
dup: External function - 
Duplicate the upper element of the stack. (a -- a a)
The help function pushes a string containing information about the given functions onto the stack.
Test it yourself
As Stacked is implemented in JavaScript, you can test it out right here in your browser. Just type in your Stacked code in the grey box and click Execute. For example, write get_global_name_list: to get the entire list of registered global names.

Have fun!
Mikael K J Ericsson
Send message to author
Who You are

Your message

This blog is powered by the Grogg blog engine
© Mikael K J Eriksson 2014-2015