gbf_core/decompiler/handlers/
jump.rs1#![deny(missing_docs)]
2
3use std::backtrace::Backtrace;
4
5use crate::{
6 decompiler::{
7 ProcessedInstruction, ProcessedInstructionBuilder,
8 ast::{bin_op::BinOpType, new_bin_op, new_unary_op, unary_op::UnaryOpType},
9 function_decompiler::FunctionDecompilerError,
10 function_decompiler_context::FunctionDecompilerContext,
11 },
12 instruction::Instruction,
13 opcode::Opcode,
14};
15
16use super::OpcodeHandler;
17
18pub struct JumpHandler;
20
21impl OpcodeHandler for JumpHandler {
22 fn handle_instruction(
23 &self,
24 context: &mut FunctionDecompilerContext,
25 instruction: &Instruction,
26 ) -> Result<ProcessedInstruction, FunctionDecompilerError> {
27 match instruction.opcode {
28 Opcode::Jne => {
29 let condition = context.pop_expression()?;
30
31 Ok(ProcessedInstructionBuilder::new()
32 .jump_condition(condition)
33 .build())
34 }
35 Opcode::Jeq => {
36 let condition = context.pop_expression()?;
37 let wrapped = new_unary_op(condition, UnaryOpType::LogicalNot).map_err(|e| {
38 FunctionDecompilerError::AstNodeError {
39 source: e,
40 context: context.get_error_context(),
41 backtrace: Backtrace::capture(),
42 }
43 })?;
44
45 Ok(ProcessedInstructionBuilder::new()
46 .jump_condition(wrapped.into())
47 .build())
48 }
49 Opcode::With => {
50 let condition = context.pop_expression()?;
51
52 Ok(ProcessedInstructionBuilder::new()
53 .jump_condition(condition)
54 .build())
55 }
56 Opcode::ForEach => {
57 let iter_var = context.pop_expression()?;
59 let arr = context.pop_expression()?;
61
62 context.push_one_node(arr.clone().into())?;
64 context.push_one_node(iter_var.clone().into())?;
65
66 let bin_op = new_bin_op(iter_var, arr, BinOpType::Foreach).map_err(|e| {
68 FunctionDecompilerError::AstNodeError {
69 source: e,
70 context: context.get_error_context(),
71 backtrace: Backtrace::capture(),
72 }
73 })?;
74
75 Ok(ProcessedInstructionBuilder::new()
76 .jump_condition(bin_op.into())
77 .build())
78 }
79 _ => Err(FunctionDecompilerError::UnimplementedOpcode {
80 opcode: instruction.opcode,
81 context: context.get_error_context(),
82 backtrace: Backtrace::capture(),
83 }),
84 }
85 }
86}