feat: implement an Expr trait
This commit is contained in:
parent
afe265eba2
commit
55894d55fb
2 changed files with 85 additions and 0 deletions
|
|
@ -4,9 +4,11 @@ mod bool_ops;
|
|||
mod internal_macros;
|
||||
pub mod iter;
|
||||
mod num_ops;
|
||||
mod traits;
|
||||
|
||||
pub use bool_ops::*;
|
||||
pub use num_ops::*;
|
||||
pub use traits::*;
|
||||
|
||||
use crate::{ArgusResult, Error};
|
||||
|
||||
|
|
@ -26,6 +28,21 @@ pub enum NumExpr {
|
|||
Div { dividend: Box<NumExpr>, divisor: Box<NumExpr> },
|
||||
}
|
||||
|
||||
impl Expr for NumExpr {
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn args(&self) -> Vec<&dyn Expr> {
|
||||
match self {
|
||||
NumExpr::Neg { arg } => vec![arg.as_ref()],
|
||||
NumExpr::Add { args } | NumExpr::Mul { args } => args.iter().map(|arg| arg as &dyn Expr).collect(),
|
||||
NumExpr::Div { dividend, divisor } => vec![dividend.as_ref(), divisor.as_ref()],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Types of comparison operations
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Ordering {
|
||||
|
|
@ -46,6 +63,21 @@ pub enum BoolExpr {
|
|||
Or { args: Vec<BoolExpr> },
|
||||
}
|
||||
|
||||
impl Expr for BoolExpr {
|
||||
fn args(&self) -> Vec<&dyn Expr> {
|
||||
match self {
|
||||
BoolExpr::Cmp { op: _, lhs, rhs } => vec![lhs.as_ref(), rhs.as_ref()],
|
||||
BoolExpr::Not { arg } => vec![arg.as_ref()],
|
||||
BoolExpr::And { args } | BoolExpr::Or { args } => args.iter().map(|arg| arg as &dyn Expr).collect(),
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Expression builder
|
||||
///
|
||||
/// The `ExprBuilder` is a factory structure that deals with the creation of
|
||||
|
|
|
|||
53
argus-core/src/expr/traits.rs
Normal file
53
argus-core/src/expr/traits.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use std::any::Any;
|
||||
|
||||
use super::iter::AstIter;
|
||||
|
||||
/// A trait representing expressions
|
||||
pub trait Expr {
|
||||
fn args(&self) -> Vec<&dyn Expr>;
|
||||
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
|
||||
fn iter(&self) -> AstIter<'_>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
AstIter::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn Expr {
|
||||
pub fn downcast_expr_ref<T>(&self) -> Option<&T>
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
self.as_any().downcast_ref::<T>()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::{arbitrary, BoolExpr, NumExpr};
|
||||
use super::*;
|
||||
use proptest::prelude::*;
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn downcast_expr_bool(bool_expr in arbitrary::bool_expr()) {
|
||||
let expr_ref = bool_expr.as_ref() as &dyn Expr;
|
||||
|
||||
let downcast_ref = expr_ref.downcast_expr_ref::<BoolExpr>().unwrap();
|
||||
assert_eq!(downcast_ref, bool_expr.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn downcast_expr_num(num_expr in arbitrary::num_expr()) {
|
||||
let expr_ref = num_expr.as_ref() as &dyn Expr;
|
||||
|
||||
let downcast_ref = expr_ref.downcast_expr_ref::<NumExpr>().unwrap();
|
||||
assert_eq!(downcast_ref, num_expr.as_ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue