July 1st is Ghana’s Republic Day, and to celebrate I’m releasing version 0.1.1 of Aburi, an in-progress but relatively comprehensive C and C++ compiler that can already compile many real world programs and parts of the C++ stdlib. To me it seems like a good milestone to release at seeing how its close approaching and it fits with the projects overall theme (if you haven’t figured it out, lurk more :).

Now you might ask, if Republic Day is on July 1st why am i posting now? Honestly, just because I don’t have plans to push any more public code between now and July 1st. I’m in the middle of some pretty substantial refactoring work, and that means a lot of testing has to happen before anything lands in the public repo.

New features

Below is a partial rundown of what’s been added since March (not exhaustive):

  • if constexpr
  • range-for
  • ParenExpr AST node.
    • When Aburi was only a C compiler, I decided against creating a parentheses node since it didn’t seem necessary. Turns out that having explicit parentheses makes several C++ features much cleaner to implement. This resulted in quite a few regressions, some of which I still haven’t fixed yet. If a C program that compiled with 0.1.0 or before the ParenExpr commits no longer does, it’s probably because of a ParenExpr issue. I tried to fix as many of them immediately after but I am sure some linger.
  • trailing return types
  • Type and function friends
  • decltype(auto)
  • Improved constexpr support
  • CTAD
  • Spaceship operator <=>
  • NSDMI (default member values declared inline with class variable declarations)
  • Additional builtins

Not every feature here has been tested to the same degree, so expect varying levels of stability. The real struggle with adding a feature is making sure it works in combination with other features, espeically in C++. C language constructs are nowhere close to being nearly as much intertwined and complex as C++ constructs. A lot of bugs surface from the interaction between different subsystems rather than from individual features. As testing expands and compiler development moves forward, both newer and older features should stabilize.

C++ stdlib/STL progress

Much of the activity in May focused on making STL libraries compilable and runnable. Template support was already largely functional, there remained a few bugs and features requiring further work. AI Agents played an invaluable role in distilling issues down to small, reproducible test cases; an especially impressive feat given the current lack of accuracy in Aburi’s error messages. The agents also were solid in resolving bugs: most of the bug fixes were concise and of high quality. Human insight is still crucial; for example I was able to suggest a more durable fix in the regression commit in this releases’ git branch because I knew it was ParenExpr related and not merely a generic cast lowering error. As models continue to evolve exponentially, they will play an increasingly important role in modern software development. Soon the models may improve themselves with recursive self-improvement, at which point it’s uncertain if compilers, PL, or human software engineering (or humans at all) will be relevant. But that’s a whole different rabbit hole for another time :)

I was able to get header-only test code including files like <memory> to compile under Aburi. Just getting headers to parse isn’t sufficient though, since the C++ standard library leans heavily on templates. Actually instantiating standard constructs like unique_ptr ended up exposing a large number of new bugs, both at compile time and runtime. Once I reach a satisfactory level of header coverage, I plan to expand the public test suite, which right now only contains small C/C++ snippets along with some real-world C programs.

Growing Pains

Something you may have noticed: this project started as a small C compiler. That meant I made a bunch of decisions that were reasonable at the time: things like a Clang-style AST and type management system, or a small custom (and crappy) arm64 backend rather than going with LLVM. As the project’s scope has expanded, I’ve had to revisit some of those architectural choices. One significant shift was introducing speculative parsing. C can largely be parsed without too much surrounding context (the typedef ambiguity being the main exception), but C++ is deeply context-dependent. That means the parser and the Collect semantic analysis component need a mechanism to back out of a parse branch when it turns into a dead end. This happens quite a bit, and it can drag down performance. I put together some optimizations for the tentative parsing system that gave a solid speed improvement. That said, I wouldn’t be shocked if performance takes another hit as more compile-time code gets layered in. There are other optimizations I could chase but have intentionally set aside for now because my current priority is correctness. For instance, I could expand lazy parsing for stdlib headers, but I’ve held off because actually parsing and compiling those headers surfaces more bugs that need fixing.

A few remarks

This officially marks exactly another year since I began working on the C++ version of this compiler. Previously, it was written in a different language. I translated all my progress by hand with no AI assistance into C++, then continued building from there. Looking at where things stand now, the progress has been genuinely remarkable.

I’d really like to get a web-based version running so people can try the compiler easily. The catch is that right now Aburi only targets Apple Silicon. The one x64 machine I have is basically unusable for development work.

Happy compiling, and congratulations to the Black Stars on their World Cup win over Panama. I’m not really a soccer person or a sports fan in general, and I don’t realistically expect Ghana to make it out of Group L. But yes, I’ll be watching Ghana vs. Croatia (and Ghana vs. England) too, obviously. Ones that lurked more will understand : )