Shroom
One of the projects I work on at the weekly OpenHack meetup is a game. It’s a classic-style, turn-based Roguelike that uses a hexagonal grid. It’s just a fun toy to work on that I don’t really ever plan on finishing.
It’s built with LÖVE, a framework for making games in Lua. I have a complicated relationship with Lua. I kinda like it, but find the language overly minimal for non-trivial work. Because of that, at some point I rewrote the game in Fennel, a Lisp that compiles to Lua. An important strategy for never finishing your projects is to rewrite them every so often.
Unfortunately, once I moved over to Fennel, the project started moving again, so I needed to figure out a strategy to slow it down. This week, inspiration hit. Lisp is great and all, but I prefer ML-style languages. OCaml is awesome and ReScript is one of my favourite languages ever. What if I rewrote the project in an ML that compiles to Lua.
Better yet, what if I wrote an ML-style language that compiles to Lua. Yes, I could use the one that already exists, but then I’d be back working on the project again after a short rewrite. Writing a new compiler myself will ensure that it’s ages before I even have to think about rewriting my ECS system.
So that’s what I did. The game is called Mycophobia, so I called the language Shroom. You can find the compiler here. Don’t use it. It’s far from complete, and I will assuredly never finish either the game or the language.
It (sort of) works though. It doesn’t have a type-checker and it only supports integer and boolean literals. Unlike Lua, it treats conditionals as expressions.
Here’s a sample program:
let x = 1 + 2 + 3
let y = 2 / 3 * x
let z = x * (1 - 2)
let y = true
print(x)
let bar = if not foo and 3 {
print(3)
} else {
3
}
print(if true { 3 + 3 * 2 } else { false })
Here’s what the shroom compiler emits:
local x = ((1 + 2) + 3)
local y = ((2 / 3) * x)
local z = (x * (1 - 2))
local y = true
print(x)
local _tmp1
if ((not foo) and 3) then
_tmp1 = print(3)
else
_tmp1 = 3
end
local bar = _tmp1
local _tmp2
if true then
_tmp2 = (3 + (3 * 2))
else
_tmp2 = false
end
print(_tmp2)
Is it useful? No. But I bailed out of my comp sci degree before taking the programming languages and compilers course, so I had to figure out stuff like recursive descent and Pratt parsing myself. It’s been fun. I’m looking forward to writing a rudimentary type-checker at next week’s meetup.
Oh, and Claude didn’t write any of this. Shroom is entirely human-written, for whatever that’s worth.
This week, I’ve been listening to One of Nine’s latest record, Dawn of the Iron Shadow. I was not familiar with the band and only threw it on because I liked the album art. What I found was an elegant fusion of melodic black metal and dungeon synth. Good music to write a compiler to.