fn compile_jump_if(
        &mut self,
        expression: &ast::Expression,
        condition: bool,
        target_label: Label,
    ) -> Result<(), CompileError> {
        // Compile expression for test, and jump to label if false
        match &expression.node {
            ast::ExpressionType::BoolOp { op, values } => {
                match op {
                    ast::BooleanOperator::And => {
                        if condition {
                            // If all values are true.
                            let end_label = self.new_label();
                            let (last_value, values) = values.split_last().unwrap();

                            // If any of the values is false, we can short-circuit.
                            for value in values {
                                self.compile_jump_if(value, false, end_label)?;
                            }

                            // It depends upon the last value now: will it be true?
                            self.compile_jump_if(last_value, true, target_label)?;
                            self.set_label(end_label);
                        } else {
                            // If any value is false, the whole condition is false.
                            for value in values {
                                self.compile_jump_if(value, false, target_label)?;
                            }
                        }
                    }
                    ast::BooleanOperator::Or => {
                        if condition {
                            // If any of the values is true.
                            for value in values {
                                self.compile_jump_if(value, true, target_label)?;
                            }
                        } else {
                            // If all of the values are false.
                            let end_label = self.new_label();
                            let (last_value, values) = values.split_last().unwrap();

                            // If any value is true, we can short-circuit:
                            for value in values {
                                self.compile_jump_if(value, true, end_label)?;
                            }

                            // It all depends upon the last value now!
                            self.compile_jump_if(last_value, false, target_label)?;
                            self.set_label(end_label);
                        }
                    }
                }
            }
            ast::ExpressionType::Unop {
                op: ast::UnaryOperator::Not,
                a,
            } => {
                self.compile_jump_if(a, !condition, target_label)?;
            }
            _ => {
                // Fall back case which always will work!
                self.compile_expression(expression)?;
                if condition {
                    self.emit(Instruction::JumpIfTrue {
                        target: target_label,
                    });
                } else {
                    self.emit(Instruction::JumpIfFalse {
                        target: target_label,
                    });
                }
            }
        }
        Ok(())
    }
/// Implement boolean short circuit evaluation logic.
/// https://en.wikipedia.org/wiki/Short-circuit_evaluation
///
/// This means, in a boolean statement 'x and y' the variable y will
/// not be evaluated when x is false.
///
/// The idea is to jump to a label if the expression is either true or false
/// (indicated by the condition parameter).
Implement boolean short circuit evaluation logic.

This means, in a boolean statement 'x and y' the variable y will
not be evaluated when x is false.

The idea is to jump to a label if the expression is either true or false
(indicated by the condition parameter).
Implement boolean short circuit evaluation logic . This means in a boolean statement ' x and y ' the variable y will not be evaluated when x is false . The idea is to jump to a label if the expression is either true or false ( indicated by the condition parameter ) .
fn compile_jump_if(
        &mut self,
        expression: &ast::Expression,
        condition: bool,
        target_label: Label,
    ) -> Result<(), CompileError> {
        // Compile expression for test, and jump to label if false
        match &expression.node {
            ast::ExpressionType::BoolOp { op, values } => {
                match op {
                    ast::BooleanOperator::And => {
                        if condition {
                            // If all values are true.
                            let end_label = self.new_label();
                            let (last_value, values) = values.split_last().unwrap();
                            // If any of the values is false, we can short-circuit.
                            for value in values {
                                self.compile_jump_if(value, false, end_label)?;
                            }
                            // It depends upon the last value now: will it be true?
                            self.compile_jump_if(last_value, true, target_label)?;
                            self.set_label(end_label);
                        } else {
                            // If any value is false, the whole condition is false.
                            for value in values {
                                self.compile_jump_if(value, false, target_label)?;
                            }
                        }
                    }
                    ast::BooleanOperator::Or => {
                        if condition {
                            // If any of the values is true.
                            for value in values {
                                self.compile_jump_if(value, true, target_label)?;
                            }
                        } else {
                            // If all of the values are false.
                            let end_label = self.new_label();
                            let (last_value, values) = values.split_last().unwrap();
                            // If any value is true, we can short-circuit:
                            for value in values {
                                self.compile_jump_if(value, true, end_label)?;
                            }
                            // It all depends upon the last value now!
                            self.compile_jump_if(last_value, false, target_label)?;
                            self.set_label(end_label);
                        }
                    }
                }
            }
            ast::ExpressionType::Unop {
                op: ast::UnaryOperator::Not,
                a,
            } => {
                self.compile_jump_if(a, !condition, target_label)?;
            }
            _ => {
                // Fall back case which always will work!
                self.compile_expression(expression)?;
                if condition {
                    self.emit(Instruction::JumpIfTrue {
                        target: target_label,
                    });
                } else {
                    self.emit(Instruction::JumpIfFalse {
                        target: target_label,
                    });
                }
            }
        }
        Ok(())
    }
fn compile_jump_if ( & mut self , expression : & ast :: Expression , condition : bool , target_label : Label , ) -> Result < ( ) , CompileError > { // Compile expression for test, and jump to label if false match & expression . node { ast :: ExpressionType :: BoolOp { op , values } => { match op { ast :: BooleanOperator :: And => { if condition { // If all values are true. let end_label = self . new_label ( ) ; let ( last_value , values ) = values . split_last ( ) . unwrap ( ) ; // If any of the values is false, we can short-circuit. for value in values { self . compile_jump_if ( value , false , end_label ) ? ; } // It depends upon the last value now: will it be true? self . compile_jump_if ( last_value , true , target_label ) ? ; self . set_label ( end_label ) ; } else { // If any value is false, the whole condition is false. for value in values { self . compile_jump_if ( value , false , target_label ) ? ; } } } ast :: BooleanOperator :: Or => { if condition { // If any of the values is true. for value in values { self . compile_jump_if ( value , true , target_label ) ? ; } } else { // If all of the values are false. let end_label = self . new_label ( ) ; let ( last_value , values ) = values . split_last ( ) . unwrap ( ) ; // If any value is true, we can short-circuit: for value in values { self . compile_jump_if ( value , true , end_label ) ? ; } // It all depends upon the last value now! self . compile_jump_if ( last_value , false , target_label ) ? ; self . set_label ( end_label ) ; } } } } ast :: ExpressionType :: Unop { op : ast :: UnaryOperator :: Not , a , } => { self . compile_jump_if ( a , ! condition , target_label ) ? ; } _ => { // Fall back case which always will work! self . compile_expression ( expression ) ? ; if condition { self . emit ( Instruction :: JumpIfTrue { target : target_label , } ) ; } else { self . emit ( Instruction :: JumpIfFalse { target : target_label , } ) ; } } } Ok ( ( ) ) }
Implement boolean short circuit evaluation logic.
Implement boolean short circuit evaluation logic .
&mut self
expression
&ast::Expression
condition
bool
target_label
Label