PINAPL - PINAPL Is Now A Programming Language
PINAPL - PINAPL Is Now A Programming Language
Note: PINAPL. my pixelbased programming language, is not related to the MATHS language which was previously known as PINAPL. Blame me for naming my language PINAPL without looking for earlier languages with the same name... :/

Simple manual/guide thing



PINAPL is strange. (and possibly quite useless, BUT FUN!)
PINAPL is a turing-complete interpreted programming language
PINAPL is a pixel-based 'esoteric programming language', currently interpreted by a little program I've written in C#.
PINAPL is pixel-based in that a 'program' is not written in plaintext into a specifically-marked-up-textfile. Instead, you draw programs, using specific pixel colours to achieve various results. For example, RED indicates a start-of-program pixel, and WHITE pixels are the basic building blocks of programs; white pixels themselves do not have any action; they only serve to lead the program towards 'meaningful' pixels, and are called idle-pixels further on in this document. A white pixel can be seen as a NOP-instruction (No-OPeration).


Interpreter
A basic interpreter for various versions of Windows requiring various runtime libraries can be found here.
More stuff
More documents, examples and other files can be found here.
Worth mentioning is PINAPLTool, a tool which allows you to convert Befunge snippets into something that can be read by the PINAPL Befunge Interpreter (see /stuff), aswell as regular text into PINAPL code that echo's said text.

Program-pixel behaviour
A program-pixel is any non-black pixel. Basically, all program-pixels have the same characteristics as idle-pixels (unless they have any special function which prohibits this, but for the sake of simplicity, these pixels too are called program-pixels).
Program-pixels lead the program in a predictable way. Basically, program-pixels always try to 'progress' the program in the current program 'direction' (4-way: up, right, down, left -- up is called '0', right is called '1', down is called '2' and left is called '3', though a synonym for 'up' is also 4, thanks to the ever-awesome modulo!). If the program can't progress in the current direction, it will search for neighboring program-pixels around the currently running pixel in an either clockwise or anti-clockwise fashion: the first pixel to be found will be the one we are jumping to. By default, searching is done clockwise. If no program-pixels can be found (other than the program-pixel we originated from), we're in a so-called deadlock and can't progress the program any further.
Some program pixels have special functions and behaviours attached to them. These are known as 'function pixels'.


This simple program will start at the red pixel, move right until it can't anymore, move down until it can't anymore, and then move left until it deadlocks.


This simple program will start at the red pixel, move right, then down, left, up, and move to the RIGHT at the T-crossing, due to the (default) clockwise checking for program-pixels. Note that at the '4-way crossing', the program won't make a left or rightwards turn; instead, it'll go forwards.

Lead-pixels
Lead-pixels are pixels with the specific task of leading the program the right way, when the 'basic' rules lead it in a way you are not fond of. Current lead-pixels are:
[255/128/0] - Initiate ANTICLOCKWISE checking for program-pixels.
[255/0/128] - Initiate CLOCKWISE checking for program-pixels.
Note that the CLOCKWISE / ANTICLOCKWISE setting is kept until changed by a CLOCKWISE / ANTICLOCKWISE setting pixel.
[255/128/128] - FORCE a turn as soon as the program can progress both forwards and to a side. If the program can progress to two sides (like for instance at a 4-way crossing), the program will progress to the side preferred by the current ANTICLOCKWISE / CLOCKWISE setting.
[255/255/x] - SET CURRENT DIRECTION to x. 0 translates to up, 1 to right, 2 to down, 3 to left. Values of x that are larger than 3 can also be used (but not preferred), in those cases the direction will be set to the modulo of x with 4.
[255/128/255] - SET CURRENT DIRECTION to a random direction.

