From a3b104aa6df205e74c116d8c9e41900807924e70 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Tue, 11 Feb 2020 22:33:11 +0100 Subject: [PATCH] Implement slice pattern AST > HIR lowering --- Cargo.lock | 1 + crates/ra_hir_def/Cargo.toml | 1 + crates/ra_hir_def/src/body/lower.rs | 16 +++++++++--- crates/ra_hir_def/src/expr.rs | 6 ++--- crates/ra_syntax/src/ast.rs | 3 ++- crates/ra_syntax/src/ast/extensions.rs | 36 ++++++++++++++++++++++++++ crates/ra_syntax/src/ast/generated.rs | 6 ++++- xtask/src/ast_src.rs | 8 +++--- 8 files changed, 64 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e29ff898d7..478c706bed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1070,6 +1070,7 @@ dependencies = [ "drop_bomb", "either", "insta", + "itertools", "log", "once_cell", "ra_arena", diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml index 1efa00fe00..6b9be9948c 100644 --- a/crates/ra_hir_def/Cargo.toml +++ b/crates/ra_hir_def/Cargo.toml @@ -14,6 +14,7 @@ rustc-hash = "1.0" either = "1.5" anymap = "0.12" drop_bomb = "0.1.4" +itertools = "0.8.2" ra_arena = { path = "../ra_arena" } ra_db = { path = "../ra_db" } diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index e656f9a41b..5c779521b0 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -8,7 +8,7 @@ use ra_arena::Arena; use ra_syntax::{ ast::{ self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, - TypeAscriptionOwner, + SlicePatComponents, TypeAscriptionOwner, }, AstNode, AstPtr, }; @@ -591,7 +591,7 @@ where let args = p.args().map(|p| self.collect_pat(p)).collect(); Pat::Tuple(args) } - ast::Pat::PlaceholderPat(_) => Pat::Wild, + ast::Pat::PlaceholderPat(_) | ast::Pat::DotDotPat(_) => Pat::Wild, ast::Pat::RecordPat(p) => { let path = p.path().and_then(|path| self.expander.parse_path(path)); let record_field_pat_list = @@ -616,12 +616,20 @@ where Pat::Record { path, args: fields } } + ast::Pat::SlicePat(p) => { + let SlicePatComponents { prefix, slice, suffix } = p.components(); + + Pat::Slice { + prefix: prefix.into_iter().map(|p| self.collect_pat(p)).collect(), + slice: slice.map(|p| self.collect_pat(p)), + suffix: suffix.into_iter().map(|p| self.collect_pat(p)).collect(), + } + } // FIXME: implement - ast::Pat::DotDotPat(_) => Pat::Missing, ast::Pat::BoxPat(_) => Pat::Missing, ast::Pat::LiteralPat(_) => Pat::Missing, - ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing, + ast::Pat::RangePat(_) => Pat::Missing, }; let ptr = AstPtr::new(&pat); self.alloc_pat(pattern, Either::Left(ptr)) diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index a75ef9970d..0358244032 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs @@ -393,7 +393,7 @@ pub enum Pat { }, Slice { prefix: Vec, - rest: Option, + slice: Option, suffix: Vec, }, Path(Path), @@ -424,8 +424,8 @@ impl Pat { args.iter().copied().for_each(f); } Pat::Ref { pat, .. } => f(*pat), - Pat::Slice { prefix, rest, suffix } => { - let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter()); + Pat::Slice { prefix, slice, suffix } => { + let total_iter = prefix.iter().chain(slice.iter()).chain(suffix.iter()); total_iter.copied().for_each(f); } Pat::Record { args, .. } => { diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 89cb9a9f39..d3e8888bd5 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -18,7 +18,8 @@ use crate::{ pub use self::{ expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp}, extensions::{ - FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind, VisibilityKind, + FieldKind, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, + VisibilityKind, }, generated::*, tokens::*, diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index cb0aee4225..7dcf084de9 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs @@ -1,6 +1,8 @@ //! Various extension methods to ast Nodes, which are hard to code-generate. //! Extensions for various expressions live in a sibling `expr_extensions` module. +use itertools::Itertools; + use crate::{ ast::{self, child_opt, children, AstNode, AttrInput, SyntaxNode}, SmolStr, SyntaxElement, @@ -293,6 +295,40 @@ impl ast::BindPat { } } +pub struct SlicePatComponents { + pub prefix: Vec, + pub slice: Option, + pub suffix: Vec, +} + +impl ast::SlicePat { + pub fn components(&self) -> SlicePatComponents { + let mut args = self.args().peekable(); + let prefix = args + .peeking_take_while(|p| match p { + ast::Pat::DotDotPat(_) => false, + ast::Pat::BindPat(bp) => match bp.pat() { + Some(ast::Pat::DotDotPat(_)) => false, + _ => true, + }, + ast::Pat::RefPat(rp) => match rp.pat() { + Some(ast::Pat::DotDotPat(_)) => false, + Some(ast::Pat::BindPat(bp)) => match bp.pat() { + Some(ast::Pat::DotDotPat(_)) => false, + _ => true, + }, + _ => true, + }, + _ => true, + }) + .collect(); + let slice = args.next(); + let suffix = args.collect(); + + SlicePatComponents { prefix, slice, suffix } + } +} + impl ast::PointerType { pub fn is_mut(&self) -> bool { self.syntax().children_with_tokens().any(|n| n.kind() == T![mut]) diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 33d5578e70..8a3669bd1a 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -2063,7 +2063,11 @@ impl AstNode for SlicePat { &self.syntax } } -impl SlicePat {} +impl SlicePat { + pub fn args(&self) -> AstChildren { + AstChildren::new(&self.syntax) + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RangePat { pub(crate) syntax: SyntaxNode, diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 67d1f41bca..efe1e795ba 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -415,14 +415,14 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { pats: [Pat], guard: MatchGuard, Expr, - } + } struct MatchGuard { Expr } struct RecordLit { Path, RecordFieldList } struct RecordFieldList { fields: [RecordField], spread: Expr, - } + } struct RecordField { NameRef, Expr } struct RefPat { Pat } @@ -430,8 +430,8 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { struct BindPat: NameOwner { Pat } struct PlaceholderPat { } struct DotDotPat { } - struct PathPat { Path } - struct SlicePat {} + struct PathPat { Path } + struct SlicePat { args: [Pat] } struct RangePat {} struct LiteralPat { Literal }