gbf_core/decompiler/handlers/
short_circuit.rs

1#![deny(missing_docs)]
2
3use std::backtrace::Backtrace;
4
5use crate::{
6    decompiler::{
7        ProcessedInstruction, ProcessedInstructionBuilder,
8        function_decompiler::FunctionDecompilerError,
9        function_decompiler_context::FunctionDecompilerContext,
10    },
11    instruction::Instruction,
12    opcode::Opcode,
13};
14
15use super::OpcodeHandler;
16
17/// Handles unary operations.
18pub struct ShortCircuitHandler;
19
20impl OpcodeHandler for ShortCircuitHandler {
21    fn handle_instruction(
22        &self,
23        context: &mut FunctionDecompilerContext,
24        instruction: &Instruction,
25    ) -> Result<ProcessedInstruction, FunctionDecompilerError> {
26        let condition = context.pop_expression()?;
27
28        // Push the condition back to the stack
29        context.push_one_node(condition.clone().into())?;
30
31        match instruction.opcode {
32            Opcode::ShortCircuitAnd => {
33                // If the operand is falsy, ShortCircuitAnd will jump and not evaluate the other operand.
34
35                Ok(ProcessedInstructionBuilder::new()
36                    .jump_condition(condition)
37                    .build())
38            }
39            Opcode::ShortCircuitOr => {
40                // If the operand is truthy, ShortCircuitOr will jump and not evaluate the other operand.
41                Ok(ProcessedInstructionBuilder::new()
42                    .jump_condition(condition)
43                    .build())
44            }
45            _ => Err(FunctionDecompilerError::UnimplementedOpcode {
46                opcode: instruction.opcode,
47                context: context.get_error_context(),
48                backtrace: Backtrace::capture(),
49            }),
50        }
51    }
52}