Pairpointing

From Esolang
Jump to navigation Jump to search

Pairpointing is an esoteric programming language made by User: Fazaazafg. In Pairpointing, every variable is a pair. Each pair holds two pointers, which both can point to some other pair, to nothing (also known as a null pointer), or even point to its own pair.

This is currently in a work in progress, so expect some sections of it being unfinished.

Syntax

The syntax itself is fairly simple. Each line is separated with a semicolon, with them being executed from top to bottom and the program terminates when it reaches the bottom. Comments can be made using the ~ symbol to mark a comment. Each comment ends after a newline character. Just like the usual stuff like on most typical programming languages.

Pairs

In this language, the only data type that exist are pairs. As said before, a pair holds two pointers. The pointer can only point to a pair or null.

The = symbol is used to modify the pointers on a pair. The syntax for doing it is like so:

name = left, right;

where name is the pair to modify on and left and right are the pairs to make the pointers point on to. If name is a pair that doesn't exist yet, then it will create a new pair with the identifier name with the pointers pointing to the left and right pairs.

You can also do this:

pair = pair2;

which will make pair now point to pair2's pointers.

pair2 = left, right;

pair = left, right; ~ Same thing
pair = pair2; ~ Same thing

The pointers of a pair can also point to null by doing this:

pair = , right; ~ left element is null
pair = left, ; ~ right element is null
pair = ,; ~ both elements are null

the last case can also be written shortly as:

pair = ; ~ both elements are null

You can also create pairs with pairs inside of them using parentheses. Here's an example.

templ = l, r;
tempr = r, l;
pair = templ, tempr; ~ Too long

pair = (l, r), (r, l); ~ Do this instead

To refer to an element in a pair, you can use < and > symbols to refer the left and right element of a pair. Example of how it can be used:

pair = left, right;
pair2 = >left;
>pair = <pair, pair2;

These can be stacked together to have the very inner elements on a pair. The order goes from right to left.

<>>>pair = pair2, pair4;
><<><>>pair3 = ><pair4, <pair;

Although pairs can only have two pointers, you can however put in more than two pairs to assign to the pointers.

pair = a, b, c, d, e;

But, how does this even work? Well, the thing is that the code above is a shorthand for:

pair = a, (b, (c, (d, e)));

Okay, so, what would this even be used for? Well, turns out, this could be used as a some sort of array actually.

pair = a, b, c, d, e;
index0 = <pair;     ~ gets the first element of [a, b, c, d, e], which is a
index1 = <>pair;    ~ gets the second element of [a, b, c, d, e], which is b
index2 = <>>pair;   ~ gets the third element of [a, b, c, d, e], which is c
index3 = <>>>pair;  ~ gets the fourth element of [a, b, c, d, e], which is d
index4 = <>>>>pair; ~ gets the fifth element of [a, b, c, d, e], which is e

If statements

The ? symbol is used to create an if statement. The code blocks for the statements are written using curly brackets. There are two types of if statements in this language:

variable? {
  statements
}
var1 = var2? {
  statements
}

The first one will execute statements if variable has at least one of its pointers not pointing to null. The only time statements will not execute after triggering this if statement is when both of the pointers are pointing null. If variable is already null, then it will not execute statements.

The second if statement will execute statements if var1's pointers are the same pointers as var2's. It will not however if at least one isn't the same, even if the contents of the pointer matches.

left = ;
right1 = , left;
right2 = , left; ~ Has the same pointers as right1, but has different names
pair1 = left, right1;
pair2 = left, right1;
pair3 = left, right2;
pair1 = pair2? {
  ~ It will execute this because right1 and right1 are the same
}
pair1 = pair3? {
  ~ It will *not* execute this because right1 is not right2
}

If var1 and var2 are the same pair, then statements will always be executed.

Else if statements in this language can be written like this:

variable? { ~ if
  statement1
}, var1 = var2? { ~ else if
  statement2
}, { ~ else
  statement3
}

One line if statements also exists in this language, and it can be written like this:

variable? statement1
, var1 = var2? statement2
, statement3

Loops

Loops in Pairpointing are while loops, in that they will keep executing until a condition is false. The syntax is very similar to if statements and uses the same two conditions as said before, but the only difference is that it uses the ! symbol and not the ? symbol. Here's some examples of loops.

pair! {
  statements
}
pair = pair2! {
  statements
}

Each iteration on a loop the program will jump at the beginning of that loop and check whether the condition is true or not. If it is still true, it will continue executing the loop, but if it's not, then it'll break out of the loop automatically.

