September 4, 2025 - Tagged as: en, fir.
A few months ago I implemented a PEG parser generator in Fir. It parses its own grammar and it’s also used to parse Fir.
This week I finished another sizable1 Fir project: a code formatter for Fir. It now formats most of the Fir code in the repo2.
Fir is being designed and implemented from day one with tooling, libraries, and backwards compatibility in mind. The compiler’s front-end is currently being reused by the formatter. Soon it’ll be reused by a syntax-aware search-and-replace tool (similar to sg), and by a tool that combines Fir packages into a single .fir file (for sharing repros and automated repro reduction), and much later, by the language server and other tools. You can see the list of tools I want to implement here.
By implementing the tooling along with the first version of the compiler (all in Fir), I want to make sure we have the right SDK design to support all these tools, and more. I want to publish the Fir front-end as a reusable package. This front-end should support the last N3 releases of Fir, so that you can parse (and analyze, modify, refactor, migrate, …) the last N versions of Fir with the latest version of Fir.
I still haven’t written a post explaining what kind of language I want Fir to be, because that’s still largely an open question. However there are a few things that are decided: a compiled, typed language with ADTs, with typeclasses (called traits) for compile-time polymorphism (monomorphised, with value types), and effects. I want Fir to be a high-level, but still efficient, language.
Even implementing just a compiler is a big task, and designing and implementing a whole language with all these tools can’t be done by one person. If this vision sounds interesting to you, and you clicked on a few links above and like what you see, please don’t hesitate to reach out. Each of these tools comes with their own issues and tasks, so it’s now a good time to start contributing to Fir. I already have a list of issues for the PEG generator and the formatter. There’s also all kinds of other things in the issue tracker. Depending on your experience, you can also keep yourself entertained in other ways: the interpreter is slow (a simple AST walker), the interpreter’s type checker is not in good shape etc. If you have the experience and opinions, you can also influence the language design.
My next task is, I’ll be implementing the search-and-replace tool mentioned above (I do this now mainly because I need it when working on Fir), and in parallel, designing and implementing the module system. The module system will need to be implemented in the interpreter too, because I’ll be using modules in the compiler and other tools. Depending on how much free time I’ll have, it should be at least a month of work.
I’m happy with how it’s coming along and I’m excited about Fir’s future.
Formatter is currently 1,086 loc. PEG is 850 loc without the parser for parsing itself. Generated Fir for the parsing PEGs is 2,364 loc, generated from 178 loc PEG.
It’s a bit more difficult to precisely measure the compiler’s grammar size, because it includes semantic actions, but the grammar is 888 loc and generated parser for the grammar is 5,147 loc.
In total (including tests), we have 21,012 loc Fir today in the repo.
All numbers excluding comments and whitespace.↩︎
We don’t format tests to avoid accidentally parsing only formatted code.↩︎
I’m not sure what the exact number here should be yet.↩︎