#![doc = include_str!("../README.md")]
use proc_macro2::Span;
use syn::{Error, Expr, ExprClosure, Meta, Pat};
use crate::qualifiers::FnQualifiers;
pub mod annotate;
pub mod instrument;
pub mod qualifiers;
#[cfg(test)]
mod test_util;
#[derive(Debug)]
pub struct Spec {
pub qualifiers: FnQualifiers,
pub requires: Vec<PreCondition>,
pub maintains: Vec<PreCondition>,
pub captures: Vec<Capture>,
pub ensures: Vec<PostCondition>,
span: Span,
}
impl Spec {
pub fn empty() -> Self {
Self {
qualifiers: FnQualifiers::empty(),
requires: vec![],
maintains: vec![],
captures: vec![],
ensures: vec![],
span: Span::call_site(),
}
}
pub fn is_empty(&self) -> bool {
self.qualifiers.is_empty()
&& self.requires.is_empty()
&& self.maintains.is_empty()
&& self.ensures.is_empty()
&& self.captures.is_empty()
}
pub fn spec_err(&self, message: &str) -> Error {
Error::new::<&str>(self.span, message)
}
}
#[derive(Debug)]
pub struct DataSpec {
pub maintains: Vec<PreCondition>,
span: Span,
}
impl DataSpec {
pub fn empty() -> Self {
Self {
maintains: vec![],
span: Span::call_site(),
}
}
pub fn is_empty(&self) -> bool {
self.maintains.is_empty()
}
pub fn spec_err(&self, message: &str) -> Error {
Error::new::<&str>(self.span, message)
}
}
#[derive(Debug)]
pub struct LoopSpec {
pub maintains: Vec<PreCondition>,
pub decreases: Option<LoopVariant>,
span: Span,
}
impl LoopSpec {
pub fn empty() -> Self {
Self {
maintains: vec![],
decreases: None,
span: Span::call_site(),
}
}
pub fn is_empty(&self) -> bool {
self.maintains.is_empty() && self.decreases.is_none()
}
pub fn spec_err(&self, message: &str) -> Error {
Error::new::<&str>(self.span, message)
}
}
#[derive(Debug)]
pub struct PreCondition {
pub closure: ExprClosure,
pub cfg: Option<Meta>,
}
#[derive(Debug)]
pub struct PostCondition {
pub closure: ExprClosure,
pub cfg: Option<Meta>,
}
#[derive(Debug)]
pub struct Capture {
pub expr: Expr,
pub pat: Pat,
}
#[derive(Debug)]
pub struct LoopVariant {
pub expr: Expr,
pub cfg: Option<Meta>,
}