Skip to content

Latest commit

 

History

History
486 lines (314 loc) · 19.8 KB

PIET.md

File metadata and controls

486 lines (314 loc) · 19.8 KB

Piet

Table of Contents

  1. Overview
  2. Program Code
  3. Program Flow

Overview

Piet is an esoteric programming language invented by David Morgen-Mar where the code looks like abstract art. If you are interested you can also take a look at the original language specification.

This is a brief overview of the language and is intended to give the reader the opportunity to understand and apply all the basic language concepts. So after reading this document you are enabled to draw pictures and program at the same time.

Since Piet is an esoteric programming language it obviously cannot be used in production. However, writing programs in Piet requires creative thinking because normal programming structures do not apply and new solutions must be found.

Happy pieting!

Program Code

In Piet you do not write conventional program code in text files like in any other programming language. Instead you draw images which represent your program code.

The program code (images) consists basically of colored squared blocks which are called Codel (see section Codel for more information) where each colored block represents a command, e.g. for numeric operations, stack operations or program flow operations - see section Commands for more information.

Piet offers you a set of 20 different colors and a corresponding set of 17 commands. The tricky part is that a single color does not represent the same command in each case. The command interpretation is dependent on the surrounding color blocks and an internal program state. A red block may represents an add operations, a stack manipulation or a no-op operations in another case - you never know what you will get.

An interesting side fact is that a totally crazy person (positive meaning) managed it to draw an interpreter for the esoteric programming language Brainfuck. I didn't verified the validity of this program but if you want to do this on your own see this website for more information. The more interesting fact is that Brainfuck is Turing-complete, which implies that Piet is also Turing-complete. Meaning you can theoretically program everything with Piet assuming you have an infinity sized image and a lot of time.

Codel

A Codel is the smallest programing unit in Piet and is represented as a colored square. The name is obviously a combination of code and pixel.

Color

The codel can have 20 different predefined colors (see section Colors)

Size

The edge length of the square can be defined for each program interpretation and has a dramatically impact on the interpretation result. E.g. if you define a edge length of 1 at the moment when you draw you program someone else could interpret the same edge length as 10 which results in a completely different result.

Codel Block

A codel block consists of 1 to N codels, where N is the total number of codels in the image. Following assumptions apply:

  • Color: All codels in the codel block must have the same color.
  • Codel neighborhood: The codels in the codel block must necessarily be adjacent through a 4-connected connectivity. So only the top, bottom, left and right codels are valid candidates for a codel block. This neighborhood is illustrated in the table below:
no neighbor (x-1, y+1) top neighbor (x, y+1) no neighbor (x+1, y+1)
left neighbor (x-1, y) current position (x,y) right neighbor (x+1, y)
no neighbor (x-1, y-1) bottom neighbor (x, y-1) no neighbor (x+1, y-1)

Colors

The following table shows all 20 colors that can be used in Piet programs:

Piet color table

The colors black and white are different from all other colors since their interpretation is constant

  • White: The neutral element which does not cause any command execution.
  • Black: Blocking elements restricting the program flow (Codel Chooser and Direction Pointer)

The remaining 18 colors are divided into 6 different hues: red, yellow, green, cyan, blue and magenta. For each hue there are 3 different satuations: light, normal and dark. This color set defines the program operations and as already mentioned: the meaning of these colors changes during the program interpretation.

Color Cycles

For the program interpretation or more precisely for the command interpretation of the individual code blocks the structure of the color table in the section Colors is essentially important.

There are two relevant aspects how the colors are connected:

  • Hue cycle
graph LR
    subgraph Hue Cycle
    R(Red):::red --> Y(Yellow)
    Y(Yellow):::yellow --> G(Green)
    G(Green):::green --> C(Cyan)
    C(Cyan):::cyan --> B(Blue)
    B(Blue):::blue --> M(Magenta)
    M(Magenta):::magenta --> R(Red)
    end

    classDef red fill:#ff0000;
    classDef yellow fill:#ffff00;
    classDef green fill:#00ff00;
    classDef cyan fill:#00ffff;
    classDef blue fill:#0000ff;
    classDef magenta fill:#ff00ff;
Loading
  • Satuation cycle
graph LR
    subgraph Satuation Cycle
    D(Dark) --> L(Light)
    L --> N(Normal)
    N --> D
    end

Loading

In section Color Commands these two cycles are essential.

Program Flow

This section explains how a piet program is interpreted.

Program Stack

Piet is based on a simple integer stack for program interpretation. During program interpretation all values of you program are stores on this stack and you program is also capable of manipulating the stack. For a detailed overview of all possible commands and ways of stack manipulation please take a look in the Commands section below.

Commands

The following commands are present in Piet and can be divided into the following groups:

Stack Manipulation Arithmetic Operation Program Flow Input / Output
Push Add Not Input (number)
Pop Subtract Greater Input (character)
Duplicate Multiply Pointer Output (number)
Roll Divide Switch Output (character)
Mod

Push

Description: Push a number on the stack. The pushed number represents the codel block size of the command.

Exceptions: None

Pop

Description: Pop the top element from the program stack.

Exceptions: Throws an exceptions if the stack is empty.

Add

Description: Pops the top two elements from the stack, perform an addition and pushes the result back on the stack.

Operation: result = (2nd top element) + (top element)

Exceptions: This command can throw an exception if the number of stack elements are insufficient.

Subtract

Description: Pops the top two elements from the stack, perform an subtraction and pushes the result back on the stack.

Operation: result = (2nd top element) - (top element)

Exceptions: This command can throw an exception if the number of stack elements are insufficient.

Multiply

Description: Pops the top two elements from the stack, perform an multiplication and pushes the result back on the stack.

Operation: result = (2nd top element) * (top element)

Exceptions: This command can throw an exception if the number of stack elements are insufficient.

Divide

Description: Pops the top two elements from the stack, perform an division and pushes the result back on the stack.

Operation: result = (2nd top element) / (top element)

Exceptions: This command can throw an exception if the number of stack elements are insufficient if the divisor is 0.

Mod

Description: Pops the top two elements from the stack, perform a modulo operation and pushes the result back on the stack.

Operation: result = (2nd top element) % (top element) - the result has the same sign as the top element.

Exceptions: This command can throw an exception if the number of stack elements are insufficient if the divisor is 0.

Not

Description: Pops the top value of the stack and pushes back a value, 1 if the popped value was zero otherwise 0.

Exceptions: This command can throw an exception if the stack is empty.

Greater

Description: Pops the top two elements from the stack, compares the two elements and pushes the result back on the stack.

Operation: result = (2nd top element) > (top element) - result: 1 if true, otherwise 0

Exceptions: This command can throw an exception if the number of stack elements are insufficient.

Pointer

Description: Pops the top element from the stack and rotate the direction pointer that many times. If the value is positive the rotation is clockwise, otherwise counterclockwise.

Exceptions: This command can throw an exception if the stack is empty.

Switch

Description: Pops the top element from the stack and toggles the codel choosers direction that many times.

Exceptions: This command can throw an exception if the stack is empty.

Duplicate

Description: Duplicate the top element of the stack.

Exceptions: This command can throw an exception if the stack is empty.

Roll

Description: Pops the top two elements from the stack and perform a roll operation. The popped values are interpreted as follows:

  • rolls: top value
  • depth: 2nd top value

The top stack value is buried in the stack at the value of depth the remaining elements above the buried elements are moved one step to the top. This operation is performed rolls times.

Exceptions: This command throws an exceptions if the number of stack elements is insufficient or rolling depth exceeds the stack height.

Example: Roll operation example

Input (integer)

Description: Requests the input of an integer value and pushes this value on the stack.

Input (character)

Description: Requests the input of a character value and pushes this value on the stack.

Output (integer)

Description: Pops the top element from the stack and outputs this elements interpreted as an integer.

Exceptions: This command can throw an exception if the stack is empty.

Output (character)

Description: Pops the top element from the stack and outputs this elements interpreted as an character.

Exceptions: This command can throw an exception if the stack is empty.

Color Commands

The commands in Piet are depending on the current codel block color and the color of the codel block which will be entered next. For more information how the next codel block are determined please refer section Determine Next Codel Blocks.

The following table provides the information needed to determine the command:

  Current Hue Hue +1 Hue +2 Hue + 3 Hue +4 Hue +5
Current satuation   Add Divide Greater Duplicate Input (character)
Satuation + 1 Push Subtract Modulo Pointer Roll Output (integer)
Satuation + 2 Pop Multiply Not Switch Input (integer) Output (character)

Usage:

Based on the Color Cycles and the colors of the current and next codel block the command can be determined with the table above.

The command is determined by the the distance between the current colors hue and satuation and the next colors hue and situation.

Example #1:

  • Current color: Red
  • Next color: Dark Red
  • Result: The satuation increases by 1 and the hue does not change, so the result is a Push operation.

Example #2:

  • Current color: Dark Blue
  • Next color: Light yellow
  • Result: Hue + 3, Satuation + 1, so the resulting command is Pointer

