1use super::{Box, Lit, SubDenomination, Type};
2use crate::BoxSlice;
3use either::Either;
4use solar_data_structures::trustme;
5use solar_interface::{Ident, Span, SpannedOption};
6use std::fmt;
7
8pub type NamedArgList<'ast> = BoxSlice<'ast, NamedArg<'ast>>;
12
13#[derive(Debug)]
17pub struct Expr<'ast> {
18 pub span: Span,
19 pub kind: ExprKind<'ast>,
20}
21
22impl AsRef<Self> for Expr<'_> {
23 fn as_ref(&self) -> &Self {
24 self
25 }
26}
27
28impl<'ast> Expr<'ast> {
29 pub fn peel_parens(&self) -> &Self {
31 let mut expr = self;
32 while let ExprKind::Tuple(x) = &expr.kind
33 && let [SpannedOption::Some(inner)] = x.as_slice()
34 {
35 expr = inner;
36 }
37 expr
38 }
39
40 pub fn peel_parens_mut(&mut self) -> &mut Self {
42 let mut expr = self;
43 while let ExprKind::Tuple(x) = &mut unsafe { trustme::decouple_lt_mut(expr) }.kind
46 && let [SpannedOption::Some(inner)] = x.as_mut_slice()
47 {
48 expr = inner;
49 }
50 expr
51 }
52
53 pub fn from_ident(ident: Ident) -> Self {
55 Self { span: ident.span, kind: ExprKind::Ident(ident) }
56 }
57
58 pub fn from_ty(ty: Type<'ast>) -> Self {
60 Self { span: ty.span, kind: ExprKind::Type(ty) }
61 }
62}
63
64#[derive(Debug)]
66pub enum ExprKind<'ast> {
67 Array(BoxSlice<'ast, Box<'ast, Expr<'ast>>>),
69
70 Assign(Box<'ast, Expr<'ast>>, Option<BinOp>, Box<'ast, Expr<'ast>>),
72
73 Binary(Box<'ast, Expr<'ast>>, BinOp, Box<'ast, Expr<'ast>>),
75
76 Call(Box<'ast, Expr<'ast>>, CallArgs<'ast>),
78
79 CallOptions(Box<'ast, Expr<'ast>>, NamedArgList<'ast>),
81
82 Delete(Box<'ast, Expr<'ast>>),
84
85 Ident(Ident),
87
88 Index(Box<'ast, Expr<'ast>>, IndexKind<'ast>),
90
91 Lit(Box<'ast, Lit<'ast>>, Option<SubDenomination>),
96
97 Member(Box<'ast, Expr<'ast>>, Ident),
99
100 New(Type<'ast>),
102
103 Payable(CallArgs<'ast>),
105
106 Ternary(Box<'ast, Expr<'ast>>, Box<'ast, Expr<'ast>>, Box<'ast, Expr<'ast>>),
108
109 Tuple(BoxSlice<'ast, SpannedOption<Box<'ast, Expr<'ast>>>>),
111
112 TypeCall(Type<'ast>),
114
115 Type(Type<'ast>),
117
118 Unary(UnOp, Box<'ast, Expr<'ast>>),
120}
121
122#[derive(Clone, Copy, Debug)]
124pub struct BinOp {
125 pub span: Span,
126 pub kind: BinOpKind,
127}
128
129#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
131pub enum BinOpKind {
132 Lt,
134 Le,
136 Gt,
138 Ge,
140 Eq,
142 Ne,
144 Or,
146 And,
148
149 Shr,
151 Shl,
153 Sar,
155 BitAnd,
157 BitOr,
159 BitXor,
161
162 Add,
164 Sub,
166 Pow,
168 Mul,
170 Div,
172 Rem,
174}
175
176impl fmt::Display for BinOp {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 f.write_str(self.kind.to_str())
179 }
180}
181
182impl BinOpKind {
183 pub const fn to_str(self) -> &'static str {
185 match self {
186 Self::Lt => "<",
187 Self::Le => "<=",
188 Self::Gt => ">",
189 Self::Ge => ">=",
190 Self::Eq => "==",
191 Self::Ne => "!=",
192 Self::Or => "||",
193 Self::And => "&&",
194 Self::Sar => ">>>",
195 Self::Shr => ">>",
196 Self::Shl => "<<",
197 Self::BitAnd => "&",
198 Self::BitOr => "|",
199 Self::BitXor => "^",
200 Self::Add => "+",
201 Self::Sub => "-",
202 Self::Pow => "**",
203 Self::Mul => "*",
204 Self::Div => "/",
205 Self::Rem => "%",
206 }
207 }
208
209 pub const fn assignable(self) -> bool {
211 match self {
213 Self::BitOr
214 | Self::BitXor
215 | Self::BitAnd
216 | Self::Shl
217 | Self::Shr
218 | Self::Sar
219 | Self::Add
220 | Self::Sub
221 | Self::Mul
222 | Self::Div
223 | Self::Rem => true,
224
225 Self::Lt
226 | Self::Le
227 | Self::Gt
228 | Self::Ge
229 | Self::Eq
230 | Self::Ne
231 | Self::Or
232 | Self::And
233 | Self::Pow => false,
234 }
235 }
236}
237
238#[derive(Clone, Copy, Debug)]
240pub struct UnOp {
241 pub span: Span,
242 pub kind: UnOpKind,
243}
244
245#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
247pub enum UnOpKind {
248 PreInc,
250 PreDec,
252 Not,
254 Neg,
256 BitNot,
258
259 PostInc,
261 PostDec,
263}
264
265impl fmt::Display for UnOp {
266 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267 f.write_str(self.kind.to_str())
268 }
269}
270
271impl UnOpKind {
272 pub const fn to_str(self) -> &'static str {
274 match self {
275 Self::PreInc => "++",
276 Self::PreDec => "--",
277 Self::Not => "!",
278 Self::Neg => "-",
279 Self::BitNot => "~",
280 Self::PostInc => "++",
281 Self::PostDec => "--",
282 }
283 }
284
285 pub const fn is_prefix(self) -> bool {
287 match self {
288 Self::PreInc | Self::PreDec | Self::Not | Self::Neg | Self::BitNot => true,
289 Self::PostInc | Self::PostDec => false,
290 }
291 }
292
293 pub const fn is_postfix(self) -> bool {
295 !self.is_prefix()
296 }
297}
298
299#[derive(Debug)]
301pub struct CallArgs<'ast> {
302 pub span: Span,
306 pub kind: CallArgsKind<'ast>,
307}
308
309impl<'ast> CallArgs<'ast> {
310 pub fn empty(span: Span) -> Self {
314 Self { span, kind: CallArgsKind::empty() }
315 }
316
317 pub fn is_dummy(&self) -> bool {
323 self.span.lo() == self.span.hi()
324 }
325
326 pub fn len(&self) -> usize {
328 self.kind.len()
329 }
330
331 pub fn is_empty(&self) -> bool {
333 self.kind.is_empty()
334 }
335
336 pub fn exprs(
338 &self,
339 ) -> impl ExactSizeIterator<Item = &Expr<'ast>> + DoubleEndedIterator + Clone {
340 self.kind.exprs()
341 }
342
343 pub fn exprs_mut(
345 &mut self,
346 ) -> impl ExactSizeIterator<Item = &mut Box<'ast, Expr<'ast>>> + DoubleEndedIterator {
347 self.kind.exprs_mut()
348 }
349}
350
351#[derive(Debug)]
353pub enum CallArgsKind<'ast> {
354 Unnamed(BoxSlice<'ast, Box<'ast, Expr<'ast>>>),
356
357 Named(NamedArgList<'ast>),
359}
360
361impl Default for CallArgsKind<'_> {
362 fn default() -> Self {
363 Self::empty()
364 }
365}
366
367impl<'ast> CallArgsKind<'ast> {
368 pub fn empty() -> Self {
370 Self::Unnamed(BoxSlice::default())
371 }
372
373 pub fn len(&self) -> usize {
375 match self {
376 Self::Unnamed(exprs) => exprs.len(),
377 Self::Named(args) => args.len(),
378 }
379 }
380
381 pub fn is_empty(&self) -> bool {
383 self.len() == 0
384 }
385
386 pub fn exprs(
388 &self,
389 ) -> impl ExactSizeIterator<Item = &Expr<'ast>> + DoubleEndedIterator + Clone {
390 match self {
391 Self::Unnamed(exprs) => Either::Left(exprs.iter().map(|expr| &**expr)),
392 Self::Named(args) => Either::Right(args.iter().map(|arg| &*arg.value)),
393 }
394 }
395
396 pub fn exprs_mut(
398 &mut self,
399 ) -> impl ExactSizeIterator<Item = &mut Box<'ast, Expr<'ast>>> + DoubleEndedIterator {
400 match self {
401 Self::Unnamed(exprs) => Either::Left(exprs.iter_mut()),
402 Self::Named(args) => Either::Right(args.iter_mut().map(|arg| &mut arg.value)),
403 }
404 }
405
406 pub fn span(&self) -> Option<Span> {
408 if self.is_empty() {
409 return None;
410 }
411 Some(Span::join_first_last(self.exprs().map(|e| e.span)))
412 }
413}
414
415#[derive(Debug)]
417pub struct NamedArg<'ast> {
418 pub name: Ident,
419 pub value: Box<'ast, Expr<'ast>>,
420}
421
422#[derive(Debug)]
424pub enum IndexKind<'ast> {
425 Index(Option<Box<'ast, Expr<'ast>>>),
427
428 Range(Option<Box<'ast, Expr<'ast>>>, Option<Box<'ast, Expr<'ast>>>),
430}