Skip to main content

ecma_syntax_cat/
declaration.rs

1//! Variable declarations.
2
3use crate::expression::Expression;
4use crate::pattern::Pattern;
5
6/// A variable declaration (`var x = 1, y;` etc.).
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct VariableDeclaration {
9    kind: VariableKind,
10    declarators: Vec<VariableDeclarator>,
11}
12
13impl VariableDeclaration {
14    /// Build a variable declaration.
15    #[must_use]
16    pub fn new(kind: VariableKind, declarators: Vec<VariableDeclarator>) -> Self {
17        Self { kind, declarators }
18    }
19
20    /// Whether the declaration uses `var`, `let`, or `const`.
21    #[must_use]
22    pub fn kind(&self) -> VariableKind {
23        self.kind
24    }
25
26    /// The individual declarators (`x = 1`, `y`, etc.).
27    #[must_use]
28    pub fn declarators(&self) -> &[VariableDeclarator] {
29        &self.declarators
30    }
31}
32
33impl std::fmt::Display for VariableDeclaration {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        write!(f, "{} ", self.kind)?;
36        let parts = self
37            .declarators
38            .iter()
39            .map(|d| format!("{d}"))
40            .collect::<Vec<_>>()
41            .join(", ");
42        f.write_str(&parts)
43    }
44}
45
46/// Which keyword introduces a variable declaration.
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
48pub enum VariableKind {
49    /// `var` (function-scoped).
50    Var,
51    /// `let` (block-scoped, mutable).
52    Let,
53    /// `const` (block-scoped, immutable binding).
54    Const,
55}
56
57impl std::fmt::Display for VariableKind {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59        f.write_str(match self {
60            Self::Var => "var",
61            Self::Let => "let",
62            Self::Const => "const",
63        })
64    }
65}
66
67/// One declarator inside a variable declaration: a binding pattern with an
68/// optional initialiser.
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct VariableDeclarator {
71    id: Pattern,
72    init: Option<Expression>,
73}
74
75impl VariableDeclarator {
76    /// Build a declarator.
77    #[must_use]
78    pub fn new(id: Pattern, init: Option<Expression>) -> Self {
79        Self { id, init }
80    }
81
82    /// The binding pattern (often just an identifier).
83    #[must_use]
84    pub fn id(&self) -> &Pattern {
85        &self.id
86    }
87
88    /// The optional initialiser expression.
89    #[must_use]
90    pub fn init(&self) -> Option<&Expression> {
91        self.init.as_ref()
92    }
93}
94
95impl std::fmt::Display for VariableDeclarator {
96    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97        match &self.init {
98            Some(expr) => write!(f, "{} = {expr}", self.id),
99            None => write!(f, "{}", self.id),
100        }
101    }
102}