Skip to main content

xpile_contract_backend/
lib.rs

1//! ContractBackend trait โ€” proof-lane rendering abstraction.
2//!
3//! Renders parsed [`xpile_contracts::Contract`] into LaTeX (math +
4//! theorem environments), Lean 4 theorem text (with `@[xpile_contract]`
5//! attribute carrying the verbatim contract ID), or mdBook.
6//!
7//! Architectural invariants codified in
8//! `contracts/xpile-contract-backend-trait-v1.yaml`. The citation bridge
9//! uses **format-native structured constructs** parseable by the host
10//! elaborator/parser, NOT regex over body text. See
11//! `docs/specifications/sub/contract-backend-trait.md` ยง"Citation bridge".
12
13use serde::{Deserialize, Serialize};
14use xpile_contracts::{Contract, ContractFormat, ContractId};
15
16/// Configuration passed to [`ContractBackend::render`].
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
18pub struct ContractRenderConfig {
19    pub format: ContractFormat,
20    /// When true, the citation ID is emitted textually (in addition to
21    /// `RenderedDoc.citations`) via the format's structured construct:
22    /// `\xpileContract{}{}` (LaTeX), `@[xpile_contract ...]` (Lean),
23    /// `<!-- xpile-contract: ... -->` (mdBook).
24    pub embed_citation: bool,
25    /// When true, every falsification_test surfaces as a `\begin{remark}`
26    /// (LaTeX), `-- FALSIFY-<ID>` block (Lean), or `> **Falsification:**`
27    /// block (mdBook). When false, falsification tests are absent.
28    pub include_falsification: bool,
29    /// (major, minor) Lean version. Only Lean 4 is supported
30    /// (`lean_version: Some((4, _))`); rendering with Lean 3 returns
31    /// `Err(ContractBackendError::UnsupportedLeanVersion)`.
32    pub lean_version: Option<(u32, u32)>,
33}
34
35/// Rendered output of a single contract.
36#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
37pub struct RenderedDoc {
38    /// Rendered `.tex` / `.lean` / `.md` text.
39    pub primary: String,
40    /// Optional sidecars (figures, BibTeX entries, oleantheorem files).
41    pub sidecars: Vec<(String, Vec<u8>)>,
42    /// Structural citation chain. Every contract ID in
43    /// `Contract.depends_on` and `Contract.references` MUST be present.
44    pub citations: Vec<ContractId>,
45}
46
47#[derive(Debug, thiserror::Error)]
48pub enum ContractBackendError {
49    #[error("unsupported format for this backend: {0:?}")]
50    UnsupportedFormat(ContractFormat),
51    #[error("unsupported Lean version: {0:?} (only Lean 4 is supported)")]
52    UnsupportedLeanVersion(Option<(u32, u32)>),
53    #[error("rendering error: {0}")]
54    Render(String),
55    #[error("citation bridge violation: {0}")]
56    CitationBridge(String),
57}
58
59/// Proof-lane rendering trait. See `docs/specifications/sub/contract-backend-trait.md`.
60pub trait ContractBackend: Send + Sync {
61    /// Human-readable name, e.g. "latex", "lean-theorem", "mdbook".
62    fn name(&self) -> &'static str;
63
64    /// Formats this backend can render. Each [`ContractFormat`] variant
65    /// is owned by exactly one ContractBackend (`format_ownership`).
66    fn formats(&self) -> &[ContractFormat];
67
68    /// Render a contract under the given config.
69    ///
70    /// Invariants: deterministic per `(contract, config)`; every cited
71    /// contract ID is parseable from `primary` via the host format's
72    /// structured parser (Lean elaborator, LaTeX label machinery,
73    /// mdBook preprocessor) โ€” NOT regex over text.
74    fn render(
75        &self,
76        contract: &Contract,
77        config: &ContractRenderConfig,
78    ) -> Result<RenderedDoc, ContractBackendError>;
79}