use crate::{ExecError, ExecResult, FullMachine};
use log::{info, warn};
use machine_check_common::{check::KnownConclusion, property::Property, ExecStats};
use machine_check_exec::{Framework, Strategy};
pub fn verify<M: FullMachine>(
system: M,
prop: Option<Property>,
assume_inherent: bool,
strategy: Strategy,
) -> ExecResult {
let abstract_system = <M::Abstr as mck::abstr::Abstr<M>>::from_concrete(system);
if prop.is_none() && assume_inherent {
return ExecResult {
result: Err(ExecError::VerifiedInherentAssumed),
stats: ExecStats::default(),
};
}
let mut framework = Framework::<M>::new(abstract_system, 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 = Property::inherent();
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(),
}
}