From 58f799c41cb71f167e6e82eb94b3cde1303de11e Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 12 Feb 2021 23:06:04 +0100 Subject: [PATCH] =?UTF-8?q?Early=20quit=20loop=20when=20body=20returns=20e?= =?UTF-8?q?rror=20=F0=9F=9B=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/eval/mod.rs | 38 +++++++++++++++++++------------------ tests/lang/typ/for-loop.typ | 7 +++++++ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 47f997eb4..98030b869 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -429,57 +429,59 @@ impl Eval for ExprFor { fn eval(&self, ctx: &mut EvalContext) -> Self::Output { macro_rules! iter { - (for ($($binding:ident => $value:ident),*) in $iter:expr) => {{ + (for ($($binding:ident => $value:ident),*) in $iter:expr) => { let mut output = vec![]; + ctx.scopes.push(); #[allow(unused_parens)] for ($($value),*) in $iter { $(ctx.scopes.def_mut($binding.as_str(), $value);)* - if let Value::Template(new) = self.body.eval(ctx) { - output.extend(new); + match self.body.eval(ctx) { + Value::Template(new) => output.extend(new), + Value::Error => { + ctx.scopes.pop(); + return Value::Error; + } + _ => {} } } - Value::Template(output) - }}; + ctx.scopes.pop(); + return Value::Template(output); + }; } - ctx.scopes.push(); - let iter = self.iter.eval(ctx); - let value = match (self.pattern.clone(), iter) { + match (self.pattern.clone(), iter) { (ForPattern::Value(v), Value::Str(string)) => { - iter!(for (v => value) in string.chars().map(|c| Value::Str(c.into()))) + iter!(for (v => value) in string.chars().map(|c| Value::Str(c.into()))); } (ForPattern::Value(v), Value::Array(array)) => { - iter!(for (v => value) in array.into_iter()) + iter!(for (v => value) in array.into_iter()); } (ForPattern::Value(v), Value::Dict(dict)) => { - iter!(for (v => value) in dict.into_iter().map(|p| p.1)) + iter!(for (v => value) in dict.into_iter().map(|p| p.1)); } (ForPattern::KeyValue(k, v), Value::Dict(dict)) => { - iter!(for (k => key, v => value) in dict.into_iter()) + iter!(for (k => key, v => value) in dict.into_iter()); } (ForPattern::KeyValue(_, _), Value::Str(_)) | (ForPattern::KeyValue(_, _), Value::Array(_)) => { ctx.diag(error!(self.pattern.span(), "mismatched pattern")); - Value::Error } - (_, Value::Error) => Value::Error, + (_, Value::Error) => {} (_, iter) => { ctx.diag(error!( self.iter.span(), "cannot loop over {}", iter.type_name(), )); - Value::Error } - }; + } - ctx.scopes.pop(); - value + Value::Error } } diff --git a/tests/lang/typ/for-loop.typ b/tests/lang/typ/for-loop.typ index 944cef1ea..2af7ab04b 100644 --- a/tests/lang/typ/for-loop.typ +++ b/tests/lang/typ/for-loop.typ @@ -42,3 +42,10 @@ // Make sure that we don't complain twice. // Error: 12-19 cannot add integer and string #for v #in 1 + "2" {} + +// Error: 14-17 cannot apply '-' to string +#let error = -"" +#let result = #for v #in (1, 2, 3) { + #if v < 2 [Ok] #else {error} +} +#[test result, error]