darklua_core/nodes/statements/
last_statement.rs

1use crate::nodes::{Expression, Token};
2
3/// Tokens associated with a return statement.
4#[derive(Clone, Debug, PartialEq, Eq)]
5pub struct ReturnTokens {
6    pub r#return: Token,
7    /// The tokens for the commas between expressions.
8    pub commas: Vec<Token>,
9}
10
11impl ReturnTokens {
12    super::impl_token_fns!(
13        target = [r#return]
14        iter = [commas]
15    );
16}
17
18/// Represents a return statement.
19#[derive(Clone, Debug, Default, PartialEq, Eq)]
20pub struct ReturnStatement {
21    expressions: Vec<Expression>,
22    tokens: Option<ReturnTokens>,
23}
24
25impl ReturnStatement {
26    /// Creates a new return statement with the given expressions.
27    pub fn new(expressions: Vec<Expression>) -> Self {
28        Self {
29            expressions,
30            tokens: None,
31        }
32    }
33
34    /// Creates a new ReturnStatement with one expression.
35    /// ```rust
36    /// # use darklua_core::nodes::{Expression, ReturnStatement};
37    ///
38    /// let statement = ReturnStatement::one(true);
39    ///
40    /// // unknown case
41    /// assert_eq!(statement.len(), 1);
42    /// ```
43    pub fn one<E: Into<Expression>>(expression: E) -> Self {
44        Self {
45            expressions: vec![expression.into()],
46            tokens: None,
47        }
48    }
49
50    /// Adds an expression to this return statement.
51    pub fn with_expression<E: Into<Expression>>(mut self, expression: E) -> Self {
52        self.expressions.push(expression.into());
53        self
54    }
55
56    /// Returns an iterator over the expressions.
57    #[inline]
58    pub fn iter_expressions(&self) -> impl Iterator<Item = &Expression> {
59        self.expressions.iter()
60    }
61
62    /// Converts this return statement into an iterator over its expressions.
63    #[inline]
64    pub fn into_iter_expressions(self) -> impl Iterator<Item = Expression> {
65        self.expressions.into_iter()
66    }
67
68    /// Returns a mutable iterator over the expressions.
69    #[inline]
70    pub fn iter_mut_expressions(&mut self) -> impl Iterator<Item = &mut Expression> {
71        self.expressions.iter_mut()
72    }
73
74    /// Returns whether this return statement has no expressions.
75    #[inline]
76    pub fn is_empty(&self) -> bool {
77        self.expressions.is_empty()
78    }
79
80    /// Returns the number of expressions.
81    #[inline]
82    pub fn len(&self) -> usize {
83        self.expressions.len()
84    }
85
86    /// Sets the tokens for this return statement.
87    pub fn with_tokens(mut self, tokens: ReturnTokens) -> Self {
88        self.tokens = Some(tokens);
89        self
90    }
91
92    /// Sets the tokens for this return statement.
93    #[inline]
94    pub fn set_tokens(&mut self, tokens: ReturnTokens) {
95        self.tokens = Some(tokens);
96    }
97
98    /// Returns the tokens for this return statement, if any.
99    #[inline]
100    pub fn get_tokens(&self) -> Option<&ReturnTokens> {
101        self.tokens.as_ref()
102    }
103
104    /// Returns a mutable reference to the tokens, if any.
105    #[inline]
106    pub fn mutate_tokens(&mut self) -> Option<&mut ReturnTokens> {
107        self.tokens.as_mut()
108    }
109
110    /// Returns a mutable reference to the first token for this statement, creating it if missing.
111    pub fn mutate_first_token(&mut self) -> &mut Token {
112        self.set_default_tokens();
113        &mut self.tokens.as_mut().unwrap().r#return
114    }
115
116    /// Returns a mutable reference to the last token for this statement,
117    /// creating it if missing.
118    pub fn mutate_last_token(&mut self) -> &mut Token {
119        if self.is_empty() {
120            self.set_default_tokens();
121            &mut self.tokens.as_mut().unwrap().r#return
122        } else {
123            self.expressions.last_mut().unwrap().mutate_last_token()
124        }
125    }
126
127    fn set_default_tokens(&mut self) {
128        if self.tokens.is_none() {
129            self.tokens = Some(ReturnTokens {
130                r#return: Token::from_content("return"),
131                commas: Vec::new(),
132            });
133        }
134    }
135
136    super::impl_token_fns!(iter = [tokens]);
137}
138
139/// Represents a statement that can appear as the last statement in a block.
140#[derive(Clone, Debug, PartialEq, Eq)]
141pub enum LastStatement {
142    Break(Option<Token>),
143    Continue(Option<Token>),
144    Return(ReturnStatement),
145}
146
147impl LastStatement {
148    /// Creates a new break statement without a token.
149    #[inline]
150    pub fn new_break() -> Self {
151        Self::Break(None)
152    }
153
154    /// Creates a new continue statement without a token.
155    #[inline]
156    pub fn new_continue() -> Self {
157        Self::Continue(None)
158    }
159
160    /// Returns a mutable reference to the first token for this statement, creating it if missing.
161    pub fn mutate_first_token(&mut self) -> &mut Token {
162        match self {
163            LastStatement::Break(token_opt) => {
164                if token_opt.is_none() {
165                    *token_opt = Some(Token::from_content("break"));
166                }
167                token_opt.as_mut().unwrap()
168            }
169            LastStatement::Continue(token_opt) => {
170                if token_opt.is_none() {
171                    *token_opt = Some(Token::from_content("continue"));
172                }
173                token_opt.as_mut().unwrap()
174            }
175            LastStatement::Return(return_stmt) => return_stmt.mutate_first_token(),
176        }
177    }
178
179    /// Returns a mutable reference to the last token for this statement,
180    /// creating it if missing.
181    pub fn mutate_last_token(&mut self) -> &mut Token {
182        match self {
183            LastStatement::Break(token_opt) => {
184                if token_opt.is_none() {
185                    *token_opt = Some(Token::from_content("break"));
186                }
187                token_opt.as_mut().unwrap()
188            }
189            LastStatement::Continue(token_opt) => {
190                if token_opt.is_none() {
191                    *token_opt = Some(Token::from_content("continue"));
192                }
193                token_opt.as_mut().unwrap()
194            }
195            LastStatement::Return(return_stmt) => return_stmt.mutate_last_token(),
196        }
197    }
198}
199
200impl From<ReturnStatement> for LastStatement {
201    fn from(statement: ReturnStatement) -> Self {
202        Self::Return(statement)
203    }
204}
205
206#[cfg(test)]
207mod test {
208    use super::*;
209
210    #[test]
211    fn default_return_statement_is_empty() {
212        assert!(ReturnStatement::default().is_empty())
213    }
214}