A compiler small enough to read, written in itself.
mc compiles a schoolbook-C language — seven types, one opaque
pointer, loop and if — into Mach-O for AArch64.
A 2,846-line C23 seed is compiled by clang exactly once; after that
mc compiles its own source, writes and signs the executable itself, and reaches a
fixed point where one generation is byte-identical to the next. Everything the core
leaves out — while, for, +=, a second
backend, a whole object model — you teach it from ordinary mc source.
-
It compiles itself
clangbuilds the C23 seed once, and never runs again. The seed compilessrc/mc.mc; that compiler compiles the same source a second time, and the third generation comes out byte for byte identical to the second.cmp mc2.o mc3.o → identical
-
Syntax you teach it
while,for,+=and++are not in the core — they are 37 lines oflib/prelude.mc. Directives add lexemes, operators and statements;pass()andbackend()add AST passes and code generators;syntaxhandlers add whole constructs.#rule · #token · #infix · pass() · backend()
-
Executables, not homework
mc --exe prog.mc -o proglays out the segments, resolves every relocation, writes the bind and rebase opcodes and ad-hoc signs the result. No linker, nocodesign— the backend that does it is itself an mc program.codesign --verify → valid on disk
The whole idea, in one file
The core has no while. This program adds one, then uses it — the
dotted underline marks every word that came from the surface rather than the core.
#include <sys>
// a statement the core does not have, taught in two lines
#rule stmt: while ( expr $c ) block $b
=> loop { if (!$c) break; $b }
i64 main(i64 argc, uptr argv) {
i64 i = 0;
while (i < 3) {
write(1, "mc\n", 3);
i = i + 1;
}
return 0;
}
- core keyword
- taught word
- directive
- $hole
- "string"
- 42
- // comment