The background of Stacked

Back in 2014 I did create 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 colleague, 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.

Introduction through examples

Let's start with the old trusty Hello World! example.

'Hello World!' .

Output:

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, let's take a look at this example.

10 5 * .

Output:

50

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 * .

Output:

16

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 .

Output:

3.141592653589793

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. As they are special operators.

Sequences

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!'.}; 

hello

Output:

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 also can be used by sequences to pass return values.

\squared {dup *}; 

5 squared .

Output:

25

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.

Serializing

{1 'string' {'A sequence'} \ something}
serialize .

Output:

{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.

stack:
10
stack:
2 3
stack:
+
stack:
*
stack:

Output:

{}
{10}
{10 2 3}
{10 5}
{50}

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' ? .

Output:

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 *'! .

Output:

25
36

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. \a 'LOCAL', @a.}! 
@a.

Output:

GLOBAL
GLOBAL
LOCAL
GLOBAL

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

Output:

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.

Conditionals

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

Output:

-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 (and one new thing) together.

\fibonacci {{n}# 
~'Calculate the n-th fibonacci number. (n -- fib)'
@n 2 lte
{1}
{@n 1 - fibonacci @n 2 - fibonacci +}
?!
};

1 fibonacci.
2 fibonacci.
3 fibonacci.
4 fibonacci. 
5 fibonacci.

Output:

1
1
2
3
5

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.

Output:

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

You can test out Stacked 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!

Published 2016-09-02 by MKJE in the blog Off-topic.

More from this blog

No coding required!

Translation of the phrase "no coding required!" as often seen in advertisement for software packages: "even mildly complex tasks will be impossible or at least cumbersome to complete".

read more

MKJE

Other blogs

News

News about the Nilwen site.

Profiles

Interviews with interesting people.

Quotes

Quotes on programming and games.