Breaking out of a loop manually (also known as the break keyword in most typical programming languages) can be done by using the < symbol, like this:

p! {
  statements
  <; ~ breaks out of the loop
  statements
}

Skipping over an iteration of a loop (also known as the continue keyword in most typical programming languages) uses the > symbol.

p! {
  statements
  >;
  more statements
}

Functions

Functions allows you to make abstractions if code gets too complex. Functions in this language only has one argument, and the argument and return type is a pair. If at by the end of the function it hasn't been returned to, then it will automatically returns with a null pair (a pair that has both of its pointers null).

func_name arg {
  statements
}

To return, use the = symbol to return with the pair at the front. Here is an example of a swap function that swap pointers.

swap p {
  = >p, <p;
}

Calling a function can be done like this:

pair2 = swap pair;

Calling multiple functions at once will make it execute from right to left.

p = func1 func2 func3 func4 p;
~ which is just func1(func2(func3(func4(p))))

Calling a function with a null pair can be written shortly as:

p = func;

IO

To take inputs from the user, call the built-in function input and it will return a pair the user has inputted. Outputting is kind of the same. When the built-in function output is called, what's in the argument of the function will be outputted.

Here's a diagram of what will be returned of the input function when inputting the word "Hi", for example.

 Input
  / \
H   .
   / \
  i  null

  H
 / \
0   .
   / \
  0   .
     / \
    0   .
       / \
      1   .
         / \
        0   .
           / \
          0   .
             / \
            1   .
               / \
              0  null
  i
 / \
1   .
   / \
  0   .
     / \
    0   .
       / \
      1   .
         / \
        0   .
           / \
          1   .
             / \
            1   .
               / \
              0  null

The 0s and 1s are both two constant pairs that are hardcoded into the language. 0 points to null and null, while 1 points to 1 and 1.

Outputting is done by doing the same thing, just in reverse. Create a pair that has the same structure as above and pass it into the arguments of the output function.

message = input; ~ Gets input from user
output message; ~ Outputs it back
output (0,1,0,1,),; ~ Print a newline (ASCII code 10)
output message; ~ Output the message again

To input and output numbers, use the hardcoded input_num and output_num functions respectively. The numbers are structured like the ASCII characters, except with an extra bit at the beginning to tell whether the number is positive or negative. It's null if it's positive and 1 if it's negative. The number 0 is considered as positive. If the input isn't a number (i.e. has letters in it), it'll return null. If the output isn't a number, it will not print anything. Example if the number 25 is inputted:

 Input
  / \
null .
    / \
   1   .
      / \
     0   .
        / \
       0   .
          / \
         1   .
            / \
           1  null

This here is all of the IO pairs and functions used in this language. These pairs are constant and will never change its value. Assigning a value to them won't have any effect.

Name Points to Description
0 null and null Used by the IO functions to represent 0
1 1 and 1 Used by the IO functions to represent 1
Name Description
input Gets input from the user and returns that input as ASCII characters, argument is ignored
output Outputs the argument as ASCII characters, function returns null
input_num Gets input from the user and returns that input as a number, argument is ignored
output_num Outputs the argument as a number, function returns null

Examples

Note that since Pairpointing currently doesn't have an implementation, I don't know if some of these programs actually work. But at least it should in theory.

Cat program

inp = input;
inp! {
  output inp;
  inp = input;
}

Truth machine

inp = input_num;
output_num inp;
<>inp? {
  output_num inp;
}

Logic gates

and p {
  <p? >p? = 1;
  = 0;
}
or p {
  <p? = 1;
  >p? = 1;
  = 0;
}
not p {
  p? = 0;
  = 1;
}
xor p {
  and p? = 0;
  q = not <p, not >p;
  and q? = 0;
  = 1;
}

Hello, world!

H = 0, 0, 0, 1, 0, 0, 1, 0, ;
e = 1, 0, 1, 0, 0, 1, 1, 0, ;
l = 0, 0, 1, 1, 0, 1, 1, 0, ;
o = 1, 1, 1, 1, 0, 1, 1, 0, ;
c = 0, 0, 1, 1, 0, 1, 0, 0, ; ~ Comma
s = 0, 0, 0, 0, 0, 1, 0, 0, ; ~ Space
w = 1, 1, 1, 0, 1, 1, 1, 0, ;
r = 0, 1, 0, 0, 1, 1, 1, 0, ;
d = 0, 0, 1, 0, 0, 1, 1, 0, ;
x = 1, 0, 0, 0, 0, 1, 0, 0, ; ~ Exclamation mark
output H,e,l,l,o,c,s,w,o,r,l,d,x,;

