Skip to main content

ecma_syntax_cat/
function.rs

1//! Function definitions shared between function declarations, function
2//! expressions, and method definitions.
3
4use crate::identifier::Identifier;
5use crate::pattern::Pattern;
6use crate::statement::Statement;
7
8/// An ECMAScript function definition.
9///
10/// Distinguishes declarations from expressions only by where the value is
11/// used; the structural shape is identical, so both share this type.
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Function {
14    id: Option<Identifier>,
15    params: Vec<Pattern>,
16    body: Vec<Statement>,
17    is_async: bool,
18    is_generator: bool,
19}
20
21impl Function {
22    /// Build a function definition.
23    #[must_use]
24    pub fn new(
25        id: Option<Identifier>,
26        params: Vec<Pattern>,
27        body: Vec<Statement>,
28        is_async: bool,
29        is_generator: bool,
30    ) -> Self {
31        Self {
32            id,
33            params,
34            body,
35            is_async,
36            is_generator,
37        }
38    }
39
40    /// The function's name, if any.  Function declarations always have one;
41    /// expressions may be anonymous.
42    #[must_use]
43    pub fn id(&self) -> Option<&Identifier> {
44        self.id.as_ref()
45    }
46
47    /// The formal parameters.
48    #[must_use]
49    pub fn params(&self) -> &[Pattern] {
50        &self.params
51    }
52
53    /// The statements making up the function body.
54    #[must_use]
55    pub fn body(&self) -> &[Statement] {
56        &self.body
57    }
58
59    /// Whether the function was declared `async`.
60    #[must_use]
61    pub fn is_async(&self) -> bool {
62        self.is_async
63    }
64
65    /// Whether the function was declared a generator (`function*`).
66    #[must_use]
67    pub fn is_generator(&self) -> bool {
68        self.is_generator
69    }
70}
71
72impl std::fmt::Display for Function {
73    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74        if self.is_async {
75            f.write_str("async ")?;
76        }
77        f.write_str("function")?;
78        if self.is_generator {
79            f.write_str("*")?;
80        }
81        if let Some(name) = &self.id {
82            write!(f, " {name}")?;
83        }
84        let params = self
85            .params
86            .iter()
87            .map(|p| format!("{p}"))
88            .collect::<Vec<_>>()
89            .join(", ");
90        write!(f, "({params}) {{ ... }}")
91    }
92}
93
94/// An arrow-function body: either an expression (concise body) or a block
95/// of statements.
96#[derive(Debug, Clone, PartialEq, Eq)]
97pub enum ArrowBody {
98    /// `=> expr`
99    Expression(Box<crate::expression::Expression>),
100    /// `=> { stmts }`
101    Block(Vec<Statement>),
102}
103
104/// An arrow function definition.
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct ArrowFunction {
107    params: Vec<Pattern>,
108    body: ArrowBody,
109    is_async: bool,
110}
111
112impl ArrowFunction {
113    /// Build an arrow function.
114    #[must_use]
115    pub fn new(params: Vec<Pattern>, body: ArrowBody, is_async: bool) -> Self {
116        Self {
117            params,
118            body,
119            is_async,
120        }
121    }
122
123    /// The formal parameters.
124    #[must_use]
125    pub fn params(&self) -> &[Pattern] {
126        &self.params
127    }
128
129    /// The body (expression or block).
130    #[must_use]
131    pub fn body(&self) -> &ArrowBody {
132        &self.body
133    }
134
135    /// Whether the arrow was declared `async`.
136    #[must_use]
137    pub fn is_async(&self) -> bool {
138        self.is_async
139    }
140}
141
142impl std::fmt::Display for ArrowFunction {
143    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144        if self.is_async {
145            f.write_str("async ")?;
146        }
147        let params = self
148            .params
149            .iter()
150            .map(|p| format!("{p}"))
151            .collect::<Vec<_>>()
152            .join(", ");
153        write!(f, "({params}) => ")?;
154        match &self.body {
155            ArrowBody::Expression(expr) => write!(f, "{expr}"),
156            ArrowBody::Block(_) => f.write_str("{ ... }"),
157        }
158    }
159}