1use super::{Box, Lit, SubDenomination, Type};
2use either::Either;
3use solar_interface::{Ident, Span};
4use std::fmt;
5
6pub type NamedArgList<'ast> = Box<'ast, [NamedArg<'ast>]>;
10
11#[derive(Debug)]
15pub struct Expr<'ast> {
16 pub span: Span,
17 pub kind: ExprKind<'ast>,
18}
19
20impl AsRef<Self> for Expr<'_> {
21 fn as_ref(&self) -> &Self {
22 self
23 }
24}
25
26impl<'ast> Expr<'ast> {
27 pub fn from_ident(ident: Ident) -> Self {
29 Self { span: ident.span, kind: ExprKind::Ident(ident) }
30 }
31
32 pub fn from_ty(ty: Type<'ast>) -> Self {
34 Self { span: ty.span, kind: ExprKind::Type(ty) }
35 }
36}
37
38#[derive(Debug)]
40pub enum ExprKind<'ast> {
41 Array(Box<'ast, [Box<'ast, Expr<'ast>>]>),
43
44 Assign(Box<'ast, Expr<'ast>>, Option<BinOp>, Box<'ast, Expr<'ast>>),
46
47 Binary(Box<'ast, Expr<'ast>>, BinOp, Box<'ast, Expr<'ast>>),
49
50 Call(Box<'ast, Expr<'ast>>, CallArgs<'ast>),
52
53 CallOptions(Box<'ast, Expr<'ast>>, NamedArgList<'ast>),
55
56 Delete(Box<'ast, Expr<'ast>>),
58
59 Ident(Ident),
61
62 Index(Box<'ast, Expr<'ast>>, IndexKind<'ast>),
64
65 Lit(Box<'ast, Lit<'ast>>, Option<SubDenomination>),
70
71 Member(Box<'ast, Expr<'ast>>, Ident),
73
74 New(Type<'ast>),
76
77 Payable(CallArgs<'ast>),
79
80 Ternary(Box<'ast, Expr<'ast>>, Box<'ast, Expr<'ast>>, Box<'ast, Expr<'ast>>),
82
83 Tuple(Box<'ast, [Option<Box<'ast, Expr<'ast>>>]>),
85
86 TypeCall(Type<'ast>),
88
89 Type(Type<'ast>),
91
92 Unary(UnOp, Box<'ast, Expr<'ast>>),
94}
95
96#[derive(Clone, Copy, Debug)]
98pub struct BinOp {
99 pub span: Span,
100 pub kind: BinOpKind,
101}
102
103#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
105pub enum BinOpKind {
106 Lt,
108 Le,
110 Gt,
112 Ge,
114 Eq,
116 Ne,
118 Or,
120 And,
122
123 Shr,
125 Shl,
127 Sar,
129 BitAnd,
131 BitOr,
133 BitXor,
135
136 Add,
138 Sub,
140 Pow,
142 Mul,
144 Div,
146 Rem,
148}
149
150impl fmt::Display for BinOp {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 f.write_str(self.kind.to_str())
153 }
154}
155
156impl BinOpKind {
157 pub const fn to_str(self) -> &'static str {
159 match self {
160 Self::Lt => "<",
161 Self::Le => "<=",
162 Self::Gt => ">",
163 Self::Ge => ">=",
164 Self::Eq => "==",
165 Self::Ne => "!=",
166 Self::Or => "||",
167 Self::And => "&&",
168 Self::Sar => ">>>",
169 Self::Shr => ">>",
170 Self::Shl => "<<",
171 Self::BitAnd => "&",
172 Self::BitOr => "|",
173 Self::BitXor => "^",
174 Self::Add => "+",
175 Self::Sub => "-",
176 Self::Pow => "**",
177 Self::Mul => "*",
178 Self::Div => "/",
179 Self::Rem => "%",
180 }
181 }
182
183 pub const fn assignable(self) -> bool {
185 match self {
187 Self::BitOr
188 | Self::BitXor
189 | Self::BitAnd
190 | Self::Shl
191 | Self::Shr
192 | Self::Sar
193 | Self::Add
194 | Self::Sub
195 | Self::Mul
196 | Self::Div
197 | Self::Rem => true,
198
199 Self::Lt
200 | Self::Le
201 | Self::Gt
202 | Self::Ge
203 | Self::Eq
204 | Self::Ne
205 | Self::Or
206 | Self::And
207 | Self::Pow => false,
208 }
209 }
210}
211
212#[derive(Clone, Copy, Debug)]
214pub struct UnOp {
215 pub span: Span,
216 pub kind: UnOpKind,
217}
218
219#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
221pub enum UnOpKind {
222 PreInc,
224 PreDec,
226 Not,
228 Neg,
230 BitNot,
232
233 PostInc,
235 PostDec,
237}
238
239impl fmt::Display for UnOp {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 f.write_str(self.kind.to_str())
242 }
243}
244
245impl UnOpKind {
246 pub const fn to_str(self) -> &'static str {
248 match self {
249 Self::PreInc => "++",
250 Self::PreDec => "--",
251 Self::Not => "!",
252 Self::Neg => "-",
253 Self::BitNot => "~",
254 Self::PostInc => "++",
255 Self::PostDec => "--",
256 }
257 }
258
259 pub const fn is_prefix(self) -> bool {
261 match self {
262 Self::PreInc | Self::PreDec | Self::Not | Self::Neg | Self::BitNot => true,
263 Self::PostInc | Self::PostDec => false,
264 }
265 }
266
267 pub const fn is_postfix(self) -> bool {
269 !self.is_prefix()
270 }
271}
272
273#[derive(Debug)]
275pub struct CallArgs<'ast> {
276 pub span: Span,
280 pub kind: CallArgsKind<'ast>,
281}
282
283impl<'ast> CallArgs<'ast> {
284 pub fn empty(span: Span) -> Self {
288 Self { span, kind: CallArgsKind::empty() }
289 }
290
291 pub fn is_dummy(&self) -> bool {
297 self.span.lo() == self.span.hi()
298 }
299
300 pub fn len(&self) -> usize {
302 self.kind.len()
303 }
304
305 pub fn is_empty(&self) -> bool {
307 self.kind.is_empty()
308 }
309
310 pub fn exprs(
312 &self,
313 ) -> impl ExactSizeIterator<Item = &Expr<'ast>> + DoubleEndedIterator + Clone {
314 self.kind.exprs()
315 }
316
317 pub fn exprs_mut(
319 &mut self,
320 ) -> impl ExactSizeIterator<Item = &mut Box<'ast, Expr<'ast>>> + DoubleEndedIterator {
321 self.kind.exprs_mut()
322 }
323}
324
325#[derive(Debug)]
327pub enum CallArgsKind<'ast> {
328 Unnamed(Box<'ast, [Box<'ast, Expr<'ast>>]>),
330
331 Named(NamedArgList<'ast>),
333}
334
335impl Default for CallArgsKind<'_> {
336 fn default() -> Self {
337 Self::empty()
338 }
339}
340
341impl<'ast> CallArgsKind<'ast> {
342 pub fn empty() -> Self {
344 Self::Unnamed(Box::default())
345 }
346
347 pub fn len(&self) -> usize {
349 match self {
350 Self::Unnamed(exprs) => exprs.len(),
351 Self::Named(args) => args.len(),
352 }
353 }
354
355 pub fn is_empty(&self) -> bool {
357 self.len() == 0
358 }
359
360 pub fn exprs(
362 &self,
363 ) -> impl ExactSizeIterator<Item = &Expr<'ast>> + DoubleEndedIterator + Clone {
364 match self {
365 Self::Unnamed(exprs) => Either::Left(exprs.iter().map(|expr| &**expr)),
366 Self::Named(args) => Either::Right(args.iter().map(|arg| &*arg.value)),
367 }
368 }
369
370 pub fn exprs_mut(
372 &mut self,
373 ) -> impl ExactSizeIterator<Item = &mut Box<'ast, Expr<'ast>>> + DoubleEndedIterator {
374 match self {
375 Self::Unnamed(exprs) => Either::Left(exprs.iter_mut()),
376 Self::Named(args) => Either::Right(args.iter_mut().map(|arg| &mut arg.value)),
377 }
378 }
379
380 pub fn span(&self) -> Option<Span> {
382 if self.is_empty() {
383 return None;
384 }
385 Some(Span::join_first_last(self.exprs().map(|e| e.span)))
386 }
387}
388
389#[derive(Debug)]
391pub struct NamedArg<'ast> {
392 pub name: Ident,
393 pub value: Box<'ast, Expr<'ast>>,
394}
395
396#[derive(Debug)]
398pub enum IndexKind<'ast> {
399 Index(Option<Box<'ast, Expr<'ast>>>),
401
402 Range(Option<Box<'ast, Expr<'ast>>>, Option<Box<'ast, Expr<'ast>>>),
404}