Esoteric Programming languages(Esolangs) are programming languages that are designed to test the boundaries of computer programming. Most Esolangs are not designed to be used in mainstream programming because of their unconventional language features. Many Esolangs are built for minimalism, specifically to have as few commands as possible. The most famous of them is called BrainFuck, created by Urban Müller in 1993, which was an attempt to create a language that he could write the smallest compiler for Amiga OS. Other esolangs are created for their weirdness . A good example is Piet which is a programming language where the programs look like abstract paintings. In this project, I will be building interpreters for Brainfuck and Piet.
Brainfuck Interpreter
Brainfuck Interpreter
Brainfuck is one of the most famous esoteric programming language that is renowned for its simplicity, only having 8 commands. Each command is represented by a certain character: > moves the pointer to the right by 1 cell, < moves the pointer to the left by 1 cell, + increases the current element by 1, - does the opposite, . outputs the current element that the pointer is on, the comma inputs a character and stores it at the current cell, [ and ] act as a while loop where the [ jumps past the matching ] if the current element is 0 and ] jumps back to the matching [ if the cell at the pointer is nonzero. I will be interpreting the Sierpinski’s triangle(iteration 5) and Hello world in BF.
sierpinskis="++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<]>.>+[>>]>+]";helloworld="++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
The tape is where the interpreter would be performing all of the BF functions on. The index tracks what cell the program is currently on. There are two index pointers that track the pointer is at. In order to know where the opening and closing brackets are, I used an association called looptable that would store each of the opening brackets and their respective closing brackets. loopstack stores all of the opening brackets which would popped out once the matching closing bracket is found. final will store all of the output which will be converted from ASCII into English.
In[]:=
intialize[] :=(tape = Table[0, 1000];index= 1;ip = 1;ip1 = 1;looptable = <||>;loopstack = {};final = {};)
The bfinterpreter takes in a BF string and will run the first while loop. In the while loop, if an opening bracket is found, it will append it to loopstack and if a closing bracket is found, it will remove the opening bracket from loopstack, and create a key-value pair between the index of the opening bracket to the index of the closing bracket. The second while loop goes through the string again and performs the intended BF functions by setting instruction1 to the string-part of ip1 and checking what character it is. After, FromCharacterCode is mapped to final in order to v it from ASCII into English.
In[]:=
bfinterpreter[x_] := While[ ip <= StringLength[x], instruction = StringPart[x, ip]; If [ instruction == "[" , AppendTo[loopstack, ip], Nothing ]; If[ instruction == "]", loopbeginningindex = loopstack[[-1]]; loopstack = Delete[loopstack, -1]; AppendTo[looptable, loopbeginningindex ->ip]; AppendTo[looptable, ip -> loopbeginningindex], Nothing ]; ip+=1; ];While[ ip1 <= StringLength[x], instruction1 = StringPart[x, ip1]; Which[ instruction1 == "+", tape[[index]]+=1; If[tape[[index]] == 256, tape[[index]] = 0, Nothing], instruction1 == "-", tape[[index]]-=1; If[tape[[index]] == -1, tape[[index]] = 255], instruction1 == "<", index -= 1, instruction1 == ">", index +=1, instruction1 == ".", AppendTo[final, tape[[index]]], instruction1 == ",", input = Input["Type in a character or a number"]; Which[ NumberQ[input] == True, tape[[index]]=input, StringQ[input] == True, tape[[index]]=ToCharacterCode[input] ], instruction1 == "[", If[tape[[index]]==0, ip1 = Key[ip1][looptable], Nothing], instruction1 == "]", If[tape[[index]]!=0, ip1 = Key[ip1][looptable], Nothing] ]; ip1+=1;]; StringJoin[FromCharacterCode[#, "ASCII"]&/@final]
Then I call the initialize function and the bfinterpreter for helloworld and sierpinskis to get the output.
Then I call the initialize function and the bfinterpreter for helloworld and sierpinskis to get the output.
intialize[]bfinterpreter[helloworld]intialize[]bfinterpreter[sierpinskis]
Out[]=
Hello World!
Out[]=
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Piet Interpreter
Piet Interpreter
Puts the pixels of the Piet image into its designated rows and orders them by its columns
If we wanted to, we could find the Hue and Brightness for each of the pixels in pietimage.
Although we will not be using these specific values for the Hue and Brightness, it is interesting to know the exact Hue and Brightness values for each of the pixels.
Piet Commands
Piet Commands
In Piet there are 15 commands:
Push : Pushes the number of codels in the previous color block .
Pop: Pops the top value off the stack.
Add : Pops the top two values off the stack, adds them up, and pushes the sum back onto the stack .
Subtract: Pops the top two values off the stack, subtracts the top value from the second-top value, and pushes the difference back onto the stack.
Multiply : Pops the top two values off the stack, multiplies them together, and pushes the product back onto the stack .
Divide : Pops the top two values off the stack, performs integer division on the second - top value divided by the top value, and pushes the quotient back onto the stack .
Modulo : Pops the top two values off the stack, divided the second - top value by the top value, and pushes the remainder back onto the stack .
Not : Pops the top value off the stack . If the value is 0, it pushes 1 onto the stack . Otherwise, it pushes 0.
Greater : Pops the top two values off the stack . If the second - top value is greater than the top value, it pushes 1 onto the stack. Otherwise, it pushes 0.
Pointer : Pops the top value off the stack, then rotates the DP one step clockwise that many times .
Switch : Pops the top value off the stack, then switches the state of the CC that many times .
Duplicate : Pushes a copy of the top value onto the stack .
Roll : Pops the top two values off the stack, and then rotates the top Y values on the stack up by X, wrapping values that pass the top around to the bottom of the rolled portion, where X is the first value popped and Y is the second value popped . For example, if the stack is currently 1, 2, 3, with 3 at the top, and then you push 3 and then 1, and then roll, the new stack is 3, 1, 2.
Input : Takes an input, either as a character or a number . If the input is a number, that value is pushed onto the stack . If it' s a character, its Unicode value is pushed onto the stack .
Output: Pops the top value off the stack. If a number should be printed, the value itself will be printed. If a character should be printed, then its corresponding character in the ASCII table will be printed.
Next I created a function that would find the amount of change of the hue and lightness between two codels
I also created an association called function finder which would map the Hue-Brightness change generated from stepfinder to their specific functions.
Now we can represent every pixel in pietflat as a Hue - Brightness by using ReplaceAll through pietflat to colortableassociation.
The variables below keep track of the current DP, current CC, current DP index, current CC index, list of DP values, list of CC Values, the pietstack where all the information will be coming in and out from and final string which will store the string that will be outputted from the Interpreter.
We will also have to create a coordinate association between pietnumberflat and the dimensions of pietimage(13x13) in order to know which pixel we are at and which pixel to go to when we will be running the interpreter.
Now we can create a function called run that will essentially go through the pixels by checking where the DP is, finding the Hue-Brightness change by calling stepfinder and then using functionfinder to perform the specific function. And we can create a function called newhead to get the new head that contains the Hue-Brightness that will passed into the run function.
And then create the edgehit function that will check if the current head is at an edge of the image and will turn the DP clockwise by 1 unit if it is at an edge.
First set the current head to a newhead by passing it through newhead, then run it through run. And lastly, print the result.
Future Directions
Future Directions
In the future, I would like to create functions that would recognize codel blocks, black codels and white codels because in my current project, I was not able to implement these with the time allotted. I think adding these features would allow my Piet interpreter to be fully complete and would allow me to run more complicated Piet programs. I could also try to build an interpreter for another esoteric programming language. The one I had in mind was Whitespace because the code is literally only whitespace characters (space, tab, and return), making it pretty interesting to build an interpreter for it.
Citations
Citations
■
sunjay. (n.d.). Brainfuck Examples. GitHub. https://github.com/brain-lang/brainfuck/tree/master/examples
■
■
Piet . Esolang . (n . d .) . https://esolangs.org/wiki/Piet
■
Mar, D . M . (n . d .) . Dangerous Mouse Piet . DM' s Esoteric Programming Languages - Piet . https://www.dangermouse.net/esoteric/piet.html
■
Schoch, T . (2006) . "Hello, world!" in Piet . "Hello, world!" in piet . https://retas.de/thomas/computer/programs/useless/piet/explain.html
■
Cadieux, G . S . (2018) . MasterPiets . Gabrielle Singh Cadieux - Piet Ide . https://gabriellesc.github.io/piet/
CITE THIS NOTEBOOK
CITE THIS NOTEBOOK
Building Interpreters for Esoteric Programming Languages
by Mich Obia
Wolfram Community, STAFF PICKS, July 13, 2023
https://community.wolfram.com/groups/-/m/t/2962594
by Mich Obia
Wolfram Community, STAFF PICKS, July 13, 2023
https://community.wolfram.com/groups/-/m/t/2962594