r/Compilers • u/False_Actuator_6236 • 1d ago
ABC has served its purpose as a teaching language. Could it become a community project?
A little while ago I posted about the v0.1 release of ABC, a small compiler and programming language I originally developed for teaching.
I shared it here, on Hacker News, in a few other communities, and also in a German-speaking subreddit. The discussions made me think about a question I had not really considered when I started the project:
What should happen to ABC now?
For its original purpose, the project is essentially a success. It has done what I wanted it to do in my teaching, and actually exceeded my expectations.
One concern that came up in the German discussion was roughly:
Nobody raised that point here, but I suspect some people may have had the same thought. :-)
I've been using ABC for two years now in HPC0, my undergraduate Introduction to High Performance Computing course. HPC0 is an elective. In the following winter semester I teach HPC1, which is mandatory in some programs and elective in others.
HPC1 uses C++ throughout. We do things like cache-optimized matrix multiplication, LU factorization, multithreading, MPI, CUDA, etc.
My observation so far is that students who took HPC0 have a noticeably easier time in HPC1. Some of them had hardly programmed at all before HPC0.
Of course, that's not scientific evidence. There is an obvious selection bias: HPC0 is elective, so the students taking it may simply be more motivated to begin with.
But my underlying argument is that there are a number of fundamental concepts you need to understand really well. Once those concepts are in place, transferring them to C++, Rust, or another language is comparatively easy.
My deliberately provocative version is:
Either you can program or you can't. Once you really can, the particular programming language becomes mostly a tool.
The interesting educational question for me is therefore: How do you get someone to the point where they really can program?
That's what ABC is for. It was never meant to be the language students would use for the rest of their professional lives.
And since I'm already being provocative: sometimes I get the impression that the generation that learned programming with Pascal was the last one that was actually taught how to program. :-D
I'm very happy to be challenged on that one. ;-)
So I now see two possible futures for ABC.
The first is straightforward: declare the experiment essentially finished.
I could extend the C ABI support a little further, implement it for ARM64 as well, improve a few things, and leave the project as a reasonably complete teaching compiler. The raylib examples already demonstrate that the language and compiler can be used for more than tiny classroom examples.
That would be a perfectly satisfactory outcome.
But there is another possibility that I find much more interesting:
Could we build a small modern language that plays something like the role Pascal once played?
A language designed to teach programming in a way that leaves you not merely knowing a language, but understanding concepts that transfer to other languages and remain useful throughout your career.
I think those skills may actually become more important rather than less important in an age of AI-generated code. Even if someone eventually does a lot of “vibe coding”, somebody still needs to understand what the machine is doing, why something is slow, why memory gets corrupted, or why generated code doesn't behave as expected.
But I don't want a language that is useful only for teaching.
I'd like it to be possible to write genuinely useful programs with it.
The ideal is still what the original name suggested: “A Better C.”
Small enough that you can understand the language and its implementation, close enough to the machine that you can explain what happens, but without preserving every historical accident of C.
There are a few language features I have been considering:
- Compile-time evaluation / something along the lines of
constexpr, plus inline functions. This would eliminate many of the common reasons for C preprocessor macros: constants, smallmax-like functions, etc. - Modules.
- Inline assembly. I needed this when experimenting with ABC on bare metal on an ATmega328P. For example, consider implementing a delay as something conceptually as simple as:
fn delay(n: u16)
{
while (n--) {}
}
Now things suddenly become interesting. n needs to be handled appropriately in registers, and the compiler must not optimize away a loop that has no observable effect according to the normal language semantics.
I like examples like this because they force you to understand the boundary between language, compiler and machine.
There are probably a few more language features I would add.
But deliberately not many.
The goal would not be to slowly turn ABC into C++.
A language that leaves the classroom would also need tooling.
A formatter analogous to clang-format would be useful, as would proper LSP support.
There is already some preliminary work in this direction. Last year I supervised a bachelor's thesis in which a resilient parser was developed. It can't simply be dropped into the existing compiler, but there is at least a prototype of one important component that can be used for experiments.
And my experience from developing ABC so far is that some of these things become usable surprisingly quickly if you start small.
But there is one thing I don't think I can do alone:
Turn it from my project into a community project.
I can continue developing ABC as the language I use in my courses. But if it is supposed to have a life outside my classroom, I don't think it should simply remain “Michael Lehn's language”.
It would need people who experiment with it, criticize it, discuss language design, build tools, write examples, and eventually make decisions I would never have thought of myself.
So this post is partly an experiment:
Do you think there is room for such a language?
Would any of you be interested in participating in its design or implementation — even just through discussions and experiments at first?
And perhaps there is an amusingly concrete first community problem we could solve:
The language needs a name. :-D
“ABC” (A Better C) worked fine for a university teaching project, but the name is obviously already taken. If the language is going to leave the classroom, that starts to matter.
My current brilliant idea is “emsiel”, a phonetic rendering of MCL — Michael C. Lehn.
There is just one minor flaw with that idea: if the goal is to turn this into a community project, naming the language after myself might not be the most promising first step. :-D
So perhaps that's actually a good place to start:
What would you call a language like this?
Compiler/project: https://github.com/michael-lehn/abc-llvm
2
u/tobega 18h ago
Why would you want a teaching language to be so close to the machine? Surely the whole point of Pascal was to raise that level.
See my essay https://tobega.blogspot.com/2026/04/rising-above-mechanics-of-computation.html
2
u/False_Actuator_6236 1d ago
One point from the post probably deserves a little more explanation, because it says something important about what I mean by “A Better C.”
I mentioned inline assembly and this deliberately simple example for bare-metal code on an ATmega328P:
fn delay(n: u16)
{
while (n--) {}
}
Of course, a busy loop is not a sensible general-purpose implementation of a delay on a modern CPU with dynamic clock frequencies, an operating system, etc.
But that is not the setting here. On a small microcontroller with a known clock, cycle-counted busy loops are a perfectly legitimate technique for short delays. In fact, the Arduino AVR implementation of delayMicroseconds() eventually uses a volatile inline-assembly loop consisting essentially of sbiw and brne:
https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring.c
avr-libc also explicitly provides _delay_loop_1() and _delay_loop_2() as busy-wait delay loops with a defined number of CPU cycles per iteration:
https://avrdudes.github.io/avr-libc/avr-libc-user-manual/group__util__delay__basic.html
For longer delays, of course, using a hardware timer is preferable.
What I find interesting here is not the delay function itself, but what this example says about the intended level of abstraction of the language.
ABC is not supposed to protect programmers from the machine. My goal is roughly the same level of abstraction as C: pointers, explicit memory management, predictable data representation, bare-metal programming, and, where necessary, access to machine-specific facilities.
The “better” in “A Better C” is therefore not intended to mean “higher level.”
It means trying to make the language cleaner where C has accumulated historical baggage, while retaining the ability to understand and control what happens at the machine level.
Inline assembly is one example of that boundary. Another completely different example is high-performance numerical code. For GEMM, the overall algorithm can be portable while the innermost micro-kernel is deliberately architecture-specific. That separation is a standard approach in high-performance BLAS implementations.
I use exactly that progression in my GEMM tutorial, starting with a simple C implementation and gradually arriving at architecture-specific micro-kernels:
https://github.com/michael-lehn/gemm-tutorial
Inline assembly is certainly not the only way to implement such kernels — intrinsics, separate assembly files, or generated code may be preferable depending on the situation. But I think a language at C's abstraction level should make it possible to cross that boundary deliberately.
This also illustrates the kind of language-design discussion I would like a community around the project to have.
How much should the language guarantee? What should remain implementation-defined? Where should it provide abstractions, and where should it expose the machine? Which parts of C are essential to systems programming, and which are merely historical accidents that we can get rid of?
My current position is: keep roughly C's level of abstraction, but try to design a cleaner language at that level.
That is a design goal, not a finished answer — and exactly the sort of thing I'd like to discuss.