summaryrefslogtreecommitdiff
path: root/src/syntax/ast.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/syntax/ast.rs')
-rw-r--r--src/syntax/ast.rs131
1 files changed, 73 insertions, 58 deletions
diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs
index e492297a..3c01bdff 100644
--- a/src/syntax/ast.rs
+++ b/src/syntax/ast.rs
@@ -1533,10 +1533,7 @@ impl Closure {
///
/// This only exists if you use the function syntax sugar: `let f(x) = y`.
pub fn name(&self) -> Option<Ident> {
- match self.0.cast_first_match::<Pattern>()?.kind() {
- PatternKind::Ident(ident) => Some(ident),
- _ => Option::None,
- }
+ self.0.children().next()?.cast()
}
/// The parameter bindings.
@@ -1594,16 +1591,7 @@ impl AstNode for Param {
node! {
/// A destructuring pattern: `x` or `(x, _, ..y)`.
- Pattern
-}
-
-/// The kind of a pattern.
-#[derive(Debug, Clone, Hash)]
-pub enum PatternKind {
- /// A single identifier: `x`.
- Ident(Ident),
- /// A destructuring pattern: `(x, _, ..y)`.
- Destructure(Vec<DestructuringKind>),
+ Destructuring
}
/// The kind of an element in a destructuring pattern.
@@ -1617,64 +1605,82 @@ pub enum DestructuringKind {
Named(Ident, Ident),
}
-impl Pattern {
- /// The kind of the pattern.
- pub fn kind(&self) -> PatternKind {
- if self
- .0
- .children()
- .map(SyntaxNode::kind)
- .skip_while(|&kind| kind == SyntaxKind::LeftParen)
- .take_while(|&kind| kind != SyntaxKind::RightParen)
- .eq([SyntaxKind::Ident])
- {
- return PatternKind::Ident(self.0.cast_first_match().unwrap_or_default());
- }
-
- let mut bindings = Vec::new();
- for child in self.0.children() {
- match child.kind() {
- SyntaxKind::Ident => {
- bindings
- .push(DestructuringKind::Ident(child.cast().unwrap_or_default()));
- }
- SyntaxKind::Spread => {
- bindings.push(DestructuringKind::Sink(child.cast_first_match()));
- }
- SyntaxKind::Named => {
- let mut filtered = child.children().filter_map(SyntaxNode::cast);
- let key = filtered.next().unwrap_or_default();
- let ident = filtered.next().unwrap_or_default();
- bindings.push(DestructuringKind::Named(key, ident));
- }
- _ => (),
+impl Destructuring {
+ /// The bindings of the destructuring.
+ pub fn bindings(&self) -> impl Iterator<Item = DestructuringKind> + '_ {
+ self.0.children().filter_map(|child| match child.kind() {
+ SyntaxKind::Ident => {
+ Some(DestructuringKind::Ident(child.cast().unwrap_or_default()))
+ }
+ SyntaxKind::Spread => Some(DestructuringKind::Sink(child.cast_first_match())),
+ SyntaxKind::Named => {
+ let mut filtered = child.children().filter_map(SyntaxNode::cast);
+ let key = filtered.next().unwrap_or_default();
+ let ident = filtered.next().unwrap_or_default();
+ Some(DestructuringKind::Named(key, ident))
}
+ _ => Option::None,
+ })
+ }
+
+ // Returns a list of all identifiers in the pattern.
+ pub fn idents(&self) -> impl Iterator<Item = Ident> + '_ {
+ self.bindings().into_iter().filter_map(|binding| match binding {
+ DestructuringKind::Ident(ident) => Some(ident),
+ DestructuringKind::Sink(ident) => ident,
+ DestructuringKind::Named(_, ident) => Some(ident),
+ })
+ }
+}
+
+/// The kind of a pattern.
+#[derive(Debug, Clone, Hash)]
+pub enum Pattern {
+ /// A single identifier: `x`.
+ Ident(Ident),
+ /// A destructuring pattern: `(x, _, ..y)`.
+ Destructuring(Destructuring),
+}
+
+impl AstNode for Pattern {
+ fn from_untyped(node: &SyntaxNode) -> Option<Self> {
+ match node.kind() {
+ SyntaxKind::Ident => node.cast().map(Self::Ident),
+ SyntaxKind::Destructuring => node.cast().map(Self::Destructuring),
+ _ => Option::None,
}
+ }
- PatternKind::Destructure(bindings)
+ fn as_untyped(&self) -> &SyntaxNode {
+ match self {
+ Self::Ident(v) => v.as_untyped(),
+ Self::Destructuring(v) => v.as_untyped(),
+ }
}
+}
+impl Pattern {
// Returns a list of all identifiers in the pattern.
pub fn idents(&self) -> Vec<Ident> {
- match self.kind() {
- PatternKind::Ident(ident) => vec![ident],
- PatternKind::Destructure(bindings) => bindings
- .into_iter()
- .filter_map(|binding| match binding {
- DestructuringKind::Ident(ident) => Some(ident),
- DestructuringKind::Sink(ident) => ident,
- DestructuringKind::Named(_, ident) => Some(ident),
- })
- .collect(),
+ match self {
+ Pattern::Ident(ident) => vec![ident.clone()],
+ Pattern::Destructuring(destruct) => destruct.idents().collect(),
}
}
}
+impl Default for Pattern {
+ fn default() -> Self {
+ Self::Ident(Ident::default())
+ }
+}
+
node! {
/// A let binding: `let x = 1`.
LetBinding
}
+#[derive(Debug)]
pub enum LetBindingKind {
/// A normal binding: `let x = 1`.
Normal(Pattern),
@@ -1713,7 +1719,12 @@ impl LetBinding {
/// The expression the binding is initialized with.
pub fn init(&self) -> Option<Expr> {
match self.kind() {
- LetBindingKind::Normal(_) => self.0.cast_last_match(),
+ LetBindingKind::Normal(Pattern::Ident(_)) => {
+ self.0.children().filter_map(SyntaxNode::cast).nth(1)
+ }
+ LetBindingKind::Normal(Pattern::Destructuring(_)) => {
+ self.0.cast_first_match()
+ }
LetBindingKind::Closure(_) => self.0.cast_first_match(),
}
}
@@ -1821,7 +1832,11 @@ impl ForLoop {
/// The expression to iterate over.
pub fn iter(&self) -> Expr {
- self.0.cast_first_match().unwrap_or_default()
+ self.0
+ .children()
+ .skip_while(|&c| c.kind() != SyntaxKind::In)
+ .find_map(SyntaxNode::cast)
+ .unwrap_or_default()
}
/// The expression to evaluate for each iteration.