#esolang #programming-language #rotation #4d #esoteric #computation #stack

bin+lib spin4

spin4 is an esoteric programming language that uses 4D rotations for computations

3 releases

0.0.3 Feb 24, 2024
0.0.2 Feb 17, 2024
0.0.1 Feb 17, 2024

#249 in Math

Download history 199/week @ 2024-02-16 172/week @ 2024-02-23 19/week @ 2024-03-01 8/week @ 2024-03-08 4/week @ 2024-03-15 70/week @ 2024-03-22 28/week @ 2024-03-29

98 downloads per month

MIT license

50KB
1K SLoC

JavaScript 635 SLoC // 0.1% comments Rust 581 SLoC // 0.0% comments

spin4

spin4 is an esoteric programming language that uses 4D rotations for computations. Its main philosophy is to write programs by rotating the 4D space which encodes a state, this state is then used to increment or decrement an accumulator vector. The accumulator components can then be put on the stack, the later can also be rotated in one direction.

Why ?

Yes.

spin4 interpeter

The current spin4 interpeter is not optimized and serves only as a proof of concept. Installation

cargo install spin4
Usage: spin4 [OPTIONS] --file <FILE>

Options:
  -f, --file <FILE>  
  -d, --debug        
  -h, --help         Print help
  -V, --version      Print version

Basic overview

Ultimately, a spin4 program has

  • An accumulator vector with 2 components: register X and Y
    • We accumulate values as we perform rotations by doing addition, substraction, multiplication or integer division
    • We can operate on its component X,
    • The value of the stack is incremented/decremented as we rotate in the 4D-space
  • A single stack:
    • We can push the value of the accumulator one component at a time i.e. push the value of X or Y
    • We can perform a push with the standard input
    • We can rotate it from left or right
    • We can pop the top element to one of the registers
    • We can display the top element

Examples

Hello World

Hello World program in spin4

{(+1>)x?y}(+0000>)*[<][<][y]y[>][>][x]x*[>][>][y]y[<][<][x]+[x]+[.c][x]x+[x]+[x]+[x]+[<][yx]y[>]-(+1054<5401>012111<)x(+0>)x[.c][<][<][<][<][yx]xy[>][>][>][>]+[xy]y+[.c][.c][x]x[<][<][<][y]y[>][>][>]+[.c][x]x+[>][>][x]x[<][y]x[<][<][<][<][<][<][.c][<][<][.c]y[.c][y][xy][yx][xy][y][.c][xy][.c][yx][.c]

Fibonacci sequence

As a tradition, here is the Fibonacci sequence in spin4. This program takes a positive integer n as an input (stdin) and then prints a list of the n first Fibonacci numbers.

[,n](+00>)y*[y]*[x]*[>][x](-00<)(+0>)xxx[.n][<][.c][>][.n][xy]xy{[xy]+x[xy]xy[<][.c][>][.n][>][>][yx]y-[yx]yx[>][>][>]?y}

Concepts

Rotation < for -π/2 and > for +π/2

