Implement slice pattern AST > HIR lowering

This commit is contained in:
Jonas Platte 2020-02-11 22:33:11 +01:00
parent 3e1d97790b
commit a3b104aa6d
No known key found for this signature in database
GPG key ID: 7D261D771D915378
8 changed files with 64 additions and 13 deletions

1
Cargo.lock generated
View file

@ -1070,6 +1070,7 @@ dependencies = [
"drop_bomb", "drop_bomb",
"either", "either",
"insta", "insta",
"itertools",
"log", "log",
"once_cell", "once_cell",
"ra_arena", "ra_arena",

View file

@ -14,6 +14,7 @@ rustc-hash = "1.0"
either = "1.5" either = "1.5"
anymap = "0.12" anymap = "0.12"
drop_bomb = "0.1.4" drop_bomb = "0.1.4"
itertools = "0.8.2"
ra_arena = { path = "../ra_arena" } ra_arena = { path = "../ra_arena" }
ra_db = { path = "../ra_db" } ra_db = { path = "../ra_db" }

View file

@ -8,7 +8,7 @@ use ra_arena::Arena;
use ra_syntax::{ use ra_syntax::{
ast::{ ast::{
self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
TypeAscriptionOwner, SlicePatComponents, TypeAscriptionOwner,
}, },
AstNode, AstPtr, AstNode, AstPtr,
}; };
@ -591,7 +591,7 @@ where
let args = p.args().map(|p| self.collect_pat(p)).collect(); let args = p.args().map(|p| self.collect_pat(p)).collect();
Pat::Tuple(args) Pat::Tuple(args)
} }
ast::Pat::PlaceholderPat(_) => Pat::Wild, ast::Pat::PlaceholderPat(_) | ast::Pat::DotDotPat(_) => Pat::Wild,
ast::Pat::RecordPat(p) => { ast::Pat::RecordPat(p) => {
let path = p.path().and_then(|path| self.expander.parse_path(path)); let path = p.path().and_then(|path| self.expander.parse_path(path));
let record_field_pat_list = let record_field_pat_list =
@ -616,12 +616,20 @@ where
Pat::Record { path, args: fields } 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 // FIXME: implement
ast::Pat::DotDotPat(_) => Pat::Missing,
ast::Pat::BoxPat(_) => Pat::Missing, ast::Pat::BoxPat(_) => Pat::Missing,
ast::Pat::LiteralPat(_) => 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); let ptr = AstPtr::new(&pat);
self.alloc_pat(pattern, Either::Left(ptr)) self.alloc_pat(pattern, Either::Left(ptr))

View file

@ -393,7 +393,7 @@ pub enum Pat {
}, },
Slice { Slice {
prefix: Vec<PatId>, prefix: Vec<PatId>,
rest: Option<PatId>, slice: Option<PatId>,
suffix: Vec<PatId>, suffix: Vec<PatId>,
}, },
Path(Path), Path(Path),
@ -424,8 +424,8 @@ impl Pat {
args.iter().copied().for_each(f); args.iter().copied().for_each(f);
} }
Pat::Ref { pat, .. } => f(*pat), Pat::Ref { pat, .. } => f(*pat),
Pat::Slice { prefix, rest, suffix } => { Pat::Slice { prefix, slice, suffix } => {
let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter()); let total_iter = prefix.iter().chain(slice.iter()).chain(suffix.iter());
total_iter.copied().for_each(f); total_iter.copied().for_each(f);
} }
Pat::Record { args, .. } => { Pat::Record { args, .. } => {

View file

@ -18,7 +18,8 @@ use crate::{
pub use self::{ pub use self::{
expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp}, expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp},
extensions::{ extensions::{
FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind, VisibilityKind, FieldKind, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind,
VisibilityKind,
}, },
generated::*, generated::*,
tokens::*, tokens::*,

View file

@ -1,6 +1,8 @@
//! Various extension methods to ast Nodes, which are hard to code-generate. //! Various extension methods to ast Nodes, which are hard to code-generate.
//! Extensions for various expressions live in a sibling `expr_extensions` module. //! Extensions for various expressions live in a sibling `expr_extensions` module.
use itertools::Itertools;
use crate::{ use crate::{
ast::{self, child_opt, children, AstNode, AttrInput, SyntaxNode}, ast::{self, child_opt, children, AstNode, AttrInput, SyntaxNode},
SmolStr, SyntaxElement, SmolStr, SyntaxElement,
@ -293,6 +295,40 @@ impl ast::BindPat {
} }
} }
pub struct SlicePatComponents {
pub prefix: Vec<ast::Pat>,
pub slice: Option<ast::Pat>,
pub suffix: Vec<ast::Pat>,
}
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 { impl ast::PointerType {
pub fn is_mut(&self) -> bool { pub fn is_mut(&self) -> bool {
self.syntax().children_with_tokens().any(|n| n.kind() == T![mut]) self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])

View file

@ -2063,7 +2063,11 @@ impl AstNode for SlicePat {
&self.syntax &self.syntax
} }
} }
impl SlicePat {} impl SlicePat {
pub fn args(&self) -> AstChildren<Pat> {
AstChildren::new(&self.syntax)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RangePat { pub struct RangePat {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,

View file

@ -415,14 +415,14 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
pats: [Pat], pats: [Pat],
guard: MatchGuard, guard: MatchGuard,
Expr, Expr,
} }
struct MatchGuard { Expr } struct MatchGuard { Expr }
struct RecordLit { Path, RecordFieldList } struct RecordLit { Path, RecordFieldList }
struct RecordFieldList { struct RecordFieldList {
fields: [RecordField], fields: [RecordField],
spread: Expr, spread: Expr,
} }
struct RecordField { NameRef, Expr } struct RecordField { NameRef, Expr }
struct RefPat { Pat } struct RefPat { Pat }
@ -430,8 +430,8 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
struct BindPat: NameOwner { Pat } struct BindPat: NameOwner { Pat }
struct PlaceholderPat { } struct PlaceholderPat { }
struct DotDotPat { } struct DotDotPat { }
struct PathPat { Path } struct PathPat { Path }
struct SlicePat {} struct SlicePat { args: [Pat] }
struct RangePat {} struct RangePat {}
struct LiteralPat { Literal } struct LiteralPat { Literal }