feat(argus): add Display trait for Expr
This commit is contained in:
parent
4f33300d1c
commit
3880356c66
5 changed files with 72 additions and 29 deletions
|
|
@ -16,6 +16,7 @@ derive_more = "0.99.17"
|
|||
enum_dispatch = "0.3.12"
|
||||
hashbrown = "0.14.1"
|
||||
itertools = "0.11"
|
||||
log = "0.4.20"
|
||||
num-traits = "0.2.16"
|
||||
paste = "1.0.14"
|
||||
proptest = { version = "1.2", optional = true }
|
||||
|
|
@ -24,6 +25,7 @@ thiserror = "1.0.47"
|
|||
[dev-dependencies]
|
||||
proptest = "1.2"
|
||||
argus = { path = ".", features = ["arbitrary"] }
|
||||
env_logger = "0.10.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ use argus::parse_str;
|
|||
use ariadne::{sources, Color, Label, Report, ReportKind};
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
let src = env::args().nth(1).expect("Expected expression");
|
||||
|
||||
match parse_str(&src) {
|
||||
Ok(expr) => println!("{:#?}", expr),
|
||||
Ok(expr) => println!("{}", expr),
|
||||
Err(errs) => {
|
||||
errs.into_iter().for_each(|e| {
|
||||
Report::build(ReportKind::Error, src.clone(), e.span().start)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ pub trait IsNumExpr: AnyExpr + Into<NumExpr> {}
|
|||
pub trait IsBoolExpr: AnyExpr + Into<BoolExpr> {}
|
||||
|
||||
/// All expressions that are numeric
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
#[enum_dispatch(AnyExpr)]
|
||||
pub enum NumExpr {
|
||||
/// A signed integer literal
|
||||
|
|
@ -73,7 +73,7 @@ impl NumExpr {
|
|||
}
|
||||
|
||||
/// All expressions that are evaluated to be of type `bool`
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[enum_dispatch(AnyExpr)]
|
||||
pub enum BoolExpr {
|
||||
/// A `bool` literal
|
||||
|
|
@ -139,7 +139,7 @@ pub enum ExprRef<'a> {
|
|||
}
|
||||
|
||||
/// An expression (either [`BoolExpr`] or [`NumExpr`])
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, derive_more::Display)]
|
||||
#[enum_dispatch(AnyExpr)]
|
||||
pub enum Expr {
|
||||
/// A reference to a [`BoolExpr`]
|
||||
|
|
|
|||
|
|
@ -1,23 +1,28 @@
|
|||
//! Boolean expression types
|
||||
|
||||
use std::ops::{Bound, RangeBounds};
|
||||
use std::time::Duration;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
use super::{AnyExpr, BoolExpr, NumExpr};
|
||||
|
||||
/// Types of comparison operations
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, derive_more::Display)]
|
||||
pub enum Ordering {
|
||||
/// Equality check for two expressions
|
||||
#[display(fmt = "==")]
|
||||
Eq,
|
||||
/// Non-equality check for two expressions
|
||||
#[display(fmt = "!=")]
|
||||
NotEq,
|
||||
/// Less than check
|
||||
#[display(fmt = "{}", r#"if *strict { "<".to_string() } else { "<=".to_string() } "#r)]
|
||||
Less {
|
||||
/// Denotes `lhs < rhs` if `strict`, and `lhs <= rhs` otherwise.
|
||||
strict: bool,
|
||||
},
|
||||
/// Greater than check
|
||||
#[display(fmt = "{}", r#"if *strict { ">".to_string() } else { ">=".to_string() } "#r)]
|
||||
Greater {
|
||||
/// Denotes `lhs > rhs` if `strict`, and `lhs >= rhs` otherwise.
|
||||
strict: bool,
|
||||
|
|
@ -66,6 +71,21 @@ pub struct Interval {
|
|||
pub end: Bound<Duration>,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for Interval {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let start_str = match self.start {
|
||||
Bound::Included(b) | Bound::Excluded(b) => b.as_secs_f64().to_string(),
|
||||
Bound::Unbounded => "".to_string(),
|
||||
};
|
||||
|
||||
let end_str = match self.end {
|
||||
Bound::Included(b) | Bound::Excluded(b) => b.as_secs_f64().to_string(),
|
||||
Bound::Unbounded => "".to_string(),
|
||||
};
|
||||
write!(f, "[{}, {}]", start_str, end_str)
|
||||
}
|
||||
}
|
||||
|
||||
impl Interval {
|
||||
/// Create a new interval
|
||||
///
|
||||
|
|
@ -174,13 +194,14 @@ macro_rules! impl_bool_expr {
|
|||
}
|
||||
|
||||
/// A `bool` literal
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
pub struct BoolLit(pub bool);
|
||||
|
||||
impl_bool_expr!(BoolLit);
|
||||
|
||||
/// A `bool` variable
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[display(fmt = "{}", name)]
|
||||
pub struct BoolVar {
|
||||
/// Variable name
|
||||
pub name: String,
|
||||
|
|
@ -189,7 +210,8 @@ pub struct BoolVar {
|
|||
impl_bool_expr!(BoolVar);
|
||||
|
||||
/// A comparison expression
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[display(fmt = "{} {} {}", lhs, op, rhs)]
|
||||
pub struct Cmp {
|
||||
/// The type of comparison
|
||||
pub op: Ordering,
|
||||
|
|
@ -202,7 +224,8 @@ pub struct Cmp {
|
|||
impl_bool_expr!(Cmp, lhs, rhs);
|
||||
|
||||
/// Logical negation of an expression
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[display(fmt = "!({})", arg)]
|
||||
pub struct Not {
|
||||
/// Expression to be negated
|
||||
pub arg: Box<BoolExpr>,
|
||||
|
|
@ -211,7 +234,8 @@ pub struct Not {
|
|||
impl_bool_expr!(Not, arg);
|
||||
|
||||
/// Logical conjunction of a list of expressions
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[display(fmt = "({})", r#"args.iter().map(ToString::to_string).join(") && (")"#r)]
|
||||
pub struct And {
|
||||
/// Expressions to be "and"-ed
|
||||
pub args: Vec<BoolExpr>,
|
||||
|
|
@ -220,7 +244,8 @@ pub struct And {
|
|||
impl_bool_expr!(And, [args]);
|
||||
|
||||
/// Logical disjunction of a list of expressions
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[display(fmt = "({})", r#"args.iter().map(ToString::to_string).join(") || (")"#r)]
|
||||
pub struct Or {
|
||||
/// Expressions to be "or"-ed
|
||||
pub args: Vec<BoolExpr>,
|
||||
|
|
@ -231,7 +256,8 @@ impl_bool_expr!(Or, [args]);
|
|||
/// A temporal next expression
|
||||
///
|
||||
/// Checks if the next time point in a signal is `true` or not.
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[display(fmt = "X ({})", arg)]
|
||||
pub struct Next {
|
||||
/// Argument for `Next`
|
||||
pub arg: Box<BoolExpr>,
|
||||
|
|
@ -242,7 +268,8 @@ impl_bool_expr!(Next, arg);
|
|||
///
|
||||
/// This is equivalent to `steps` number of nested [`Next`](BoolExpr::Next)
|
||||
/// expressions.
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[display(fmt = "X[0,{}]({})", steps, arg)]
|
||||
pub struct Oracle {
|
||||
/// Number of steps to look ahead
|
||||
pub steps: usize,
|
||||
|
|
@ -256,7 +283,8 @@ impl_bool_expr!(Oracle, arg);
|
|||
/// - If the `interval` is `(Unbounded, Unbounded)` or equivalent to `(0, Unbounded)`:
|
||||
/// checks if the signal is `true` for all points in a signal.
|
||||
/// - Otherwise: checks if the signal is `true` for all points within the `interval`.
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[display(fmt = "G{}({})", interval, arg)]
|
||||
pub struct Always {
|
||||
/// Argument for `Always`
|
||||
pub arg: Box<BoolExpr>,
|
||||
|
|
@ -270,7 +298,8 @@ impl_bool_expr!(Always, arg);
|
|||
/// - If the `interval` is `(Unbounded, Unbounded)` or equivalent to `(0, Unbounded)`:
|
||||
/// checks if the signal is `true` for some point in a signal.
|
||||
/// - Otherwise: checks if the signal is `true` for some point within the `interval`.
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[display(fmt = "F{}({})", interval, arg)]
|
||||
pub struct Eventually {
|
||||
/// Argument for `Eventually`
|
||||
pub arg: Box<BoolExpr>,
|
||||
|
|
@ -282,7 +311,8 @@ impl_bool_expr!(Eventually, arg);
|
|||
/// A temporal until expression
|
||||
///
|
||||
/// Checks if the `lhs` is always `true` for a signal until `rhs` becomes `true`.
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::BoolExpr, derive_more::Display)]
|
||||
#[display(fmt = "({}) U{} ({})", lhs, interval, rhs)]
|
||||
pub struct Until {
|
||||
/// LHS to `lhs Until rhs`
|
||||
pub lhs: Box<BoolExpr>,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
//! Numeric expression types
|
||||
use itertools::Itertools;
|
||||
|
||||
use super::{AnyExpr, NumExpr};
|
||||
|
||||
|
|
@ -37,22 +38,23 @@ macro_rules! impl_num_expr {
|
|||
}
|
||||
|
||||
/// A signed integer literal
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
pub struct IntLit(pub i64);
|
||||
impl_num_expr!(IntLit);
|
||||
|
||||
/// An unsigned integer literal
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
pub struct UIntLit(pub u64);
|
||||
impl_num_expr!(UIntLit);
|
||||
|
||||
/// A floating point literal
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
pub struct FloatLit(pub f64);
|
||||
impl_num_expr!(FloatLit);
|
||||
|
||||
/// A signed integer variable
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
#[display(fmt = "{}", name)]
|
||||
pub struct IntVar {
|
||||
/// Name of the variable
|
||||
pub name: String,
|
||||
|
|
@ -60,7 +62,8 @@ pub struct IntVar {
|
|||
impl_num_expr!(IntVar);
|
||||
|
||||
/// A unsigned integer variable
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
#[display(fmt = "{}", name)]
|
||||
pub struct UIntVar {
|
||||
/// Name of the variable
|
||||
pub name: String,
|
||||
|
|
@ -68,7 +71,8 @@ pub struct UIntVar {
|
|||
impl_num_expr!(UIntVar);
|
||||
|
||||
/// A floating point number variable
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
#[display(fmt = "{}", name)]
|
||||
pub struct FloatVar {
|
||||
/// Name of the variable
|
||||
pub name: String,
|
||||
|
|
@ -76,7 +80,8 @@ pub struct FloatVar {
|
|||
impl_num_expr!(FloatVar);
|
||||
|
||||
/// Numeric negation of a numeric expression
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
#[display(fmt = "-({})", arg)]
|
||||
pub struct Neg {
|
||||
/// Numeric expression being negated
|
||||
pub arg: Box<NumExpr>,
|
||||
|
|
@ -84,7 +89,8 @@ pub struct Neg {
|
|||
impl_num_expr!(Neg, arg);
|
||||
|
||||
/// Arithmetic addition of a list of numeric expressions
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
#[display(fmt = "({})", r#"args.iter().map(ToString::to_string).join(" + ")"#r)]
|
||||
pub struct Add {
|
||||
/// List of expressions being added
|
||||
pub args: Vec<NumExpr>,
|
||||
|
|
@ -92,7 +98,8 @@ pub struct Add {
|
|||
impl_num_expr!(Add, [args]);
|
||||
|
||||
/// Subtraction of two numbers
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
#[display(fmt = "({} - {})", lhs, rhs)]
|
||||
pub struct Sub {
|
||||
/// LHS to the expression `lhs - rhs`
|
||||
pub lhs: Box<NumExpr>,
|
||||
|
|
@ -102,7 +109,8 @@ pub struct Sub {
|
|||
impl_num_expr!(Sub, lhs, rhs);
|
||||
|
||||
/// Arithmetic multiplication of a list of numeric expressions
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
#[display(fmt = "({})", r#"args.iter().map(ToString::to_string).join(" * ")"#r)]
|
||||
pub struct Mul {
|
||||
/// List of expressions being multiplied
|
||||
pub args: Vec<NumExpr>,
|
||||
|
|
@ -110,7 +118,8 @@ pub struct Mul {
|
|||
impl_num_expr!(Mul, [args]);
|
||||
|
||||
/// Divide two expressions `dividend / divisor`
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
#[display(fmt = "({} / {})", dividend, divisor)]
|
||||
pub struct Div {
|
||||
/// The dividend
|
||||
pub dividend: Box<NumExpr>,
|
||||
|
|
@ -120,7 +129,8 @@ pub struct Div {
|
|||
impl_num_expr!(Div, dividend, divisor);
|
||||
|
||||
/// The absolute value of an expression
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr)]
|
||||
#[derive(Clone, Debug, PartialEq, argus_derive::NumExpr, derive_more::Display)]
|
||||
#[display(fmt = "abs({})", arg)]
|
||||
pub struct Abs {
|
||||
/// Argument to `abs`
|
||||
pub arg: Box<NumExpr>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue