Piet


Introduction

Piet is a programming language in which programs look like abstract paintings. The language is named after Piet Mondrian, who pioneered the field of geometric abstract art. I would have liked to call the language Mondrian, but someone beat me to it with a rather mundane-looking scripting language. Oh well, we can't all be esoteric language writers I suppose.

Design Principles

Language Concepts

Colours

#FFC0C0
light red
#FFFFC0
light yellow
#C0FFC0
light green
#C0FFFF
light cyan
#C0C0FF
light blue
#FFC0FF
light magenta
#FF0000
red
#FFFF00
yellow
#00FF00
green
#00FFFF
cyan
#0000FF
blue
#FF00FF
magenta
#C00000
dark red
#C0C000
dark yellow
#00C000
dark green
#00C0C0
dark cyan
#0000C0
dark blue
#C000C0
dark magenta
#FFFFFF white #000000 black
Piet uses 20 distinct colours, as shown in the table at right. The 18 colours in the first 3 rows of the table are related cyclically in the following two ways: Note that "light" is considered to be one step "darker" than "dark", and vice versa. White and black do not fall into either cycle.

Additional colours (such as orange, brown) may be used, though their effect is implementation-dependent. In the simplest case, non-standard colours are treated by the language interpreter as the same as white, so may be used freely wherever white is used. (Another possibility is that they are treated the same as black.)

Codels

Piet code takes the form of graphics made up of the recognised colours. Individual pixels of colour are significant in the language, so it is common for programs to be enlarged for viewing so that the details are easily visible. In such enlarged programs, the term "codel" is used to mean a block of colour equivalent to a single pixel of code, to avoid confusion with the actual pixels of the enlarged graphic, of which many may make up one codel.

Colour Blocks

The basic unit of Piet code is the colour block. A colour block is a contiguous block of any number of codels of one colour, bounded by blocks of other colours or by the edge of the program graphic. Blocks of colour adjacent only diagonally are not considered contiguous. A colour block may be any shape and may have "holes" of other colours inside it, which are not considered part of the block.

Stack

Piet uses a stack for storage of all data values. Data values exist only as integers, though they may be read in or printed as Unicode character values with appropriate commands.

Program Execution

DP CC Codel chosen
right left uppermost
right lowermost
down left rightmost
right leftmost
left left lowermost
right uppermost
up left leftmost
right rightmost
The Piet language interpreter begins executing a program in the colour block which includes the upper left codel of the program. The interpreter maintains a Direction Pointer (DP), initially pointing to the right. The DP may point either right, left, down or up. The interpreter also maintains a Codel Chooser (CC), initially pointing left. The CC may point either left or right. The directions of the DP and CC will often change during program execution.

As it executes the program, the interpreter traverses the colour blocks of the program under the following rules:

  1. The interpreter finds the edge of the current colour block which is furthest in the direction of the DP. (This edge may be disjoint if the block is of a complex shape.)
  2. The interpreter finds the codel of the current colour block on that edge which is furthest to the CC's direction of the DP's direction of travel. (Visualise this as standing on the program and walking in the direction of the DP; see table at right.)
  3. The interpreter travels from that codel into the colour block containing the codel immediately in the direction of the DP.
The interpreter continues doing this until the program terminates.

Syntax Elements

Numbers

Each non-black, non-white colour block in a Piet program represents an integer equal to the number of codels in that block. Note that non-positive integers cannot be represented, although they can be constructed with operators. When the interpreter encounters a number, it does not necessarily do anything with it. In particular, it is not automatically pushed on to the stack - there is an explicit command for that (see below).

Black Blocks and Edges

Black colour blocks and the edges of the program restrict program flow. If the Piet interpreter attempts to move into a black block or off an edge, it is stopped and the CC is toggled. The interpreter then attempts to move from its current block again. If it fails a second time, the DP is moved clockwise one step. These attempts are repeated, with the CC and DP being changed between alternate attempts. If after eight attempts the interpreter cannot leave its current colour block, there is no way out and the program terminates.

White Blocks

White colour blocks are "free" zones through which the interpreter passes unhindered. If it moves from a colour block into a white area, the interpreter "slides" through the white codels in the direction of the DP until it reaches a non-white colour block. If the interpreter slides into a black block or an edge, it is considered restricted (see above), otherwise it moves into the colour block so encountered. Sliding across white blocks does not cause a command to be executed (see below).

Commands

  Lightness change
Hue change None 1 Darker 2 Darker
None   push pop
1 Step add subtract multiply
2 Steps divide mod not
3 Steps greater pointer switch
4 Steps duplicate roll in(number)
5 Steps in(char) out(number) out(char)
Commands are defined by the transition of colour from one colour block to the next as the interpreter travels through the program. The number of steps along the Hue Cycle and Lightness Cycle in each transition determine the command executed, as shown in the table at right. If the transition between colour blocks occurs via a slide across a white block, no command is executed. The individual commands are explained below. Any operations which cannot be performed (such as popping values when not enough are on the stack) are simply ignored.

Sample Programs

Hello World

This program prints "Hello world!" and then exits. It is shown in two sizes: 1 pixel per codel, and 25 pixels per codel. Program flow proceeds clockwise from the upper left red block along the edge of the program until the dark blue block at lower left is reached. It then proceeds up to the single light blue codel, right to the dark cyan codel, and right into the large green block at centre. From there it flows left through the dark green codel to the yellow block, then up through the dark yellow codel to the red block inside the black codels, where execution halts. This produces the required ASCII codes in a brute force manner, with each of the large blocks coding one of the required characters, but there are a few stack tricks in there to prevent having to redefine the same character more than once. (Thanks to Matt Rudary for debugging!)

Fibonacci Numbers

This program prints the first 100 Fibonacci numbers. It is shown at 1 pixel per codel, and twice at 121 pixels per codel. The second copy of the large version is overlaid with a black line to show program flow, beginning at the upper left. The flow sets up initial stack entries and prints the first two numbers before entering a loop at the dark blue codel in the centre of the left edge. The loop executes clockwise, rejoining itself at the dark blue codel. The branch in the long green block at the bottom is the test to see whether the 100th number has been printed. If it has, the code branches up to the red block and terminates there. Note that the yellow->dark blue transition on both entry points to the loop are "pointer" commands defining rotations of the DP, necessary to get the DP pointing in the right direction to trace the loop. Non-significant codels are left white to emphasise readability of the code, but in practice these could be filled with other colours for greater artistic effect. The only significant white codel is the slide from dark blue to yellow just before rejoining the loop, required to get the yellow to dark blue transition for the "pointer" command.

Towers of Hanoi

This program solves the Towers of Hanoi problem. It was written by Sylvain Tintillier. Don't ask me how it works, I have no idea!

Fancy Hello World

To show you how different two programs that do the same thing can look, this is another version of "Hello World!" written by Matt Rudary. I'm not sure how it works, but it looks a lot more elegant than my version.

Piet on the Net



Home | Esoteric Programming Languages
Last updated: Saturday, 20 March, 2004; 16:32:29 PST.
Hosted by: DreamHost