From fe4bb1c9d72a82b9392e333c273d3d36a33b0c6c Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Mon, 26 Nov 2018 23:03:11 -0600 Subject: [PATCH] FEATURE: allow tuples to have true or false as field names. this allows selects where the condiotion is a boolean and you can choose the true or false branch. --- docsite/site/content/reference/expressions.md | 12 +++++++++--- integration_tests/select_expressions_test.ucg | 9 +++++++++ src/build/mod.rs | 11 +++++++++++ src/parse/mod.rs | 2 +- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/docsite/site/content/reference/expressions.md b/docsite/site/content/reference/expressions.md index 716d473..73cafd4 100644 --- a/docsite/site/content/reference/expressions.md +++ b/docsite/site/content/reference/expressions.md @@ -212,9 +212,10 @@ Conditionals UCG supports a limited conditional expression called a select. A select expression starts with the `select` keyword and is followed by a an expression -resolving to a string naming the field to select, an expression resolving to -the default value, and finally a tuple literal to select the field from. If the -field selected is not in the tuple then the default value will be used. +resolving to a string or boolean naming the field to select, an expression +resolving to the default value, and finally a tuple literal to select the field +from. If the field selected is not in the tuple then the default value will be +used. ``` let want = "baz"; @@ -230,6 +231,11 @@ select "quack", "quux", { baz = "foo", fuzz = "bang", }; // result will be "quux" + +let ifresult = select true, NULL, { + true = "true result", + false = "false result", +}; // result will be "true result" ``` Macros diff --git a/integration_tests/select_expressions_test.ucg b/integration_tests/select_expressions_test.ucg index f49b9cd..6856e9e 100644 --- a/integration_tests/select_expressions_test.ucg +++ b/integration_tests/select_expressions_test.ucg @@ -37,4 +37,13 @@ assert | |; assert | condmacro("invalid") == {output = NULL}; +|; + +let iflike = select true, "default", { + true = "I was true", + false = "I was false", +}; + +assert | + iflike == "I was true"; |; \ No newline at end of file diff --git a/src/build/mod.rs b/src/build/mod.rs index da428de..79fe2c5 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -1132,6 +1132,17 @@ impl<'a> Builder<'a> { } // Otherwise return the default. return self.eval_expr(def_expr); + } else if let &Val::Boolean(b) = v.deref() { + for &(ref fname, ref val_expr) in fields.iter() { + if &fname.fragment == "true" && b { + // Fourth return the result of evaluating that field. + return self.eval_expr(val_expr); + } else if &fname.fragment == "false" && !b { + return self.eval_expr(val_expr); + } + } + // Otherwise return the default. + return self.eval_expr(def_expr); } else { return Err(Box::new(error::BuildError::new( format!( diff --git a/src/parse/mod.rs b/src/parse/mod.rs index fdc0bf0..6e1a984 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -301,7 +301,7 @@ make_fn!( make_fn!( field_value, (Token, Expression)>, do_each!( - field => wrap_err!(either!(match_type!(BAREWORD), match_type!(STR)), + field => wrap_err!(either!(match_type!(BOOLEAN), match_type!(BAREWORD), match_type!(STR)), "Field names must be a bareword or a string."), _ => punct!("="), value => expression,