Make some operators lazily evaluated (#627)
* Make some operators lazily evaluated Fixes #624 * Add to CHANGELOG.md
This commit is contained in:
parent
678e4dbc6b
commit
3ae34602eb
2 changed files with 33 additions and 21 deletions
|
@ -8,6 +8,7 @@ All notable changes to eww will be listed here, starting at changes since versio
|
|||
### Features
|
||||
- Add support for safe access (`?.`) in simplexpr (By: oldwomanjosiah)
|
||||
- Allow floating-point numbers in percentages for window-geometry
|
||||
- Made `and`, `or` and `?:` lazily evaluated in simplexpr (By: ModProg)
|
||||
|
||||
## [0.4.0] (04.09.2022)
|
||||
|
||||
|
|
|
@ -179,35 +179,43 @@ impl SimplExpr {
|
|||
}
|
||||
SimplExpr::BinOp(span, a, op, b) => {
|
||||
let a = a.eval(values)?;
|
||||
let b = b.eval(values)?;
|
||||
let b = || b.eval(values);
|
||||
// Lazy operators
|
||||
let dynval = match op {
|
||||
BinOp::Equals => DynVal::from(a == b),
|
||||
BinOp::NotEquals => DynVal::from(a != b),
|
||||
BinOp::And => DynVal::from(a.as_bool()? && b.as_bool()?),
|
||||
BinOp::Or => DynVal::from(a.as_bool()? || b.as_bool()?),
|
||||
BinOp::Plus => match (a.as_f64(), b.as_f64()) {
|
||||
(Ok(a), Ok(b)) => DynVal::from(a + b),
|
||||
_ => DynVal::from(format!("{}{}", a.as_string()?, b.as_string()?)),
|
||||
},
|
||||
BinOp::Minus => DynVal::from(a.as_f64()? - b.as_f64()?),
|
||||
BinOp::Times => DynVal::from(a.as_f64()? * b.as_f64()?),
|
||||
BinOp::Div => DynVal::from(a.as_f64()? / b.as_f64()?),
|
||||
BinOp::Mod => DynVal::from(a.as_f64()? % b.as_f64()?),
|
||||
BinOp::GT => DynVal::from(a.as_f64()? > b.as_f64()?),
|
||||
BinOp::LT => DynVal::from(a.as_f64()? < b.as_f64()?),
|
||||
BinOp::GE => DynVal::from(a.as_f64()? >= b.as_f64()?),
|
||||
BinOp::LE => DynVal::from(a.as_f64()? <= b.as_f64()?),
|
||||
BinOp::And => DynVal::from(a.as_bool()? && b()?.as_bool()?),
|
||||
BinOp::Or => DynVal::from(a.as_bool()? || b()?.as_bool()?),
|
||||
BinOp::Elvis => {
|
||||
let is_null = matches!(serde_json::from_str(&a.0), Ok(serde_json::Value::Null));
|
||||
if a.0.is_empty() || is_null {
|
||||
b
|
||||
b()?
|
||||
} else {
|
||||
a
|
||||
}
|
||||
}
|
||||
BinOp::RegexMatch => {
|
||||
let regex = regex::Regex::new(&b.as_string()?)?;
|
||||
DynVal::from(regex.is_match(&a.as_string()?))
|
||||
// Eager operators
|
||||
_ => {
|
||||
let b = b()?;
|
||||
match op {
|
||||
BinOp::Equals => DynVal::from(a == b),
|
||||
BinOp::NotEquals => DynVal::from(a != b),
|
||||
BinOp::Plus => match (a.as_f64(), b.as_f64()) {
|
||||
(Ok(a), Ok(b)) => DynVal::from(a + b),
|
||||
_ => DynVal::from(format!("{}{}", a.as_string()?, b.as_string()?)),
|
||||
},
|
||||
BinOp::Minus => DynVal::from(a.as_f64()? - b.as_f64()?),
|
||||
BinOp::Times => DynVal::from(a.as_f64()? * b.as_f64()?),
|
||||
BinOp::Div => DynVal::from(a.as_f64()? / b.as_f64()?),
|
||||
BinOp::Mod => DynVal::from(a.as_f64()? % b.as_f64()?),
|
||||
BinOp::GT => DynVal::from(a.as_f64()? > b.as_f64()?),
|
||||
BinOp::LT => DynVal::from(a.as_f64()? < b.as_f64()?),
|
||||
BinOp::GE => DynVal::from(a.as_f64()? >= b.as_f64()?),
|
||||
BinOp::LE => DynVal::from(a.as_f64()? <= b.as_f64()?),
|
||||
BinOp::RegexMatch => {
|
||||
let regex = regex::Regex::new(&b.as_string()?)?;
|
||||
DynVal::from(regex.is_match(&a.as_string()?))
|
||||
}
|
||||
_ => unreachable!("Lazy operators already handled"),
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(dynval.at(*span))
|
||||
|
@ -395,5 +403,8 @@ mod tests {
|
|||
safe_access_to_missing(r#"{ "a": { "b": 2 } }.b?.b"#) => Ok(DynVal::from(&serde_json::Value::Null)),
|
||||
normal_access_to_existing(r#"{ "a": { "b": 2 } }.a.b"#) => Ok(DynVal::from(2)),
|
||||
normal_access_to_missing(r#"{ "a": { "b": 2 } }.b.b"#) => Err(super::EvalError::CannotIndex("null".to_string())),
|
||||
lazy_evaluation_and(r#"false && "null".test"#) => Ok(DynVal::from(false)),
|
||||
lazy_evaluation_or(r#"true || "null".test"#) => Ok(DynVal::from(true)),
|
||||
lazy_evaluation_elvis(r#""test"?: "null".test"#) => Ok(DynVal::from("test")),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue