fn const_fold(&mut self, expr: &ExprNode) -> Option<Expr> {
        match expr.inner() {
            Expr::UnaryOp(UnaryOpr::Minus, ref subexpr) => {
                match self.const_fold(subexpr) {
                    None => if let Expr::Number(n) = subexpr.inner() { Some(Expr::Number(-n)) } else { None }
                    Some(sub) => {
                        if let Expr::Number(n) = sub {
                            Some(Expr::Number(-n))
                        } else {
                            unreachable!()
                        }
                    }
                }
            }
            Expr::BinaryOp(ref opr, ref lhs, ref rhs)
            if opr == &BinaryOpr::Add ||
                opr == &BinaryOpr::Sub ||
                opr == &BinaryOpr::Mul ||
                opr == &BinaryOpr::Div ||
                opr == &BinaryOpr::Mod ||
                opr == &BinaryOpr::Pow => {
                if let Expr::Number(l) = lhs.inner() {
                    if let Expr::Number(r) = rhs.inner() {
                        let v = match opr {
                            &BinaryOpr::Add => { l + r }
                            &BinaryOpr::Sub => { l - r }
                            &BinaryOpr::Mul => { l * r }
                            &BinaryOpr::Div => { l / r }
                            &BinaryOpr::Mod => { lua_modulo(*l, *r) }
                            &BinaryOpr::Pow => { l.powf(*r) }
                            _ => unreachable!()
                        };
                        return Some(Expr::Number(v));
                    }
                }

                // TODO: partial fold
                let subl = Box::new(ExprNode::new(self.const_fold(lhs)?, lhs.lineinfo()));
                let subr = Box::new(ExprNode::new(self.const_fold(rhs)?, lhs.lineinfo()));
                Some(Expr::BinaryOp(*opr, subl, subr))
            }
            Expr::Number(n) => Some(Expr::Number(*n)),
            _ => None
        }
    }
/// Attempts to constant fold (i.e. evaluate at compile time as an optimization) the given
/// operation on the two expressions.
/// Folding is attempted only on operations on numbers that are known constants
/// (e.g. `local x = 1+1` -> `local x = 2`).  Moreover, constant folding is skipped on
/// division (or modulo) by zero (resulting in not-a-number, NaN), which Lua 5.1 folded
/// but it caused problems so this folding was eliminated in Lua 5.2.
/// Returns 1 (not 0) if folding was possible.
/// --see http://lua-users.org/lists/lua-l/2007-02/msg00207.html.
Attempts to constant fold  the given
operation on the two expressions.
Folding is attempted only on operations on numbers that are known constants
.  Moreover, constant folding is skipped on
division (or modulo) by zero (resulting in not-a-number, NaN), which Lua 5.1 folded
but it caused problems so this folding was eliminated in Lua 5.2.
Returns 1 (not 0) if folding was possible.
Attempts to constant fold the given operation on the two expressions . Folding is attempted only on operations on numbers that are known constants . Moreover constant folding is skipped on division ( or modulo ) by zero ( resulting in not - a - number NaN ) which Lua 5 . 1 folded but it caused problems so this folding was eliminated in Lua 5 . 2 . Returns 1 ( not 0 ) if folding was possible .
fn const_fold(&mut self, expr: &ExprNode) -> Option<Expr> {
        match expr.inner() {
            Expr::UnaryOp(UnaryOpr::Minus, ref subexpr) => {
                match self.const_fold(subexpr) {
                    None => if let Expr::Number(n) = subexpr.inner() { Some(Expr::Number(-n)) } else { None }
                    Some(sub) => {
                        if let Expr::Number(n) = sub {
                            Some(Expr::Number(-n))
                        } else {
                            unreachable!()
                        }
                    }
                }
            }
            Expr::BinaryOp(ref opr, ref lhs, ref rhs)
            if opr == &BinaryOpr::Add ||
                opr == &BinaryOpr::Sub ||
                opr == &BinaryOpr::Mul ||
                opr == &BinaryOpr::Div ||
                opr == &BinaryOpr::Mod ||
                opr == &BinaryOpr::Pow => {
                if let Expr::Number(l) = lhs.inner() {
                    if let Expr::Number(r) = rhs.inner() {
                        let v = match opr {
                            &BinaryOpr::Add => { l + r }
                            &BinaryOpr::Sub => { l - r }
                            &BinaryOpr::Mul => { l * r }
                            &BinaryOpr::Div => { l / r }
                            &BinaryOpr::Mod => { lua_modulo(*l, *r) }
                            &BinaryOpr::Pow => { l.powf(*r) }
                            _ => unreachable!()
                        };
                        return Some(Expr::Number(v));
                    }
                }
                // TODO: partial fold
                let subl = Box::new(ExprNode::new(self.const_fold(lhs)?, lhs.lineinfo()));
                let subr = Box::new(ExprNode::new(self.const_fold(rhs)?, lhs.lineinfo()));
                Some(Expr::BinaryOp(*opr, subl, subr))
            }
            Expr::Number(n) => Some(Expr::Number(*n)),
            _ => None
        }
    }
fn const_fold ( & mut self , expr : & ExprNode ) -> Option < Expr > { match expr . inner ( ) { Expr :: UnaryOp ( UnaryOpr :: Minus , ref subexpr ) => { match self . const_fold ( subexpr ) { None => if let Expr :: Number ( n ) = subexpr . inner ( ) { Some ( Expr :: Number ( - n ) ) } else { None } Some ( sub ) => { if let Expr :: Number ( n ) = sub { Some ( Expr :: Number ( - n ) ) } else { unreachable ! ( ) } } } } Expr :: BinaryOp ( ref opr , ref lhs , ref rhs ) if opr == & BinaryOpr :: Add || opr == & BinaryOpr :: Sub || opr == & BinaryOpr :: Mul || opr == & BinaryOpr :: Div || opr == & BinaryOpr :: Mod || opr == & BinaryOpr :: Pow => { if let Expr :: Number ( l ) = lhs . inner ( ) { if let Expr :: Number ( r ) = rhs . inner ( ) { let v = match opr { & BinaryOpr :: Add => { l + r } & BinaryOpr :: Sub => { l - r } & BinaryOpr :: Mul => { l * r } & BinaryOpr :: Div => { l / r } & BinaryOpr :: Mod => { lua_modulo ( * l , * r ) } & BinaryOpr :: Pow => { l . powf ( * r ) } _ => unreachable ! ( ) } ; return Some ( Expr :: Number ( v ) ) ; } } // TODO: partial fold let subl = Box :: new ( ExprNode :: new ( self . const_fold ( lhs ) ? , lhs . lineinfo ( ) ) ) ; let subr = Box :: new ( ExprNode :: new ( self . const_fold ( rhs ) ? , lhs . lineinfo ( ) ) ) ; Some ( Expr :: BinaryOp ( * opr , subl , subr ) ) } Expr :: Number ( n ) => Some ( Expr :: Number ( * n ) ) , _ => None } }
Attempts to constant fold (i.e.
Attempts to constant fold ( i . e .
&mut self
expr
&ExprNode