feat(argus): add Display trait for Expr

This commit is contained in:
Anand Balakrishnan 2023-10-12 16:27:02 -07:00
parent 4f33300d1c
commit 3880356c66
No known key found for this signature in database
5 changed files with 72 additions and 29 deletions

View file

@ -16,6 +16,7 @@ derive_more = "0.99.17"
enum_dispatch = "0.3.12" enum_dispatch = "0.3.12"
hashbrown = "0.14.1" hashbrown = "0.14.1"
itertools = "0.11" itertools = "0.11"
log = "0.4.20"
num-traits = "0.2.16" num-traits = "0.2.16"
paste = "1.0.14" paste = "1.0.14"
proptest = { version = "1.2", optional = true } proptest = { version = "1.2", optional = true }
@ -24,6 +25,7 @@ thiserror = "1.0.47"
[dev-dependencies] [dev-dependencies]
proptest = "1.2" proptest = "1.2"
argus = { path = ".", features = ["arbitrary"] } argus = { path = ".", features = ["arbitrary"] }
env_logger = "0.10.0"
[features] [features]
default = [] default = []

View file

@ -4,10 +4,11 @@ use argus::parse_str;
use ariadne::{sources, Color, Label, Report, ReportKind}; use ariadne::{sources, Color, Label, Report, ReportKind};
fn main() { fn main() {
env_logger::init();
let src = env::args().nth(1).expect("Expected expression"); let src = env::args().nth(1).expect("Expected expression");
match parse_str(&src) { match parse_str(&src) {
Ok(expr) => println!("{:#?}", expr), Ok(expr) => println!("{}", expr),
Err(errs) => { Err(errs) => {
errs.into_iter().for_each(|e| { errs.into_iter().for_each(|e| {
Report::build(ReportKind::Error, src.clone(), e.span().start) Report::build(ReportKind::Error, src.clone(), e.span().start)

View file

@ -36,7 +36,7 @@ pub trait IsNumExpr: AnyExpr + Into<NumExpr> {}
pub trait IsBoolExpr: AnyExpr + Into<BoolExpr> {} pub trait IsBoolExpr: AnyExpr + Into<BoolExpr> {}
/// All expressions that are numeric /// 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)] #[enum_dispatch(AnyExpr)]
pub enum NumExpr { pub enum NumExpr {
/// A signed integer literal /// A signed integer literal
@ -73,7 +73,7 @@ impl NumExpr {
} }
/// All expressions that are evaluated to be of type `bool` /// 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)] #[enum_dispatch(AnyExpr)]
pub enum BoolExpr { pub enum BoolExpr {
/// A `bool` literal /// A `bool` literal
@ -139,7 +139,7 @@ pub enum ExprRef<'a> {
} }
/// An expression (either [`BoolExpr`] or [`NumExpr`]) /// An expression (either [`BoolExpr`] or [`NumExpr`])
#[derive(Clone, Debug)] #[derive(Clone, Debug, derive_more::Display)]
#[enum_dispatch(AnyExpr)] #[enum_dispatch(AnyExpr)]
pub enum Expr { pub enum Expr {
/// A reference to a [`BoolExpr`] /// A reference to a [`BoolExpr`]

View file

@ -1,23 +1,28 @@
//! Boolean expression types //! Boolean expression types
use std::ops::{Bound, RangeBounds}; use std::ops::{Bound, RangeBounds};
use std::time::Duration; use std::time::Duration;
use itertools::Itertools;
use super::{AnyExpr, BoolExpr, NumExpr}; use super::{AnyExpr, BoolExpr, NumExpr};
/// Types of comparison operations /// Types of comparison operations
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq, derive_more::Display)]
pub enum Ordering { pub enum Ordering {
/// Equality check for two expressions /// Equality check for two expressions
#[display(fmt = "==")]
Eq, Eq,
/// Non-equality check for two expressions /// Non-equality check for two expressions
#[display(fmt = "!=")]
NotEq, NotEq,
/// Less than check /// Less than check
#[display(fmt = "{}", r#"if *strict { "<".to_string() } else { "<=".to_string() } "#r)]
Less { Less {
/// Denotes `lhs < rhs` if `strict`, and `lhs <= rhs` otherwise. /// Denotes `lhs < rhs` if `strict`, and `lhs <= rhs` otherwise.
strict: bool, strict: bool,
}, },
/// Greater than check /// Greater than check
#[display(fmt = "{}", r#"if *strict { ">".to_string() } else { ">=".to_string() } "#r)]
Greater { Greater {
/// Denotes `lhs > rhs` if `strict`, and `lhs >= rhs` otherwise. /// Denotes `lhs > rhs` if `strict`, and `lhs >= rhs` otherwise.
strict: bool, strict: bool,
@ -66,6 +71,21 @@ pub struct Interval {
pub end: Bound<Duration>, 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 { impl Interval {
/// Create a new interval /// Create a new interval
/// ///
@ -174,13 +194,14 @@ macro_rules! impl_bool_expr {
} }
/// A `bool` literal /// 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); pub struct BoolLit(pub bool);
impl_bool_expr!(BoolLit); impl_bool_expr!(BoolLit);
/// A `bool` variable /// 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 { pub struct BoolVar {
/// Variable name /// Variable name
pub name: String, pub name: String,
@ -189,7 +210,8 @@ pub struct BoolVar {
impl_bool_expr!(BoolVar); impl_bool_expr!(BoolVar);
/// A comparison expression /// 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 { pub struct Cmp {
/// The type of comparison /// The type of comparison
pub op: Ordering, pub op: Ordering,
@ -202,7 +224,8 @@ pub struct Cmp {
impl_bool_expr!(Cmp, lhs, rhs); impl_bool_expr!(Cmp, lhs, rhs);
/// Logical negation of an expression /// 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 { pub struct Not {
/// Expression to be negated /// Expression to be negated
pub arg: Box<BoolExpr>, pub arg: Box<BoolExpr>,
@ -211,7 +234,8 @@ pub struct Not {
impl_bool_expr!(Not, arg); impl_bool_expr!(Not, arg);
/// Logical conjunction of a list of expressions /// 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 { pub struct And {
/// Expressions to be "and"-ed /// Expressions to be "and"-ed
pub args: Vec<BoolExpr>, pub args: Vec<BoolExpr>,
@ -220,7 +244,8 @@ pub struct And {
impl_bool_expr!(And, [args]); impl_bool_expr!(And, [args]);
/// Logical disjunction of a list of expressions /// 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 { pub struct Or {
/// Expressions to be "or"-ed /// Expressions to be "or"-ed
pub args: Vec<BoolExpr>, pub args: Vec<BoolExpr>,
@ -231,7 +256,8 @@ impl_bool_expr!(Or, [args]);
/// A temporal next expression /// A temporal next expression
/// ///
/// Checks if the next time point in a signal is `true` or not. /// 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 { pub struct Next {
/// Argument for `Next` /// Argument for `Next`
pub arg: Box<BoolExpr>, pub arg: Box<BoolExpr>,
@ -242,7 +268,8 @@ impl_bool_expr!(Next, arg);
/// ///
/// This is equivalent to `steps` number of nested [`Next`](BoolExpr::Next) /// This is equivalent to `steps` number of nested [`Next`](BoolExpr::Next)
/// expressions. /// 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 { pub struct Oracle {
/// Number of steps to look ahead /// Number of steps to look ahead
pub steps: usize, pub steps: usize,
@ -256,7 +283,8 @@ impl_bool_expr!(Oracle, arg);
/// - If the `interval` is `(Unbounded, Unbounded)` or equivalent to `(0, Unbounded)`: /// - If the `interval` is `(Unbounded, Unbounded)` or equivalent to `(0, Unbounded)`:
/// checks if the signal is `true` for all points in a signal. /// 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`. /// - 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 { pub struct Always {
/// Argument for `Always` /// Argument for `Always`
pub arg: Box<BoolExpr>, pub arg: Box<BoolExpr>,
@ -270,7 +298,8 @@ impl_bool_expr!(Always, arg);
/// - If the `interval` is `(Unbounded, Unbounded)` or equivalent to `(0, Unbounded)`: /// - If the `interval` is `(Unbounded, Unbounded)` or equivalent to `(0, Unbounded)`:
/// checks if the signal is `true` for some point in a signal. /// 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`. /// - 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 { pub struct Eventually {
/// Argument for `Eventually` /// Argument for `Eventually`
pub arg: Box<BoolExpr>, pub arg: Box<BoolExpr>,
@ -282,7 +311,8 @@ impl_bool_expr!(Eventually, arg);
/// A temporal until expression /// A temporal until expression
/// ///
/// Checks if the `lhs` is always `true` for a signal until `rhs` becomes `true`. /// 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 { pub struct Until {
/// LHS to `lhs Until rhs` /// LHS to `lhs Until rhs`
pub lhs: Box<BoolExpr>, pub lhs: Box<BoolExpr>,

View file

@ -1,4 +1,5 @@
//! Numeric expression types //! Numeric expression types
use itertools::Itertools;
use super::{AnyExpr, NumExpr}; use super::{AnyExpr, NumExpr};
@ -37,22 +38,23 @@ macro_rules! impl_num_expr {
} }
/// A signed integer literal /// 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); pub struct IntLit(pub i64);
impl_num_expr!(IntLit); impl_num_expr!(IntLit);
/// An unsigned integer literal /// 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); pub struct UIntLit(pub u64);
impl_num_expr!(UIntLit); impl_num_expr!(UIntLit);
/// A floating point literal /// 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); pub struct FloatLit(pub f64);
impl_num_expr!(FloatLit); impl_num_expr!(FloatLit);
/// A signed integer variable /// 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 { pub struct IntVar {
/// Name of the variable /// Name of the variable
pub name: String, pub name: String,
@ -60,7 +62,8 @@ pub struct IntVar {
impl_num_expr!(IntVar); impl_num_expr!(IntVar);
/// A unsigned integer variable /// 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 { pub struct UIntVar {
/// Name of the variable /// Name of the variable
pub name: String, pub name: String,
@ -68,7 +71,8 @@ pub struct UIntVar {
impl_num_expr!(UIntVar); impl_num_expr!(UIntVar);
/// A floating point number variable /// 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 { pub struct FloatVar {
/// Name of the variable /// Name of the variable
pub name: String, pub name: String,
@ -76,7 +80,8 @@ pub struct FloatVar {
impl_num_expr!(FloatVar); impl_num_expr!(FloatVar);
/// Numeric negation of a numeric expression /// 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 { pub struct Neg {
/// Numeric expression being negated /// Numeric expression being negated
pub arg: Box<NumExpr>, pub arg: Box<NumExpr>,
@ -84,7 +89,8 @@ pub struct Neg {
impl_num_expr!(Neg, arg); impl_num_expr!(Neg, arg);
/// Arithmetic addition of a list of numeric expressions /// 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 { pub struct Add {
/// List of expressions being added /// List of expressions being added
pub args: Vec<NumExpr>, pub args: Vec<NumExpr>,
@ -92,7 +98,8 @@ pub struct Add {
impl_num_expr!(Add, [args]); impl_num_expr!(Add, [args]);
/// Subtraction of two numbers /// 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 { pub struct Sub {
/// LHS to the expression `lhs - rhs` /// LHS to the expression `lhs - rhs`
pub lhs: Box<NumExpr>, pub lhs: Box<NumExpr>,
@ -102,7 +109,8 @@ pub struct Sub {
impl_num_expr!(Sub, lhs, rhs); impl_num_expr!(Sub, lhs, rhs);
/// Arithmetic multiplication of a list of numeric expressions /// 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 { pub struct Mul {
/// List of expressions being multiplied /// List of expressions being multiplied
pub args: Vec<NumExpr>, pub args: Vec<NumExpr>,
@ -110,7 +118,8 @@ pub struct Mul {
impl_num_expr!(Mul, [args]); impl_num_expr!(Mul, [args]);
/// Divide two expressions `dividend / divisor` /// 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 { pub struct Div {
/// The dividend /// The dividend
pub dividend: Box<NumExpr>, pub dividend: Box<NumExpr>,
@ -120,7 +129,8 @@ pub struct Div {
impl_num_expr!(Div, dividend, divisor); impl_num_expr!(Div, dividend, divisor);
/// The absolute value of an expression /// 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 { pub struct Abs {
/// Argument to `abs` /// Argument to `abs`
pub arg: Box<NumExpr>, pub arg: Box<NumExpr>,