Writing 12 programming languages in 2023 pt. 1

Why programming languages?

I think I want to work on programming languages. I want to work on programming languages because I write programs all day. When I write programs, I see a lot of things that can be improved, so I have ideas for programming languages.

I went to college for videogame programming. I wanted to work on videogames because I played videogames all day. When I played videogames, I saw a lot of things that could be improved, so I had ideas for videogames.

I started learning how to program in order to write videogames, and soon I was spending more time programming than playing videogames. Then I started to think more about programming and less about videogames. Slowly, over many years, my ideas about programming grew and stuck in my brain for longer, and my ideas about videogames shrank. I want to work on things that I have ideas about.

On one hand, this feels kind of silly. I feel like I should be able to be interested in working on something that I am not personally engaging with every day. I think that most jobs are like that. Most lawyers are not caught up in their own legal cases (hopefully). Most pharmacologists don’t personally take the medicine they develop. Most truck builders are not also truck drivers. Most programmers don’t work on programming tools (professionally at least).

On the other hand, this feels completely natural. Isn’t it obvious that I would have ideas about the stuff I do all day? Wouldn’t trucks be better if the people making them spent lots of time driving them as well?

This isn’t so easy for most jobs. Building trucks and driving trucks are pretty different skills (I assume – I admit I’ve never done either one). Generally speaking, using a tool and making that tool are different acts, but most of a programmer’s tools are programs. There is the physical computer, of course, and keyboards, mice, monitors, etc… Building computer hardware is a different skill set than building computer software. But at least half of the experience of writing programs comes down to software. The operating system is software. The text editor is software. The debugger is software. The version control is software. The programming language is software, sort of.

What is a programming language anyway?

To understand what a programming language is, we have to understand what a program is. A program is a list of instructions, designed to be carried out by a computer. That's it. This is a program in English:

Add 2 and 2, then print the result.

The problem with that program is that no computer knows how to execute it. It's ambiguous, because English is ambiguous. What does print mean in that sentence? Does it mean to show it on the screen or to use an attached printer and print the result on a blank piece of paper?

Here's another program in English:

Take the number 2.
Add the number 2.
Print the result.

You and I can see that this is the same program as the previous one, but the computer doesn't know that. English is flexible. There are lots and lots of ways to explain the same thing in English, and if we wanted the computer to understand English we would have to show it how to handle every possible type of explanation.

You might be thinking, "ChatGPT could execute both of those programs and get the right result!" And that's a good point! But even the mighty English-understander ChatGPT gives different output for these two programs. From the first it tells me "The result of adding 2 and 2 is 4." From the second it just gives "4" For now, programs based on rules are better at giving consistent output than programs based on machine learning, so I still have a career, but that might not be true in the future.

So programming languages are languages designed for writing lists of instructions in ways that are unambiguous and follow a consistent structure. To be clear, computers don't understand most programming languages either, out of the box. They have their own languages, sometimes called machine code. In order to translate the nice languages programmers like to use into machine code, language developers write translation programs. Those programs are called compilers or interpreters. People argue about the differences between compilers and interpreters, but for the most part the terms are interchangeable and for the rest of this post I’m just going to stick with "compiler".

The most fundamental tool of a programmer is logic, I guess, or maybe the computer. But the most fundamental tool which is also software is a programming language. Programming languages bridge the gap between designs that manifest in the mind of the programmer, and programs running on computers. That's why I think they're so neat.

I hope that this can be the last stop on the train of working on something while wanting to work on the tools I’m using instead. I try not to get my hopes up too high though. I am capricious.

12 languages

In the spirit of finding quality through quantity, I came up with this idea to write twelve programming languages, one per month, in 2023. “That’s ridiculous,” you might object, “programming languages are huge undertakings. Many languages have seen 50+ years of continuous development.” That’s true, but I have three tricks up my sleeve:

  1. The languages are going to be really small and specialized (domain-specific languages, in the nomenclature)
  2. I’m going to write them in Racket
  3. I’m going to ignore a large part of compiler-writing, thanks to point 2

Racket

Racket is a weird programming language. Weird because it’s part of a lineage of languages that occupy relatively little space in the development of useful programs, and very much space in the minds of computer scientists. The reason I’m going to write my languages in Racket is because Racket is designed for experimenting with programming language design. It’s the perfect language for writing small languages, according to this guy:

That guy is Matthew Butterick and he likes writing languages in Racket so much that he wrote a book about it. It’s called Beautiful Racket. I’ve been poking at this book for years, so this is my excuse to finally read it all the way through. In the book, Butterick lays out the case for Racket as the ideal language for experimenting with programming language design, and walks the reader through the implementation of a few small languages.

One of the reasons Racket is so great for writing programming languages, is that it lets you skip the whole “back end” of writing a compiler. Compilers have a front end and a back end (and a, uh, middle end), but they’re not the typical back and front ends we think of in software.

To recap, the goal of a compiler is to take code in a language that’s nice for humans to deal with and turn it into code that’s nice for computers to deal with. One question is, which computers? It would be nice for people to be able to write their code in Language X and run it on Mac and Windows and Linux PCs, Android phones and iPhones, WiFi routers and TVs and refrigerators and light bulbs and cars and everything else that's a computer, but all of those computers speak (roughly) different languages. That’s a lot of compilers to write.

To resolve this issue, it’s common to use an intermediate language in between the nice source code and the nasty machine code. The front end takes source code and translates it into the intermediate language. Then, the back end takes code in the intermediate language and converts it to machine code. This pattern is so popular that there are open-source intermediate languages like LLVM IR for language designers to share in mutual benefit.

When I write a language in Racket, I’m only concerned about converting code in my language into Racket. Then I let the Racket compiler do the rest of the work of turning it into machine code. I get to use Racket as my intermediate language.

Language #1

So where am I now, at the end of January? Beautiful Racket features seven languages. I've followed along and written four of them so far. I’ve been taking it kind of slow, and there is lots of other good content in Beautiful Racket I’ve been trying to absorb, so four out of seven probably sounds better than it is. The next three languages are much more complex. That being said, my goal is to finish Beautiful Racket by the end of February, and start working on languages of my own design in March. This will leave me with more than two languages by the end of February, but I’m not designing them so I’m just calling it two.

I’d like to highlight the latest language I implemented, but first I want to talk briefly about my goals for the posts in this series. I want to use these posts to talk about my language designs and to practice explaining them in a straightforward way. The target audience is closer to people that have no programming experience than people who implement their own languages. The posts will be much more on the “why” side of things, rather than the “how” side. I hope that’s okay. Thanks for understanding.

Anyway, on to the latest language – the fourth language featured in Beautiful Racket. The book calls it “bf” and mentions that that’s an acronym, but we can expand the acronym here. The language is called Brainfuck. Brainfuck is a minimal, esoteric language designed to challenge and delight nerds. Here is the premise of Brainfuck: You have a 30,000 byte array, a pointer into the array and eight instructions:

>

Increment the data pointer (to point to the next cell to the right).

<

Decrement the data pointer (to point to the next cell to the left).

+

Increment (increase by one) the byte at the data pointer.

-

Decrement (decrease by one) the byte at the data pointer.

.

Output the byte at the data pointer.

,

Accept one byte of input, storing its value in the byte at the data pointer.

[

If the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ] command.

]

If the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching [ command.

(table stolen from Wikipedia)

It’s typical (if a little silly) in programming languages to show off a program that prints the text “Hello, world!”. Here is that program in Python:

print(“Hello, world!”)

Here is that program in Brainfuck:

++++++[>++++++++++++<-]>.
>++++++++++[>++++++++++<-]>+.
+++++++..+++.>++++[>+++++++++++<-]>.
<+++[>----<-]>.<<<<<+++++[>+++++++++<-]>++.
>>.+++.------.--------.>>+.

Fun, huh?

Here it is running through my Brainfuck implementation:

No much to look at, but it's a start! I hope to have something more interesting for you in the next one.

Subscribe to Buncha Nonsense

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe