gbf_core/decompiler/ast/
identifier.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#![deny(missing_docs)]

use gbf_macros::AstNodeTransform;
use serde::{Deserialize, Serialize};

use super::{
    assignable::AssignableKind, expr::ExprKind, ssa::SsaVersion, visitors::AstVisitor, AstKind,
    AstVisitable,
};

/// Represents a type of literal.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, AstNodeTransform)]
#[convert_to(ExprKind::Assignable, AstKind::Expression, AssignableKind::Identifier)]
pub struct IdentifierNode {
    id: String,
    /// Represents the SSA version of a variable.
    pub ssa_version: Option<SsaVersion>,
}

impl IdentifierNode {
    /// Creates a new `IdentifierNode` from any type that can be converted into a `String`.
    ///
    /// # Arguments
    /// - `s`: The input string-like type.
    ///
    /// # Returns
    /// - An `IdentifierNode` instance containing the provided identifier.
    pub fn new<S: Into<String>>(s: S) -> Self {
        Self {
            id: s.into(),
            ssa_version: None,
        }
    }

    /// Creates a new `IdentifierNode` with an SSA version from any type that can be converted into a `String`.
    /// This is useful for creating an `IdentifierNode` with an SSA version.
    ///
    /// # Arguments
    /// - `s`: The input string-like type.
    /// - `ssa_version`: The SSA version of the identifier.
    ///
    /// # Returns
    /// - An `IdentifierNode` instance containing the provided identifier and SSA version.
    pub fn with_ssa<S: Into<String>>(s: S, ssa_version: SsaVersion) -> Self {
        Self {
            id: s.into(),
            ssa_version: Some(ssa_version),
        }
    }

    /// Returns the identifier as a reference to a `String`.
    pub fn id(&self) -> &String {
        &self.id
    }

    /// Returns the identifier as a `&str`.
    pub fn as_str(&self) -> &str {
        &self.id
    }
}

// == Other implementations for literal ==

impl AstVisitable for IdentifierNode {
    fn accept(&self, visitor: &mut dyn AstVisitor) {
        visitor.visit_identifier(self);
    }
}

#[cfg(test)]
mod tests {
    use crate::decompiler::ast::{emit, new_id};

    #[test]
    fn test_identifier_emit() {
        let id = new_id("test");
        assert_eq!(emit(id), "test");
    }

    #[test]
    fn test_identifier_equality() {
        let id1 = new_id("test");
        let id2 = new_id("test");
        assert_eq!(id1, id2);

        let id3 = new_id("test2");
        assert_ne!(id1, id3);
    }
}