#[macro_export]
macro_rules! fact {
($predicate:expr, $($args:tt)*) => {{
let mut args = vec![];
$crate::push_values!(args; $($args)+);
$crate::Fact {
predicate: $predicate.to_owned(),
args,
}
}};
}
#[macro_export]
macro_rules! value {
($lit:literal) => {
$crate::Value::from($lit)
};
($type_:ident { $id:expr }) => {
$crate::Value::new(stringify!($type_), $id)
};
($val:expr) => {
$crate::Value::from($val)
};
}
#[macro_export]
macro_rules! push_values {
($args:expr; $str:literal) => {{
$args.push($crate::value!($str));
}};
($args:expr; $type_:ident { $id:expr }) => {{
$args.push($crate::value!($type_ { $id }));
}};
($args:expr; $str:literal, $($rest:tt)*) => {{
$args.push($crate::value!($str));
$crate::push_values!($args; $($rest)*);
}};
($args:expr; $type_:ident { $id:expr }, $($rest:tt)*) => {{
$args.push($crate::value!($type_ { $id }));
$crate::push_values!($args; $($rest)*);
}};
($args:expr; $val:expr) => {{
$args.push($crate::value!($val));
}};
($args:expr; $val:expr, $($rest:tt)*) => {{
$args.push($crate::value!($val));
$crate::push_values!($args; $($rest)*);
}};
}
#[cfg(test)]
mod test {
use crate::{
polar_ast::{PRIMITIVE_BOOLEAN_SYMBOL, PRIMITIVE_INTEGER_SYMBOL, PRIMITIVE_STRING_SYMBOL},
Fact, Value,
};
#[test]
fn test_macro_expansion() {
let bool_val = value!(true);
assert_eq!(bool_val, Value::new(PRIMITIVE_BOOLEAN_SYMBOL, "true"));
let string_val = value!("foo");
assert_eq!(string_val, Value::new(PRIMITIVE_STRING_SYMBOL, "foo"));
let int_val = value!(42);
assert_eq!(int_val, Value::new(PRIMITIVE_INTEGER_SYMBOL, "42"));
let literal_val = value!(Foo { "bar" });
assert_eq!(literal_val, Value::new("Foo", "bar"));
let fact = fact!("foo", "bar", 42, true, Foo { "bar" });
assert_eq!(
fact,
Fact {
predicate: "foo".to_string(),
args: vec![
Value::new(PRIMITIVE_STRING_SYMBOL, "bar"),
Value::new(PRIMITIVE_INTEGER_SYMBOL, "42"),
Value::new(PRIMITIVE_BOOLEAN_SYMBOL, "true"),
Value::new("Foo", "bar"),
],
}
);
}
}