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.