Skip to main content

boa_ast/function/
mod.rs

1//! This module contains Function and Class AST nodes.
2//!
3//! ECMAScript defines multiple types of functions and classes.
4//! They are split into different AST nodes to reduce ambiguity and to make the AST more readable.
5//!
6//! - Functions:
7//!   - [`FunctionDeclaration`]
8//!   - [`FunctionExpression`]
9//! - Async functions:
10//!   - [`AsyncFunctionDeclaration`]
11//!   - [`AsyncFunctionExpression`]
12//! - Generators
13//!   - [`GeneratorDeclaration`]
14//!   - [`GeneratorExpression`]
15//! - Async Generators
16//!   - [`AsyncGeneratorDeclaration`]
17//!   - [`AsyncGeneratorExpression`]
18//! - Arrow Functions
19//!   - [`ArrowFunction`]
20//! - Async Arrow Functions
21//!   - [`AsyncArrowFunction`]
22//! - Classes
23//!   - [`ClassDeclaration`]
24//!   - [`ClassExpression`]
25
26mod arrow_function;
27mod async_arrow_function;
28mod async_function;
29mod async_generator;
30mod class;
31mod generator;
32mod ordinary_function;
33mod parameters;
34
35use std::ops::ControlFlow;
36
37pub use arrow_function::ArrowFunction;
38pub use async_arrow_function::AsyncArrowFunction;
39pub use async_function::{AsyncFunctionDeclaration, AsyncFunctionExpression};
40pub use async_generator::{AsyncGeneratorDeclaration, AsyncGeneratorExpression};
41use boa_interner::{Interner, ToIndentedString};
42pub use class::{
43    ClassDeclaration, ClassElement, ClassElementName, ClassExpression, ClassFieldDefinition,
44    ClassMethodDefinition, PrivateFieldDefinition, PrivateName, StaticBlockBody,
45};
46pub use generator::{GeneratorDeclaration, GeneratorExpression};
47pub use ordinary_function::{FunctionDeclaration, FunctionExpression};
48pub use parameters::{FormalParameter, FormalParameterList, FormalParameterListFlags};
49
50use crate::{
51    LinearPosition, Span, Spanned, StatementList, StatementListItem,
52    visitor::{VisitWith, Visitor, VisitorMut},
53};
54
55/// A Function body.
56///
57/// Since `Script` and `FunctionBody` have the same semantics, this is currently
58/// only an alias of the former.
59///
60/// More information:
61///  - [ECMAScript reference][spec]
62///
63/// [spec]: https://tc39.es/ecma262/#prod-FunctionBody
64#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
65#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
66#[derive(Clone, Debug, PartialEq)]
67pub struct FunctionBody {
68    pub(crate) statements: StatementList,
69    span: Span,
70}
71
72impl FunctionBody {
73    /// Creates a new `FunctionBody` AST node.
74    #[inline]
75    #[must_use]
76    pub fn new(statements: StatementList, span: Span) -> Self {
77        Self { statements, span }
78    }
79
80    /// Gets the list of statements.
81    #[inline]
82    #[must_use]
83    pub const fn statements(&self) -> &[StatementListItem] {
84        self.statements.statements()
85    }
86
87    /// Gets the statement list.
88    #[inline]
89    #[must_use]
90    pub const fn statement_list(&self) -> &StatementList {
91        &self.statements
92    }
93
94    /// Get the strict mode.
95    #[inline]
96    #[must_use]
97    pub const fn strict(&self) -> bool {
98        self.statements.strict()
99    }
100
101    /// Get end of linear position in source code.
102    #[inline]
103    #[must_use]
104    pub const fn linear_pos_end(&self) -> LinearPosition {
105        self.statements.linear_pos_end()
106    }
107}
108
109impl Spanned for FunctionBody {
110    #[inline]
111    fn span(&self) -> Span {
112        self.span
113    }
114}
115
116impl ToIndentedString for FunctionBody {
117    fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
118        self.statements.to_indented_string(interner, indentation)
119    }
120}
121
122impl VisitWith for FunctionBody {
123    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
124    where
125        V: Visitor<'a>,
126    {
127        for statement in &*self.statements {
128            visitor.visit_statement_list_item(statement)?;
129        }
130        ControlFlow::Continue(())
131    }
132
133    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
134    where
135        V: VisitorMut<'a>,
136    {
137        for statement in &mut *self.statements.statements {
138            visitor.visit_statement_list_item_mut(statement)?;
139        }
140        ControlFlow::Continue(())
141    }
142}