From f084165eabbb8ad1b8e8969078fce89070ab4d96 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 24 Feb 2021 21:29:32 +0100 Subject: =?UTF-8?q?While=20loops=20=F0=9F=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/eval/mod.rs | 58 +++++++++++++++++++++++++++++++++++++++++++------------ src/eval/value.rs | 6 +++++- 2 files changed, 51 insertions(+), 13 deletions(-) (limited to 'src/eval') diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 596ceb50..3cf97860 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -118,6 +118,7 @@ impl Eval for Expr { Self::Binary(v) => v.eval(ctx), Self::Let(v) => v.eval(ctx), Self::If(v) => v.eval(ctx), + Self::While(v) => v.eval(ctx), Self::For(v) => v.eval(ctx), } } @@ -403,24 +404,56 @@ impl Eval for ExprIf { fn eval(&self, ctx: &mut EvalContext) -> Self::Output { let condition = self.condition.eval(ctx); - - if let Value::Bool(boolean) = condition { - return if boolean { + if let Value::Bool(condition) = condition { + if condition { self.if_body.eval(ctx) } else if let Some(expr) = &self.else_body { expr.eval(ctx) } else { Value::None - }; - } else if condition != Value::Error { - ctx.diag(error!( - self.condition.span(), - "expected boolean, found {}", - condition.type_name(), - )); + } + } else { + if condition != Value::Error { + ctx.diag(error!( + self.condition.span(), + "expected boolean, found {}", + condition.type_name(), + )); + } + Value::Error } + } +} - Value::Error +impl Eval for ExprWhile { + type Output = Value; + + fn eval(&self, ctx: &mut EvalContext) -> Self::Output { + let mut output = vec![]; + loop { + let condition = self.condition.eval(ctx); + if let Value::Bool(condition) = condition { + if condition { + match self.body.eval(ctx) { + Value::Template(v) => output.extend(v), + Value::Str(v) => output.push(TemplateNode::Str(v)), + Value::Error => return Value::Error, + _ => {} + } + } else { + return Value::Template(output); + } + } else { + if condition != Value::Error { + ctx.diag(error!( + self.condition.span(), + "expected boolean, found {}", + condition.type_name(), + )); + } + return Value::Error; + } + } } } @@ -438,7 +471,8 @@ impl Eval for ExprFor { $(ctx.scopes.def_mut($binding.as_str(), $value);)* match self.body.eval(ctx) { - Value::Template(new) => output.extend(new), + Value::Template(v) => output.extend(v), + Value::Str(v) => output.push(TemplateNode::Str(v)), Value::Error => { ctx.scopes.pop(); return Value::Error; diff --git a/src/eval/value.rs b/src/eval/value.rs index 2a91cf8a..d910155a 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -586,7 +586,11 @@ primitive! { Color: "color", Value::Color } primitive! { String: "string", Value::Str } primitive! { ValueArray: "array", Value::Array } primitive! { ValueDict: "dictionary", Value::Dict } -primitive! { ValueTemplate: "template", Value::Template } +primitive! { + ValueTemplate: "template", + Value::Template, + Value::Str(v) => vec![TemplateNode::Str(v)], +} primitive! { ValueFunc: "function", Value::Func } primitive! { ValueArgs: "arguments", Value::Args } -- cgit v1.2.3