In 4D, we can form a total of 6 planes from the base vectors, a plane of rotation is the equivalent concept to the center of rotation in 2D i.e. there is always an invariant plane under a 4D rotation.

  • xy as 0 (xy-plane is invariant)
  • xz as 1 (xz-plane is invariant)
  • xw as 2 (xw-plane is invariant)
  • yz as 3 (yz-plane is invariant)
  • yw as 4 (yw-plane is invariant)
  • zw as 5 (zw-plane is invariant)
  • We start a rotation or a sequence of rotations with the syntax (main_operator seq_of_rotation)

  • What happens to the accumulator after a rotation ?

    • The accumulator vector state is changed: X and Y increment/decrement
    • The system becomes oriented in some way
    • Conceptually speaking, in order to compute the next state of the accumulator vector, spin4 takes the two only base vectors which generate the same plane as $\vec{u} = (1 \space 0 \space 0 \space 0)^T$ and $\vec{v} = (0 \space 1 \space 0 \space 0)^T$. Suppose for example that we have the columns $(0 \space -1 \space 0 \space 0)^T$ and $(1 \space 0 \space 0 \space 0)^T$ in the system matrix, the orientation signature becomes [-1, 1], we can then compute the next accumulator state acc <- acc + [-1, 1].

    The easiest implementation for computing the signature is to iterate through each column pair combination $(\vec{u}', \vec{v}')$ that satisfies the projections $\vec{u}.\vec{v}'=0$ and $\vec{u}'.\vec{v}=0$, which basically guarantees that the generated plane is congruent to the initial.

    A nice trick is to notice that a $\pm \pi / 2$ rotation applied on the identity matrix or a signed permutation of its columns will always result on a generalized permutation matrix whose non-zero entries are -1, 1, we can simply extract the relevant entries with some algebra.

$$T \leftarrow R_{Index, Dir} T$$

$$ (Acc_X \space Acc_Y) \leftarrow (Acc_X \space Acc_Y) + \begin{pmatrix}1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\end{pmatrix} T \begin{pmatrix}1 \\ 1 \\ 1 \\ 1\end{pmatrix} $$

Instructions

  • Arithmetic operators +, -, /, *, _ (no op).

  • Rotation sequence (Op Seq)

    • Op can be any of the above binary operator
    • Seq is a sequence of ordered rotation
      For example (+1>1<01>) is equivalent to (+01>)
  • x or y : push a specific component of the accumulator to the stack.
    Examples :

    • (+03<5>)x => push -1 to the stack, accumulator [-1, 1]
      • stack := ... -1
    • (+03<5>)yx => push 1 then -1 to the stack, accumulator [-1, 1]
      • stack := ... 1 -1
    • (+03<5>)* => push -1 (or x=-1 * y=1) to the stack, accumulator [-1, 1]
      • stack := ... -1
    • (+03<5>)x+y => push -1 then 0 then 1, accumulator vector is [-1, 1]
      • stack := ... -1 0 1
    • (+03<5>)yx/+x => push 1, -1, -1, 0, then -1, accumulator [-1, 1]
      • stack := ... 1 -1 -1 0 -1
  • [>]/[<] : rotate stack right/left

  • [x], [y], [xy] or [yx] : pop the stack then put the value(s) in the corresponding accumulator component in order

  • [.n] : print the top element as a number

  • [.c] : print the top element as a char

  • [,n] : number input (int32)

  • [,c] : char input

  • Loop { .. ?t}: t is either x or y, it checks a single accumulator component and breaks if the value is 0.

    Example :

    • {(+50>)?x}y stops as soon as the accumulator x component is 0 then pushes y component value to the stack

More examples..

  • Example 1 : The no op operator _

    In some case, we just want to do a sequence of rotation and do nothing along the way. In the expression (_03>5<), the accumulator vector remains [0, 0].

  • Example 2 : Doing addition/substraction/... as we are rotating.

    Consider the following program (+03<5>)

    • Rotate 0 (90deg), perform addition according to the orientation of the congruent plane to the initial xy
      • acc = [0, 0] + [+1, +1] = [1, 1]
    • Rotate 3 (90deg), perform addition according to the orientation of the congruent plane to the initial xy
      • acc = [1, 1] + [-1, +1] = [0, 2]
    • Rotate 5 (-90deg), perform addition according to the orientation of the congruent plane to the initial xy
      • acc = [0, 2] + [-1, -1] = [-1, 1] The accumulator vector then becomes [-1, 1]
  • Example 3 :

    Let acc = [2, 4]

    The + in a program .. + .. computes 2 + 4, the result is stored in the stack.

  • Example 4:

    The x in the expression (-01>3<)x extracts the x component of the accumulator and store it in the stack.

Dependencies

~5MB
~95K SLoC