rsdiff_core/ops/
ops.rs

1/*
2    Appellation: kinds <mod>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use crate::ops::traits::OperandType;
6use crate::ops::{BinaryOp, NaryOp, Operator, TernaryOp, UnaryOp};
7use strum::{Display, EnumCount, EnumDiscriminants, EnumIs, EnumIter, EnumString, VariantNames};
8
9#[derive(
10    Clone,
11    Copy,
12    Debug,
13    Display,
14    EnumCount,
15    EnumDiscriminants,
16    EnumIs,
17    Eq,
18    Hash,
19    Ord,
20    PartialEq,
21    PartialOrd,
22    VariantNames,
23)]
24#[cfg_attr(
25    feature = "serde",
26    derive(serde::Deserialize, serde::Serialize,),
27    serde(rename_all = "lowercase", untagged),
28    strum_discriminants(derive(serde::Deserialize, serde::Serialize))
29)]
30#[strum(serialize_all = "lowercase")]
31#[strum_discriminants(
32    derive(
33        Display,
34        EnumCount,
35        EnumIs,
36        EnumIter,
37        EnumString,
38        Hash,
39        Ord,
40        PartialOrd,
41        VariantNames
42    ),
43    name(OpKind)
44)]
45pub enum Op {
46    Binary(BinaryOp),
47    Nary(NaryOp),
48    Ternary(TernaryOp),
49    Unary(UnaryOp),
50}
51
52impl OpKind {
53    pub fn from_type(op: impl OperandType) -> Self {
54        op.kind()
55    }
56
57    pub fn optype(&self) -> Box<dyn OperandType> {
58        use crate::ops::{Binary, Nary, Ternary, Unary};
59        match self {
60            OpKind::Binary => Box::new(Binary),
61            OpKind::Nary => Box::new(Nary),
62            OpKind::Ternary => Box::new(Ternary),
63            OpKind::Unary => Box::new(Unary),
64        }
65    }
66}
67impl Op {
68    pub fn binary(op: BinaryOp) -> Self {
69        Self::Binary(op)
70    }
71
72    pub fn nary(op: NaryOp) -> Self {
73        Self::Nary(op)
74    }
75
76    pub fn ternary(op: TernaryOp) -> Self {
77        Self::Ternary(op)
78    }
79
80    pub fn unary(op: UnaryOp) -> Self {
81        Self::Unary(op)
82    }
83
84    pub fn operator(&self) -> Box<dyn Operator> {
85        match self.clone() {
86            Self::Binary(op) => Box::new(op),
87            Self::Nary(op) => Box::new(op),
88            Self::Ternary(op) => Box::new(op),
89            Self::Unary(op) => Box::new(op),
90        }
91    }
92}
93
94impl Operator for Op {
95    fn name(&self) -> &str {
96        match self {
97            Self::Binary(op) => op.name(),
98            Self::Nary(op) => op.name(),
99            Self::Ternary(op) => op.name(),
100            Self::Unary(op) => op.name(),
101        }
102    }
103
104    fn kind(&self) -> OpKind {
105        self.operator().kind()
106    }
107}
108
109macro_rules! impl_from_op {
110    ($($var:ident($op:ident)),*) => {
111        $(
112            impl_from_op!(@impl $var($op));
113        )*
114    };
115    (@impl $var:ident($op:ident)) => {
116        impl From<$op> for Op {
117            fn from(op: $op) -> Self {
118                Self::$var(op)
119            }
120        }
121    };
122
123}
124
125impl_from_op! {
126    Binary(BinaryOp),
127    Nary(NaryOp),
128    Ternary(TernaryOp),
129    Unary(UnaryOp)
130}