Language Design

Implementing An Esoteric Programming

Implementing An Esoteric Programming

by Tom E Enebo

In the video titled "Implementing An Esoteric Programming," Tom E Enebo presents an exploration of the esoteric programming language 'Piatt' at the Keep Ruby Weird 2016 event. Tom begins by introducing himself as an implementer rather than the creator of the language and explains the concept of esoteric programming languages, which are designed to be challenging to understand.

Key points discussed include:

  • Definition of Esoteric Languages: Tom defines esoteric languages, noting that their complexity often depends on the user's familiarity with them. He humorously cites Perl as an example of a well-known esoteric language.
  • Introduction of 'Piatt': 'Piatt' is an image-based programming language inspired by the artist Piet Mondrian, wherein the source code is an image (PNG) that interacts with a coordinate system. It utilizes stacks and has a unique way of manipulating data through color changes.
  • How 'Piatt' Works: The language operates through a direction pointer and a color chooser, allowing users to navigate groups of colors to execute commands based on predefined operations. Tom explains the mechanics of navigating groups and performing operations like pushes and transitions across shades of colors.
  • Programming and Debugging: Tom shares his experience porting Python code to Ruby for the 'Piatt' implementation, discussing the challenges and advantages of debugging through graphical interfaces and JRuby.
  • Performance Improvements: He outlines the journey toward optimizing 'Piatt's performance, detailing conversions into virtual machine instructions and accumulating significant speedup through various implementations, achieving a speed increase of up to 305 times.
  • General Insights: Throughout, he emphasizes how working with esoteric languages like 'Piatt' can expand one's mindset and enhance programming skills, encouraging the audience to engage with unconventional coding practices.

In conclusion, Tom advocates for the pursuit of esoteric programming as a means to deepen understanding and appreciation of coding, suggesting that it fosters creativity and functional excellence within programming. The presentation showcases the intersection of art and code while highlighting the journey of implementing a unique language through visualization and optimization methods.

