[ Flip Home | Language Description | Programs | Mail authors ]

The Flip Language

Contents

The architecture

The architecture of Flip is a two-dimensional grid of squares, in each of which can be placed an object. The source code of a program is simply a map of this space.
The program execution is performed in Flip by one or more balls, which move around and interact with the objects (Flip is a little like a game of billard. If you play Programmers' Billard). Each ball contains a numerical value1.
When a Flip program is executed, there is just one ball - of numerical value 0 - which is placed in the upper left corner of the program (the beginning of the source code) and moving to the right. This ball is called the initial ball.

Tutorial

You will here learn the operating principles of Flip; the different objects in Flip are introduced step-by-step, along with a series of sample programs demonstrating the behaviour of these objects.

The objects with which the balls interact are represented in the source code as characters. Some ASCII characters (called meaningful characters) correspond to object kinds; others (meaningless characters) don't. Flip programs may contain meaningless characters as well as meaningful ones; this is not regarded as an error. This enables you to write comments in your programs - you only need to make sure that the balls do not accidently hit meaningless characters (if this happens, the program will terminate with an error message).

An overview of the object kinds can be found after the tutorial.

Flow-controlling Objects

Walls

Balls simply bounce off walls, as you would expect.

There are four kinds of wall:
Wall
-horizontal wall
|vertical wall
/diagonal wall
\
Diagonal walls make the ball go in a new direction, perpendicular to the old one; horizontal and vertical walls make a ball turn around. Horizontal and vertical walls are also called mirrors, and diagonal walls are also called flippers (especially if they're modified - we'll get to that).

Sample program 1: Walls
        \
|       /
In this program, the ball moves right until it hits the upper diagonal wall, then down to lower diagonal wall, then left again. Then it hits the vertical wall, and retraces its path back to where it started. It continues left and out of the program.

Simple and intuitive, so far.

Diagonal walls - flippers - can be modified to alter their behaviour, but more about that later.

Sluices

Another important flow-directing object type is the sluice. It is a device which allows motion in one direction, but not in the other.

There are four kinds of sluice:
Sluice
>'right' sluice
<'left' sluice
^'up' sluice
v'down' sluice

A sluice works like this: If a ball hits a sluice moving in the direction in the sluice (eg., hits a ^ sluice moving upwards), it just continues. If it hits it in the opposite direction, it is reflected 180°. And finally, if it hits the sluice from one of the sides, it is deflected 90° such that it continues in the direction of the sluice.

Sample program 2: Walls
  >  v2
 5v
 4^  <3     
In this program, the ball passes through the first sluice, hits the sluice labeled '2', is deflected down, hits '3', is deflected left, hits '4', is deflected up, and hits the sluice labeled '5'. This sluice it hits against its direction, so it is reflected downwards, where it hits '4', is again reflected, and so on. If the '5' sluice was removed, the ball would move in a square going between the other four sluices.

Sluices can be modified to alter their behaviour, but more about that later.

Numbers and Arithmetics

Number Generators

Number Generators generate numbers.
That is, they generate new balls with specified numbers as their values. A such new ball is generated when a ball hits the number generator; the new ball will be moving in the direction of the hitting ball, and the hitting ball will be reflected 180°.

Number generators exist to create a ball with any one-digit number (in decimal).
Number Generator
0 1 2 3 4
5 6 7 8 9
number generator

Sample program 3:
Number Generators
   2   4    
===========
When the initial ball hits the '2', it is reflected and leaves the program to the left. A new 2-ball is created at the impact, moving right. When it hits the '4', a 4-ball is created - it leaves the program shortly after, to the right. The 2-ball bounces back and hits the '2', creating a 2-ball which leaves to the left. The first 2-ball will keep bouncing back and forth between the two numbers, generating 2's and 4's which escape from the program, forever. With number generators come, of course, the opportunity (although in Flip it is close to a necessity) of creating multi-threaded programs.

Binary Arithmetics

Now, there isn't really a reason for having different numbers, if you can't do calculations on them, is there? There are two types of objects, which can do binary arithmetics - these are for soon obvious reasons also known as tarpits:
Tarpit
+additive tarpit
*multiplicative tarpit
A tarpit works like this: If a ball hits an empty tarpit, it gets stuck and stays in the tarpit. When another ball then hits the tarpit, the sum or product - as the case may be - of the balls' numbers are formed, and a single ball with this value continues in the same direction as the second original ball. The two original balls do not exist anymore.
Sample program 4:
Arithmetics
 > 2 + *
==========
The initial balls passes through the sluice, and then keep bouncing between the '2' and the sluice, generating series of 2-balls. The first 2-ball gets stuck on the '+'-tarpit, where it waits for the second 2-ball. From the two, a 4-ball is formed, which then gets stuck on the '*'-tarpit, waiting for the next 4-ball (which is generated from the third and fourth 2-ball). A 16-ball is formed from the two 4-balls and leaves the program to the right. All in all, the effect of the program is to create a series of such 16-balls.

Notice that the 16-ball is represented as '6' on the screen; balls are always just represented by their last decimal digit.

Unary Arithmetics

They unary operations are:
Unary Arithmetics
~invert sign (negate)
'increment
,decrement
.reset
These object alter the value of the balls which hit them (the balls continues through them). The reset operator resets a ball's value to zero.
Sample program 5:
Unary operators
 ' ' , ' ~ 
============
After going through the operators, the ball has the value -2.

Program Control and I/O

Output

It would be nice, now we can do arithmetics, to be able to print out balls' values - at least it enables us to verify that the 16-balls generated by Sample Program 4 are indeed 16-balls and not 6-balls. There are two kinds of output objects:
Output
pprint out values in decimal
Pprint out as ASCII character
Balls disappear when they hit an output object, after being printed out. A ball hitting an ASCII output object will result in the ASCII character corresponding to the ball's value being printed.
Sample program 6:
Arithmetics with Output
 > 2 + *  p
============
This program is an extension of Program 4, and repeatedly prints '16'.

Note: When printing out decimal values, a space character is automatically printed after each value for convenience.

Sample program 7:
ASCII Output
 > 8 * P
=========
This program demonstrates ASCII output; a series of 64-balls are generated and printed out ASCII-wise (as the '@' character).

Input

In Flip it is also possible to read input. Input works similar to output:
Input
rread values in decimal
Rread ASCII characters
If an input object is hit by a ball and some input is ready then the value of the ball is set to the input value. If no input is ready then the behaviour depends of the value of the ball:
Input-ball
zeroThe ball is erased.
positiveThe ball is trapped, waiting for input.
negativeThe program is suspended until input is ready.
If multiple balls are trapped waiting for input then one of them is released as soon as more input is ready - the others keep on waiting. It is unspecified which of the balls is selected.
Sample program 8:
Input
> 0  r '                 p
==========================
This program inputs a series of numbers, increases them by one, and prints them out again.
Sample program 9:
Program suspending Input
> 1~ r '                 p
==========================
This program is almost identical to the previous one. The difference is that because the numbers are read by a negative number then the program is frozen whenever no input is ready. - The balls travelling tovards the p are halted as soon as no input is ready. This means that the first number isn't printed until 8 numbers have been read.

Program Termination

As one of our goals with Flip is for it to be Turing-complete, it would be nice if Flip-programs could terminate. Here is the appropriate object:
Program Control
Qterminate program
The program terminates, when a ball hits the terminator. The program's exit value is that of the ball.

Cloning and disappearance of balls

The Grille

The grille lets balls with positive values pass, but eats balls with zero or negative values (they are simply too small).
Grille
#grille
Sample program 10:
The Grille
  2  #  p
===========
In this program, a 2-ball is created and sent over a grille - it passes.
Try removing the '2' - you can then see that the initial 0-ball won't pass, but is eaten.

The Processor

The processor is so named, because it is able to perform many different functions, depending on how it is modified. In its basic form, however, it'll only do one thing, namely clone a ball.
Processor
Xprocessor
When an unmodified processor is hit by a ball, it is made into two identical clones, leaving the processor in opposite directions at 90° to the direction of the original ball.
Sample program 11:
The Processor
 3   \  p
   / X  +
   \    X
   Q    /
=============
A 3-ball is generated and sent into a processor for cloning. One copy hits a '+'-tarpit. The other is cloned again; one copy hits the waiting ball in the '+'-tarpit a little later, causing '6' to be printed; the last clone makes the program terminate shortly after.

As mentioned, processors can be modified to alter their behaviour, but more about that later.

Modifiers

Those were the basic, real objects; now we get to the interesting topic of modifiers. These are markers that tell flippers, sluices and processors to act differently - and when to do so.
Until now, we can hardly just output the sum of two different numbers (and do so once) - with modifiers, things are a little more flexible.
Modifiers
NameMeaning
@alwaysalways true
+positivevalue > 0
-negativevalue < 0
0zerovalue = 0
~oddvalue is odd
%randomrandom truth value
(yes, some of these characters are also used for normal objects).
If there is more than one random-modifier around the object, they'll all respond with the same truth value.

Modifiers are placed in the four squares one step diagonally from an object. Which modifiers are placed where does matter.

There is a seventh modifier, namely false. And actually, all modifiable objects always have four modifiers - but as default, these are all false unless another is specified.

Modifiers are mostly grouped together. The value of the group's response on a ball is then the exclusive or of the responses of the modifiers in the group. In this way, it is possible to make many useful, and some useless, combinations.

Modified Flipper

A diagonal wall can be modified to flip - that is, change its orientation at impact. The flipping is decided by the modifier group containing the modifiers in the corners in the wall's current direction (that is, the upper left and lower right modifier for a \, and the upper right and lower left modifier for a /).
Sample program 12:
Modified Flippers
  \   \   \     \
   @   @   @
  2   3   4
p +   +   /     Q
=================
In this program, the inital ball is deflected downwards by the first flipper, while at the same time flipping it. The deflected ball generates a 2-ball and returns to the flipper, which deflects it to the right. In the same way, the initial ball generates a 3-ball and 4-ball. The 2-ball and 3-ball get stuck on the '+'-tarpits; the 4-ball triggers the additions 4+3=7 and 7+2=9. The resulting 9-ball is then output, and right after that, the 0-ball makes the program terminate.
Thus, the effect of this program is to add 2, 3, 4 and print the result.

Modified Sluice

Remember that a sluice will reflect a ball hitting it in the opposite direction of the sluice? That behaviour can be altered with modifiers into deflecting the ball to the left or to the right instead.

The direction of the deflection is determined by the modifier groups containing the modifiers at either side - left or right, as seen by the ball - by the following rule:

If the truth values given by the modifiers are equal, the ball is relected.
Otherwise, the ball is deflected in the direction whose modifier group returned true.

Sample program 13:
Modified Sluices
  > 5  \   p
   @      ~ @
       >   <1
          ~
  > 4  /   \ 
   @
  \         Q
=============
In this program, the initial ball passes through the first sluice, generates a 5-ball, and on its way back, it is deflect downwards by the modified sluice. Likewise, it generates a 4-ball. The 4-ball and 5-ball are both sent to the sluiced marked with a '1'; here, the 5-ball is deflected downwards and sent out of the progam, because the'down' modifier group has condition 'odd'. The 4-ball, however, does not fulfill the condition 'odd', but it fulfills the upward condition, which is 'odd XOR true' - that is, 'even'.
Thus, '4' is printed, and the inital ball make the program terminate.

Modified Processor

The processor can clone, sort or remove balls, depending on its modifiers.

When hit by a ball, a processor can send out a copy of the ball in each of the two directions perpendicular to where it was hit from - or it can chose not to send out a copy. As the default, it does send one. You can suppress the copies by telling the processor to do so, with modifiers. The relevant modifier groups are the ones which contain modifiers in directions adjacent to the output direction in question.

For example, let's say a processor is hit by a ball from the left. Normally, it would send out copies of that ball upwards and downwards (instead of the original ball). If we now want to send out a ball upwards only if the original ball was positive, we modify the processor by placing appropriate modifiers on its up-left and up-right neighbour squares - in this case, either a ('zero' + 'negative') modifier combination or a ('positive' + 'always') modifier combination will do.
Likewise, which balls are output downwards can be selected by placing modifiers on the down-left and down-right neighbour squares.

Sample program 14:
Modified Processor
(or the Odd/Even Sorter)
 >   \    p     /      \
 '       ~ @    
 \   X    X   
         ~\     >      /
=======|=====|==========
In the left part of this program, a ball cycles around. For each cycle, a clone is passed on to the middle part, and the ball's value is incremented by 1.
In the middle part, the balls are sorted. The processor sends the odd balls upwards (it stops the ('odd' XOR 'all'), that is, the even balls) for printing, and the even balls are sent downward (odd balls are prevented).
Just for the fun of it, the even balls are sent to the right part of the program: An infinite storage loop for the balls. (you could also place a '+' tarpit somewhere in the loop, in which case the even numbers will all be added...)

There is no reason the 'upward'- and 'downward'-conditions should be opposite, as they are in this sample program - you might as well choose to let the odd balls go up, while 50% of the balls are randomly chosen to go downwards. Processors are flexible.

Levels

This is a new feature in version 2.0

Because the values contained in the balls cannot be arbitrarily large - for practical reasons, there is a fixed limit - the language as described so far is not Turing complete, i.e. it is not possible to write all the programs which can be written in most other programming languages.

The levels aspect of Flip changes this. It is relatively simple: Instead of just the two dimensions we've seen so far, in Flip you actually have three.

The space is divided into mostly independent levels (or layers), each containing a copy of the 2D source program.
This means that all levels look alike, in that the same objects are present on all levels, in the same places. But there can be certain differences:

There are an (in theory, at least) infinite number of layers, arranged as floors in an infinitely high tower. Thus, there is one layer for each of the natural numbers and zero. Level zero is the lowest level (the ground floor; there is no basement). This is where the inital ball starts.

These are the object kinds dealing with levels:
Levels
Zgo up one level
Ngo down one level
The behaviour of 'Z' is simple: Every ball passing through it is raised one level. Similarily, every ball passing through an 'N' is lowered one level. There is one small twist, though: Balls on level zero cannot be lowered, and they are therefore reflected by 'N'. This makes is possible to test whether a ball is on level zero.

Sample program 15:
Levels
 >  2   4 \ 
 #@
 \  Z     +
          \
==============
This program is an extension of program 3. As in the original, a stream of 4-balls is generated to the right and a stream of 2-balls to the left. Each stream is directed towards the '+' tarpit, but because the 2-balls are first elevated one level, the two streams actually pass through different tarpits.

When the program is run, can be seen that although a 4-ball seemingly arrives on the tarpit at a time when a 2-ball is trapped there, no addition takes place - the 4-ball is trapped too. This demonstrates that the two balls are indeed on different levels.

The effect of the program is thus to produce a series of 8-balls (made from 4-balls) and a series of 4-balls (made from 2-balls).

Sample program 16:
Going up and down
> 0 >    \

        @    / ' \
    \ Z  \   > N /
         1    @
             p
===|=======|====
In this program, both 'N' and 'Z' are demonstrated.
The program is divided into three parts. The left part consists of a simple generator of 0-balls.

In the middle part, the orientation of the flipper labeled '1' is tested. If it is in its original position ('\'), the ball is sent to the right part of the program, and at the same time, the flipper is flipped. Otherwise, the ball is raised one level and the flipper on that level is tested, and so on.
The effect is that the first ball is passed on to the right on level zero, the next ball on level 1, the third on level 2, etc.

In the right part of the program, the ball is sent through an 'N'. If it is on level zero, then it is reflected by the 'N', deflected by the sluice and its value is printed out. Otherwise, the value of the ball is incremented by 1 and the ball sent through the 'N' on the new (lower) level.
The effect on this part of the program is that each ball is sent to level zero, and at the same time incremented by the number of its original level.

All in all, this program prints "0 1 2 3 ...".
(The same effect could of course have been obtained much easier, but it is a nice program anyhow.)

Object Overview

Objects
ClassName
Wall -horizontal wall
|vertical wall
/diagonal wall
\
Sluice >'right' sluice
<'left' sluice
^'up' sluice
v'down' sluice
Number Generator 0 number generator
1
2
3
4
5
6
7
8
9
Tarpit +additive tarpit
*multiplicative tarpit
Unary Arihtmetics ~invert sign (negate)
'increment
,decrement
.reset
Output pprint out values in decimal
Pprint out as ASCII character
Input rread values in decimal
Rread ASCII characters
Levels ZUp one level
NDown one level
Program Control Qterminate program
Grille #grille
Processor Xprocessor

Modifiers
NameMeaning
@alwaysalways true
+positivevalue > 0
-negativevalue < 0
0zerovalue = 0
~oddvalue is odd
%randomrandom truth value


1) The ball values are really 32-bit signed values - overflow may occur.