diff --git a/compiler/cl-ast/src/ast.rs b/compiler/cl-ast/src/ast.rs index 880db11..1f073b6 100644 --- a/compiler/cl-ast/src/ast.rs +++ b/compiler/cl-ast/src/ast.rs @@ -424,6 +424,7 @@ pub enum Pattern { Tuple(Vec), Array(Vec), Struct(Path, Vec<(Sym, Option)>), + TupleStruct(Path, Vec), } /// A `match` expression: `match` `{` ([MatchArm] `,`)* [MatchArm]? `}` diff --git a/compiler/cl-ast/src/ast_impl.rs b/compiler/cl-ast/src/ast_impl.rs index 7d048cf..0e29f88 100644 --- a/compiler/cl-ast/src/ast_impl.rs +++ b/compiler/cl-ast/src/ast_impl.rs @@ -487,6 +487,10 @@ mod display { } Ok(()) } + Pattern::TupleStruct(path, items) => { + write!(f, "{path}")?; + separate(items, ", ")(f.delimit(INLINE_PARENS)) + } } } } @@ -884,8 +888,19 @@ mod convert { .map(|e| Pattern::try_from(e.kind)) .collect::>()?, ), - // ExprKind::Index(index) => todo!(), - // ExprKind::Member(member) => todo!(), + ExprKind::Binary(Binary { kind: BinaryKind::Call, parts }) => { + let (ExprKind::Path(path), args) = *parts else { + return Err(parts.0); + }; + match args { + ExprKind::Empty | ExprKind::Tuple(_) => {} + _ => return Err(args), + } + let Pattern::Tuple(args) = Pattern::try_from(args)? else { + unreachable!("Arguments should be convertible to pattern!") + }; + Pattern::TupleStruct(path, args) + } ExprKind::Structor(Structor { to, init }) => { let fields = init .into_iter() diff --git a/compiler/cl-ast/src/ast_visitor/fold.rs b/compiler/cl-ast/src/ast_visitor/fold.rs index 774be2b..52e8b07 100644 --- a/compiler/cl-ast/src/ast_visitor/fold.rs +++ b/compiler/cl-ast/src/ast_visitor/fold.rs @@ -267,6 +267,13 @@ pub trait Fold { .map(|(name, bind)| (name, bind.map(|p| self.fold_pattern(p)))) .collect(), ), + Pattern::TupleStruct(path, items) => Pattern::TupleStruct( + self.fold_path(path), + items + .into_iter() + .map(|bind| self.fold_pattern(bind)) + .collect(), + ), } } diff --git a/compiler/cl-ast/src/ast_visitor/visit.rs b/compiler/cl-ast/src/ast_visitor/visit.rs index a6ea5bc..420a5fb 100644 --- a/compiler/cl-ast/src/ast_visitor/visit.rs +++ b/compiler/cl-ast/src/ast_visitor/visit.rs @@ -234,6 +234,10 @@ pub trait Visit<'a>: Sized { }); }); } + Pattern::TupleStruct(path, items) => { + self.visit_path(path); + items.iter().for_each(|bind| self.visit_pattern(bind)); + } } } diff --git a/compiler/cl-interpret/src/function/collect_upvars.rs b/compiler/cl-interpret/src/function/collect_upvars.rs index 0af1412..ce87361 100644 --- a/compiler/cl-interpret/src/function/collect_upvars.rs +++ b/compiler/cl-interpret/src/function/collect_upvars.rs @@ -127,6 +127,10 @@ impl<'a> Visit<'a> for CollectUpvars<'_> { }); }); } + Pattern::TupleStruct(path, items) => { + self.visit_path(path); + items.iter().for_each(|bind| self.visit_pattern(bind)); + } } } } diff --git a/compiler/cl-interpret/src/interpret.rs b/compiler/cl-interpret/src/interpret.rs index d0edc9a..cbeecca 100644 --- a/compiler/cl-interpret/src/interpret.rs +++ b/compiler/cl-interpret/src/interpret.rs @@ -320,6 +320,9 @@ mod assignment { None => set.push(name), }); } + Pattern::TupleStruct(_path, items) => { + items.iter().for_each(|pat| patvars(set, pat)); + } } } let mut set = Vec::new(); diff --git a/compiler/cl-parser/src/parser.rs b/compiler/cl-parser/src/parser.rs index d60eff9..e1aa1f7 100644 --- a/compiler/cl-parser/src/parser.rs +++ b/compiler/cl-parser/src/parser.rs @@ -1080,7 +1080,7 @@ impl Parse<'_> for Return { impl Parse<'_> for Pattern { fn parse(p: &mut Parser<'_>) -> PResult { - let value = prec::exprkind(p, prec::Precedence::Highest.level())?; + let value = prec::exprkind(p, prec::Precedence::Pattern.level())?; Pattern::try_from(value) .map_err(|_| p.error(ExpectedParsing { want: Parsing::Pattern }, Parsing::Pattern)) } diff --git a/compiler/cl-parser/src/parser/prec.rs b/compiler/cl-parser/src/parser/prec.rs index 19a966b..a13584e 100644 --- a/compiler/cl-parser/src/parser/prec.rs +++ b/compiler/cl-parser/src/parser/prec.rs @@ -255,8 +255,8 @@ pub enum Precedence { Index, Cast, Member, // left-associative + Pattern, Call, - Highest, } impl Precedence { diff --git a/compiler/cl-repl/examples/yaml.rs b/compiler/cl-repl/examples/yaml.rs index 9c425a1..887b83f 100644 --- a/compiler/cl-repl/examples/yaml.rs +++ b/compiler/cl-repl/examples/yaml.rs @@ -438,13 +438,20 @@ pub mod yamlify { Pattern::Struct(path, items) => { { let mut y = y.key("Struct"); - y.pair("name", path); + y.yaml(path); for (name, item) in items { y.pair(name, item); } } y } + Pattern::TupleStruct(path, items) => { + { + let mut y = y.key("TupleStruct"); + y.yaml(path).list(items); + } + y + } }; } }