summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/func.rs29
-rw-r--r--src/eval/mod.rs5
2 files changed, 19 insertions, 15 deletions
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<Ident>),
- /// 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::<Value>(ident)?);
- }
+ Param::Pos(pattern) => match pattern {
+ ast::Pattern::Normal(ast::Expr::Ident(ident)) => {
+ vm.define(ident.clone(), args.expect::<Value>(ident)?)
+ }
+ ast::Pattern::Normal(_) => unreachable!(),
+ _ => {
+ pattern.define(
+ &mut vm,
+ args.expect::<Value>("pattern parameter")?,
+ )?;
+ }
+ },
Param::Sink(ident) => {
sink = ident.clone();
if let Some(sink_size) = sink_size {
@@ -344,9 +351,6 @@ impl Closure {
args.named::<Value>(ident)?.unwrap_or_else(|| default.clone());
vm.define(ident.clone(), value);
}
- Param::Placeholder => {
- args.eat::<Value>()?;
- }
}
}
@@ -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),
}
}