machine_check_common/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use serde::{Deserialize, Serialize};
4use std::{fmt::Display, ops::Not};
5use thiserror::Error;
6
7pub mod check;
8mod node_id;
9pub mod property;
10
11pub use node_id::{NodeId, StateId};
12
13/// Execution error that occured during **machine-check** execution.
14#[derive(Error, Debug, Serialize, Deserialize, Clone)]
15#[non_exhaustive]
16pub enum ExecError {
17    /// The verification result could not be obtained as the abstraction is too coarse.
18    ///  
19    /// Currently, this should never happen, as only three-valued abstraction is supported.
20    #[error("incomplete verification")]
21    Incomplete,
22    /// The specified property field was not found in the system.
23    #[error("field '{0}' not found")]
24    FieldNotFound(String),
25    /// The used index was invalid.
26    ///
27    /// This can happen either due to the field not being indexable
28    /// or the index being too high.
29    #[error("index {0} is invalid for the field '{1}'")]
30    IndexInvalid(u64, String),
31    /// The use of an index is required to use the field in an operation.
32    ///
33    /// This happens because an array type was used where a bit-vector type
34    /// was expected.
35    #[error("indexing is required for the field '{0}'")]
36    IndexRequired(String),
37    /// The signedness of the field was required for a comparison, but not estabilished.
38    ///
39    /// Currently, if needed, the signedness must be forced by `as_unsigned` or `as_signed`,
40    /// as field signedness currently does not yet propagate to property verification.
41    #[error("signedness of the use of field '{0}' was not estabilished")]
42    SignednessNotEstabilished(String),
43    /// The specified property is invalid and could not be lexed into tokens.
44    #[error("property '{0}' could not be lexed: {1}")]
45    PropertyNotLexable(String, String),
46    /// The specified property is invalid and could not be parsed.
47    #[error("property '{0}' could not be parsed: {1}")]
48    PropertyNotParseable(String, String),
49    /// Verification of a standard property was requested, but the inherent property does not hold.
50    #[error("inherent panic")]
51    InherentPanic,
52    /// It was requested to verify an inherent property while assuming that it holds.
53    #[error("cannot verify inherent property while assuming it")]
54    VerifiedInherentAssumed,
55    /// The Graphical User Interface emitted an error.
56    #[error("GUI error: {0}")]
57    GuiError(String),
58    /// No verification was requested, so there is no verification result.
59    #[error("no result")]
60    NoResult,
61    /// Other error.
62    #[error("{0}")]
63    OtherError(String),
64}
65
66/// Execution result of **machine-check**.
67#[derive(Debug, Serialize, Deserialize, Clone)]
68pub struct ExecResult {
69    /// The verification result.
70    ///
71    /// A non-error result says whether the property holds or not.
72    pub result: Result<bool, ExecError>,
73    /// Execution statistics.
74    pub stats: ExecStats,
75}
76
77/// Execution statistics.
78#[derive(Debug, Serialize, Deserialize, Clone, Default)]
79pub struct ExecStats {
80    /// Total number of refinements performed.
81    pub num_refinements: usize,
82    /// Total number of generated states.
83    pub num_generated_states: usize,
84    /// Number of states currently in the state space.
85    pub num_final_states: usize,
86    /// Total number of generated transitions.
87    pub num_generated_transitions: usize,
88    /// Number of transitions currently in the state space.
89    pub num_final_transitions: usize,
90    /// If present, the message of the panic causes inherent property violation.
91    pub inherent_panic_message: Option<String>,
92}
93
94/// An extension of a Boolean to three-valued logic.
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
96pub enum ThreeValued {
97    // Known false.
98    False,
99    // Known true.
100    True,
101    // Either false or true, but it is unknown which one.
102    Unknown,
103}
104
105impl ThreeValued {
106    /// Whether the value is unknown, i.e. neither false nor true.
107    pub fn is_unknown(&self) -> bool {
108        matches!(self, ThreeValued::Unknown)
109    }
110
111    /// Whether the value is known, i.e. false or true.
112    pub fn is_known(&self) -> bool {
113        !self.is_unknown()
114    }
115
116    /// Whether the value is definitely false.
117    pub fn is_false(&self) -> bool {
118        matches!(self, ThreeValued::False)
119    }
120
121    /// Whether the value is definitely true.
122    pub fn is_true(&self) -> bool {
123        matches!(self, ThreeValued::True)
124    }
125}
126
127impl Not for ThreeValued {
128    type Output = Self;
129
130    fn not(self) -> Self {
131        match self {
132            ThreeValued::False => ThreeValued::True,
133            ThreeValued::True => ThreeValued::False,
134            ThreeValued::Unknown => ThreeValued::Unknown,
135        }
136    }
137}
138
139impl Display for ThreeValued {
140    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141        let str = match self {
142            ThreeValued::False => "false",
143            ThreeValued::True => "true",
144            ThreeValued::Unknown => "unknown",
145        };
146        write!(f, "{}", str)
147    }
148}
149
150/// Signedness of a bit-vector type.
151///
152/// In **machine-check**, bit-vectors can have no signedness,
153/// as the interpretation of its value may completely depend on the operation performed.
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
155pub enum Signedness {
156    None,
157    Unsigned,
158    Signed,
159}