1use 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}