#[macro_use]
extern crate quote;
use syn::parse_str;
use std::collections::{BTreeMap, HashMap};
mod reflect;
pub use self::reflect::{eval, Value};
pub struct Eval(HashMap<String, syn::Expr>);
impl Default for Eval {
fn default() -> Self {
Self(HashMap::new())
}
}
impl Eval {
pub fn new(c: HashMap<String, syn::Expr>) -> Self {
Self(c)
}
pub fn insert(mut self, k: &str, v: &str) -> Result<Self, ()> {
let e = parse_str::<syn::Expr>(v).map_err(|_| ())?;
self.0.insert(k.to_owned(), e);
Ok(self)
}
pub fn remove(mut self, k: &str) -> Self {
self.0.remove(k);
self
}
pub fn eval(&self, src: &str) -> Option<Value> {
parse_str::<syn::Expr>(src)
.ok()
.map_or(None, |src| eval(&ctx_as_ref(&self.0), &src))
}
}
pub fn ctx_as_ref(ctx: &HashMap<String, syn::Expr>) -> BTreeMap<&str, &syn::Expr> {
let mut b: BTreeMap<&str, &syn::Expr> = BTreeMap::new();
for (k, v) in ctx {
b.insert(k, v);
}
b
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() -> Result<(), ()> {
let e = Eval::default().insert("foo", "1")?.insert("bar", "0")?;
assert_eq!(e.eval("foo + bar").unwrap(), 1.0);
assert_eq!(e.eval("foo - bar * 1").unwrap(), 1.0);
assert_eq!(e.eval("1 + bar").unwrap(), 1.0);
Ok(())
}
}