summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-02-24 21:29:32 +0100
committerLaurenz <laurmaedje@gmail.com>2021-02-24 21:29:32 +0100
commitf084165eabbb8ad1b8e8969078fce89070ab4d96 (patch)
tree6003822cc646ecf0ba6a3070c87ab283503a4c3b /src/eval
parentdae3dad5407e49715736a2a3d8735e65027e6c11 (diff)
While loops 🔁
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/mod.rs58
-rw-r--r--src/eval/value.rs6
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 }