machine_check_exec/
framework.rs1use std::collections::BTreeMap;
2use std::ops::ControlFlow;
3
4use log::log_enabled;
5use log::trace;
6use machine_check_common::check::Conclusion;
7use machine_check_common::check::KnownConclusion;
8use machine_check_common::iir::description::IMachine;
9use machine_check_common::iir::property::IProperty;
10use machine_check_common::ExecError;
11use machine_check_common::ExecStats;
12use machine_check_common::NodeId;
13use machine_check_common::ParamValuation;
14use machine_check_common::StateId;
15use mck::concr::FullMachine;
16use work_state::WorkState;
17
18use crate::space::StateSpace;
19use crate::Strategy;
20use mck::refin::RefinementValue;
21
22mod refine;
23mod regenerate;
24mod work_state;
25
26pub struct Framework<M: FullMachine> {
28 abstract_system: M::Abstr,
30
31 machine: IMachine,
32
33 default_input_precision: RefinementValue,
35
36 default_param_precision: RefinementValue,
38
39 default_step_precision: RefinementValue,
41
42 work_state: WorkState<M>,
44}
45
46impl<M: FullMachine> Framework<M> {
47 pub fn new(abstract_system: M::Abstr, machine: IMachine, strategy: Strategy) -> Self {
49 let input = machine.input();
50 let param = machine.param();
51 let state = machine.state();
52
53 let description = &machine.description;
54
55 let (default_input_precision, default_param_precision) = if strategy.naive_inputs {
57 (
58 input.dirty_refin(description),
59 param.dirty_refin(description),
60 )
61 } else {
62 (
63 input.clean_refin(description),
64 param.clean_refin(description),
65 )
66 };
67
68 let default_step_precision = if strategy.use_decay {
70 state.clean_refin(description)
71 } else {
72 state.dirty_refin(description)
73 };
74
75 Framework {
77 abstract_system,
78 machine,
79 default_input_precision,
80 default_step_precision,
81 default_param_precision,
82 work_state: WorkState::new(),
83 }
84 }
85
86 pub fn verify(&mut self, property: &IProperty) -> Result<KnownConclusion, ExecError> {
87 let result = loop {
89 match self.step_verification(property) {
90 ControlFlow::Continue(()) => {}
91 ControlFlow::Break(result) => break result,
92 }
93 };
94
95 self.work_state.make_compact();
97
98 if log_enabled!(log::Level::Trace) {
99 trace!("Verification final space: {:#?}", self.work_state.space);
100 }
101 result
102 }
103
104 pub fn step_verification(
105 &mut self,
106 property: &IProperty,
107 ) -> ControlFlow<Result<KnownConclusion, ExecError>> {
108 if !self.work_state.space.is_valid() {
110 self.regenerate(NodeId::ROOT);
111 } else if let Some(culprit) = self.work_state.culprit.take() {
112 if let Err(err) = self.refine(&culprit) {
114 return ControlFlow::Break(Err(err));
116 }
117 self.work_state.garbage_collect();
119 }
120
121 if log_enabled!(log::Level::Trace) {
122 trace!("Model-checking state space: {:#?}", self.work_state.space);
123 }
124
125 match self.work_state.checker.check_property(
127 &self.work_state.space,
128 &self.machine,
129 property,
130 ) {
131 Ok(Conclusion::Known(conclusion)) => {
132 ControlFlow::Break(Ok(conclusion))
134 }
135 Ok(Conclusion::Unknown(culprit)) => {
136 self.work_state.culprit = Some(culprit);
138 ControlFlow::Continue(())
139 }
140 Ok(Conclusion::NotCheckable) => {
141 panic!("The state space should be valid after stepping verification");
143 }
144 Err(err) => {
145 ControlFlow::Break(Err(err))
147 }
148 }
149 }
150
151 pub fn current_labellings(
152 &mut self,
153 property: &IProperty,
154 ) -> Result<BTreeMap<usize, BTreeMap<StateId, ParamValuation>>, ExecError> {
155 self.work_state
156 .checker
157 .get_labellings(&self.machine, &self.work_state.space, property)
158 }
159
160 pub fn current_conclusion(&mut self, property: &IProperty) -> Result<Conclusion, ExecError> {
161 self.work_state
162 .checker
163 .check_property(&self.work_state.space, &self.machine, property)
164 }
165
166 pub fn find_panic_string(&mut self) -> Option<&'static str> {
167 self.work_state.find_panic_string()
168 }
169
170 pub fn reset(&mut self) {
171 self.work_state = WorkState::new()
173 }
174
175 pub fn info(&mut self) -> ExecStats {
176 self.work_state.info()
177 }
178
179 pub fn space(&self) -> &StateSpace<M> {
180 &self.work_state.space
181 }
182
183 pub fn make_compact(&mut self) {
184 self.work_state.make_compact();
185 }
186
187 pub fn abstract_system(&self) -> &M::Abstr {
188 &self.abstract_system
189 }
190 pub fn machine(&self) -> &IMachine {
191 &self.machine
192 }
193}