use btor2rs::op::{UniOp, UniOpType};
use syn::{parse_quote, Expr};
use crate::translate::btor2::{
node::bi::create_add,
util::{create_rnid_expr, single_bits_xor},
Error,
};
use super::{
bi::create_sub,
constant::{create_minus_one_expr, create_one_expr, create_value_expr, create_zero_expr},
NodeTranslator,
};
impl NodeTranslator<'_> {
pub fn uni_op_expr(&mut self, op: &UniOp) -> Result<(syn::Expr, Vec<syn::Stmt>), Error> {
let result_bitvec = self.get_bitvec(op.sid)?;
let a_bitvec = self.get_nid_bitvec(op.a.nid())?;
let a_expr = create_rnid_expr(op.a);
Ok((
match op.ty {
UniOpType::Not => create_bit_not(a_expr),
UniOpType::Inc => create_add(a_expr, create_one_expr(result_bitvec)),
UniOpType::Dec => create_sub(a_expr, create_one_expr(result_bitvec)),
UniOpType::Neg => create_arith_neg_expr(a_expr, a_bitvec.length.get()),
UniOpType::Redand => {
let all_ones_expr = create_minus_one_expr(a_bitvec);
return self.create_eq(a_expr, all_ones_expr);
}
UniOpType::Redor => {
let zero_expr = create_zero_expr(a_bitvec);
return self.create_ne(a_expr, zero_expr);
}
UniOpType::Redxor => {
let a_length = a_bitvec.length.get();
let mut slice_exprs = Vec::new();
let mut stmts = Vec::new();
let a_bitvec = a_bitvec.clone();
for i in 0..a_length {
let shift_length_expr = create_value_expr(i.into(), &a_bitvec);
let a_srl = self.shr_expr_from_exprs(
a_expr.clone(),
shift_length_expr,
a_length,
false,
)?;
let (uext_expr, uext_stmts) =
self.create_uext(a_srl, a_bitvec.length.get(), 1)?;
stmts.extend(uext_stmts);
slice_exprs.push(uext_expr);
}
let result_expr = single_bits_xor(slice_exprs.into_iter());
return Ok((result_expr, stmts));
}
},
vec![],
))
}
}
pub fn create_bit_not(inner: Expr) -> Expr {
parse_quote!((!#inner))
}
pub fn create_arith_neg_expr(inner: Expr, length: u32) -> Expr {
parse_quote!((::machine_check::Bitvector::<#length>::new(0)-#inner))
}