Built to be read, then compiled

Ignis started from a plain question: what does a language look like when the type system is as strict as Rust's, the syntax reads like TypeScript, and the output is C that any toolchain can build? Not a VM, not a runtime — a compiler that hands GCC something ordinary.

The compiler is written in Rust as a Cargo workspace: a hand-written lexer and recursive-descent parser, a multi-phase analyzer that binds, resolves, typechecks and borrow-checks, two intermediate representations, and a C backend. Everything the language promises is enforced before a single line of C is emitted.

How a program becomes a binary

Five stages, each a crate in the workspace. A failure in any of them is a diagnostic, never a broken binary.

  1. 01

    Parse

    Lexer and recursive-descent parser with Pratt precedence produce the AST.

  2. 02

    Analyze

    Bind, resolve, typecheck, const-eval and lint in ordered phases.

  3. 03

    Lower

    HIR carries types and captures; monomorphization removes every generic.

  4. 04

    Emit

    LIR becomes basic blocks, then C structs, tagged unions and functions.

  5. 05

    Link

    GCC compiles the C, ar archives it, and the linker produces the executable.

Where it is going

Shipped
Generics, traits, pattern matching, closures, borrow checking, UTF-8 strings, HashMap and HashSet.
Next
Self-hosting the compiler front end, and widening the standard library past the current collection set.
Later
macOS and WebAssembly as compilation targets. Windows comes much later — the emitted C is portable, the toolchain assumptions around it are not.

Working on it

Ignis is early and moving. Syntax changes between versions, and the changelog is the honest record of what broke. If you want to help, the compiler crates are documented and the test suite runs from a single command.