gbf_core/decompiler/ast/
func_call.rs

1#![deny(missing_docs)]
2
3use gbf_macros::AstNodeTransform;
4use serde::{Deserialize, Serialize};
5
6use super::{
7    AstKind, AstVisitable, array_kind::ArrayKind, expr::ExprKind, ptr::P, visitors::AstVisitor,
8};
9
10/// Represents a function call
11#[derive(Debug, Clone, Serialize, Deserialize, Eq, AstNodeTransform)]
12#[convert_to(ExprKind::FunctionCall, AstKind::Expression)]
13pub struct FunctionCallNode {
14    /// The arguments to the function.
15    pub arguments: ArrayKind,
16}
17
18impl FunctionCallNode {
19    /// Creates a new function call node.
20    ///
21    /// # Arguments
22    /// - `arguments`: The arguments to the function.
23    pub fn new(arguments: ArrayKind) -> Self {
24        Self { arguments }
25    }
26}
27
28impl AstVisitable for P<FunctionCallNode> {
29    fn accept<V: AstVisitor>(&self, visitor: &mut V) -> V::Output {
30        visitor.visit_function_call(self)
31    }
32}
33
34// == Other implementations for unary operations ==
35impl PartialEq for FunctionCallNode {
36    fn eq(&self, other: &Self) -> bool {
37        self.arguments == other.arguments
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use crate::decompiler::ast::{
44        AstNodeError, emit, new_fn_call_normal, new_id, new_member_access,
45    };
46
47    #[test]
48    fn test_call_emit() -> Result<(), AstNodeError> {
49        let call = new_fn_call_normal(new_id("echo"), vec![new_id("hello").into()]);
50        assert_eq!(emit(call), "echo(hello)");
51
52        // foo.bar(baz)
53        let ma = new_member_access(new_id("foo"), new_id("bar"))?;
54        let call = new_fn_call_normal(ma, vec![new_id("baz").into()]);
55        assert_eq!(emit(call), "foo.bar(baz)");
56        Ok(())
57    }
58
59    #[test]
60    fn test_call_equality() {
61        let call1 = new_fn_call_normal(new_id("echo"), vec![new_id("hello").into()]);
62        let call2 = new_fn_call_normal(new_id("echo"), vec![new_id("hello").into()]);
63        assert_eq!(call1, call2);
64
65        let call3 = new_fn_call_normal(new_id("echo"), vec![new_id("world").into()]);
66        assert_ne!(call1, call3);
67    }
68
69    #[test]
70    fn test_nested_call_emit() {
71        let call = new_fn_call_normal(
72            new_id("foo"),
73            vec![new_fn_call_normal(new_id("bar"), vec![new_id("baz").into()]).into()],
74        );
75        assert_eq!(emit(call), "foo(bar(baz))");
76    }
77}