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"
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 = []

View file

@ -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)

View file

@ -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`]

View file

@ -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>,

View file

@ -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>,