Jump-pixels
Jump-pixels are pixels that cause the program's current location to change. Note that after a jump has been made, searching for the next pixel is done either clockwise or anticlockwise from the current direction, and 'going backwards' is temporarily allowed.
[1/128/x] - JUMP TO a JUMP TO TARGET with ID = x
[2/128/x] - JUMP TO TARGET, ID = x
[1/200/x] - CALL PROCEDURE, will push the current position and direction of the program to the programstack, then jump to a PROCECURE TARGET where ID = x
[2/200/x] - PROCEDURE TARGET, ID -= x
[3/x/y] - CALL FUNCTION, will search for a matching 4/x/* pixel, push Y onto the stack, then push the current position and direction of the program to the programstack., and eventually jump to a matching 4/x/* pixel. The matching 4/x/* pixel used is determined as follows. First, the 4/x/y pixel will be searched for. If it exists, that pixel will be designated as the jump to target. If it can't be found, a pixel with red=4 green=x will be searched for. The first occurance of such a pixel will be designated as the jump target. If none is found, nothing will happen.
[4/x/y] - FUNCTION TARGET, ID = x, argument = Y
[0/0/255] - Although not technically a jump pixel, the RETURN PIXEL will pop an element from the programstack, and jump there. If the programstack is empty, the program will terminate.




Examples

JUMPS!


Previous image is equal (in function) to this one above..


It's a FOR loop!




Quick PINAPLinterpreter info
*Clicking anywhere within the image window will shift the image around.

Todo:
-Port PINAPL to Java
-Write a proper PINAPL test that verifies if the PINAPL interpreter is performing according to the PINAPL specs (this way, anyone can make their own interpreter and see if it works correctly)
-Write a Tetris clone in PINAPL that makes extensive use of the self-modifying code aspect of PINAPL
-Finish writing documentation

ALL FUNCTION PIXELS:
255/0/0 - START OF PROGRAM
0/0/255 - RETURN (will END PROGRAM if no position/direction is on the stack)
0/1/255 - FORCE QUIT
255/128/0 - ANTICLOCKWISE
255/0/128 - CLOCKWISE
255/128/128 - FORCE TURN
255/255/x - SET DIRECTION TO x
255/200/200 - Don't execute next pixel ('trampoline')
255/128/255 - Set direction to a random direction

1/128/x - JUMP TO a JUMP TO TARGET, ID = x
2/128/x - JUMP TO TARGET, ID = x
1/200/x - CALL PROCEDURE, ID = x (matches PROCEDURE TARGET)
2/200/x - PROCEDURE TARGET, ID = x
3/x/y - PUSH Y ONTO STACK (but only if 4/x/* exists), CALL FUNCTION X
4/x/y - FUNCTION TARGET, ID = x, argument = y (if 3/x/y is called and no corresponding 4/x/y is found, the first occuring 4/x/* is used instead)
    (this allows you to exclude certain arguments)

125/x/y - SET INTEGER X TO VALUE OF INTEGER Y
126/x/y - SUBSTRACT INTEGER y FROM INTEGER x (RESULT IN INTEGER x)
127/x/y - SUBSTRACT VALUE y FROM INTEGER x
128/x/y - SET INTEGER x TO VALUE y
129/x/y - ADD VALUE y TO INTEGER x
130/x/y - ADD INTEGER y TO INTEGER x (RESULT IN INTEGER x)

120/x/y - COMPARE INTEGER x TO VALUE y (IF EQUAL, EXECUTE NEXT PROGRAM PIXEL; IF NOT, DO NOT EXECUTE IT).
121/x/y - COMPARE INTEGER x TO INTEGER y (IF EQUAL, EXECUTE NEXT PROGRAM PIXEL; IF NOT, DO NOT EXECUTE IT).
122/x/y - COMPARE INTEGER x TO INTEGER y (IF X>Y, EXECUTE NEXT PROGRAM PIXEL; IF NOT, DO NOT EXECUTE IT)

100/0/x - Push x onto the stack
100/1/x - Pop from the stack into INTEGER x
100/2/0 - Pop from the stack and output as ASCII (stdout)
100/3/x - Push INTEGER X onto the stack
100/255/255 - Pop from the stack (discard)
100/255/0 - Pop YXBGR and set pixel using those values
100/255/1 - Pop from PROGRAMSTACK, then push X, Y, Direction to the stack
100/255/2 - Pop Direction, Y, X. Push that to PROGRAMSTACK
100/255/3 - Push current stack size to the stack
100/255/4 - Pop YX and push RGB of pixel at (X,Y)


80/0/x - Output X as ASCII (stdout)
80/1/x - Output INTEGER X as ASCII (stdout)
80/2/x - Output INTEGER X (convert to string, output to stdout)

240/0/x - Ask for input, convert to integer and store in INTEGER X
240/1/0 - Ask for input, push input (ascii values) to stack
240/1/1 - Ask for input, push input (converted to integer) to stack