swc_ecma_ast/
macros.rs

1/// Creates a corresponding operator. This macro is used to make code more
2/// readable.
3///
4/// This can used to represent [UnaryOp](crate::UnaryOp),
5/// [BinaryOp](crate::BinaryOp), or [AssignOp](crate::AssignOp).
6///
7/// Actual type is determined by the input.
8///
9/// # Note about `+` and `-`
10///
11/// As this macro is intended to be used in anywhere, including pattern
12/// bindings, this macro cannot use trick to determine type for `+` and `-`.
13///
14/// So we have to use some special syntax for `+` and `-`:
15///
16///  - If you need [UnaryOp](crate::UnaryOp), use `op!(unary, "+")` and
17///    `op!(unary, "-")`.
18///
19///  - If you need [BinaryOp](crate::BinaryOp), use `op!(bin, "+")` and
20///    `op!(bin, "-")`.
21#[macro_export]
22macro_rules! op {
23    (unary,"-") => {
24        $crate::UnaryOp::Minus
25    };
26    (unary,"+") => {
27        $crate::UnaryOp::Plus
28    };
29    ("!") => {
30        $crate::UnaryOp::Bang
31    };
32    ("~") => {
33        $crate::UnaryOp::Tilde
34    };
35    ("typeof") => {
36        $crate::UnaryOp::TypeOf
37    };
38    ("void") => {
39        $crate::UnaryOp::Void
40    };
41    ("delete") => {
42        $crate::UnaryOp::Delete
43    };
44
45    ("++") => {
46        $crate::UpdateOp::PlusPlus
47    };
48    ("--") => {
49        $crate::UpdateOp::MinusMinus
50    };
51
52    ("==") => {
53        $crate::BinaryOp::EqEq
54    };
55    ("!=") => {
56        $crate::BinaryOp::NotEq
57    };
58    ("===") => {
59        $crate::BinaryOp::EqEqEq
60    };
61    ("!==") => {
62        $crate::BinaryOp::NotEqEq
63    };
64    ("<") => {
65        $crate::BinaryOp::Lt
66    };
67    ("<=") => {
68        $crate::BinaryOp::LtEq
69    };
70    (">") => {
71        $crate::BinaryOp::Gt
72    };
73    (">=") => {
74        $crate::BinaryOp::GtEq
75    };
76    ("<<") => {
77        $crate::BinaryOp::LShift
78    };
79    (">>") => {
80        $crate::BinaryOp::RShift
81    };
82    (">>>") => {
83        $crate::BinaryOp::ZeroFillRShift
84    };
85    (bin,"+") => {
86        $crate::BinaryOp::Add
87    };
88    (bin,"-") => {
89        $crate::BinaryOp::Sub
90    };
91    ("*") => {
92        $crate::BinaryOp::Mul
93    };
94    ("/") => {
95        $crate::BinaryOp::Div
96    };
97    ("%") => {
98        $crate::BinaryOp::Mod
99    };
100    ("|") => {
101        $crate::BinaryOp::BitOr
102    };
103    ("^") => {
104        $crate::BinaryOp::BitXor
105    };
106    ("&") => {
107        $crate::BinaryOp::BitAnd
108    };
109    ("||") => {
110        $crate::BinaryOp::LogicalOr
111    };
112    ("&&") => {
113        $crate::BinaryOp::LogicalAnd
114    };
115    ("in") => {
116        $crate::BinaryOp::In
117    };
118    ("instanceof") => {
119        $crate::BinaryOp::InstanceOf
120    };
121    ("**") => {
122        $crate::BinaryOp::Exp
123    };
124    ("??") => {
125        $crate::BinaryOp::NullishCoalescing
126    };
127
128    ("=") => {
129        $crate::AssignOp::Assign
130    };
131    ("+=") => {
132        $crate::AssignOp::AddAssign
133    };
134    ("-=") => {
135        $crate::AssignOp::SubAssign
136    };
137    ("*=") => {
138        $crate::AssignOp::MulAssign
139    };
140    ("/=") => {
141        $crate::AssignOp::DivAssign
142    };
143    ("%=") => {
144        $crate::AssignOp::ModAssign
145    };
146    ("<<=") => {
147        $crate::AssignOp::LShiftAssign
148    };
149    (">>=") => {
150        $crate::AssignOp::RShiftAssign
151    };
152    (">>>=") => {
153        $crate::AssignOp::ZeroFillRShiftAssign
154    };
155    ("|=") => {
156        $crate::AssignOp::BitOrAssign
157    };
158    ("^=") => {
159        $crate::AssignOp::BitXorAssign
160    };
161    ("&=") => {
162        $crate::AssignOp::BitAndAssign
163    };
164    ("**=") => {
165        $crate::AssignOp::ExpAssign
166    };
167    ("&&=") => {
168        $crate::AssignOp::AndAssign
169    };
170    ("||=") => {
171        $crate::AssignOp::OrAssign
172    };
173    ("??=") => {
174        $crate::AssignOp::NullishAssign
175    };
176}
177
178macro_rules! test_de {
179    ($name:ident, $T:path, $s:literal) => {
180        #[test]
181        #[cfg(feature = "serde-impl")]
182        fn $name() {
183            let _var: $T = ::serde_json::from_str(&$s).expect("failed to parse json");
184        }
185    };
186}
187
188macro_rules! boxed {
189    ($T:ty, [$($variant_ty:ty),*]) => {
190        $(
191            bridge_from!($T, Box<$variant_ty>, $variant_ty);
192        )*
193    };
194}
195
196/// Implement `From<$src>` for `$dst`, by using implementation of `From<$src>`
197/// for `$bridge`.
198///
199/// - `$dst` must implement `From<$bridge>`.
200/// - `$bridge` must implement `From<$src>`.
201///
202///
203/// e.g. For `&str` -> `Box<Expr>`, we convert it by `&str` -> `Atom` -> `Str`
204/// -> `Lit` -> `Expr` -> `Box<Expr>`.
205macro_rules! bridge_from {
206    ($dst:ty, $bridge:ty, $src:ty) => {
207        impl From<$src> for $dst {
208            #[cfg_attr(not(debug_assertions), inline(always))]
209            fn from(src: $src) -> $dst {
210                let src: $bridge = src.into();
211                src.into()
212            }
213        }
214    };
215}
216
217macro_rules! bridge_expr_from {
218    ($bridge:ty, $src:ty) => {
219        bridge_from!(crate::Expr, $bridge, $src);
220        bridge_from!(Box<crate::Expr>, crate::Expr, $src);
221    };
222}
223
224macro_rules! bridge_pat_from {
225    ($bridge:ty, $src:ty) => {
226        bridge_from!(crate::Pat, $bridge, $src);
227        bridge_from!(crate::Param, crate::Pat, $src);
228        bridge_from!(Box<crate::Pat>, crate::Pat, $src);
229    };
230}