use super::constants::BUILTIN_CONSTANTS;
use pyisheval::{Interpreter, Value};
pub(crate) fn init_interpreter() -> Interpreter {
let mut interp = Interpreter::new();
for (name, value) in BUILTIN_CONSTANTS {
if let Err(e) = interp.eval(&format!("{} = {}", name, value)) {
log::warn!(
"Could not initialize built-in constant '{}': {}. \
This constant will not be available in expressions.",
name,
e
);
}
}
if let Err(e) = interp.eval("radians = lambda x: x * pi / 180") {
log::warn!(
"Could not define built-in function 'radians': {}. \
This function will not be available in expressions. \
(May be due to missing 'pi' constant)",
e
);
}
if let Err(e) = interp.eval("degrees = lambda x: x * 180 / pi") {
log::warn!(
"Could not define built-in function 'degrees': {}. \
This function will not be available in expressions. \
(May be due to missing 'pi' constant)",
e
);
}
interp
}
#[derive(Debug, thiserror::Error)]
pub enum EvalError {
#[error("Failed to evaluate expression '{expr}': {source}")]
PyishEval {
expr: String,
#[source]
source: pyisheval::EvalError,
},
#[error("Xacro conditional \"{condition}\" evaluated to \"{evaluated}\", which is not a boolean expression.")]
InvalidBoolean {
condition: String,
evaluated: String,
},
}
pub(crate) fn format_value_python_style(
value: &Value,
force_float: bool,
) -> String {
match value {
Value::Number(n) if n.is_finite() => {
const PYTHON_SCIENTIFIC_THRESHOLD: f64 = 1e16;
if n.fract() == 0.0 && n.abs() < PYTHON_SCIENTIFIC_THRESHOLD {
if force_float {
format!("{:.1}", n) } else {
format!("{:.0}", n) }
} else {
n.to_string()
}
}
_ => value.to_string(),
}
}