Skip to main content

boa_ast/expression/
mod.rs

1//! The [`Expression`] Parse Node, as defined by the [spec].
2//!
3//! ECMAScript expressions include:
4//! - [Primary][primary] expressions (`this`, function expressions, literals).
5//! - [Left hand side][lhs] expressions (accessors, `new` operator, `super`).
6//! - [operator] expressions.
7//!
8//! [spec]: https://tc39.es/ecma262/#prod-Expression
9//! [primary]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#primary_expressions
10//! [lhs]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#left-hand-side_expressions
11
12use self::{
13    access::PropertyAccess,
14    literal::{ArrayLiteral, ObjectLiteral, TemplateLiteral},
15    operator::{Assign, Binary, BinaryInPrivate, Conditional, Unary, Update},
16};
17use super::{
18    Spanned, Statement,
19    function::AsyncArrowFunction,
20    function::{
21        ArrowFunction, AsyncFunctionExpression, AsyncGeneratorExpression, ClassExpression,
22        FunctionExpression, GeneratorExpression,
23    },
24};
25use boa_interner::{Interner, ToIndentedString, ToInternedString};
26use core::ops::ControlFlow;
27use literal::Literal;
28
29mod r#await;
30mod call;
31mod identifier;
32mod import_meta;
33mod new;
34mod new_target;
35mod optional;
36mod parenthesized;
37mod regexp;
38mod spread;
39mod tagged_template;
40mod this;
41mod r#yield;
42
43use crate::{
44    Span,
45    visitor::{VisitWith, Visitor, VisitorMut},
46};
47pub use r#await::Await;
48pub use call::{Call, ImportCall, ImportPhase, SuperCall};
49pub use identifier::{Identifier, RESERVED_IDENTIFIERS_STRICT};
50pub use import_meta::ImportMeta;
51pub use new::New;
52pub use new_target::NewTarget;
53pub use optional::{Optional, OptionalOperation, OptionalOperationKind};
54pub use parenthesized::Parenthesized;
55pub use regexp::RegExpLiteral;
56pub use spread::Spread;
57pub use tagged_template::TaggedTemplate;
58pub use this::This;
59pub use r#yield::Yield;
60
61pub mod access;
62pub mod literal;
63pub mod operator;
64
65/// The `Expression` Parse Node.
66///
67/// See the [module level documentation][self] for more information.
68#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
69#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
70#[derive(Debug, Clone, PartialEq)]
71pub enum Expression {
72    /// The ECMAScript `this` keyword refers to the object it belongs to.
73    ///
74    /// A property of an execution context (global, function or eval) that,
75    /// in non–strict mode, is always a reference to an object and in strict
76    /// mode can be any value.
77    ///
78    /// More information:
79    ///  - [ECMAScript reference][spec]
80    ///  - [MDN documentation][mdn]
81    ///
82    /// [spec]: https://tc39.es/ecma262/#sec-this-keyword
83    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
84    This(This),
85
86    /// See [`Identifier`].
87    Identifier(Identifier),
88
89    /// See [`Literal`].
90    Literal(Literal),
91
92    /// See [`RegExpLiteral`].
93    RegExpLiteral(RegExpLiteral),
94
95    /// See [`ArrayLiteral`].
96    ArrayLiteral(ArrayLiteral),
97
98    /// See [`ObjectLiteral`].
99    ObjectLiteral(ObjectLiteral),
100
101    /// See [`Spread`],
102    Spread(Spread),
103
104    /// See [`FunctionExpression`].
105    FunctionExpression(FunctionExpression),
106
107    /// See [`ArrowFunction`].
108    ArrowFunction(ArrowFunction),
109
110    /// See [`AsyncArrowFunction`].
111    AsyncArrowFunction(AsyncArrowFunction),
112
113    /// See [`GeneratorExpression`].
114    GeneratorExpression(GeneratorExpression),
115
116    /// See [`AsyncFunctionExpression`].
117    AsyncFunctionExpression(AsyncFunctionExpression),
118
119    /// See [`AsyncGeneratorExpression`].
120    AsyncGeneratorExpression(AsyncGeneratorExpression),
121
122    /// See [`ClassExpression`].
123    ClassExpression(Box<ClassExpression>),
124
125    /// See [`TemplateLiteral`].
126    TemplateLiteral(TemplateLiteral),
127
128    /// See [`PropertyAccess`].
129    PropertyAccess(PropertyAccess),
130
131    /// See [`New`].
132    New(New),
133
134    /// See [`Call`].
135    Call(Call),
136
137    /// See [`SuperCall`].
138    SuperCall(SuperCall),
139
140    /// See [`ImportCall`].
141    ImportCall(ImportCall),
142
143    /// See [`Optional`].
144    Optional(Optional),
145
146    /// See [`TaggedTemplate`].
147    TaggedTemplate(TaggedTemplate),
148
149    /// The `new.target` pseudo-property expression.
150    NewTarget(NewTarget),
151
152    /// The `import.meta` pseudo-property expression.
153    ImportMeta(ImportMeta),
154
155    /// See [`Assign`].
156    Assign(Assign),
157
158    /// See [`Unary`].
159    Unary(Unary),
160
161    /// See [`Unary`].
162    Update(Update),
163
164    /// See [`Binary`].
165    Binary(Binary),
166
167    /// See [`BinaryInPrivate`].
168    BinaryInPrivate(BinaryInPrivate),
169
170    /// See [`Conditional`].
171    Conditional(Conditional),
172
173    /// See [`Await`].
174    Await(Await),
175
176    /// See [`Yield`].
177    Yield(Yield),
178
179    /// See [`Parenthesized`].
180    Parenthesized(Parenthesized),
181}
182
183impl Expression {
184    /// Implements the display formatting with indentation.
185    ///
186    /// This will not prefix the value with any indentation. If you want to prefix this with proper
187    /// indents, use [`to_indented_string()`](Self::to_indented_string).
188    pub(crate) fn to_no_indent_string(&self, interner: &Interner, indentation: usize) -> String {
189        match self {
190            Self::This(this) => this.to_interned_string(interner),
191            Self::Identifier(id) => id.to_interned_string(interner),
192            Self::Literal(lit) => lit.to_interned_string(interner),
193            Self::ArrayLiteral(arr) => arr.to_interned_string(interner),
194            Self::ObjectLiteral(o) => o.to_indented_string(interner, indentation),
195            Self::Spread(sp) => sp.to_interned_string(interner),
196            Self::FunctionExpression(f) => f.to_indented_string(interner, indentation),
197            Self::AsyncArrowFunction(f) => f.to_indented_string(interner, indentation),
198            Self::ArrowFunction(arrf) => arrf.to_indented_string(interner, indentation),
199            Self::ClassExpression(cl) => cl.to_indented_string(interner, indentation),
200            Self::GeneratorExpression(r#gen) => r#gen.to_indented_string(interner, indentation),
201            Self::AsyncFunctionExpression(asf) => asf.to_indented_string(interner, indentation),
202            Self::AsyncGeneratorExpression(asgen) => {
203                asgen.to_indented_string(interner, indentation)
204            }
205            Self::TemplateLiteral(tem) => tem.to_interned_string(interner),
206            Self::PropertyAccess(prop) => prop.to_interned_string(interner),
207            Self::New(new) => new.to_interned_string(interner),
208            Self::Call(call) => call.to_interned_string(interner),
209            Self::SuperCall(supc) => supc.to_interned_string(interner),
210            Self::ImportCall(impc) => impc.to_interned_string(interner),
211            Self::Optional(opt) => opt.to_interned_string(interner),
212            Self::NewTarget(new_target) => new_target.to_interned_string(interner),
213            Self::ImportMeta(import_meta) => import_meta.to_interned_string(interner),
214            Self::TaggedTemplate(tag) => tag.to_interned_string(interner),
215            Self::Assign(assign) => assign.to_interned_string(interner),
216            Self::Unary(unary) => unary.to_interned_string(interner),
217            Self::Update(update) => update.to_interned_string(interner),
218            Self::Binary(bin) => bin.to_interned_string(interner),
219            Self::BinaryInPrivate(bin) => bin.to_interned_string(interner),
220            Self::Conditional(cond) => cond.to_interned_string(interner),
221            Self::Await(aw) => aw.to_interned_string(interner),
222            Self::Yield(yi) => yi.to_interned_string(interner),
223            Self::Parenthesized(expr) => expr.to_interned_string(interner),
224            Self::RegExpLiteral(regexp) => regexp.to_interned_string(interner),
225        }
226    }
227
228    /// Returns if the expression is a function definition without a name.
229    ///
230    /// More information:
231    ///  - [ECMAScript reference][spec]
232    ///
233    /// [spec]: https://tc39.es/ecma262/#sec-isanonymousfunctiondefinition
234    #[must_use]
235    #[inline]
236    pub const fn is_anonymous_function_definition(&self) -> bool {
237        match self {
238            Self::ArrowFunction(f) => f.name().is_none(),
239            Self::AsyncArrowFunction(f) => f.name().is_none(),
240            Self::FunctionExpression(f) => f.name().is_none(),
241            Self::GeneratorExpression(f) => f.name().is_none(),
242            Self::AsyncGeneratorExpression(f) => f.name().is_none(),
243            Self::AsyncFunctionExpression(f) => f.name().is_none(),
244            Self::ClassExpression(f) => f.name().is_none(),
245            Self::Parenthesized(p) => p.expression().is_anonymous_function_definition(),
246            _ => false,
247        }
248    }
249
250    /// Sets the name of an anonymous function definition.
251    ///
252    /// This is used to set the name of a function expression when it is assigned to a variable.
253    /// If the function already has a name, this does nothing.
254    pub fn set_anonymous_function_definition_name(&mut self, name: &Identifier) {
255        match self {
256            Self::ArrowFunction(f) if f.name().is_none() => f.name = Some(*name),
257            Self::AsyncArrowFunction(f) if f.name().is_none() => f.name = Some(*name),
258            Self::FunctionExpression(f) if f.name().is_none() => f.name = Some(*name),
259            Self::GeneratorExpression(f) if f.name().is_none() => f.name = Some(*name),
260            Self::AsyncGeneratorExpression(f) if f.name().is_none() => f.name = Some(*name),
261            Self::AsyncFunctionExpression(f) if f.name().is_none() => f.name = Some(*name),
262            Self::ClassExpression(f) if f.name().is_none() => f.name = Some(*name),
263            Self::Parenthesized(p) => p.expression.set_anonymous_function_definition_name(name),
264            _ => {}
265        }
266    }
267
268    /// Returns the expression without any outer parenthesized expressions.
269    #[must_use]
270    #[inline]
271    pub const fn flatten(&self) -> &Self {
272        let mut expression = self;
273        while let Self::Parenthesized(p) = expression {
274            expression = p.expression();
275        }
276        expression
277    }
278}
279
280impl Spanned for Expression {
281    #[inline]
282    fn span(&self) -> Span {
283        match self {
284            Self::This(this) => this.span(),
285            Self::Identifier(id) => id.span(),
286            Self::Literal(lit) => lit.span(),
287            Self::ArrayLiteral(arr) => arr.span(),
288            Self::ObjectLiteral(o) => o.span(),
289            Self::Spread(sp) => sp.span(),
290            Self::FunctionExpression(f) => f.span(),
291            Self::AsyncArrowFunction(f) => f.span(),
292            Self::ArrowFunction(arrf) => arrf.span(),
293            Self::ClassExpression(cl) => cl.span(),
294            Self::GeneratorExpression(r#gen) => r#gen.span(),
295            Self::AsyncFunctionExpression(asf) => asf.span(),
296            Self::AsyncGeneratorExpression(asgen) => asgen.span(),
297            Self::TemplateLiteral(tem) => tem.span(),
298            Self::PropertyAccess(prop) => prop.span(),
299            Self::New(new) => new.span(),
300            Self::Call(call) => call.span(),
301            Self::SuperCall(supc) => supc.span(),
302            Self::ImportCall(impc) => impc.span(),
303            Self::Optional(opt) => opt.span(),
304            Self::NewTarget(new_target) => new_target.span(),
305            Self::ImportMeta(import_meta) => import_meta.span(),
306            Self::TaggedTemplate(tag) => tag.span(),
307            Self::Assign(assign) => assign.span(),
308            Self::Unary(unary) => unary.span(),
309            Self::Update(update) => update.span(),
310            Self::Binary(bin) => bin.span(),
311            Self::BinaryInPrivate(bin) => bin.span(),
312            Self::Conditional(cond) => cond.span(),
313            Self::Await(aw) => aw.span(),
314            Self::Yield(yi) => yi.span(),
315            Self::Parenthesized(expr) => expr.span(),
316            Self::RegExpLiteral(regexp) => regexp.span(),
317        }
318    }
319}
320
321impl From<Expression> for Statement {
322    #[inline]
323    fn from(expr: Expression) -> Self {
324        Self::Expression(expr)
325    }
326}
327
328impl ToIndentedString for Expression {
329    #[inline]
330    fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
331        self.to_no_indent_string(interner, indentation)
332    }
333}
334
335impl VisitWith for Expression {
336    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
337    where
338        V: Visitor<'a>,
339    {
340        match self {
341            Self::This(this) => visitor.visit_this(this),
342            Self::Identifier(id) => visitor.visit_identifier(id),
343            Self::Literal(lit) => visitor.visit_literal(lit),
344            Self::RegExpLiteral(regexp) => visitor.visit_reg_exp_literal(regexp),
345            Self::ArrayLiteral(arlit) => visitor.visit_array_literal(arlit),
346            Self::ObjectLiteral(olit) => visitor.visit_object_literal(olit),
347            Self::Spread(sp) => visitor.visit_spread(sp),
348            Self::FunctionExpression(f) => visitor.visit_function_expression(f),
349            Self::ArrowFunction(af) => visitor.visit_arrow_function(af),
350            Self::AsyncArrowFunction(af) => visitor.visit_async_arrow_function(af),
351            Self::GeneratorExpression(g) => visitor.visit_generator_expression(g),
352            Self::AsyncFunctionExpression(af) => visitor.visit_async_function_expression(af),
353            Self::AsyncGeneratorExpression(ag) => visitor.visit_async_generator_expression(ag),
354            Self::ClassExpression(c) => visitor.visit_class_expression(c),
355            Self::TemplateLiteral(tlit) => visitor.visit_template_literal(tlit),
356            Self::PropertyAccess(pa) => visitor.visit_property_access(pa),
357            Self::New(n) => visitor.visit_new(n),
358            Self::Call(c) => visitor.visit_call(c),
359            Self::SuperCall(sc) => visitor.visit_super_call(sc),
360            Self::ImportCall(ic) => visitor.visit_import_call(ic),
361            Self::Optional(opt) => visitor.visit_optional(opt),
362            Self::TaggedTemplate(tt) => visitor.visit_tagged_template(tt),
363            Self::Assign(a) => visitor.visit_assign(a),
364            Self::Unary(u) => visitor.visit_unary(u),
365            Self::Update(u) => visitor.visit_update(u),
366            Self::Binary(b) => visitor.visit_binary(b),
367            Self::BinaryInPrivate(b) => visitor.visit_binary_in_private(b),
368            Self::Conditional(c) => visitor.visit_conditional(c),
369            Self::Await(a) => visitor.visit_await(a),
370            Self::Yield(y) => visitor.visit_yield(y),
371            Self::Parenthesized(e) => visitor.visit_parenthesized(e),
372            Self::NewTarget(new_target) => visitor.visit_new_target(new_target),
373            Self::ImportMeta(import_meta) => visitor.visit_import_meta(import_meta),
374        }
375    }
376
377    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
378    where
379        V: VisitorMut<'a>,
380    {
381        match self {
382            Self::This(this) => visitor.visit_this_mut(this),
383            Self::Identifier(id) => visitor.visit_identifier_mut(id),
384            Self::Literal(lit) => visitor.visit_literal_mut(lit),
385            Self::RegExpLiteral(regexp) => visitor.visit_reg_exp_literal_mut(regexp),
386            Self::ArrayLiteral(arlit) => visitor.visit_array_literal_mut(arlit),
387            Self::ObjectLiteral(olit) => visitor.visit_object_literal_mut(olit),
388            Self::Spread(sp) => visitor.visit_spread_mut(sp),
389            Self::FunctionExpression(f) => visitor.visit_function_expression_mut(f),
390            Self::ArrowFunction(af) => visitor.visit_arrow_function_mut(af),
391            Self::AsyncArrowFunction(af) => visitor.visit_async_arrow_function_mut(af),
392            Self::GeneratorExpression(g) => visitor.visit_generator_expression_mut(g),
393            Self::AsyncFunctionExpression(af) => visitor.visit_async_function_expression_mut(af),
394            Self::AsyncGeneratorExpression(ag) => visitor.visit_async_generator_expression_mut(ag),
395            Self::ClassExpression(c) => visitor.visit_class_expression_mut(c),
396            Self::TemplateLiteral(tlit) => visitor.visit_template_literal_mut(tlit),
397            Self::PropertyAccess(pa) => visitor.visit_property_access_mut(pa),
398            Self::New(n) => visitor.visit_new_mut(n),
399            Self::Call(c) => visitor.visit_call_mut(c),
400            Self::SuperCall(sc) => visitor.visit_super_call_mut(sc),
401            Self::ImportCall(ic) => visitor.visit_import_call_mut(ic),
402            Self::Optional(opt) => visitor.visit_optional_mut(opt),
403            Self::TaggedTemplate(tt) => visitor.visit_tagged_template_mut(tt),
404            Self::Assign(a) => visitor.visit_assign_mut(a),
405            Self::Unary(u) => visitor.visit_unary_mut(u),
406            Self::Update(u) => visitor.visit_update_mut(u),
407            Self::Binary(b) => visitor.visit_binary_mut(b),
408            Self::BinaryInPrivate(b) => visitor.visit_binary_in_private_mut(b),
409            Self::Conditional(c) => visitor.visit_conditional_mut(c),
410            Self::Await(a) => visitor.visit_await_mut(a),
411            Self::Yield(y) => visitor.visit_yield_mut(y),
412            Self::Parenthesized(e) => visitor.visit_parenthesized_mut(e),
413            Self::NewTarget(new_target) => visitor.visit_new_target_mut(new_target),
414            Self::ImportMeta(import_meta) => visitor.visit_import_meta_mut(import_meta),
415        }
416    }
417}