use crate::error::IrError;
use crate::expr::TLExpr;
use super::clause::Clause;
use super::literal::Literal;
pub fn to_cnf(expr: &TLExpr) -> Result<Vec<Clause>, IrError> {
match expr {
TLExpr::And(left, right) => {
let mut clauses = to_cnf(left)?;
clauses.extend(to_cnf(right)?);
Ok(clauses)
}
TLExpr::Or(left, right) => {
let left_clauses = to_cnf(left)?;
let right_clauses = to_cnf(right)?;
if left_clauses.len() == 1 && right_clauses.len() == 1 {
let mut literals = left_clauses[0].literals.clone();
literals.extend(right_clauses[0].literals.clone());
Ok(vec![Clause::from_literals(literals)])
} else {
let mut result = left_clauses;
result.extend(right_clauses);
Ok(result)
}
}
TLExpr::Not(inner) => {
match &**inner {
TLExpr::Pred { .. } => {
Ok(vec![Clause::unit(Literal::negative((**inner).clone()))])
}
_ => {
Err(IrError::ConstraintViolation {
message: "Complex negation not supported in simplified CNF conversion"
.to_string(),
})
}
}
}
TLExpr::Pred { .. } => {
Ok(vec![Clause::unit(Literal::positive(expr.clone()))])
}
_ => Err(IrError::ConstraintViolation {
message: format!(
"Expression type not supported in CNF conversion: {:?}",
expr
),
}),
}
}