00:00:08.000 I'm surprisingly nervous today, combining my thoughts. First, let me introduce myself. I didn't create this esoteric language; I'm just implementing it.
00:00:12.500 As you can see from the JRuby logo here, this isn't a JRuby talk. It's about an esoteric programming language. I don't usually look like this, but it is my avatar. I co-lead the JRuby project and work at Red Hat. My hobbies include wine and craft beer, so if anyone knows a good brewery in the Houston area, I'll be here until Sunday morning.
00:00:21.930 I know there are a lot of opinions on that matter. So, what exactly is an esoteric language? If we look at Wikipedia, it has a lot to say, but it's all quite vague. Essentially, it's a language intentionally designed to be hard to understand and read. The most famous one is Perl. I've used Perl for 10 years and I genuinely like the language, so I feel entitled to make this joke.
00:00:54.449 I wanted to point out that if you've never seen Perl before, you can still figure out that this prints something out five times. When you look at it, it seems like creating a space for an object is natural. However, once you start looking at some of the Perl 6 features, it becomes confusing for many Perl programmers. Essentially, something may seem esoteric if you have no experience with it. My philosophical part of this talk is done now, but it's something to think about.
00:01:19.680 Now, I'm going to focus on 'Piatt' for the rest of this talk. It was named after Piet Mondrian, who is responsible for the artwork on the right. I find it amusing how he looked much cooler when he was younger. I don't know how you can evolve into something unrecognizable, but perhaps bad choices accumulate with age.
00:01:44.050 So, I'm going to talk about the language itself. It's image-based, similar to Smalltalk. Your source code is literally an image—it’s a PNG image. If you go and execute this program, it prints 'Piatt' to standard output. It's also known as a 'Fund' language because it works with coordinate systems, which makes sense since the program is an image.
00:02:01.290 It's stack-based as well. In fact, most esoteric languages are based on stacks and are quite primitive machines. Piatt's structure is based on a grid made up of n-by-n pixel squares. On the upper left-hand corner, we have a 3x3 pixel group, which has a size of nine. Next to it is a dark blue group, which may be slightly altered by adjacent colors.
00:02:30.920 There is some runtime state called the direction pointer which initially points to the right and navigates around in a clockwise manner. It can change, however, with execution. Moreover, there is a color chooser that can either be left or right. You carry out Piatt's program by moving from one group to the next based on a navigation rule.
00:02:58.250 You need to follow the direction pointer to the farthest extreme of the group and then, depending on whether the color chooser is set to left or right, you move to the leftmost or rightmost extreme. Oftentimes, that's the same color.
00:03:09.310 To illustrate, when we start the program, we enter this normal blue group and the direction pointer is set to right. If the color chooser is left, we enter at the top; but if the color chooser were set to right, then we would enter at the bottom. It's quite simple.
00:03:29.480 Let's move to a slightly more tricky example in this group where the direction pointer is right and the color chooser is left. We go all the way to the right and select the top one to progress. Clearly, if the direction were set to right, we would go there.
00:03:47.289 This looks like a simple language, doesn't it? Well, there are six colors, and each color has three different shades. When you move from one group to the next, you look up in this table to determine what operation you should perform. You have stack-based operations, math comparators, input and output, and then pointer controls that typically take the top value and manipulate those values.
00:04:10.519 These three transitions of blue demonstrate the process of going from lighter to darker shades. This transition can function as a push operation, indicating a cycle where the darkest value transitions to the lightest. In contrast, here's a divide operation, where you merely follow the circle around.
00:04:29.800 Let's step through the program a little bit more. We enter from the upper left-hand side into the normal blue section. As we need to transition to dark blue, we'll look up in the table—which indicates that the next step is to go one shade darker. We will push in a value, defined as nine in this case; that is the size of the normal blue group.
00:04:50.710 This is the only group size that I’ll mention for now. So, stepping to the next phase, we focus on black, which means going off the image or encountering an impassable obstacle. Whenever you run into those conditions, you utilize an algorithm to assess movement based on the color chooser and the direction pointer, up to eight attempts. If a valid next action is found, you proceed; otherwise, the program terminates.
00:05:08.240 Returning to our step with the color chooser directing left/right, we will move down and navigate accordingly. Consequently, white represents a no-action; you can slide right through it, and in fact, placing other unrecognizable colors in the white space is also permissible.
00:05:23.340 Let me tell a joke to lighten the moment: I'll do anything for humor! After engaging with 'Piatt', I've created it into a gem. I just realized this morning that I hadn't actually released it since I finished my work. For demonstration, here’s a simple program using our Piatt gem. You can download an image from the internet and execute it, which is quite fascinating! Furthermore, after executing this program, a prompt appears for user input. The interesting bit is that it can get convoluted, leading to some 'mind-bending' experiences.
00:07:23.070 Another cool feature is the ability to specify the covel size. For instance, if you input a 2x2 colon, it prints 'Piatt'. If you use a covel size of one, it prints 'Hello World'. This is quite unusual.
00:07:38.620 Conceptually, if you go to the upper left, the first value you push is something half the image height representing the radius. Later, you input a jagged circle as the area and perform calculations to derive a rough estimate of Pi. As the image grows larger, this estimate improves, but it'll never be perfect.
00:08:03.000 The core of the talk revolves around implementing our 'Piatt'. To achieve this, I ported Python code to Ruby. However, I'm not particularly well-versed in Python, so it resulted in some errors.
00:08:35.060 The initial file I started with was a single dot PY file. When first creating a non-functional program, the natural response is to troubleshoot it. It turned out that all Piatt interpreters share similar debugging outputs, which proved advantageous as I began making example programs run. Subsequently, I decided to take it a step further by creating a graphical debugger.
00:09:01.740 Here’s a brief demonstration. This is the program I've created, which counts down from a million—or any number I input. I'm taking in numeric input and echoing it. You can step through it while observing the stack operations. I also set breakpoints for more control.
00:09:50.980 Next, the stack visibly reduces from three down to two as it processes the values. As execution proceeds into a conditional branch and the pointer command, I likely should have pressed back to two on the stack a couple of times.
00:10:22.840 After optimizing some elements, I decided it would be prudent to begin writing tests. I created an ASCII image format that streamlined some of the processes compared to working with images directly. Additionally, I ended up developing an image generator application.
00:10:51.839 One key point to note is that the debugging capability we used was based on JRuby and utilized a library called JRubyFX, which is quite slick. The image generation application was built with another JRuby library called ImageMagick.
00:11:09.750 This isn't the last mention of JRuby, however. Once you generate an image, you can run it across various implementations to ensure consistency. When creating the program I demonstrated earlier in the graphical debugger, I initiated an ASCII image format.
00:11:26.360 After five minutes, I realized I wanted to add a second loop in the center, which needed adjustments to the remaining color sequences. Since every color after that second loop would change, I created a tool to regenerate these sequences. It's all one-dimensional, but it greatly simplified the process of image generation.
00:11:47.490 Initially, I began with the Python implementation, but I found myself unimpressed with it. Albeit you likely won’t read this code, it's what I would call 'code chowder', which combines various elements chaotically. Each Piatt implementation usually contains similar code structures, just in different programming languages.
00:12:12.260 We face two main issues: I can't accelerate my conversions any further and those out-of-bounds checks degrade the performance when evaluating up to eight times. Unfortunately, this presents challenges to optimizations since we are merging two concerns: parsing and execution.
00:12:30.319 To move forward, does anyone recall McDoodles? When typically processing programming languages, you would parse to produce an abstract syntax tree. In this instance with Piatt, this graph is two-dimensional and may introduce natural cycles.
00:12:55.590 Based on this idea, we're committed to designing an abstract syntax graph. This graph will represent each operation we execute, and nodes will reflect operations like addition, subtractions, and direction pointers. Each time we reach the edge of our image, we’ll log that and adjust the runtime state.
00:13:20.940 Now, let me illustrate a somewhat challenging slide. At the inception of our implementation, the first priority is managing the 'not' operations using the graph interpreter, which pulls a value from the stack, checks if it equals zero, and subsequently pushes one or zero back under the stack.
00:13:42.250 This first line consequently equates to a pop instruction. Thus, we achieve a seamless mapping for the instruction that saves the popped value and lines up the remainder.
00:14:01.960 For those familiar with assembly language, this should resonate; think of it as a straightforward if-else statement. This approach checks the last variable and restarts processing the graph. The outcome is a streamlined list of elementary instructions.
00:14:27.069 For every occurrence demanding a jump or branch, we’ll note the label within the instruction list, which appears uniquely at another point in that list.
00:14:41.699 Here's the complete list of instructions for executing. You initiate at the start of the list, retrieve and perform an instruction. For branches, the label directs you to the appropriate next step, enhancing performance and optimizing execution.
00:15:06.389 As an overview of the performance when counting down from a million, the execution time improved roughly seven times faster. There's a multitude of invariants occurring throughout this process.
00:15:28.149 But we won’t halt here; we'll explore additional accelerations by converting the abstract syntax graph into a suite of virtual machine instructions, serving as input for a compiler back end.
00:16:05.069 Taking a closer look, we aim to eliminate cycles, which can create discrepancies for a compiler back end. Thus, every cycle will transition into a jump or branch statement.
00:16:30.049 Following through, the remaining operations will translate into a more detailed variant of virtual machine instructions. Here’s a very challenging slide, but it’s worthwhile.
00:16:56.720 The initial subject of backend operations is the 'not' implementations through the interpreter graphs, which facilitate a valuable push and pop sequence, enhancing processing efficiency.
00:17:25.110 I know this might become convoluted. Nevertheless, implementing a functional virtual machine adds complexity to the process as we maintain a program counter and manage jumps.
00:17:49.110 Even with this adjustment, we aim toward compilation, which gives rise to developing a back end. This is when matters begin to get truly peculiar.
00:18:07.640 My extension of work on JRuby and familiarity with its internal instruction sets—as when parsing Ruby code—translates efforts into generating virtual machine instructions that encapsulate our Piatt code.
00:18:32.820 If one finds themselves immersed in JRuby, they can use piatt by requiring the image file and subsequently executing the lambda returned. Consequently, JRuby accommodates both Piatt and Ruby.
00:19:14.520 Analyzing the results reveals a growing speed disparity. The first number illustrates running JRuby in interpreted mode; you'll see it's about 17 times faster compared to executing the Piatt instructions directly through its interpreter.
00:19:44.510 This increase arises from combining fast Java execution with any optimizations implemented in the JRuby framework. Moreover, if I compile it, performance impressively boosts another five times.
00:20:13.920 So far, I've managed a 305-times speedup overall. Additionally, I aimed to run benchmarks using LLVM to count down from a million and could employ various compiler optimizations.
00:20:47.566 Alas, time constraints thwarted those endeavors; I also anticipated discussing JRuby's optimizations, but this 25-minute session already accommodates too much material.
00:21:16.000 To conclude, delving into various programming languages is highly enjoyable. It’s commonly acknowledged that many people learn new languages for utility and job opportunities.
00:21:40.320 However, esoteric languages expand your minds divergently, engaging you in ways you might not foresee. Working with a language based in two-dimensional flow is undeniably fascinating.
00:22:06.000 I encourage you to explore esoteric languages as this talk demonstrates that you can transform mired code complexity into refined functionality that performs excellently.
00:22:23.290 Thank you.