4DL
Preface FROM THE FUTURE! (2013)
Where HQ9+ was a gag, 4DL began as a thought experiment. I was working at Charlie’s Espresso in Tempe at the time, and my shifts often had dead time that I used designing processor architectures and programming languages.
I later learned, to my horror, that three- and four-dimensional instruction spaces are not actually uncommon (think: page-switching).
I’ve preserved the 4DL definition below verbatim, in case people are curious. It contains an error, which I discovered early on but left in to see if anyone actually tried implementing the language. This became a habit.
Original content follows.
Most computer languages are one-dimensional. You start at Point A (the beginning of the program) and simply work your way down the list, doing each operation in turn. Sure, you might skip a few operations once in a while, but you're still just operating in one dimension.
In 1993, Chris Pressey (recently loony operator of the Esolang list) graced the world with Befunge, the world's first (to my knowledge) two-dimensional programming language. In Befunge, your code is laid out on a page, and execution can move in any direction across the page. This transforms programming into a very visual process. I like.
But two dimensions just weren't enough for me, now, were they? No. So I created 4DL, the world's first (and I can say that with some confidence) four-dimensional programming language. Why, you ask? Well, I know how much trouble most people have thinking visually in three dimensions (or even two). 4DL turns programming into not only a visual task, but an exercise in visualizing higher-order dimensional spaces--which everyone does in their free time, right?
Introduction to Four-Dimensional Representation
While writing code in four dimensions might seem a tad tricky, it's really not. I'll walk you
through it.
First, we have a one-dimensional grid of size 3.
Pretty straightforward. As you can see, this one-dimensional grid has only one axis, which
we'll call X. You can be at X=0, X=1, X=2.
Now, a two dimensional grid, size 3x3:
Again, pretty simple. We've simply added a Y, so that coordinates are the familar (X, Y) we all learned in grade school. Now, how do we extend this into a third dimension, Z? We're working on a two-dimensional surface here--your monitor. So, I'll slice the three-dimensional cube up. Here's a sliced-up cube, size 3x3x3:
* |
* |
Each of those slices represents a position on the Z axis--0, 1, and 2, from top to bottom. Each has its own X and Y coordinates, so that (1,2) in the top slice and (1,2) in the next slice -- that is, (1,2,0) and (1,2,1) -- are different. (These two locations are marked with a star.) Note that these are, however, adjacent. They're only one step apart, even though that step is on the Z axis, and they look far away on your two-dimensional monitor. So moving one step higher on the Z axis is shown by moving one slice down, but staying on the same (X,Y) coordinate.
I hope I've explained that well enough, because we're going to need it--right now. I'm going to take the cube and represent it in four dimensions. This new axis is called T, and you may think of it as time if you wish (though in 4DL we can move freely along it). Thus, slices along T can be thought of as identical to the 3-D cube shown above, but at different points in time. Here's the resulting figure, with dimensions 3x3x3x3 (X, Y, Z, and T).
|
|
|
|||||||||||||||||||||||||||
|
|
|
|||||||||||||||||||||||||||
|
|
|
I've still marked (1,2) in three of the slices, but this time I've marked (1,2) in slices along the T axis, instead of the Z axis [coordinates (1,2,0,0), (1,2,0,1), and (1,2,0,2), respectively]. So moving forward a step in T is shown by moving right one slice but keeping the same (X,Y) within the slice. Thus, all the stars shown above are adjacent.
This concludes our crash course in thinking in four dimensions. If you're still a bit hazy, you should be. Humans were never really designed to reason well in three dimensions, and since we only live in three dimensions, trying to deal with four or more really twists our brains around. That's precisely why I designed 4DL. If you develop even the most trivial application in 4DL, you have instant job security, unless the programmer that follows you was once a theoretical physicist.
The 4DL Language
4DL is a very simple language based around a stack of bytes. All operators are single ASCII characters appearing in a four-dimensional grid of arbitrary size. (The size along each dimension must be at least one.)
In most languages, the instruction pointer always moves in the same direction. In 4DL, the instruction pointer--the flow of execution--can be steered along any axis. Execution begins at coordinate (0,0,0,0), moving in the positive direction along the X axis (that is, to the right within the slice). This direction is referred to below as X+. The full set of directions includes X+, X-, Y+, Y-, Z+, Z-, T+, and T- -- that is, moving "forward" or "backward" along any axis.
4DL has a very small set of commands. If any character not in this list is encountered during execution, nothing happens. That allows execution to "pass through" irrelevant data on its way to the next instruction.
Char | Function |
---|---|
p | Pushes the character adjacent along X-. |
P | Pushes the character adjacent along X+. |
b | Pushes the character adjacent along Y-. |
B | Pushes the character adjacent along Y+. |
d | Pushes the character adjacent along Z-. |
D | Pushes the character adjacent along Z+. |
q | Pushes the character adjacent along T-. |
Q | Pushes the character adjacent along T+. |
+ | Adds top two values, leaving result on stack. |
- | Subtracts top value from next value, leaving result on stack. |
, | Inputs a character from the user, pushes it on the stack. |
. | Pops a character from the stack and prints it on the screen. |
X | Turns the instruction pointer to travel along X+. |
x | Turns the instruction pointer to travel along X-. |
Y | Turns the instruction pointer to travel along Y+. |
y | Turns the instruction pointer to travel along Y-. |
Z | Turns the instruction pointer to travel along Z+. |
z | Turns the instruction pointer to travel along Z-. |
T | Turns the instruction pointer to travel along T+. |
t | Turns the instruction pointer to travel along t-. |
? | Pops a value from the stack. If it's non-zero, skips the next coordinate (along whatever axis the instruction pointer is currently traversing). |
# | Skip the next coordinate along the current axis. |
X | Turns the instruction pointer to travel along X+. |
0 | Push the number 0 onto the stack. |
2 | Duplicate the top value on the stack. |
X | Turns the instruction pointer to travel along X+. |
% | Stop execution. |
Of course, it's my obligation as Language Master to supply examples. Here is a 4x4x4x2 program
that displays the quintessential "Hello, world!"
And, for the curious, a version with program flow marked out in red: