Guppy Architecture Overview
This article reflects my personal understanding of the Guppy codebase and has not been reviewed or approved by Quantinuum. For official documentation, refer to the guppylang repository or the official Guppy docs.
In the previous post, we looked at what Guppy is and wrote our first quantum circuit. Now let’s go one level deeper — how is the Guppy project actually structured, and what happens to your code between the @guppy decorator and running on hardware?
Project Structure
The repository is organized as a monorepo workspace with three packages, plus supporting directories:
guppylang/
├── guppylang/ # User-facing API package
├── guppylang-internals/ # Compiler implementation (~100 Python files)
├── tests/ # 100+ test files
├── examples/ # Jupyter notebook examples
└── docs/ # Sphinx documentation
guppylang/
The stable, public-facing package. This is what users import. It contains the @guppy decorator, the standard library (quantum gates, collections, builtins), and the emulator interface. The goal is a clean API boundary — users should never need to touch guppylang-internals directly.
guppylang-internals/
The full compiler implementation — around 100 Python files. This is where parsing, type checking, CFG construction, and HUGR code generation live. It’s intentionally marked as unstable; the internal APIs can change between versions without notice.
tests/
100+ test files split across integration tests (compilation and emulation), error tests (validating diagnostic output), benchmarks, and issue regression tests.
examples/
A collection of Jupyter notebooks demonstrating real Guppy programs — quantum algorithms, gate-level circuits, and emulator usage. A good starting point for seeing what Guppy code actually looks like before diving into the compiler internals.
docs/
Sphinx-generated documentation for the public API. Covers the decorator system, standard library, and emulator interface.
Core Components
- Compilation Engine — Central orchestrator. Manages a
DefinitionStoreand drives the 4-phase definition lifecycle. - Type System — Linear/affine types for quantum resource management. Tracks whether values are copyable or droppable.
- Type Checker — Checks expressions, statements, and linearity. Ensures qubits are used exactly once.
- Control Flow Graph (CFG) — Intermediate representation between the AST and HUGR. Enables flow-sensitive analysis.
- HUGR Compiler — Compiles CFG to HUGR operations, handles monomorphization and dataflow graph generation.
- Standard Library — Quantum gates, measurements, collections, and builtins.
- Emulator — Runs programs via
selene-simwithout targeting real hardware.
Compilation Pipeline
Every Guppy function passes through five phases:
- Decoration & Registration —
@guppycaptures the function and registers it in theDefinitionStore. - Parsing — Type annotations are parsed and the signature is validated.
- Type Checking — CFG is built, expressions are type-checked, linearity is enforced.
- Monomorphization — Generic parameters are instantiated where needed.
- HUGR Compilation — The CFG is compiled into a HUGR package ready for execution or simulation.
HUGR (Hierarchical Unified Graph Representation) is the target IR that Guppy compiles to. It’s a separate open-source project also maintained by Quantinuum — designed to be a portable, hardware-agnostic format for quantum programs.