use polydat::ast::Value;
use crate::wires::WireSource;
pub const UNTIL_BINDING: &str = "__poll_until";
pub fn is_truthy(value: &Value) -> bool {
match value {
Value::None => false,
Value::U64(v) => *v != 0,
Value::F64(v) => *v != 0.0,
Value::Bool(v) => *v,
Value::Str(s) => !s.is_empty(),
_ => true,
}
}
pub fn holds(wires: &dyn WireSource, binding: &str) -> Option<bool> {
wires.get(binding).map(|v| is_truthy(&v))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn falsy_values_are_exactly_none_zero_false_and_empty() {
assert!(!is_truthy(&Value::None));
assert!(!is_truthy(&Value::U64(0)));
assert!(!is_truthy(&Value::F64(0.0)));
assert!(!is_truthy(&Value::Bool(false)));
assert!(!is_truthy(&Value::Str(String::new().into())));
}
#[test]
fn everything_else_is_truthy() {
assert!(is_truthy(&Value::U64(1)));
assert!(is_truthy(&Value::F64(-0.5)));
assert!(is_truthy(&Value::Bool(true)));
assert!(is_truthy(&Value::Str("no".to_string().into())));
}
#[test]
fn an_unresolved_binding_is_distinguishable_from_false() {
struct OnlyX(bool);
impl WireSource for OnlyX {
fn get(&self, name: &str) -> Option<Value> {
(name == "x").then(|| Value::Bool(self.0))
}
fn names(&self) -> Box<dyn Iterator<Item = String> + '_> {
Box::new(std::iter::once("x".to_string()))
}
}
assert_eq!(holds(&OnlyX(false), "x"), Some(false));
assert_eq!(holds(&OnlyX(true), "x"), Some(true));
assert_eq!(holds(&OnlyX(true), "missing"), None);
}
}