99 bottles of beer

S = 0, 0, 0, 0, 0, 1, 0, 0, ; ~ Space
P = 0, 1, 1, 1, 0, 1, 0, 0, ; ~ Period
C = 0, 0, 1, 1, 0, 1, 0, 0, ; ~ Comma
L = 0, 1, 0, 1, 0, 0, 0, 0, ; ~ Newline

b = 0, 1, 0, 0, 0, 1, 1, 0, ;
o = 1, 1, 1, 1, 0, 1, 1, 0, ;
t = 0, 0, 1, 0, 1, 1, 1, 0, ;
l = 0, 0, 1, 1, 0, 1, 1, 0, ;
e = 1, 0, 1, 0, 0, 1, 1, 0, ;
s = 1, 1, 0, 0, 1, 1, 1, 0, ;
f = 0, 1, 1, 0, 0, 1, 1, 0, ;
r = 0, 1, 0, 0, 1, 1, 1, 0, ;
n = 0, 1, 1, 1, 0, 1, 1, 0, ;
h = 0, 0, 0, 1, 0, 1, 1, 0, ;
w = 1, 1, 1, 0, 1, 1, 1, 0, ;
a = 1, 0, 0, 0, 0, 1, 1, 0, ;
T = 0, 0, 1, 0, 1, 0, 1, 0, ;
k = 1, 1, 0, 1, 0, 1, 1, 0, ;
d = 0, 0, 1, 0, 0, 1, 1, 0, ;
p = 0, 0, 0, 0, 1, 1, 1, 0, ;
i = 1, 0, 0, 1, 0, 1, 1, 0, ;
u = 1, 0, 1, 0, 1, 1, 1, 0, ;
N = 0, 1, 1, 1, 0, 0, 1, 0, ; ~ Capital N. Only used for: "No bottles of beer on the wall."

bottles = 1, 1, 0, 0, 0, 1, 1, 0, ;

1! {
  output_num bottles;
  output S,b,o,t,t,l,e,s,S,o,f,S,b,e,e,r,S,o,n,S,t,h,e,S,w,a,l,l,C,L;
  ~ [bottles] bottles of beer on the wall,
  
  output_num bottles;
  output S,b,o,t,t,l,e,s,S,o,f,S,b,e,e,r,P,L,
         T,a,k,e,S,o,n,e,S,d,o,w,n,C,S,p,a,s,s,S,i,t,S,a,r,o,u,n,d,C,L;
  ~ [bottles] bottles of beer.
  ~ Take one down, pass it around,
  
  decrement bottles;
  >>bottles? , { ~ if bottles equals one
    output_num bottles;
    output S,b,o,t,t,l,e,S,o,f,S,b,e,e,r,S,o,n,S,t,h,e,S,w,a,l,l,P,L;
    ~ [bottles] bottle of beer on the wall.
    
    output_num bottles;
    output S,b,o,t,t,l,e,S,o,f,S,b,e,e,r,S,o,n,S,t,h,e,S,w,a,l,l,C,L;
    ~ [bottles] bottle of beer on the wall,
    
    output_num bottles;
    output S,b,o,t,t,l,e,S,o,f,S,b,e,e,r,P,L,
           T,a,k,e,S,o,n,e,S,d,o,w,n,C,S,p,a,s,s,S,i,t,S,a,r,o,u,n,d,C,L,
           N,o,S,b,o,t,t,l,e,s,S,o,f,S,b,e,e,r,S,o,n,S,t,h,e,S,w,a,l,l,P,L;
    ~ [bottles] bottle of beer.
    ~ Take one down, pass it around,
    ~ No bottles of beer on the wall.
    
    <;
  }
  output_num bottles;
  output S,b,o,t,t,l,e,s,S,o,f,S,b,e,e,r,S,o,n,S,t,h,e,S,w,a,l,l,P,L;
  ~ [bottles] bottles of beer on the wall.
  
}

decrement p {
  <p? {
    p = 0, >p;
    =;
  }
  p = 1, >p;
  decrement >p;
}

Notes

  1. Pairs and functions can't have the same name at the same time. For example, you can't have a pair named name and a function named name at once. Since pairs and null argument function calls both look identical.
  2. In Pairpointing, null is defined as a constant pair that points to null and null.
  3. Constant pairs are pairs that has pointers that can't change what it's pointing to. Pairs can't be set as constant manually in code.