diff --git a/pyargus/Cargo.toml b/pyargus/Cargo.toml index ee3b0a4..3e3a9f7 100644 --- a/pyargus/Cargo.toml +++ b/pyargus/Cargo.toml @@ -10,4 +10,5 @@ crate-type = ["cdylib"] [dependencies] argus-core = { version = "0.1.0", path = "../argus-core" } +derive_more = "0.99.17" pyo3 = "0.18.1" diff --git a/pyargus/argus/__init__.py b/pyargus/argus/__init__.py new file mode 100644 index 0000000..7cc936e --- /dev/null +++ b/pyargus/argus/__init__.py @@ -0,0 +1,6 @@ +from argus import _argus +from argus._argus import * + +__doc__ = _argus.__doc__ +if hasattr(_argus, "__all__"): + __all__ = _argus.__all__ diff --git a/pyargus/pyproject.toml b/pyargus/pyproject.toml index 46ac758..498769a 100644 --- a/pyargus/pyproject.toml +++ b/pyargus/pyproject.toml @@ -6,11 +6,12 @@ build-backend = "maturin" name = "pyargus" requires-python = ">=3.7" classifiers = [ - "Programming Language :: Rust", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", + "Programming Language :: Rust", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", ] [tool.maturin] features = ["pyo3/extension-module"] +module-name = "argus._argus" diff --git a/pyargus/src/lib.rs b/pyargus/src/lib.rs index a3e1f3b..1f27bb1 100644 --- a/pyargus/src/lib.rs +++ b/pyargus/src/lib.rs @@ -1,9 +1,10 @@ -use argus_core::expr::{BoolExpr, NumExpr}; +use argus_core::expr::Ordering; use argus_core::prelude::*; use pyo3::prelude::*; +use pyo3::pyclass::CompareOp; #[pyclass(name = "NumExpr", subclass)] -#[derive(Clone)] +#[derive(Clone, derive_more::From)] struct PyNumExpr(Box); #[pymethods] @@ -24,6 +25,10 @@ impl PyNumExpr { Python::with_gil(|py| Py::new(py, Mul::new(vec![self.clone(), other.clone()]))) } + fn __sub__(&self, other: &Self) -> PyResult> { + Python::with_gil(|py| Py::new(py, Sub::new(self.clone(), other.clone()))) + } + fn __truediv__(&self, other: &Self) -> PyResult> { Python::with_gil(|py| Py::new(py, Div::new(self.clone(), other.clone()))) } @@ -31,6 +36,17 @@ impl PyNumExpr { fn __abs__(&self) -> PyResult> { Python::with_gil(|py| Py::new(py, Abs::new(self.clone()))) } + + fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult> { + match op { + CompareOp::Lt => Cmp::less_than(self.clone(), other.clone()), + CompareOp::Le => Cmp::less_than_eq(self.clone(), other.clone()), + CompareOp::Eq => Cmp::equal(self.clone(), other.clone()), + CompareOp::Ne => Cmp::not_equal(self.clone(), other.clone()), + CompareOp::Gt => Cmp::greater_than(self.clone(), other.clone()), + CompareOp::Ge => Cmp::greater_than_eq(self.clone(), other.clone()), + } + } } #[pyclass(extends=PyNumExpr)] @@ -40,7 +56,7 @@ struct ConstInt; impl ConstInt { #[new] fn new(val: i64) -> (Self, PyNumExpr) { - (Self, PyNumExpr(Box::new(NumExpr::IntLit(val)))) + (Self, Box::new(NumExpr::IntLit(val)).into()) } } @@ -51,7 +67,7 @@ struct ConstUInt; impl ConstUInt { #[new] fn new(val: u64) -> (Self, PyNumExpr) { - (Self, PyNumExpr(Box::new(NumExpr::UIntLit(val)))) + (Self, Box::new(NumExpr::UIntLit(val)).into()) } } @@ -62,7 +78,7 @@ struct ConstFloat; impl ConstFloat { #[new] fn new(val: f64) -> (Self, PyNumExpr) { - (Self, PyNumExpr(Box::new(NumExpr::FloatLit(val)))) + (Self, Box::new(NumExpr::FloatLit(val)).into()) } } @@ -73,7 +89,7 @@ struct VarInt; impl VarInt { #[new] fn new(name: String) -> (Self, PyNumExpr) { - (Self, PyNumExpr(Box::new(NumExpr::IntVar { name }))) + (Self, Box::new(NumExpr::IntVar { name }).into()) } } @@ -84,7 +100,7 @@ struct VarUInt; impl VarUInt { #[new] fn new(name: String) -> (Self, PyNumExpr) { - (Self, PyNumExpr(Box::new(NumExpr::UIntVar { name }))) + (Self, Box::new(NumExpr::UIntVar { name }).into()) } } @@ -95,7 +111,7 @@ struct VarFloat; impl VarFloat { #[new] fn new(name: String) -> (Self, PyNumExpr) { - (Self, PyNumExpr(Box::new(NumExpr::FloatVar { name }))) + (Self, Box::new(NumExpr::FloatVar { name }).into()) } } @@ -107,7 +123,7 @@ impl Negate { #[new] fn new(arg: PyNumExpr) -> (Self, PyNumExpr) { let arg = arg.0; - (Self, PyNumExpr(Box::new(NumExpr::Neg { arg }))) + (Self, Box::new(NumExpr::Neg { arg }).into()) } } @@ -119,7 +135,7 @@ impl Add { #[new] fn new(args: Vec) -> (Self, PyNumExpr) { let args: Vec = args.into_iter().map(|arg| *arg.0).collect(); - (Self, PyNumExpr(Box::new(NumExpr::Add { args }))) + (Self, Box::new(NumExpr::Add { args }).into()) } } @@ -132,7 +148,7 @@ impl Sub { fn new(lhs: PyNumExpr, rhs: PyNumExpr) -> (Self, PyNumExpr) { let lhs = lhs.0; let rhs = rhs.0; - (Self, PyNumExpr(Box::new(NumExpr::Sub { lhs, rhs }))) + (Self, Box::new(NumExpr::Sub { lhs, rhs }).into()) } } @@ -144,7 +160,7 @@ impl Mul { #[new] fn new(args: Vec) -> (Self, PyNumExpr) { let args: Vec = args.into_iter().map(|arg| *arg.0).collect(); - (Self, PyNumExpr(Box::new(NumExpr::Mul { args }))) + (Self, Box::new(NumExpr::Mul { args }).into()) } } @@ -157,23 +173,10 @@ impl Div { fn new(dividend: PyNumExpr, divisor: PyNumExpr) -> (Self, PyNumExpr) { let dividend = dividend.0; let divisor = divisor.0; - (Self, PyNumExpr(Box::new(NumExpr::Div { dividend, divisor }))) + (Self, Box::new(NumExpr::Div { dividend, divisor }).into()) } } -// #[pyclass(extends=PyNumExpr)] -// struct Pow; -// -// #[pymethods] -// impl Pow { -// #[new] -// fn new(base: PyNumExpr, exponent: PyNumExpr) -> (Self, PyNumExpr) { -// let base = base.0; -// let exponent = exponent.0; -// (Self, PyNumExpr(Box::new(NumExpr:: { base, exponent }))) -// } -// } - #[pyclass(extends=PyNumExpr)] struct Abs; @@ -182,14 +185,141 @@ impl Abs { #[new] fn new(arg: PyNumExpr) -> (Self, PyNumExpr) { let arg = arg.0; - (Self, PyNumExpr(Box::new(NumExpr::Abs { arg }))) + (Self, Box::new(NumExpr::Abs { arg }).into()) } } -#[pyclass(name = "BoolExpr")] -struct PyBoolExpr(BoolExpr); +#[pyclass(name = "BoolExpr", subclass)] +#[derive(Clone, derive_more::From)] +struct PyBoolExpr(Box); + +#[pymethods] +impl PyBoolExpr { + fn __repr__(&self) -> String { + format!("{:?}", &self.0) + } + + fn __invert__(&self) -> PyResult> { + Python::with_gil(|py| Py::new(py, Not::new(self.clone()))) + } + + fn __or__(&self, other: &Self) -> PyResult> { + Python::with_gil(|py| Py::new(py, Or::new(vec![self.clone(), other.clone()]))) + } + + fn __and__(&self, other: &Self) -> PyResult> { + Python::with_gil(|py| Py::new(py, And::new(vec![self.clone(), other.clone()]))) + } +} + +#[pyclass(extends=PyBoolExpr)] +struct ConstBool; + +#[pymethods] +impl ConstBool { + #[new] + fn new(val: bool) -> (Self, PyBoolExpr) { + (Self, Box::new(BoolExpr::BoolLit(val)).into()) + } +} + +#[pyclass(extends=PyBoolExpr)] +struct VarBool; + +#[pymethods] +impl VarBool { + #[new] + fn new(name: String) -> (Self, PyBoolExpr) { + (Self, Box::new(BoolExpr::BoolVar { name }).into()) + } +} + +#[pyclass(extends=PyBoolExpr)] +struct Cmp; + +#[pyclass] +#[derive(Copy, Clone, derive_more::From)] +struct PyOrdering(Ordering); + +#[pymethods] +impl Cmp { + #[new] + fn new(op: PyOrdering, lhs: PyNumExpr, rhs: PyNumExpr) -> (Self, PyBoolExpr) { + let op = op.0; + let lhs = lhs.0; + let rhs = rhs.0; + (Self, Box::new(BoolExpr::Cmp { op, lhs, rhs }).into()) + } + + #[staticmethod] + fn less_than(lhs: PyNumExpr, rhs: PyNumExpr) -> PyResult> { + Python::with_gil(|py| Py::new(py, Cmp::new(PyOrdering(Ordering::less_than()), lhs, rhs))) + } + + #[staticmethod] + fn less_than_eq(lhs: PyNumExpr, rhs: PyNumExpr) -> PyResult> { + Python::with_gil(|py| Py::new(py, Cmp::new(PyOrdering(Ordering::less_than_eq()), lhs, rhs))) + } + + #[staticmethod] + fn greater_than(lhs: PyNumExpr, rhs: PyNumExpr) -> PyResult> { + Python::with_gil(|py| Py::new(py, Cmp::new(PyOrdering(Ordering::greater_than()), lhs, rhs))) + } + + #[staticmethod] + fn greater_than_eq(lhs: PyNumExpr, rhs: PyNumExpr) -> PyResult> { + Python::with_gil(|py| Py::new(py, Cmp::new(PyOrdering(Ordering::greater_than_eq()), lhs, rhs))) + } + + #[staticmethod] + fn equal(lhs: PyNumExpr, rhs: PyNumExpr) -> PyResult> { + Python::with_gil(|py| Py::new(py, Cmp::new(PyOrdering(Ordering::equal()), lhs, rhs))) + } + + #[staticmethod] + fn not_equal(lhs: PyNumExpr, rhs: PyNumExpr) -> PyResult> { + Python::with_gil(|py| Py::new(py, Cmp::new(PyOrdering(Ordering::not_equal()), lhs, rhs))) + } +} + +#[pyclass(extends=PyBoolExpr)] +struct Not; + +#[pymethods] +impl Not { + #[new] + fn new(arg: PyBoolExpr) -> (Self, PyBoolExpr) { + let arg = arg.0; + (Self, PyBoolExpr(Box::new(BoolExpr::Not { arg }))) + } +} + +#[pyclass(extends=PyBoolExpr)] +struct And; + +#[pymethods] +impl And { + #[new] + fn new(args: Vec) -> (Self, PyBoolExpr) { + let args: Vec = args.into_iter().map(|arg| *arg.0).collect(); + (Self, PyBoolExpr(Box::new(BoolExpr::And { args }))) + } +} + +#[pyclass(extends=PyBoolExpr)] +struct Or; + +#[pymethods] +impl Or { + #[new] + fn new(args: Vec) -> (Self, PyBoolExpr) { + let args: Vec = args.into_iter().map(|arg| *arg.0).collect(); + (Self, PyBoolExpr(Box::new(BoolExpr::Or { args }))) + } +} #[pymodule] +#[pyo3(name = "_argus")] fn pyargus(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; @@ -202,9 +332,14 @@ fn pyargus(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::
()?; - // m.add_class::()?; m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; Ok(()) }