summaryrefslogtreecommitdiff
path: root/src/eval/func.rs
diff options
context:
space:
mode:
authorMarmare314 <49279081+Marmare314@users.noreply.github.com>2023-04-26 11:32:11 +0200
committerGitHub <noreply@github.com>2023-04-26 11:32:11 +0200
commit59957746e91c1322a8ca6d228bcaa0f31941ee1b (patch)
treed928dea7c99f1d9f17107aac8008b5b7e870d190 /src/eval/func.rs
parent6134e3f4ee5298153c36d344df97f36279931c33 (diff)
Pattern as parameter (#854)
Diffstat (limited to 'src/eval/func.rs')
-rw-r--r--src/eval/func.rs29
1 files changed, 18 insertions, 11 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())
}
- _ => {}
}
}