Codel Chooser

The Code Chooser (CC) is an internal program state controlling the program flow and is used to determine the next codel block - the Direction Pointer is also needed.

  • Values: left, right
  • Initial value: left

Direction Pointer

The direction pointer (DP) is an internal program state controlling the program flow and is used to determine the next codel block - the Codel Chooser is also needed.

  • Values: up, right, bottom, down
  • Initial value: right

Determine Next Codel Blocks

Determine the next codel block is an essential operation during the interpretation of a Piet program. Moving from one codel block to the next one are based on the state of the Direction Pointer and the Codel Chooser.

The following diagram shows this process

flowchart TB
    start(Start):::grey --> edge(Step 1: Determine Codel Edge)
    edge --> transitionPosition("Step 2: Find transition position")
    transitionPosition --> nextStartCodel("Step 3: Find next starting Codel")
    nextStartCodel -- "Codel is valid" --> newCodelBlock("Step 4:Get new codel block (region growing)")
    nextStartCodel -- "Codel is invalid" --> updateState("Step 5 (optional): Update internal program state")
    updateState -- "Toggle CC or Rotate DP \n max 7 tries" --> edge
    newCodelBlock --> End(End):::grey

    classDef grey fill:#2d2330
Loading

Step 1: Determine the codel edge using the Direction Pointer.

This codel edge consists of all codels which have the maximum value in direction of the Direction Pointer. The edge can be disjoint.

Examples: Example: Codel Edge

Step 2: Determine transition position in the edge based on the Codel Chooser state.

This is the position in the current codel block from which you "walk" to the next codel in direction of the Direction Pointer in the next step. The transition position depends also on the state of Direction Pointer and Codel Chooser. The table below defines which codel is the transition codel:

Direction Pointer Codel Chooser Transition Codel
up left leftmost
up right rightmost
right left uppermost
right right lowermost
down left rightmost
down right leftmost
left left lowermost
left right uppermost

Examples: Example: Transition Codel

Step 3: Step: Find and validate candidate

Determine the position where you would enter the next codel block based on the transition codel (step 2) and the Direction Pointer.

There are the following scenarios:

  • Next codel has a valid hue (red, yellow, green, cyan, blue, magenta): Codel is valid (see Example 1). Proceed with step 4.
  • Next codel is white: Traverse white codels in direction of direction pointer until the next non white codel or the image border is reached (see Example 2, 3 and 4).
  • Next codel is black: Black codels are blocking the program flow (see Example 3). Proceed with step 5.
  • Coordinates out of Bounds (see Example 5). Proceed with step 5.

If this position exceeds the image boundaries proceed with step 5. If not, pick the codel at this position and proceed as follows depending on the codels color.

  • Color is valid: Color is not Black or white: Candidate is valid.
  • Black: Codel in invalid, proceed to step 5.
  • White: This color is neutral so traverse along the direction of the direction pointer until you reach the border or a black codel (then proceed with step 5) or until you found a color different from black or white.

Examples: Example: Next Codels

Step 4:

Staring on the first codel of the new codel block (step 3) use region growing to determine the next codel block. The new codel block can consist of 1 or many codels with the same color and a 4-neighborhood connection (see section Codel Blocks).

Examples: Example: New codel Block

Step 5 (optional):

This step is only entered if the candidate from the previous step 3 was invalid. In this case :

  • Toggle the Codel Chooser and proceed with step 1.
  • If this fails again, rotate the Direction Pointer clockwise and go back to step 1.

This procedure is repeated 8 times until all possible options have been tried - this triggers the termination of the interpreter.

Program Execution

The program execution starts with the codel block in the top left corner of the Piet program with the Direction Pointer facing to the right and the Codel Chooser is set to left.

From this codel the first codel block is determined and the following program flow starts:

flowchart LR
    Start(Program Start) --> nextCodel
    subgraph InterpreterLoop["Interpreter Loop"]
    direction LR
    execution[Execute command] --> nextCodel[Find next codel]
    nextCodel --> valuateCodelBlock{Valid?}
    valuateCodelBlock -- Yes --> execution
    end
    valuateCodelBlock -- No --> Terminate(Terminate Program)
    execution -- Error --> Terminate 
Loading

Program Termination

Successful program termination

The program terminates if there is no next codel available. This can only in the progress of finding the next codel block (see section Determine Next Codel Blocks).

If this happens all possible ways from the current codel block to all possible 8 candidate are tested.

Termination in case of errors

During the program interpretation errors can occur while executing the commands, e.g. there are insufficient elements on the stack or a division by zero was performed.