Skip to content

Building a Minimal Yet Extensible Language: Acorn

When embarking on the journey of creating a programming language, it is (very) tempting to start with the simplest possible feature set. For Acorn, that meant supporting just one statement: print <int>.

At first glance, this seems extremely trivial - and honestly, it is. But somehow I managed to turn "print a number" into a full-blown C++ architectural odyssey, complete with smart pointers, visitor pattern and an excessive number of header files.

As soon as you aim for extensibility and modularity, even this basic goal becomes a surprisingly complex engineering challenge.

Illusions of Simplicity

Obviously, a language that only prints an integer could be implemented in about five lines of Python. In fact, print(42) already exists and works perfectly fine. But where's the fun - or the learning opportunity - in that?

If you want to:

  • Compile to Java bytecode (using C++)
  • Implement your own flavour of the JVM spec (yes, really)
  • Support future language features
  • Build both a compiler AND an interpreter
  • Maintain clean separation of concerns

...then you need to design a system with clear abstractions and modular components right out of the gate.

Acorn's Architecture: Designed for Growth

Being somewhat serious for a moment, Acorn is structured with extensibility in mind:

  • AST (Abstract Syntax Tree): Even for a single statement, it uses an AST to represent the program. This makes it easy to add new statement types later.
  • Compiler and Interpreter: The codebase supports both compiling to .class files and executing the code directly. This dual approach is possible thanks to a well-defined visitor pattern.
  • Separation of Concerns: Scanning, bytecode generation, and interpretation are all handled by separate modules. This modularity will (fingers crossed) pay off as the language grows.

Why Not Just Hardcode Everything?

It's tempting to write a single function that parses and prints an integer. It would be about ten lines, work perfectly, and I could have finished this project in an afternoon.

But that approach quickly becomes unmanageable as soon as you want to add features. By investing in a modular design early, you avoid painful rewrites later. At least, that's the theory. In practice, you just get to rewrite things in a more architecturally sound way.

Key Takeaways

  • Even the simplest language benefits from a solid architecture
  • Design for extensibility from day one
  • Separation of concerns makes future changes easier and safer
  • Modularity enables both compilation and interpretation

Try It Yourself

Check out the project README for build and usage instructions.

Fair warning: the setup process is probably more complex than the language itself. Explore the codebase to see how even a minimal language can be a playground for software architecture best practices - or a masterclass in enthusiastic over-engineering, depending on your perspective.


Acorn is open source (MIT) and welcomes contributions! Especially if you want to help me figure out why I thought this was a good idea.