use crate::{ExecError, ExecResult, FullMachine};
use log::{info, warn};
use machine_check_common::{
check::KnownConclusion,
iir::{description::IMachine, property::IProperty},
ExecStats,
};
use machine_check_exec::{Framework, Strategy};
pub fn verify<M: FullMachine>(
abstract_system: M::Abstr,
machine: IMachine,
prop: Option<IProperty>,
assume_inherent: bool,
strategy: Strategy,
) -> ExecResult {
if prop.is_none() && assume_inherent {
return ExecResult {
result: Err(ExecError::VerifiedInherentAssumed),
stats: ExecStats::default(),
};
}
let mut framework = Framework::<M>::new(abstract_system, machine, strategy);
let inherent_result = if assume_inherent {
None
} else {
if prop.is_some() {
info!("Verifying the inherent property first.");
} else {
info!("Verifying the inherent property.");
}
let inherent_property = machine_check_machine::inherent_property();
Some(framework.verify(&inherent_property))
};
let Some(property) = prop else {
return ExecResult {
result: inherent_result.expect("Inherent property should not be assumed"),
stats: framework.info(),
};
};
if let Some(inherent_result) = inherent_result {
match inherent_result {
Ok(KnownConclusion::True) => {
info!("The inherent property holds, proceeding to the given property.");
}
Ok(KnownConclusion::False) => {
return ExecResult {
result: Err(ExecError::InherentPanic),
stats: framework.info(),
};
}
Ok(KnownConclusion::Dependent) => {
return ExecResult {
result: Err(ExecError::InherentPanicDependent),
stats: framework.info(),
};
}
Err(_) => {
return ExecResult {
result: inherent_result,
stats: framework.info(),
};
}
}
} else {
warn!("Assuming that the inherent property holds. If it does not, the verification result will be unusable.");
}
info!("Verifying the given property.");
let result = framework.verify(&property);
ExecResult {
result,
stats: framework.info(),
}
}