Skip to main content

swc_ecma_ast/
operators.rs

1use string_enum::StringEnum;
2use swc_common::EqIgnoreSpan;
3
4#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan, Default)]
5#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
6#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
7#[cfg_attr(
8    feature = "encoding-impl",
9    derive(::swc_common::Encode, ::swc_common::Decode)
10)]
11#[cfg_attr(swc_ast_unknown, non_exhaustive)]
12pub enum BinaryOp {
13    /// `==`
14    #[default]
15    EqEq,
16    /// `!=`
17    NotEq,
18    /// `===`
19    EqEqEq,
20    /// `!==`
21    NotEqEq,
22    /// `<`
23    Lt,
24    /// `<=`
25    LtEq,
26    /// `>`
27    Gt,
28    /// `>=`
29    GtEq,
30    /// `<<`
31    LShift,
32    /// `>>`
33    RShift,
34    /// `>>>`
35    ZeroFillRShift,
36
37    /// `+`
38    Add,
39    /// `-`
40    Sub,
41    /// `*`
42    Mul,
43    /// `/`
44    Div,
45    /// `%`
46    Mod,
47
48    /// `|`
49    BitOr,
50    /// `^`
51    BitXor,
52    /// `&`
53    BitAnd,
54
55    /// `||`
56    LogicalOr,
57
58    /// `&&`
59    LogicalAnd,
60
61    /// `in`
62    In,
63    /// `instanceof`
64    InstanceOf,
65
66    /// `**`
67    Exp,
68
69    /// `??`
70    NullishCoalescing,
71}
72
73impl BinaryOp {
74    pub fn precedence(self) -> u8 {
75        match self {
76            BinaryOp::EqEq => 6,
77            BinaryOp::NotEq => 6,
78            BinaryOp::EqEqEq => 6,
79            BinaryOp::NotEqEq => 6,
80            BinaryOp::Lt => 7,
81            BinaryOp::LtEq => 7,
82            BinaryOp::Gt => 7,
83            BinaryOp::GtEq => 7,
84            BinaryOp::LShift => 8,
85            BinaryOp::RShift => 8,
86            BinaryOp::ZeroFillRShift => 8,
87
88            BinaryOp::Add => 9,
89            BinaryOp::Sub => 9,
90            BinaryOp::Mul => 10,
91            BinaryOp::Div => 10,
92            BinaryOp::Mod => 10,
93
94            BinaryOp::BitOr => 3,
95            BinaryOp::BitXor => 4,
96
97            BinaryOp::BitAnd => 5,
98
99            BinaryOp::LogicalOr => 1,
100
101            BinaryOp::LogicalAnd => 2,
102            BinaryOp::In => 7,
103            BinaryOp::InstanceOf => 7,
104
105            BinaryOp::Exp => 11,
106
107            BinaryOp::NullishCoalescing => 1,
108        }
109    }
110
111    pub fn may_short_circuit(&self) -> bool {
112        matches!(self, op!("??") | op!("||") | op!("&&"))
113    }
114}
115
116#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan, Default)]
117#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
118#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
119#[cfg_attr(
120    feature = "encoding-impl",
121    derive(::swc_common::Encode, ::swc_common::Decode)
122)]
123#[cfg_attr(swc_ast_unknown, non_exhaustive)]
124pub enum AssignOp {
125    /// `=`
126    #[default]
127    Assign,
128    /// `+=`
129    AddAssign,
130    /// `-=`
131    SubAssign,
132    /// `*=`
133    MulAssign,
134    /// `/=`
135    DivAssign,
136    /// `%=`
137    ModAssign,
138    /// `<<=`
139    LShiftAssign,
140    /// `>>=`
141    RShiftAssign,
142    /// `>>>=`
143    ZeroFillRShiftAssign,
144    /// `|=`
145    BitOrAssign,
146    /// `^=`
147    BitXorAssign,
148    /// `&=`
149    BitAndAssign,
150
151    /// `**=`
152    ExpAssign,
153
154    /// `&&=`
155    AndAssign,
156
157    /// `||=`
158    OrAssign,
159
160    /// `??=`
161    NullishAssign,
162}
163
164impl AssignOp {
165    pub fn to_update(self) -> Option<BinaryOp> {
166        match self {
167            op!("=") => None,
168
169            op!("+=") => Some(op!(bin, "+")),
170            op!("-=") => Some(op!(bin, "-")),
171            op!("*=") => Some(op!("*")),
172            op!("/=") => Some(op!("/")),
173            op!("%=") => Some(op!("%")),
174            op!("<<=") => Some(op!("<<")),
175            op!(">>=") => Some(op!(">>")),
176            op!(">>>=") => Some(op!(">>>")),
177            op!("|=") => Some(op!("|")),
178            op!("&=") => Some(op!("&")),
179            op!("^=") => Some(op!("^")),
180            op!("**=") => Some(op!("**")),
181            op!("&&=") => Some(op!("&&")),
182            op!("||=") => Some(op!("||")),
183            op!("??=") => Some(op!("??")),
184        }
185    }
186
187    pub fn may_short_circuit(&self) -> bool {
188        matches!(self, op!("??=") | op!("||=") | op!("&&="))
189    }
190}
191
192#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan, Default)]
193#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
194#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
195#[cfg_attr(
196    feature = "encoding-impl",
197    derive(::swc_common::Encode, ::swc_common::Decode)
198)]
199#[cfg_attr(swc_ast_unknown, non_exhaustive)]
200pub enum UpdateOp {
201    /// `++`
202    #[default]
203    PlusPlus,
204    /// `--`
205    MinusMinus,
206}
207
208#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan, Default)]
209#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
210#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
211#[cfg_attr(
212    feature = "encoding-impl",
213    derive(::swc_common::Encode, ::swc_common::Decode)
214)]
215#[cfg_attr(swc_ast_unknown, non_exhaustive)]
216pub enum UnaryOp {
217    /// `-`
218    Minus,
219    /// `+`
220    Plus,
221    /// `!`
222    Bang,
223    /// `~`
224    Tilde,
225    /// `typeof`
226    TypeOf,
227    /// `void`
228    #[default]
229    Void,
230    /// `delete`
231    Delete,
232}