diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-01-30 16:26:21 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-01-30 16:26:44 +0100 |
| commit | bcb2c46a10caa63378725f58e866e54faf4122cf (patch) | |
| tree | 3ba5769e910a12bf7607ad48baaf46cd304c1f5c /src/eval/mod.rs | |
| parent | 5943f552e512f940d4b76055d51215c23420f03a (diff) | |
Scoped for loop bindings 🏔️
Previously for loop bindings were leaked until after the loop.
Diffstat (limited to 'src/eval/mod.rs')
| -rw-r--r-- | src/eval/mod.rs | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 996c908c..a43219e7 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -410,11 +410,10 @@ impl Eval for Spanned<&ExprFor> { type Output = Value; fn eval(self, ctx: &mut EvalContext) -> Self::Output { - let iter = self.v.iter.eval(ctx); - let mut output = vec![]; - macro_rules! iterate { - (for ($($binding:ident => $value:ident),*) in $iter:expr) => { + (for ($($binding:ident => $value:ident),*) in $iter:expr) => {{ + let mut output = vec![]; + #[allow(unused_parens)] for ($($value),*) in $iter { $(ctx.scopes.def_mut($binding.as_str(), $value);)* @@ -424,37 +423,45 @@ impl Eval for Spanned<&ExprFor> { } } - return Value::Template(output); - }; + Value::Template(output) + }}; } - match (self.v.pat.v.clone(), iter) { + ctx.scopes.push(); + + let iter = self.v.iter.eval(ctx); + let value = match (self.v.pat.v.clone(), iter) { (ForPattern::Value(v), Value::Str(string)) => { - iterate!(for (v => value) in string.chars().map(|c| Value::Str(c.into()))); + iterate!(for (v => value) in string.chars().map(|c| Value::Str(c.into()))) } (ForPattern::Value(v), Value::Array(array)) => { - iterate!(for (v => value) in array.into_iter()); + iterate!(for (v => value) in array.into_iter()) } (ForPattern::Value(v), Value::Dict(dict)) => { - iterate!(for (v => value) in dict.into_iter().map(|p| p.1)); + iterate!(for (v => value) in dict.into_iter().map(|p| p.1)) } (ForPattern::KeyValue(k, v), Value::Dict(dict)) => { - iterate!(for (k => key, v => value) in dict.into_iter()); + iterate!(for (k => key, v => value) in dict.into_iter()) } (ForPattern::KeyValue(..), Value::Str(_)) | (ForPattern::KeyValue(..), Value::Array(_)) => { ctx.diag(error!(self.v.pat.span, "mismatched pattern")); + Value::Error } - (_, Value::Error) => {} - (_, iter) => ctx.diag(error!( - self.v.iter.span, - "cannot loop over {}", - iter.type_name(), - )), - } + (_, Value::Error) => Value::Error, + (_, iter) => { + ctx.diag(error!( + self.v.iter.span, + "cannot loop over {}", + iter.type_name(), + )); + Value::Error + } + }; - Value::Error + ctx.scopes.pop(); + value } } |
