#[derive(Debug, Clone, Copy)]
pub(crate) struct BddNode {
pub condition_index: i32,
pub high_ref: i32,
pub low_ref: i32,
}
#[allow(dead_code)]
const RESULT_LIMIT: i32 = 100_000_000;
#[allow(dead_code)]
const TERMINAL_TRUE: i32 = 1;
#[allow(dead_code)]
const TERMINAL_FALSE: i32 = -1;
#[allow(clippy::too_many_arguments, dead_code)]
pub(crate) fn evaluate_bdd<'a, Cond, Params, R, Context>(
nodes: &[BddNode],
conditions: &[Cond],
root_ref: i32,
params: &'a Params,
context: &mut Context,
diagnostic_collector: &mut crate::endpoint_lib::diagnostic::DiagnosticCollector,
mut condition_evaluator: impl FnMut(&Cond, &'a Params, &mut Context, &mut crate::endpoint_lib::diagnostic::DiagnosticCollector) -> bool,
result_builder: impl FnOnce(usize, &'a Params, &Context) -> R,
) -> Option<R> {
let mut current_ref = root_ref;
loop {
match current_ref {
ref_val if ref_val >= RESULT_LIMIT => {
let result_index = (ref_val - RESULT_LIMIT) as usize;
return Some(result_builder(result_index, params, context));
}
TERMINAL_TRUE | TERMINAL_FALSE => {
return Some(result_builder(0, params, context));
}
ref_val => {
let is_complement = ref_val < 0;
let node_index = (ref_val.abs() - 1) as usize;
let node = nodes.get(node_index)?;
let condition_index = node.condition_index as usize;
let condition = conditions.get(condition_index)?;
let condition_result = condition_evaluator(condition, params, context, diagnostic_collector);
current_ref = if is_complement ^ condition_result { node.high_ref } else { node.low_ref };
}
}
}
}