Floater

From Esolang
Jump to navigation Jump to search

Floater is a 2-dimensional esoteric programming language designed by Zom-B in 2014. It's loosely inspired by Piet.

Overview

Floater is a language in which the program is an image and pixels define the instructions. The instruction pointer can move in four directions. The memory layout is random-access and stack-based at the same time. Most instructions operate on the top of the stack, some instructions can access the stack using indirect addressing (random-access). The stack pointer defines how large the 'memory' is; addresses below 1 and above the stack pointer don't exist. The language is weak-typed and all memory location contains real numbers ℝ. The size of the stack is unbounded.

The program is self-modifying, and this is in fact the only way to make choices and branches. All 'amounts' are 1-base, meaning the value 1 is the lowest index in all data structures (memory, image, and instruction group). This does not apply to colors.

The author was inspired by PIET, and wanted to make something that didn't require remembering all the cycles, and to make both programming in it and running it easier. Strictly speaking, the former requirement (remembering lots of stuff) hasn't been solved. The amount of essential instructions is low, but there are a lot of exotic instructions (higher arithmetic, trigonometric, etc..). The subset of the language with only the essential instructions should, however, be Turing-complete. The set of instructions is primarily influenced by Assembly language and the memory model by the x87 FPU.

Syntax and Execution

Yes this section bloated a bit, i need to move stuff out here to a section below #Instruction table

Syntax

The instruction pointer is like a turtle walking over the grid of the image. The upper-left pixel of the image is coordinate (1, 1), X increases to the right and Y increases downwards. Each pixel in the image is a discrete location. There are 16 instruction groups assigned to each of the 16 EGA colors (the 16 Windows colors can also be used). Images can however contain other colors, and when these are encountered the closest EGA color is calculated (allowing lossy compression).

Params

Each instruction group (except NOP) needs a parameter (param) to define which instruction to execute or which literal value to take. The parameter is encoded in the area of all 4-connected pixels with the same instruction color. However, when two instructions from the same instruction group are in direct succession, this would cause a conflict, because the area of the entire connected blob would be the same for both instructions. To prevent this, a mechanism is built in to prevent the area of the next and previous instruction from contributing to the area of the current instruction. Instructions which are more than 1 step away, or not on the line of direction of the instruction pointer, are still counted, and this can be exploited as a feature.

Here the param is 8
Here the param is 10
Here the param is 18
Here the param is 15


Memory

The memory starts empty, and the stack pointer starts at 0. When you push a value, the stack pointer and memory size increases by 1. The stack pointer always points to the top value of the stack.

Data types

Some instructions need a data type more restricted than a float, so here are the conversion rules:

  • Float: any possible value (theoretically unbounded and infinitely accurate; only limited by the implementation)
  • Integer: A float is rounded to the closest integer (0.5 becomes 1).
  • Boolean: Any non-zero value is true. True becomes −1.
  • Sign: −1 means negative, 0 means zero, 1 means positive.

Configuration

There are some configuration flags that modify certain behavior:

  • logbase: The value such that log(logbase) = 1 and exp(1) = logbase. Default = e.
  • angbase: The minimum value such that cos(ℤ*angbase) = 1 for any integer ℤ. Default = τ = 2π
  • iomode: The way values are converted to/from strings when using STDIO. Default = 0.
    • 0 = character mode
    • 1 = integer mode
    • 2 = float mode
  • gfxmode: The way to convert values to/from colors when using GRAPHICS. Default = 0.
    • 0 = 4 BPP, EGA (0..15) in rgbRGB format
    • 1 = 8 BPP, 256 gray shades (0..255)
    • 2 = 6 BPP (0..64) in RRGGBB format
    • 3 = 12 BPP (0..4095) in RRRRGGGGBBBB format
    • 4 = 18 BPP (0..262144) in RRRRRRGGGGGGBBBBBB format
    • 5 = 24 BPP (0..16777215) in RRRRRRRRGGGGGGGGBBBBBBBB format

Error handling

Any instruction that results in an illegal action or state is handled gracefully, using special values or by executing NOP instead. Examples:

  • Popping a value when the stack is empty results in the value 0 and no change to the stack pointer.
  • Writing a value to a non-existing memory location does NOP.
  • Reading a pixel from a non-existing coordinate, e.g. (0, 0), returns 0.
  • Dividing by zero returns Infinity or -Infinity. (NaN can also be generated in some cases)
  • When param is higher than the highest instruction in the group, NOP is executed.

Start and end

The program starts at the first non-NOP instruction on the first line of the image, otherwise in the upper-left pixel. The instruction pointer always starts facing down. When the instruction pointer walks off of any edge of the image, the program halts.

Execution cycle

There are three phases to running a program:

  • Fetch instruction,
  • Execute instruction,
  • Update instruction pointer.

Fetch instruction

  1. Look at the color of the pixel under the instruction pointer,
  2. Find the closest matching color from the 16-color palette, the index in the palette is the 'instruction group'.
  3. Count the area (param) of the instruction, like so:
    1. Check if the next and/or previous instructions (in the line of direction of the instruction pointer) have the same color,
    2. If so, use a complex algorithm to mark cells from those instructions as unavailable,
    3. Apply a generic 4-connected flood fill algorithm to find the area.

