leo3

Crates.ioleo3
lib.rsleo3
version0.1.6
created_at2025-12-09 08:52:08.174156+00
updated_at2025-12-14 06:24:21.399555+00
descriptionRust bindings for the Lean4 theorem prover
homepage
repositoryhttps://github.com/AndPuQing/leo3.git
max_upload_size
id1975141
size887,102
PuQing (AndPuQing)

documentation

README

Leo3: Rust Bindings for Lean4

GitHub Actions Workflow Status Crates.io Version Crates.io Downloads (recent) dependency status Crates.io License Crates.io Size

Leo3 provides safe, ergonomic Rust bindings to the Lean4 theorem prover, inspired by PyO3's architecture for Python-Rust bindings.

Project Status

⚠️ Work in Progress - Leo3 is in early development. The core architecture is established, but many features are not yet implemented.

Architecture

Leo3 is organized as a workspace with multiple crates:

leo3/
├── leo3                  # Main crate - high-level safe abstractions
├── leo3-ffi              # Raw FFI bindings to Lean4's C API
├── leo3-build-config     # Build-time Lean4 detection and configuration
├── leo3-macros           # Procedural macro entry points
└── leo3-macros-backend   # Procedural macro implementations

Design Philosophy

Leo3 follows PyO3's proven architecture patterns:

  1. Layered Abstraction: Clear separation between raw FFI, safe wrappers, and user-facing API
  2. Zero-Cost: #[repr(transparent)] wrappers with compile-time safety
  3. Lifetime Safety: The Lean<'l> token ensures Lean runtime initialization at compile-time
  4. Automatic Memory Management: Smart pointers handle reference counting
  5. Macro-Driven Ergonomics: Procedural macros reduce boilerplate

Core Concepts

The Lean<'l> Token

All Lean operations require a Lean<'l> token, proving the runtime is initialized:

use leo3::prelude::*;

fn process_data<'l>(lean: Lean<'l>) -> LeanResult<()> {
    let s = LeanString::new(lean, "Hello, Lean!")?;
    Ok(())
}

Smart Pointers

Leo3 provides two primary smart pointer types:

  • LeanBound<'l, T>: Tied to Lean<'l> lifetime, used for most operations
  • LeanRef<T>: Can cross initialization boundaries, useful for storage

Both handle reference counting automatically.

Type System

Lean types are wrapped in safe Rust types with automatic conversions:

use leo3::conversion::{IntoLean, FromLean};

// Strings
let s = LeanString::new(lean, "Hello")?;
let rust_str = LeanString::to_str(&s)?;

// Natural numbers
let n = LeanNat::from_usize(lean, 42)?;
let value = LeanNat::to_usize(&n)?;

// Signed integers (i8, i16, i32, i64, isize)
let rust_int: i32 = -42;
let lean_int = rust_int.into_lean(lean)?;
let back: i32 = FromLean::from_lean(&lean_int)?;

// Floating-point (f32, f64)
let rust_float: f64 = 3.14159;
let lean_float = rust_float.into_lean(lean)?;
let back: f64 = FromLean::from_lean(&lean_float)?;

// Option<T>
let rust_opt: Option<u64> = Some(42);
let lean_opt = rust_opt.into_lean(lean)?;
let back: Option<u64> = FromLean::from_lean(&lean_opt)?;

// Result<T, E>
let rust_result: Result<i32, String> = Ok(42);
let lean_result = rust_result.into_lean(lean)?;
let back: Result<i32, String> = FromLean::from_lean(&lean_result)?;

// Arrays and vectors
let vec = vec![1, 2, 3, 4, 5];
let lean_arr = vec.into_lean(lean)?;
let back: Vec<i32> = FromLean::from_lean(&lean_arr)?;

Installation

Note: Lean4 must be installed on your system. Leo3 will attempt to detect it via:

  1. LEAN_HOME or ELAN_HOME environment variables
  2. lake command
  3. elan toolchain manager
  4. lean in PATH

Add to your Cargo.toml:

[dependencies]
leo3 = "0.1.0"

Example Usage

use leo3::prelude::*;

#[leanfn]
fn add(a: u64, b: u64) -> u64 {
    a + b
}

fn main() -> LeanResult<()> {
    // Initialize Lean runtime
    leo3::prepare_freethreaded_lean();

    leo3::with_lean(|lean| {
        // Create Lean objects
        let s = LeanString::new(lean, "Hello from Rust!")?;
        println!("Created string: {}", LeanString::to_str(&s)?);

        let n = LeanNat::from_usize(lean, 100)?;
        println!("Created nat: {}", LeanNat::to_usize(&n)?);

        Ok(())
    })
}

Feature Flags

  • macros (default): Enable procedural macros (#[leanfn], #[leanclass], etc.)

Comparison with PyO3

Leo3 adapts PyO3's architecture for Lean4:

PyO3 Concept Leo3 Equivalent Notes
Python<'py> Lean<'l> Runtime initialization token
Bound<'py, T> LeanBound<'l, T> Lifetime-bound smart pointer
Py<T> LeanRef<T> Unbound smart pointer
#[pyfunction] #[leanfn] Function export macro
#[pyclass] #[leanclass] Class export macro (planned)
PyObject lean_object Base object type
GIL Lean runtime No equivalent (Lean has no GIL)

Key Differences from PyO3

  1. No GIL: Lean4 doesn't have a Global Interpreter Lock, simplifying thread safety
  2. Different Memory Model: Lean uses reference counting without generational GC
  3. Theorem Proving Focus: Leo3 will support proof objects and tactics
  4. Dependent Types: Future support for Lean's dependent type system

Roadmap

Completed ✅

  • #[leanfn] macro implementation
  • String parameter passing (String, &str ↔ LeanString)
  • Unsigned integer conversions (u8, u16, u32, u64, usize ↔ UInt8, UInt16, UInt32, UInt64, USize)
  • Array parameter passing (Vec ↔ LeanArray)
  • Signed integer conversions (i8, i16, i32, i64, isize ↔ Int8, Int16, Int32, Int64, ISize)
  • Floating-point conversions (f32, f64 ↔ LeanFloat)
  • Option type conversions (Option ↔ LeanOption)
  • Result type conversions (Result<T, E> ↔ LeanExcept)

In Progress 🚧

  • Complete FFI bindings (more Lean API functions)
  • Error handling improvements

Planned 📋

  • IO monad support
  • #[leanclass] for Rust structs as Lean classes
  • #[leanmodule] for module creation
  • Proof object support
  • Tactic integration
  • Environment and context management
  • Async support
  • Documentation generation
  • Integration tests with actual Lean4
  • CI/CD pipeline
  • Example projects

Development

Building

# Build all crates
cargo build

# Build specific crate
cargo build -p leo3-ffi

# Run tests
cargo test

Testing

Currently, most tests are unit tests. Integration tests requiring a Lean4 installation will be added.

Contributing

Contributions are welcome! Areas that need work:

  • Completing FFI bindings
  • Implementing macro code generation
  • Adding more type wrappers
  • Documentation
  • Examples
  • Tests

Acknowledgments

  • PyO3: The architectural inspiration for Leo3
  • Lean4: The theorem prover Leo3 binds to

License

Licensed under either of:

at your option.

Related Projects

  • PyO3 - Rust bindings for Python
  • Lean4 - The Lean theorem prover
  • LeanInk - Lean documentation tool
Commit count: 0

cargo fmt