Build Story
1. Why Build a Language
There is a particular kind of madness that visits certain programmers. It arrives late at night as a simple question: what if I just built my own language?
I had a problem the available tools weren't solving cleanly. The right language for the job didn't exist. So I started writing Blu.
2. Phases 1–3 — The Foundation
The early work was clean and methodical. Lexer first — make it deterministic. Parser next — make it reliable. Then semantic analysis: catch undefined variables, wrong argument counts, duplicate declarations. The kind of work nobody sees but everybody feels when it's missing.
Then freeze the semantics. Decide what the language actually is. Forms instead of structs. give instead of return. show instead of print. when instead of if. Small choices, but they add up to a voice. Blu began to sound like itself.
Then the standard library: JSON, CSV, databases as key-value arrays, binary encoding. The things you need the moment you try to do anything real.
3. Phase 4 — Regression Infrastructure
By phase 4 Blu had opinions. It had a style guide. It had regression tests — hundreds of them, organized by category, run by shell scripts that report pass rates. No phase closes until every test is green. This discipline is what keeps the language from quietly breaking while new features go in.
4. Phase 5 — Closures, Forms, and a Namespace War
Phase 5 is where the ambition showed its teeth. Closures — nested functions that capture variables from their enclosing scope — required environment objects, closure allocation, and a whole new family of IR instructions. Forms required type inference from usage patterns across the entire call graph.
Then the build broke. A cascade of errors. The cause: #include directives had been placed after the namespace blu { opening brace. The namespace had swallowed the standard library.
The fix was to delete ir_builder.cpp and rewrite it from scratch — pulling out layers of accumulated corruption, duplicate function bodies, orphaned copy-paste blocks. Each fix revealed the next problem. Each problem was small. Together they were a wall.
Forms edge cases: 113/113. Closure regression: 10/10. Phase 5 closed.
5. Phase 6 — File I/O and What Comes Next
Phase 6 started with the obvious gap: Blu couldn't touch the filesystem. file.read, file.write, file.append, file.exists. Four C symbols, four arity checks, four codegen entries. The test program wrote a file, read it back, and confirmed it existed. Small thing. Not a small thing.
What comes next: a map type, a garbage collector, better error messages with line numbers, a formatter, a REPL, a module system, a C FFI bridge, and eventually a platform layer. Eighteen phases in the plan. Five complete.
The tests are green. The compiler compiles. The binary runs.