Skip to main content

formally/
lib.rs

1//
2// ::formally - the open-source formal methods toolchain
3//
4// Copyright (c) 2025 Nicola Gigante
5//
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to deal
8// in the Software without restriction, including without limitation the rights
9// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10// copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12//
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15//
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22// SOFTWARE.
23//
24
25//!
26//! The open-source formal methods toolchain.
27//!
28//! `::formally` is a project that aims to build a comprehensive open-source framework and
29//! toolchain to help the development of formal methods applications.
30//!
31//! # What the project currently provides
32//! The project is still in its very early stages and is in active development. These early releases
33//! are meant to be a preview of where the project is going and the start of an open development
34//! process for the project.
35//!
36//! What the project *does* currently provide consists in the following:
37//! 1. [formally::support](support) provides common facilities useful for the rest of the project.
38//!    Crucially, it provides a mechanism of error reporting based on the concept of *diagnostic*,
39//!    similar to what seen in many modern compilers, and facilities to produce precise and
40//!    informative error messages throughout the project.
41//! 2. [formally::io](io) provides utilities to parse input and produce output. The main part of the
42//!    module is a *parser combinators* library that allows easy and quick writing of parsers that
43//!    automatically produce precise and high-quality error messages, integrated with the project's
44//!    error reporting infrastructure.
45//! 3. [formally::smt](smt) provides an abstraction over Satisfiability Modulo Theories solvers and
46//!    (what will hopefully become) a fully conformant implementation of the SMT-LIBv2 language.
47//! 4. A simple toy command-line frontend to test the [formally::smt](smt) module.
48//!
49//! The [formally::smt](smt) module is quite under heavy development but can already handle simple
50//! SMT-LIBv2 scripts, solving them with a [Z3](https://github.com/Z3Prover/z3) backend.
51//!
52//! # How to build the crate
53//!
54//! The Z3 backend is based on the [z3_sys](https://crates.io/crates/z3-sys) crate which does not
55//! discover Z3's library automatically, so we currently need to set include paths and linker
56//! arguments manually.
57//!
58//! This is done by setting the `Z3_SYS_Z3_HEADER` environment variable with the path to
59//! `z3.h` and passing the correct `-L` flag to the compiler to find the shared library.
60//!
61//! This can be done conveniently and once and for all by adding the following lines to Cargo's
62//! `config.toml` (see the *Configuration* section in the
63//! [Cargo Book](https://doc.rust-lang.org/cargo/reference/config.html)):
64//!
65//! For example, supposing Z3 has been installed with Homebrew on a macOS system:
66//! ```cargo
67//! [env]
68//! Z3_SYS_Z3_HEADER="/opt/homebrew/Cellar/z3/4.15.3/include/z3.h"
69//!
70//! [build]
71//! rustflags=["-C", "link-arg=-L/opt/homebrew/Cellar/z3/4.15.3/lib/"]
72//! rustdocflags=["-C", "link-arg=-L/opt/homebrew/Cellar/z3/4.15.3/lib/"]
73//! ```
74//! Version numbers have to be changed accordingly, of course.
75//!
76//! Then, one can add the crate to their own project's dependencies as usual:
77//! ```text
78//! $ cargo add formally
79//! ```
80//!
81//! # How to run the command-line frontend
82//!
83//! The front-end can be installed through the `formally-cli` package.
84//! ```text
85//! $ cargo install formally-cli
86//! ```
87//! Then, the `formally` command accepts a `solve` subcommand with the name of an SMT-LIBv2 file to
88//! run.
89//!
90//! ```text
91//! $ cat test.smtlib
92//! (set-logic ALIA)
93//! (declare-const array (Array Int Int))
94//!
95//! (assert (not (= (select (store array 0 42) 0) 42)))
96//!
97//! (check-sat)
98//!
99//! $ formally solve test.smtlib
100//! unsat
101//! ```
102//!
103//! # How to use the sub-crates
104#![doc = document_features::document_features!()]
105//!
106//! Each feature enables a specific sub-crate and re-exports it as a submodule of [formally].
107//! Sub-crates are designed to be used in this way, and not by directly adding them as dependencies.
108//! Macros may not work otherwise, because they expect the crates to be reachable as e.g.
109//! `formally::support` instead of `formally_support`.
110
111#![cfg_attr(docsrs, feature(doc_cfg))]
112
113extern crate self as formally;
114
115#[doc(inline)]
116pub extern crate formally_support as support;
117
118#[cfg_attr(docsrs, doc(cfg(feature = "io")))]
119#[cfg(feature = "io")]
120#[doc(inline)]
121pub extern crate formally_io as io;
122
123#[cfg_attr(docsrs, doc(cfg(feature = "smt")))]
124#[cfg(feature = "smt")]
125#[doc(inline)]
126pub extern crate formally_smt as smt;