From 59957746e91c1322a8ca6d228bcaa0f31941ee1b Mon Sep 17 00:00:00 2001 From: Marmare314 <49279081+Marmare314@users.noreply.github.com> Date: Wed, 26 Apr 2023 11:32:11 +0200 Subject: Pattern as parameter (#854) --- src/eval/func.rs | 29 ++++++++++++++++++----------- src/eval/mod.rs | 5 +---- 2 files changed, 19 insertions(+), 15 deletions(-) (limited to 'src/eval') diff --git a/src/eval/func.rs b/src/eval/func.rs index e3b6a99c..a6e0de84 100644 --- a/src/eval/func.rs +++ b/src/eval/func.rs @@ -276,13 +276,11 @@ pub(super) struct Closure { #[derive(Hash)] pub enum Param { /// A positional parameter: `x`. - Pos(Ident), + Pos(ast::Pattern), /// A named parameter with a default value: `draw: false`. Named(Ident, Value), /// An argument sink: `..args`. Sink(Option), - /// A placeholder: `_`. - Placeholder, } impl Closure { @@ -330,9 +328,18 @@ impl Closure { let mut sink_pos_values = None; for p in &closure.params { match p { - Param::Pos(ident) => { - vm.define(ident.clone(), args.expect::(ident)?); - } + Param::Pos(pattern) => match pattern { + ast::Pattern::Normal(ast::Expr::Ident(ident)) => { + vm.define(ident.clone(), args.expect::(ident)?) + } + ast::Pattern::Normal(_) => unreachable!(), + _ => { + pattern.define( + &mut vm, + args.expect::("pattern parameter")?, + )?; + } + }, Param::Sink(ident) => { sink = ident.clone(); if let Some(sink_size) = sink_size { @@ -344,9 +351,6 @@ impl Closure { args.named::(ident)?.unwrap_or_else(|| default.clone()); vm.define(ident.clone(), value); } - Param::Placeholder => { - args.eat::()?; - } } } @@ -443,12 +447,15 @@ impl<'a> CapturesVisitor<'a> { for param in expr.params().children() { match param { - ast::Param::Pos(ident) => self.bind(ident), + ast::Param::Pos(pattern) => { + for ident in pattern.idents() { + self.bind(ident); + } + } ast::Param::Named(named) => self.bind(named.name()), ast::Param::Sink(spread) => { self.bind(spread.name().unwrap_or_default()) } - _ => {} } } diff --git a/src/eval/mod.rs b/src/eval/mod.rs index d2ca0e74..e8e1af51 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -1207,14 +1207,11 @@ impl Eval for ast::Closure { let mut params = Vec::new(); for param in self.params().children() { match param { - ast::Param::Pos(name) => { - params.push(Param::Pos(name)); - } + ast::Param::Pos(pattern) => params.push(Param::Pos(pattern)), ast::Param::Named(named) => { params.push(Param::Named(named.name(), named.expr().eval(vm)?)); } ast::Param::Sink(spread) => params.push(Param::Sink(spread.name())), - ast::Param::Placeholder(_) => params.push(Param::Placeholder), } } -- cgit v1.2.3