Week 3: Learning New Programming Languages
March 26, 2023
Welcome back to the weekly blog for my project. As I’ve been working on the beginning stage of the project, namely writing a program to generate BrainF code for every piece of Piet code I can find. I feel I’ve gained a greater intuitive understanding of BrainF, and partially Piet. To manage creating this BrainF data, I decided it would be best to use a preexisting Piet interpreter, called npiet. I have npiet run a Piet program, and print out what operations are being done.
From there, I look at the “action:” section of each step, to see what action is being done, and copy that down to a list. This list describes in close to plain English what is being done to the stack. For example, in this hello world Piet program, the first eleven actions are
Push:
- A Value Of 72 Onto The Stack [72]
- print Out The Top Element As A Character, 72=”H” []
- push A Value Of 101 Onto The Stack [101]
- print Out The Top Element As A Character, 101=”E” []
- push A Value Of 108 Onto The Stack [108]
- duplicate The Top Value Of The Stack, And Place The Copied Value Onto The Top Of The Stack [108][108]
- duplicate The Top Value Of The Stack, And Place The Copied Value Onto The Top Of The Stack [108][108][108]
- print Out The Top Element As A Character, 108=”L” [108][108]
- print Out The Top Element As A Character, 108=”L” [108]
- push A Value Of 111 Onto The Stack [111][108]
- duplicate The Top Value Of The Stack, And Place The Copied Value Onto The Top Of The Stack [111][111][108]]
- print Out The Top Element As A Character, 111=”O” [111][108]
This prints the first part of the program, the word “Hello.” The remaining parts of the stack ([111][108]) are later printed out for the “o” and “l” in “world!”
Since there is a list of simple actions, each action can be mapped onto a specific piece of BrainF code. For example pushing to the stack is written as such in my code:
Take the first action “push, value 72.” This segment would recognize the action as a push to the stack, and look at the value being pushed. For the number listed, it would add that many “+”s. In this case 72, followed by the symbol to move to the next cell “>”. So pushing 72 to the Piet stack is represented as “++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>” in BrainF, which is equivalent to 72 incrementing the current cell by 72, and moving to the right.
In its current state, here all the commands I’ve added:
So now all the Piet commands are written out as equivalent BrainF. To verify that the programs are running similarly, I run the generated BrainF through a set of BrainF interpreters.
Originally I used a standard interpreter written in Python, a language I’m familiar with. I had to make some modifications to it to handle programs that output numbers instead of ASCII characters, and to add more debugging information. This worked fine for the majority of Piet programs I’ve tested it on, but I ran into issues involving very large numbers. In one program, there is an operation to multiply 10,000 by 8,492. This is extremely fast in Piet because it has its own multiplication operation, but BrainF does not have this, so many steps have to be processed to multiply even small numbers. This means that for a multiplication this large, a Python interpreter is simply too slow, and can’t process it even after a few minutes. This led me to switch over to a BrainF interpreter written in C, a language I was not familiar with, but one which I heard was significantly faster than Python.
I had to make similar changes to this new interpreter, in terms of debugging capabilities and handling of integers. To do this I had to learn some basic C, a language I had no practice in beforehand. It was interesting in that it reminded me somewhat of BrainF. Both rely heavily on managing pointers and low-level memory. Thinking about this led me to realize that in some respects, BrainF is more similar to C than Piet. Where Piet and BrainF may share similar motivations behind the creation of each language, BrainF and C are similar in how the program runs, and manipulates data. This is because both are pointer-based, where Piet is stack-based. This difference has caused some challenges in creating mappings for each Piet operation, but it still is possible.