1#![deny(missing_docs)]
2
3use crate::{decompiler::ast::visitors::AstVisitor, opcode::Opcode};
4use array_access::ArrayAccessNode;
5use array_kind::ArrayKind;
6use assignment::AssignmentNode;
7use bin_op::BinaryOperationNode;
8use block::BlockNode;
9use control_flow::{ControlFlowNode, ControlFlowType};
10use expr::ExprKind;
11use func_call::FunctionCallNode;
12use function::FunctionNode;
13use identifier::IdentifierNode;
14use literal::LiteralNode;
15use member_access::MemberAccessNode;
16use new_array::NewArrayNode;
17use phi::PhiNode;
18use ptr::P;
19use range::RangeNode;
20use ret::ReturnNode;
21use serde::{Deserialize, Serialize};
22use ssa::SsaVersion;
23use statement::StatementKind;
24use thiserror::Error;
25use unary_op::UnaryOperationNode;
26use vbranch::VirtualBranchNode;
27use visitors::{emit_context::EmitContext, emitter::Gs2Emitter};
28
29use super::structure_analysis::region::RegionId;
30
31pub mod array_access;
33pub mod array_kind;
35pub mod array_node;
37pub mod assignment;
39pub mod ast_enum_type;
41pub mod bin_op;
43pub mod block;
45pub mod control_flow;
47pub mod expr;
49pub mod func_call;
51pub mod function;
53pub mod identifier;
55pub mod literal;
57pub mod member_access;
59pub mod meta;
61pub mod new;
63pub mod new_array;
65pub mod node_id;
67pub mod phi;
69pub mod phi_array;
71pub mod ptr;
73pub mod range;
75pub mod ret;
77pub mod ssa;
79pub mod statement;
81pub mod unary_op;
83pub mod vbranch;
85pub mod visitors;
87
88#[derive(Debug, Error, Clone, Serialize, Deserialize)]
90pub enum AstNodeError {
91 #[error("Expected {0}, found {1}")]
93 InvalidConversion(String, String),
94
95 #[error("Invalid operand type")]
97 InvalidOperand,
98
99 #[error("Cannot invert {0}")]
101 CannotInvert(String),
102}
103
104pub trait AstVisitable: Clone {
106 fn accept<V: AstVisitor>(&self, visitor: &mut V) -> V::Output;
108}
109
110#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
112pub enum AstKind {
113 Statement(StatementKind),
115 Function(P<FunctionNode>),
117 Expression(ExprKind),
119 Block(P<BlockNode>),
121 ControlFlow(P<ControlFlowNode>),
123}
124
125impl AstVisitable for AstKind {
126 fn accept<V: AstVisitor>(&self, visitor: &mut V) -> V::Output {
127 match self {
128 AstKind::Expression(expr) => expr.accept(visitor),
129 AstKind::Statement(stmt) => stmt.accept(visitor),
130 AstKind::Function(func) => func.accept(visitor),
131 AstKind::Block(block) => block.accept(visitor),
132 AstKind::ControlFlow(control_flow) => control_flow.accept(visitor),
133 }
134 }
135}
136
137pub fn emit<N>(node: N) -> String
139where
140 N: Into<AstKind>,
141{
142 let node: AstKind = node.into();
143 let mut emit = Gs2Emitter::new(EmitContext::default());
144 let ouput = node.accept(&mut emit);
145 ouput.node
146}
147
148pub fn new_assignment<L, R>(lhs: L, rhs: R) -> AssignmentNode
152where
153 L: Into<ExprKind>,
154 R: Into<ExprKind>,
155{
156 AssignmentNode {
157 lhs: lhs.into(),
158 rhs: rhs.into(),
159 }
160}
161
162pub fn new_return<N>(node: N) -> ReturnNode
164where
165 N: Into<ExprKind>,
166{
167 ReturnNode::new(node.into())
168}
169
170pub fn new_virtual_branch(branch: RegionId) -> VirtualBranchNode {
172 VirtualBranchNode::new(branch)
173}
174
175pub fn new_member_access<L, R>(lhs: L, rhs: R) -> Result<MemberAccessNode, AstNodeError>
177where
178 L: Into<ExprKind>,
179 R: Into<ExprKind>,
180{
181 MemberAccessNode::new(lhs.into(), rhs.into())
182}
183
184pub fn new_id(name: &str) -> IdentifierNode {
188 IdentifierNode::new(name)
189}
190
191pub fn new_id_with_version(name: &str, version: SsaVersion) -> IdentifierNode {
193 IdentifierNode::with_ssa(name, version)
194}
195
196pub fn new_fn_call_normal<N>(name: N, args: Vec<ExprKind>) -> FunctionCallNode
198where
199 N: Into<ExprKind>,
200{
201 let mut args = new_array(args);
203 args.elements.insert(0, name.into());
204 FunctionCallNode::new(args.into())
205}
206
207pub fn new_fn_call(args: ArrayKind) -> FunctionCallNode {
209 FunctionCallNode::new(args)
210}
211
212pub fn new_array<E>(elements: Vec<E>) -> array_node::ArrayNode
214where
215 E: Into<ExprKind>,
216{
217 array_node::ArrayNode::new(elements.into_iter().map(Into::into).collect())
218}
219
220pub fn new_phi_array<E>(phi: P<PhiNode>, elements: Vec<E>) -> phi_array::PhiArrayNode
222where
223 E: Into<ExprKind>,
224{
225 phi_array::PhiArrayNode::new(phi, elements.into_iter().map(Into::into).collect())
226}
227
228pub fn new_uninitialized_array<E>(size: E) -> NewArrayNode
230where
231 E: Into<ExprKind>,
232{
233 NewArrayNode::new(size.into())
234}
235
236pub fn new_array_access<A, I>(array: A, index: I) -> ArrayAccessNode
238where
239 A: Into<ExprKind>,
240 I: Into<ExprKind>,
241{
242 ArrayAccessNode::new(array.into(), index.into())
243}
244
245pub fn new_bin_op<L, R>(
247 lhs: L,
248 rhs: R,
249 op_type: bin_op::BinOpType,
250) -> Result<BinaryOperationNode, AstNodeError>
251where
252 L: Into<ExprKind>,
253 R: Into<ExprKind>,
254{
255 BinaryOperationNode::new(lhs.into(), rhs.into(), op_type)
256}
257
258pub fn new_unary_op<A>(
260 operand: A,
261 op_type: unary_op::UnaryOpType,
262) -> Result<UnaryOperationNode, AstNodeError>
263where
264 A: Into<ExprKind>,
265{
266 UnaryOperationNode::new(operand.into(), op_type)
267}
268
269pub fn new_range<L, R>(lhs: L, rhs: R) -> RangeNode
271where
272 L: Into<ExprKind>,
273 R: Into<ExprKind>,
274{
275 RangeNode::new(lhs.into(), rhs.into())
276}
277
278pub fn new_str(value: &str) -> LiteralNode {
282 LiteralNode::String(value.to_string())
283}
284
285pub fn new_num(value: i32) -> LiteralNode {
287 LiteralNode::Number(value)
288}
289
290pub fn new_float(value: &str) -> LiteralNode {
292 LiteralNode::Float(value.to_string())
293}
294
295pub fn new_bool(value: bool) -> LiteralNode {
297 LiteralNode::Boolean(value)
298}
299
300pub fn new_null() -> LiteralNode {
302 LiteralNode::Null
303}
304
305pub fn new_fn<V, E>(name: Option<String>, params: Vec<E>, body: Vec<V>) -> FunctionNode
308where
309 V: Into<AstKind>,
310 E: Into<ExprKind>,
311{
312 FunctionNode::new(
313 name,
314 new_array(params).into(),
315 body.into_iter().map(Into::into).collect::<Vec<AstKind>>(),
316 )
317}
318
319pub fn new_if<C, E>(condition: C, then_block: Vec<E>) -> ControlFlowNode
322where
323 C: Into<ExprKind>,
324 E: Into<AstKind>,
325{
326 ControlFlowNode::new(
327 ControlFlowType::If,
328 Some(condition),
329 then_block
330 .into_iter()
331 .map(Into::into)
332 .collect::<Vec<AstKind>>(),
333 )
334}
335
336pub fn new_else<T>(else_block: Vec<T>) -> ControlFlowNode
338where
339 T: Into<AstKind>,
340{
341 ControlFlowNode::new(
342 ControlFlowType::Else,
343 None::<ExprKind>,
344 else_block
345 .into_iter()
346 .map(Into::into)
347 .collect::<Vec<AstKind>>(),
348 )
349}
350
351pub fn new_with<C, T>(condition: C, then_block: Vec<T>) -> ControlFlowNode
353where
354 C: Into<ExprKind>,
355 T: Into<AstKind>,
356{
357 ControlFlowNode::new(
358 ControlFlowType::With,
359 Some(condition),
360 then_block
361 .into_iter()
362 .map(Into::into)
363 .collect::<Vec<AstKind>>(),
364 )
365}
366
367pub fn new_phi(idx: usize) -> phi::PhiNode {
370 PhiNode::new(idx)
371}
372
373pub fn new_while<C, T>(condition: C, then_block: Vec<T>) -> ControlFlowNode
375where
376 C: Into<ExprKind>,
377 T: Into<AstKind>,
378{
379 ControlFlowNode::new(
380 ControlFlowType::While,
381 Some(condition),
382 then_block
383 .into_iter()
384 .map(Into::into)
385 .collect::<Vec<AstKind>>(),
386 )
387}
388
389pub fn new_do_while<C, T>(condition: C, then_block: Vec<T>) -> ControlFlowNode
392where
393 C: Into<ExprKind>,
394 T: Into<AstKind>,
395{
396 ControlFlowNode::new(
397 ControlFlowType::DoWhile,
398 Some(condition),
399 then_block
400 .into_iter()
401 .map(Into::into)
402 .collect::<Vec<AstKind>>(),
403 )
404}
405
406pub fn new_for<C, T>(condition: C, then_block: Vec<T>) -> ControlFlowNode
408where
409 C: Into<ExprKind>,
410 T: Into<AstKind>,
411{
412 ControlFlowNode::new(
413 ControlFlowType::For,
414 Some(condition),
415 then_block
416 .into_iter()
417 .map(Into::into)
418 .collect::<Vec<AstKind>>(),
419 )
420}
421
422pub fn new_cyclic_condition<C, T>(
424 condition: C,
425 then_block: Vec<T>,
426 opcode: Option<Opcode>,
427) -> Result<ControlFlowNode, AstNodeError>
428where
429 C: Into<ExprKind>,
430 T: Into<AstKind>,
431{
432 match opcode {
433 Some(Opcode::Jne) => Ok(new_while(condition, then_block)),
434 Some(Opcode::Jeq) => Ok(new_while(condition, then_block)),
436 Some(Opcode::ShortCircuitAnd) => Ok(new_while(condition, then_block)),
438 Some(Opcode::ShortCircuitOr) => Ok(new_while(condition, then_block)),
439 Some(Opcode::ForEach) => Ok(new_for(condition, then_block)),
440 None => Ok(new_while(condition, then_block)),
441 _ => Err(AstNodeError::InvalidOperand),
442 }
443}
444
445pub fn new_acylic_condition<C, T>(
447 condition: C,
448 then_block: Vec<T>,
449 opcode: Option<Opcode>,
450) -> Result<ControlFlowNode, AstNodeError>
451where
452 C: Into<ExprKind>,
453 T: Into<AstKind>,
454{
455 match opcode {
456 Some(Opcode::Jne) => Ok(new_if(
457 condition,
458 then_block
459 .into_iter()
460 .map(Into::into)
461 .collect::<Vec<AstKind>>(),
462 )),
463 Some(Opcode::Jeq) => Ok(new_if(condition, then_block)),
465 Some(Opcode::ShortCircuitAnd) => Ok(new_if(condition, then_block)),
467 Some(Opcode::ShortCircuitOr) => Ok(new_if(condition, then_block)),
468 Some(Opcode::With) => Ok(new_with(condition, then_block)),
469 None => Ok(new_if(condition, then_block)),
470 _ => Err(AstNodeError::InvalidOperand),
471 }
472}
473
474pub fn new_new<N>(new_type: N, arg: N) -> Result<new::NewNode, AstNodeError>
476where
477 N: Into<ExprKind>,
478{
479 new::NewNode::new(new_type.into(), arg.into())
480}