Execute instruction

The instruction can update the memory and/or the source image. Therefore execute should commence after fetch to prevent a paradox.

Update instruction pointer

  • Depending on the specific instruction, the instruction pointer may be rotated in one of the four cardinal directions.
  • It then takes one step in the current direction.
  • If the new location does not fall with in the image, execution halts.

Note that the source image might be enlarged by certain instructions, but never by the instruction pointer.

Instruction table

Color, param Instruction group Mnemonic Instruction
0 NOP NOP No operation - use for traveling
1, param STACK1 PUSH Push the integer value equal to the param
2, ○ STACK2 DUP Push the value at the top of the stack
2, ○○ SWAP Swaps the two top elements of the stack
3, ○ RAM GET Pop address, if address < 0 then address = (SP + address), read value from memory at address, push value
3, ○○ SET Pop address, if address < 0 then address = (SP + address + 1), pop value, write value to memory at address
4, ○ CONTROL PAUSE Stops the interpreter (no effect when running outside of the Designer)
5, ○ LOGIC NOT Pop value, push binary inverse (¬value)
5, ○○ AND Pop value1, pop value2, push binary intersection (value1 ∧ value2)
5, ○○○ OR Pop value1, pop value2, push binary union (value1 ∨ value2)
5, ○○○○ XOR Pop value1, pop value2, push binary exclusion (value1 ⊕ value2)
6, ○ COMPARE EQ Pop value, if value = 0 then push -1 else push 0
6, ○○ LT Pop value, if value < 0 then push -1 else push 0
6, ○○○ GT Pop value, if value > 0 then push -1 else push 0
6, ○○○○ SIGN Pop value, if value < 0 push -1 else if value = 0 push 0 else if value > 0 push 1
7, ○ STDIO PRINT Pop value, write value to stdout using the current iomode
7, ○○ INPUT Read value from stdin using current iomode, push value
7, ○○○ IOMODE (Configuration) Pop iomode
8, ○ GRAPHICS SET PIXEL Pop Y, pop X, pop color, put color to pixel to source image (X, Y) using current gfxmode
8, ○○ GET PIXEL Pop Y, pop X, push color of pixel in source image (X, Y) using current gfxmode
8, ○○○○ GFXMODE (Configuration) Pop gfxmode
9, ○ NUMBERS ZERO Push 0
9, ○○ COMPLEX Pop value, push (value × i)
9, ○○○ RND Generate random value between 0 (inclusive) and 1 (exclusive), push value(2π)
10, ○ ROUND ROUND Pop value, push value rounded to closest integer
10, ○○ FLOOR Pop value, push value rounded to next lower integer (⌊value⌋)
10, ○○○ CEIL Pop value, push value rounded to next higher integer (⌈value⌉)
10, ○○○○ TRUNC Pop value, push value rounded to integer closest to zero
11, ○ ARITHMETIC ADD Pop value1, pop value2, push (value2 + value1)
11, ○○ SUB Pop value1, pop value2, push (value2 − value1)
11, ○○○ MUL Pop value1, pop value2, push (value2 × value1)
11, ○○○○ DIV Pop value1, pop value2, push (value2 ÷ value1)
12, ○ SCIENTIFIC POW Pop value1, pop value2, push the power (value2value1)
12, ○○ SQRT Pop value, push square root (√value)
12, ○○○ EXP Pop value, push exponent of value
12, ○○○○ LOG Pop value, push logarithm of value
12, ○○○○○ LOGBASE (Configuration) Pop logbase
13, ○ TRIGONOMETRIC SIN Pop value, push sine of value
13, ○○ COS Pop value, push cosine of value
13, ○○○ TAN Pop value, push tangent of value
13, ○○○○ ATN Pop value, push arc-tangent of value
13, ○○○○○ ANGBASE (Configuration) Pop angbase
14 <reserved>
15, ○ FLOW FORWARD Executes NOP
15, ○○ DEFLECT Rotate CW or CCW (avoids the other white pixel)

Examples

Hello world

"Hello, World!":
Note: This is an older version. The brown pixels should be light gray to make it work.

Enlarged, animated (note, the instruction pointer starts at the top-left):

Transcription:

PUSH 33  #'!'
PUSH 100 #'d'
PUSH 108 #'l'
PUSH 114 #'r'
PUSH 111 #'o'
PUSH 119 #'w'
PUSH 32  #' '
PUSH 44  #','
PUSH 111 #'o'
PUSH 108 #'l'
PUSH 108 #'l'
PUSH 101 #'e'
PUSH 72  #'H'
PRINT
PRINT
PRINT
PRINT
PRINT
PRINT
PRINT
PRINT
PRINT
PRINT
PRINT
PRINT
PRINT

Cat

Simple, infinite version:

Version which stops at -1 (EOF):

Mandelbrot


Enlarged and run:
edit: it contains a bug. A kudos if you find it.

Brainfuck interpreter

//TODO

Computational class

Turing-complete because it can interpret Brainfuck. This has not been tested yet, but if for some reason it can not interpret Brainfuck, then, by definition, the specification of this language is erroneous and should be fixed.

External resources