diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-02-24 21:29:32 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-02-24 21:29:32 +0100 |
| commit | f084165eabbb8ad1b8e8969078fce89070ab4d96 (patch) | |
| tree | 6003822cc646ecf0ba6a3070c87ab283503a4c3b /src/eval | |
| parent | dae3dad5407e49715736a2a3d8735e65027e6c11 (diff) | |
While loops 🔁
Diffstat (limited to 'src/eval')
| -rw-r--r-- | src/eval/mod.rs | 58 | ||||
| -rw-r--r-- | src/eval/value.rs | 6 |
2 files changed, 51 insertions, 13 deletions
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 } |
