use super::{BinaryOperator, ComprehensionOp, Expr, Literal, UnaryOperator};
pub fn ident(name: &str) -> Expr {
Expr::Identifier(name.to_string())
}
pub fn lit(val: impl Into<Literal>) -> Expr {
Expr::Literal(val.into())
}
pub fn null() -> Expr {
Expr::Literal(Literal::Null)
}
pub fn list(elements: Vec<Expr>) -> Expr {
Expr::List { elements }
}
pub fn map(entries: Vec<(Expr, Expr)>) -> Expr {
Expr::MapLiteral { entries }
}
pub fn not(operand: impl Into<Expr>) -> Expr {
Expr::UnaryOp {
op: UnaryOperator::Not,
operand: Box::new(operand.into()),
}
}
pub fn neg(operand: impl Into<Expr>) -> Expr {
Expr::UnaryOp {
op: UnaryOperator::Neg,
operand: Box::new(operand.into()),
}
}
macro_rules! define_binary_op {
($name:ident, $op:expr) => {
#[doc = concat!("Creates an `Expr::BinaryOp` node with the `", stringify!($op), "` operator.")]
pub fn $name(left: impl Into<Expr>, right: impl Into<Expr>) -> Expr {
Expr::BinaryOp {
op: $op,
left: Box::new(left.into()),
right: Box::new(right.into()),
}
}
};
}
define_binary_op!(add, BinaryOperator::Add);
define_binary_op!(sub, BinaryOperator::Sub);
define_binary_op!(mul, BinaryOperator::Mul);
define_binary_op!(div, BinaryOperator::Div);
define_binary_op!(rem, BinaryOperator::Rem);
define_binary_op!(eq, BinaryOperator::Eq);
define_binary_op!(ne, BinaryOperator::Ne);
define_binary_op!(lt, BinaryOperator::Lt);
define_binary_op!(le, BinaryOperator::Le);
define_binary_op!(gt, BinaryOperator::Gt);
define_binary_op!(ge, BinaryOperator::Ge);
define_binary_op!(and, BinaryOperator::And);
define_binary_op!(or, BinaryOperator::Or);
define_binary_op!(r#in, BinaryOperator::In);
pub fn field_access(base: impl Into<Expr>, field: &str) -> Expr {
Expr::FieldAccess {
base: Box::new(base.into()),
field: field.to_string(),
}
}
pub fn index(base: impl Into<Expr>, index: impl Into<Expr>) -> Expr {
Expr::Index {
base: Box::new(base.into()),
index: Box::new(index.into()),
}
}
pub fn call(target: impl Into<Expr>, args: Vec<Expr>) -> Expr {
Expr::Call {
target: Box::new(target.into()),
args,
}
}
pub fn conditional(
cond: impl Into<Expr>,
true_branch: impl Into<Expr>,
false_branch: impl Into<Expr>,
) -> Expr {
Expr::Conditional {
cond: Box::new(cond.into()),
true_branch: Box::new(true_branch.into()),
false_branch: Box::new(false_branch.into()),
}
}
pub fn has(target: impl Into<Expr>) -> Expr {
Expr::Has {
target: Box::new(target.into()),
}
}
pub fn comprehension(
op: ComprehensionOp,
target: impl Into<Expr>,
iter_var: &str,
predicate: impl Into<Expr>,
) -> Expr {
Expr::Comprehension {
op,
target: Box::new(target.into()),
iter_var: iter_var.to_string(),
predicate: Box::new(predicate.into()),
}
}
pub fn map_macro(
target: impl Into<Expr>,
iter_var: &str,
filter: Option<impl Into<Expr>>,
transform: impl Into<Expr>,
) -> Expr {
let filter_box = filter.map(|f| Box::new(f.into()));
Expr::Map {
target: Box::new(target.into()),
iter_var: iter_var.to_string(),
filter: filter_box,
transform: Box::new(transform.into()),
}
}