mago_syntax/ast/ast/
unary.rs

1use serde::Serialize;
2use strum::Display;
3
4use mago_span::HasSpan;
5use mago_span::Span;
6
7use crate::ast::ast::expression::Expression;
8use crate::token::GetPrecedence;
9use crate::token::Precedence;
10
11#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
12#[serde(tag = "type", content = "value")]
13#[repr(u8)]
14pub enum UnaryPrefixOperator<'arena> {
15    ErrorControl(Span),             // `@$expr`
16    Reference(Span),                // `&$expr`
17    ArrayCast(Span, &'arena str),   // `(array) $expr`
18    BoolCast(Span, &'arena str),    // `(bool) $expr`
19    BooleanCast(Span, &'arena str), // `(boolean) $expr`
20    DoubleCast(Span, &'arena str),  // `(double) $expr`
21    RealCast(Span, &'arena str),    // `(real) $expr`
22    FloatCast(Span, &'arena str),   // `(float) $expr`
23    IntCast(Span, &'arena str),     // `(int) $expr`
24    IntegerCast(Span, &'arena str), // `(integer) $expr`
25    ObjectCast(Span, &'arena str),  // `(object) $expr`
26    UnsetCast(Span, &'arena str),   // `(unset) $expr`
27    StringCast(Span, &'arena str),  // `(string) $expr`
28    BinaryCast(Span, &'arena str),  // `(binary) $expr`
29    VoidCast(Span, &'arena str),    // `(void) $expr`
30    BitwiseNot(Span),               // `~$expr`
31    Not(Span),                      // `!$expr`
32    PreIncrement(Span),             // `++$expr`
33    PreDecrement(Span),             // `--$expr`
34    Plus(Span),                     // `+$expr`
35    Negation(Span),                 // `-$expr`
36}
37
38#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
39#[serde(tag = "type", content = "value")]
40#[repr(u8)]
41pub enum UnaryPostfixOperator {
42    PostIncrement(Span), // `$expr++`
43    PostDecrement(Span), // `$expr--`
44}
45
46#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
47pub struct UnaryPrefix<'arena> {
48    pub operator: UnaryPrefixOperator<'arena>,
49    pub operand: &'arena Expression<'arena>,
50}
51
52#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
53pub struct UnaryPostfix<'arena> {
54    pub operand: &'arena Expression<'arena>,
55    pub operator: UnaryPostfixOperator,
56}
57
58impl<'arena> UnaryPrefixOperator<'arena> {
59    #[inline]
60    pub const fn is_error_control(&self) -> bool {
61        matches!(self, Self::ErrorControl(_))
62    }
63
64    #[inline]
65    pub const fn is_constant(&self) -> bool {
66        matches!(
67            self,
68            Self::BitwiseNot(_)
69                | Self::Not(_)
70                | Self::PreIncrement(_)
71                | Self::PreDecrement(_)
72                | Self::Plus(_)
73                | Self::Negation(_)
74        )
75    }
76
77    #[inline]
78    pub const fn is_cast(&self) -> bool {
79        matches!(
80            self,
81            Self::ArrayCast(_, _)
82                | Self::BoolCast(_, _)
83                | Self::BooleanCast(_, _)
84                | Self::DoubleCast(_, _)
85                | Self::RealCast(_, _)
86                | Self::FloatCast(_, _)
87                | Self::IntCast(_, _)
88                | Self::IntegerCast(_, _)
89                | Self::ObjectCast(_, _)
90                | Self::UnsetCast(_, _)
91                | Self::StringCast(_, _)
92                | Self::BinaryCast(_, _)
93                | Self::VoidCast(_, _)
94        )
95    }
96
97    #[inline]
98    pub const fn is_reference(&self) -> bool {
99        matches!(self, Self::Reference(_))
100    }
101
102    #[inline]
103    pub const fn is_arithmetic(&self) -> bool {
104        matches!(self, Self::Plus(_) | Self::Negation(_) | Self::PreIncrement(_) | Self::PreDecrement(_))
105    }
106
107    #[inline]
108    pub const fn is_increment_or_decrement(&self) -> bool {
109        matches!(self, Self::PreIncrement(_) | Self::PreDecrement(_))
110    }
111
112    #[inline]
113    pub const fn is_not(&self) -> bool {
114        matches!(self, Self::Not(_))
115    }
116
117    #[inline]
118    pub fn as_str(&self) -> &'arena str {
119        match self {
120            UnaryPrefixOperator::ErrorControl(_) => "@",
121            UnaryPrefixOperator::Reference(_) => "&",
122            UnaryPrefixOperator::ArrayCast(_, value)
123            | UnaryPrefixOperator::BoolCast(_, value)
124            | UnaryPrefixOperator::BooleanCast(_, value)
125            | UnaryPrefixOperator::DoubleCast(_, value)
126            | UnaryPrefixOperator::RealCast(_, value)
127            | UnaryPrefixOperator::FloatCast(_, value)
128            | UnaryPrefixOperator::IntCast(_, value)
129            | UnaryPrefixOperator::IntegerCast(_, value)
130            | UnaryPrefixOperator::ObjectCast(_, value)
131            | UnaryPrefixOperator::UnsetCast(_, value)
132            | UnaryPrefixOperator::StringCast(_, value)
133            | UnaryPrefixOperator::BinaryCast(_, value)
134            | UnaryPrefixOperator::VoidCast(_, value) => value,
135            UnaryPrefixOperator::BitwiseNot(_) => "~",
136            UnaryPrefixOperator::Not(_) => "!",
137            UnaryPrefixOperator::PreIncrement(_) => "++",
138            UnaryPrefixOperator::PreDecrement(_) => "--",
139            UnaryPrefixOperator::Plus(_) => "+",
140            UnaryPrefixOperator::Negation(_) => "-",
141        }
142    }
143
144    #[inline]
145    pub const fn is_same_as(&self, other: &Self) -> bool {
146        matches!(
147            (self, other),
148            (Self::ErrorControl(_), Self::ErrorControl(_))
149                | (Self::Reference(_), Self::Reference(_))
150                | (Self::ArrayCast(_, _), Self::ArrayCast(_, _))
151                | (Self::BoolCast(_, _), Self::BoolCast(_, _))
152                | (Self::BooleanCast(_, _), Self::BooleanCast(_, _))
153                | (Self::DoubleCast(_, _), Self::DoubleCast(_, _))
154                | (Self::RealCast(_, _), Self::RealCast(_, _))
155                | (Self::FloatCast(_, _), Self::FloatCast(_, _))
156                | (Self::IntCast(_, _), Self::IntCast(_, _))
157                | (Self::IntegerCast(_, _), Self::IntegerCast(_, _))
158                | (Self::ObjectCast(_, _), Self::ObjectCast(_, _))
159                | (Self::UnsetCast(_, _), Self::UnsetCast(_, _))
160                | (Self::StringCast(_, _), Self::StringCast(_, _))
161                | (Self::BinaryCast(_, _), Self::BinaryCast(_, _))
162                | (Self::VoidCast(_, _), Self::VoidCast(_, _))
163                | (Self::BitwiseNot(_), Self::BitwiseNot(_))
164                | (Self::Not(_), Self::Not(_))
165                | (Self::PreIncrement(_), Self::PreIncrement(_))
166                | (Self::PreDecrement(_), Self::PreDecrement(_))
167                | (Self::Plus(_), Self::Plus(_))
168                | (Self::Negation(_), Self::Negation(_))
169        )
170    }
171}
172
173impl GetPrecedence for UnaryPrefixOperator<'_> {
174    fn precedence(&self) -> Precedence {
175        match self {
176            Self::Reference(_) => Precedence::Reference,
177            Self::ErrorControl(_) => Precedence::ErrorControl,
178            Self::PreIncrement(_) | Self::PreDecrement(_) => Precedence::IncDec,
179            _ => Precedence::Unary,
180        }
181    }
182}
183
184impl UnaryPostfixOperator {
185    #[inline]
186    pub const fn is_constant(&self) -> bool {
187        match self {
188            Self::PostIncrement(_) | Self::PostDecrement(_) => false,
189        }
190    }
191
192    #[inline]
193    pub const fn as_str<'a>(&self) -> &'a str {
194        match self {
195            UnaryPostfixOperator::PostIncrement(_) => "++",
196            UnaryPostfixOperator::PostDecrement(_) => "--",
197        }
198    }
199
200    #[inline]
201    pub const fn is_same_as(&self, other: &Self) -> bool {
202        matches!(
203            (self, other),
204            (Self::PostIncrement(_), Self::PostIncrement(_)) | (Self::PostDecrement(_), Self::PostDecrement(_))
205        )
206    }
207}
208
209impl GetPrecedence for UnaryPostfixOperator {
210    fn precedence(&self) -> Precedence {
211        match self {
212            Self::PostIncrement(_) | Self::PostDecrement(_) => Precedence::Unary,
213        }
214    }
215}
216
217impl HasSpan for UnaryPrefixOperator<'_> {
218    fn span(&self) -> Span {
219        match self {
220            Self::ErrorControl(span) => *span,
221            Self::Reference(span) => *span,
222            Self::ArrayCast(span, ..) => *span,
223            Self::BoolCast(span, ..) => *span,
224            Self::BooleanCast(span, ..) => *span,
225            Self::DoubleCast(span, ..) => *span,
226            Self::RealCast(span, ..) => *span,
227            Self::FloatCast(span, ..) => *span,
228            Self::IntCast(span, ..) => *span,
229            Self::IntegerCast(span, ..) => *span,
230            Self::ObjectCast(span, ..) => *span,
231            Self::UnsetCast(span, ..) => *span,
232            Self::StringCast(span, ..) => *span,
233            Self::BinaryCast(span, ..) => *span,
234            Self::VoidCast(span, ..) => *span,
235            Self::BitwiseNot(span) => *span,
236            Self::Not(span) => *span,
237            Self::PreIncrement(span) => *span,
238            Self::PreDecrement(span) => *span,
239            Self::Plus(span) => *span,
240            Self::Negation(span) => *span,
241        }
242    }
243}
244
245impl HasSpan for UnaryPostfixOperator {
246    fn span(&self) -> Span {
247        match self {
248            Self::PostIncrement(span) => *span,
249            Self::PostDecrement(span) => *span,
250        }
251    }
252}
253
254impl HasSpan for UnaryPrefix<'_> {
255    fn span(&self) -> Span {
256        self.operator.span().join(self.operand.span())
257    }
258}
259
260impl HasSpan for UnaryPostfix<'_> {
261    fn span(&self) -> Span {
262        self.operand.span().join(self.operator.span())
263    }
264}