use super::{defs::{GetType, NoReturn}, rustexpr::*};
macro_rules! impl_noreturn {
($for:ty : $id:ident) => {
impl NoReturn for $for {
fn simplify(self) -> Self {
match self {
Self::$id(rfield_expr) => Self::$id(rfield_expr.simplify()),
_ => self
}
}
}
};
($for:ty : $id:ident;) => {
impl NoReturn for $for {
fn simplify(self) -> Self {
match self {
Self::$id(rfield_expr) => Self::$id(Box::new(rfield_expr.simplify())),
_ => self
}
}
}
};
}
impl NoReturn for RFieldExpr {
fn simplify(mut self) -> Self {
macro_rules! assign {
($id:ident,$rexpr:expr) => {
RExpr::Expr(Box::new(RAssignExpr::$id(self.0.into(), Box::new($rexpr.remove(0).into())))).into()
};
}
if self.get_type().get_type_alias().is_pointer() { return self }
if self.1.len()==1 {
let fst=self.1.remove(0);
if let RField::Method(rident, mut rexprs) = fst {
match rident.0.as_str() {
"inc_post"|"pre_inc" => {
if let RExpr::Expr(assign)=RExpr::from(1) {
RExpr::Expr(Box::new(RAssignExpr::AddAssign(self.0.into(), assign))).into()
} else { Self::default() } },
"dec_post"|"pre_dec" => {
if let RExpr::Expr(assign)=RExpr::from(1) {
RExpr::Expr(Box::new(RAssignExpr::SubAssign(self.0.into(), assign))).into()
} else { Self::default() } },
"c_assign" => assign!(Assign,rexprs),
"c_add_assign" => assign!(AddAssign,rexprs),
"c_sub_assign" => assign!(SubAssign,rexprs),
"c_mul_assign" => assign!(MulAssign,rexprs),
"c_div_assign" => assign!(DivAssign,rexprs),
"c_mod_assign" => assign!(ModAssign,rexprs),
"c_rshift_assign" => assign!(RShiftAssign,rexprs),
"c_lshift_assign" => assign!(LShiftAssign,rexprs),
"c_and_assign" => assign!(AndAssign,rexprs),
"c_or_assign" => assign!(OrAssign,rexprs),
"c_xor_assign" => assign!(XorAssign,rexprs),
_ => { self.1.push(RField::Method(rident, rexprs)); self }
}
}
else { self.1.push(fst); self }
}
else { self }
}
}
impl_noreturn!(RPostfixExpr : Field;);
impl_noreturn!(RUnaryExpr : Postfix;);
impl_noreturn!(RCastExpr : Unary);
impl_noreturn!(RMulExpr : Cast);
impl_noreturn!(RAddExpr : Mul);
impl_noreturn!(RShiftExpr : Add);
impl_noreturn!(RAndExpr : Shift);
impl_noreturn!(RXorExpr : And);
impl_noreturn!(ROrExpr : Xor);
impl_noreturn!(RCompExpr : Or);
impl_noreturn!(RLogAndExpr : Comp);
impl_noreturn!(RLogOrExpr : And);
impl_noreturn!(RTernary : Or;);
impl_noreturn!(RAssignExpr : Ternary);
impl NoReturn for RExpr {
fn simplify(self) -> Self {
match self {
Self::Expr(rassign_expr) => Self::Expr(Box::new(rassign_expr.simplify())),
Self::Block(rassign_exprs) => Self::Block(rassign_exprs.into_iter().map(NoReturn::simplify).collect()),
}
}
}