Pairpointing
Pairpointing is an esoteric programming language made by 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.
To make null as the pointers, just put nothing in it, which looks like this:
pair = , right; ~ left element is null pair = left, ; ~ right element is null pair = ,; ~ both elements are null
or can be written shortly as:
pair = , right; ~ left element is null pair = left; ~ right element is null pair = ; ~ both elements are null
Another thing you can do is that using brackets, you can put pairs inside of pairs however you want on a single line.
pair = l, r; pair2 = (ll, lr), (rl, rr); pair3 = ((lll, llr), (lrl, lrr)), ((rll, rlr), (rrl, rrr));
Using nulls like that would still work.
pair = ; pair2 = (), (); pair3 = ((), ()), ((), ());
If you don't use brackets, things would still work. It will interpret as if there were brackets there. Turns out, you can easily create a some sort of an array with this.
pair1 = a, b, c, d, e; pair2 = (a, (b, (c, (d, e)))); ~ Same thing as pair1 pair3 = a, b, (c, d), e; pair4 = (a, (b, ((c, d), e))); ~ Same thing as pair3
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; ><<><>>pair3 = ><pair4;
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.
Breaking out of a loop can be done by using the <
symbol, like this:
p! { statements <; ~ breaks out of the loop }
Skipping over an iteration of a loop (also known as the continue keyword in most typical programming languages), uses the >
symbol. Again, just like <
, it will only work if there's no pair at the front.
p! { statements >; more statements }
Functions
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).
funcName 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 built-in pairs that are hardcoded into this 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.
To input and output numbers, use the inputNum
and outputNum
built-in 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 27 is inputted:
Input / \ null . / \ 1 . / \ 1 . / \ 0 . / \ 1 . / \ 1 null
Built-ins
This section covers all of the built-in pairs and functions in this language. These pairs can't be changed while runtime.
Built-in pairs
Name | Points to | Description |
---|---|---|
0 |
Used by the IO functions to represent 0 | |
1 |
1 and 1 |
Used by the IO functions to represent 1 |
Built-in functions
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 |
inputNum |
Gets input from the user and returns that input as a number, argument is ignored |
outputNum |
Outputs the argument as a number, function returns null |
Examples
inp = input; inp! { output inp; inp = input; }
inp = inputNum; outputNum inp; <>inp? { outputNum inp; }
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; }
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, ; s = 0, 0, 0, 0, 0, 1, 0, 0, ; 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, ; output H,e,l,l,o,c,s,w,o,r,l,d,x,;
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, ; bottles = 1, 1, 0, 0, 0, 1, 1, 0, ; 1! { outputNum 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; outputNum 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; --u bottles; ~ decrement bottles >>bottles? , { ~ if bottles equals one outputNum 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; outputNum 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; outputNum 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; <; } outputNum 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; } --u p { ~ decrement <p? { p = 0, >p; =; } p = 1, >p; --u >p; }
Notes
- Identifiers in this language are allowed to use all characters, except for whitespace characters, and the characters that are used by the language. This includes
; ~ , = ( ) > < ? ! { }
. - Pairs and functions can't have the same name and must be different.
- The pointers of null are null and null.