use stellar_xdr::curr::ScSpecEntry;
use crate::ir::{Expr, Statement};
pub(super) fn reconstruct_error_branches(stmts: Vec<Statement>, all_entries: &[ScSpecEntry]) -> Vec<Statement> {
let first_error_val = all_entries.iter().find_map(|e| {
if let ScSpecEntry::UdtErrorEnumV0(err) = e {
err.cases.first().map(|c| c.value)
} else {
None
}
});
let error_val = match first_error_val {
Some(v) => v,
None => return stmts, };
let n = stmts.len();
if n < 2 {
return stmts;
}
let last_idx = n - 1;
let penult_idx = n - 2;
let is_pattern = matches!(
(&stmts[penult_idx], &stmts[last_idx]),
(
Statement::If { else_body, .. },
Statement::Return(Some(_))
) if else_body.is_empty()
);
if !is_pattern {
return stmts;
}
let has_side_effects = if let Statement::If { then_body, .. } = &stmts[penult_idx] {
then_body.iter().any(|s| matches!(s, Statement::Expr(_)))
} else {
false
};
if !has_side_effects {
return stmts;
}
let mut result: Vec<Statement> = stmts[..penult_idx].to_vec();
let return_stmt = stmts[last_idx].clone();
if let Statement::If { condition, then_body, .. } = &stmts[penult_idx] {
let mut new_then = then_body.clone();
new_then.push(return_stmt);
let error_placeholder = format!("__contract_error_{}", error_val);
let else_body = vec![
Statement::Return(Some(Expr::Var(error_placeholder))),
];
result.push(Statement::If {
condition: condition.clone(),
then_body: new_then,
else_body,
});
}
result
}