Skip to main content

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