ccarp 0.1.2

(trans)Compile C And Rust Partially
Documentation
//! Simplifying Non Returning Statements
//! 
//! This module implements traits associated with simplifying statements, which have
//! no return value (unit/void).
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() } // unreachable
                    },
                    "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() } // unreachable
                    },
                    "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()),
        }
    }
}