gbf_core/decompiler/ast/
identifier.rs

1#![deny(missing_docs)]
2
3use gbf_macros::AstNodeTransform;
4use serde::{Deserialize, Serialize};
5
6use super::{AstKind, AstVisitable, expr::ExprKind, ptr::P, ssa::SsaVersion, visitors::AstVisitor};
7
8/// Represents a type of literal.
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, AstNodeTransform)]
10#[convert_to(ExprKind::Identifier, AstKind::Expression)]
11pub struct IdentifierNode {
12    id: String,
13    /// Represents the SSA version of a variable.
14    pub ssa_version: Option<SsaVersion>,
15}
16
17impl IdentifierNode {
18    /// Creates a new `IdentifierNode` from any type that can be converted into a `String`.
19    ///
20    /// # Arguments
21    /// - `s`: The input string-like type.
22    ///
23    /// # Returns
24    /// - An `IdentifierNode` instance containing the provided identifier.
25    pub fn new<S: Into<String>>(s: S) -> Self {
26        Self {
27            id: s.into(),
28            ssa_version: None,
29        }
30    }
31
32    /// Creates a new `IdentifierNode` with an SSA version from any type that can be converted into a `String`.
33    /// This is useful for creating an `IdentifierNode` with an SSA version.
34    ///
35    /// # Arguments
36    /// - `s`: The input string-like type.
37    /// - `ssa_version`: The SSA version of the identifier.
38    ///
39    /// # Returns
40    /// - An `IdentifierNode` instance containing the provided identifier and SSA version.
41    pub fn with_ssa<S: Into<String>>(s: S, ssa_version: SsaVersion) -> Self {
42        Self {
43            id: s.into(),
44            ssa_version: Some(ssa_version),
45        }
46    }
47
48    /// Returns the identifier as a reference to a `String`.
49    pub fn id(&self) -> &String {
50        &self.id
51    }
52
53    /// Returns the identifier as a `&str`.
54    pub fn as_str(&self) -> &str {
55        &self.id
56    }
57}
58
59// == Other implementations for literal ==
60
61impl AstVisitable for P<IdentifierNode> {
62    fn accept<V: AstVisitor>(&self, visitor: &mut V) -> V::Output {
63        visitor.visit_identifier(self)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use crate::decompiler::ast::{emit, new_id};
70
71    #[test]
72    fn test_identifier_emit() {
73        let id = new_id("test");
74        assert_eq!(emit(id), "test");
75    }
76
77    #[test]
78    fn test_identifier_equality() {
79        let id1 = new_id("test");
80        let id2 = new_id("test");
81        assert_eq!(id1, id2);
82
83        let id3 = new_id("test2");
84        assert_ne!(id1, id3);
85    }
86}