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).
(
&mut self,
expression: &ast::Expr,
condition: bool,
target_block: BlockIdx,
)
| 7340 | /// The idea is to jump to a label if the expression is either true or false |
| 7341 | /// (indicated by the condition parameter). |
| 7342 | fn compile_jump_if( |
| 7343 | &mut self, |
| 7344 | expression: &ast::Expr, |
| 7345 | condition: bool, |
| 7346 | target_block: BlockIdx, |
| 7347 | ) -> CompileResult<()> { |
| 7348 | let prev_source_range = self.current_source_range; |
| 7349 | self.set_source_range(expression.range()); |
| 7350 | |
| 7351 | // Compile expression for test, and jump to label if false |
| 7352 | let result = match &expression { |
| 7353 | ast::Expr::BoolOp(ast::ExprBoolOp { op, values, .. }) => { |
| 7354 | match op { |
| 7355 | ast::BoolOp::And => { |
| 7356 | if condition { |
| 7357 | // If all values are true. |
| 7358 | let end_block = self.new_block(); |
| 7359 | let (last_value, values) = values.split_last().unwrap(); |
| 7360 | |
| 7361 | // If any of the values is false, we can short-circuit. |
| 7362 | for value in values { |
| 7363 | self.compile_jump_if(value, false, end_block)?; |
| 7364 | } |
| 7365 | |
| 7366 | // It depends upon the last value now: will it be true? |
| 7367 | self.compile_jump_if(last_value, true, target_block)?; |
| 7368 | self.switch_to_block(end_block); |
| 7369 | } else { |
| 7370 | // If any value is false, the whole condition is false. |
| 7371 | for value in values { |
| 7372 | self.compile_jump_if(value, false, target_block)?; |
| 7373 | } |
| 7374 | } |
| 7375 | } |
| 7376 | ast::BoolOp::Or => { |
| 7377 | if condition { |
| 7378 | // If any of the values is true. |
| 7379 | for value in values { |
| 7380 | self.compile_jump_if(value, true, target_block)?; |
| 7381 | } |
| 7382 | } else { |
| 7383 | // If all of the values are false. |
| 7384 | let end_block = self.new_block(); |
| 7385 | let (last_value, values) = values.split_last().unwrap(); |
| 7386 | |
| 7387 | // If any value is true, we can short-circuit: |
| 7388 | for value in values { |
| 7389 | self.compile_jump_if(value, true, end_block)?; |
| 7390 | } |
| 7391 | |
| 7392 | // It all depends upon the last value now! |
| 7393 | self.compile_jump_if(last_value, false, target_block)?; |
| 7394 | self.switch_to_block(end_block); |
| 7395 | } |
| 7396 | } |
| 7397 | } |
| 7398 | Ok(()) |
| 7399 | } |
no test coverage detected