Track
Systems & Languages
Editor tooling that runs the real compiler instead of approximating it: a C++/CLI shim exposes the native parser in-process, and identifiers are classified by asking the AST what they are.
The same language, redesigned and rebuilt across four years. Each attempt was driven by a diagnosed failure in the one before it. The last stalled because type checking had grown inside the code generator, so every new feature cost more than the last. It is still going, and the next compiler is now underway, written in Alloy itself.
2024
With a collaborator · archived
A statically-typed systems language, designed to replace C++ in my game engine, with an LLVM backend.
My project and my design, built with my father. I wrote the language design, the tokenizer, the parser, the module system and the semantic analyzer; he wrote most of the code generator and the editor tooling.
- Designed the language and specified it before building it: an EBNF grammar, and a written type-system spec focused on reducing common bugs in game development.
- Hand-written tokenizer and recursive-descent parser, ~3,700 lines, over a bump-allocated AST.
- No build file and no manifest: every .alloy file under the entry point is a module named by its path, so the directory tree is the module graph, with pub/exp visibility and cross-module symbol resolution.
- Editor tooling calls the real compiler rather than approximating it; a C++/CLI shim exposes the native parser to .NET, and identifiers are classified by asking the AST what they are.
- Twenty tests, each compiling a real .alloy program in-process, JIT-executing it and asserting on the value main returns.
- Compiles to LLVM IR through the ORC JIT; generics monomorphize on demand at the point of use; tagged-union enums carry typed payloads with capture in if and switch.
- my commits / total
- 194 / 321
- lexer, parser, modules
- 4,025 LOC · 99% mine
- JIT-executing tests
- 20
Abandoned mid-refactor: type checking lived inside the code generator, and the semantic-analysis phase meant to fix that was never finished. These lessons led me to the staged approach I've adopted for future versions of this compiler.
To run the project, use branch Test. IR is the unfinished refactor and does not compile; Test is the last working state, from December 2024.
2025
Solo · archived
A rewrite of the Alloy front end around staged passes, so that type information stops leaking into code generation.
- A 1,534-line recursive-descent parser over an arena of AST nodes.
- Symbol resolution with overload-aware tables: overloads are permitted for functions and externs, and rejected on any collision with a type or variable.
- Stages are dependency-gated rather than fail-fast, so one bad file no longer aborts the whole batch.
- A bump allocator that spills into a fresh block when full, rather than asserting the way the previous one did.
- commits
- 20
- LOC
- 3,981
Scoped deliberately: this entry covers the hand-written front end only. Later stages of the compiler were AI-assisted and are not presented as personal work.
2026
Designed and directed, AI-implemented · active
A reference implementation of Alloy, built to quickly iterate and validate my ideas for the language.
An experiment on my own design. The language and the specification are mine; the implementation was written by an AI working strictly to that spec. Every gap it hit came back to me to resolve. I never let it decide the language.
- Four years of design written down properly: a ~1,000-line formal specification covering lexical and syntactic grammar, static semantics, execution semantics, the standard library and compile-time evaluation.
- It resolves the flaw that killed the previous compiler. Named types are nominally distinct, structural compatibility applies only where one side is an inline type, and narrowing requires an explicit cast; the rule AlloyLang specified but could never enforce.
- It has the features the earlier attempts specified and never built: interfaces, closures, constructors, and compile-time macros that can generate types and static data.
- A complete toolchain rather than just a compiler: checker, comptime interpreter, LLVM IR backend, language server, debug adapter, formatter and a VS Code extension.
- The specification, the packaged compiler and the standard library live in their own repository, consumed as a submodule by both this compiler and the self-hosted one, so there is exactly one definition of the language.
- compiler
- 24,338 LOC Zig
- specification
- 1,067 lines
- commits
- 21
The implementation is AI-written. I designed the language, wrote the specification and set the compiler's structure; I did not write the Zig.
This is the reference implementation, and it is still moving. The self-hosted compiler is checked against this.
Solo · active
The Alloy compiler, written in Alloy, by hand. The current work and the point of the whole exercise.
- Written in Alloy itself rather than C++ so I can test the language and craft the compiler exactly the way I want it.
- The tokenizer's token kinds are synthesized at compile time from arrays of keywords and operators, so adding a token means editing one place. Proves the usefulness of Alloy's comptime machinery.
- It consumes the specification repository as a submodule, so the language it implements and the language it is checked against cannot drift apart.
- Early: a working entry point and the start of the tokenizer. Real Alloy, compiled by the reference implementation.
- written in
- Alloy
- so far
- 181 lines · 3 commits
Started August 2026 and deliberately early on this page. It is the active work, not a finished result.