conjure_core/ast/
ac_operators.rs1use crate::{
2 ast::{Domain, Range, ReturnType},
3 matrix_expr,
4 metadata::Metadata,
5};
6
7use super::{Expression, Literal, Typeable};
8
9#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
13pub enum ACOperatorKind {
14 And,
15 Or,
16 Product,
17 Sum,
18}
19
20impl ACOperatorKind {
21 pub fn as_expression(&self, child_expr: Expression) -> Expression {
25 assert!(
26 matches!(child_expr.return_type(), Some(ReturnType::Matrix(_))),
27 "The child expression given to ACOperatorKind::to_expression should be of type matrix."
28 );
29 let box_expr = Box::new(child_expr);
30 match self {
31 ACOperatorKind::And => Expression::And(Metadata::new(), box_expr),
32 ACOperatorKind::Or => Expression::Or(Metadata::new(), box_expr),
33 ACOperatorKind::Product => Expression::Product(Metadata::new(), box_expr),
34 ACOperatorKind::Sum => Expression::Sum(Metadata::new(), box_expr),
35 }
36 }
37
38 pub fn identity(&self) -> Literal {
49 match self {
50 ACOperatorKind::And => Literal::Bool(true),
51 ACOperatorKind::Or => Literal::Bool(false),
52 ACOperatorKind::Product => Literal::Int(1),
53 ACOperatorKind::Sum => Literal::Int(0),
54 }
55 }
56
57 pub fn make_skip_operation(&self, guard_expr: Expression, tail_expr: Expression) -> Expression {
84 assert!(
85 matches!(guard_expr.return_type(), Some(ReturnType::Bool)),
86 "The guard expression in a skipping operation should be type boolean."
87 );
88
89 match self {
90 ACOperatorKind::And => {
91 assert!(
92 matches!(tail_expr.return_type(), Some(ReturnType::Bool)),
93 "The tail expression in an and skipping operation should be type boolean."
94 );
95 let tail_expr_boxed = Box::new(tail_expr);
96 let guard_expr_boxed = Box::new(guard_expr);
97 Expression::Imply(Metadata::new(), guard_expr_boxed, tail_expr_boxed)
98 }
99 ACOperatorKind::Or => {
100 assert!(
101 matches!(tail_expr.return_type(), Some(ReturnType::Bool)),
102 "The tail expression in an or skipping operation should be type boolean."
103 );
104 Expression::And(
105 Metadata::new(),
106 Box::new(matrix_expr![guard_expr, tail_expr]),
107 )
108 }
109 ACOperatorKind::Product => {
110 assert!(
111 matches!(tail_expr.return_type(), Some(ReturnType::Int)),
112 "The tail expression in a product skipping operation should be type int."
113 );
114 let guard_expr_boxed = Box::new(guard_expr);
115 Expression::UnsafeIndex(
116 Metadata::new(),
117 Box::new(
118 matrix_expr![Expression::Atomic(Metadata::new(),1.into()),tail_expr;Domain::Int(vec![Range::Bounded(0,1)])],
119 ),
120 vec![Expression::ToInt(Metadata::new(), guard_expr_boxed)],
121 )
122 }
123 ACOperatorKind::Sum => {
124 let guard_expr_boxed = Box::new(guard_expr);
125 assert!(
126 matches!(tail_expr.return_type(), Some(ReturnType::Int)),
127 "The tail expression in a sum skipping operation should be type int."
128 );
129 Expression::Product(
130 Metadata::new(),
131 Box::new(matrix_expr![
132 Expression::ToInt(Metadata::new(), guard_expr_boxed),
133 tail_expr
134 ]),
135 )
136 }
137 }
138 }
139}
140
141impl TryFrom<&Expression> for ACOperatorKind {
142 type Error = ();
143 fn try_from(expr: &Expression) -> Result<Self, Self::Error> {
144 match expr {
145 Expression::And(_, _) => Ok(ACOperatorKind::And),
146 Expression::Or(_, _) => Ok(ACOperatorKind::Or),
147 Expression::Product(_, _) => Ok(ACOperatorKind::Product),
148 Expression::Sum(_, _) => Ok(ACOperatorKind::Sum),
149 _ => Err(()),
150 }
151 }
152}
153
154impl TryFrom<Expression> for ACOperatorKind {
155 type Error = ();
156
157 fn try_from(value: Expression) -> Result<Self, Self::Error> {
158 TryFrom::try_from(&value)
159 }
160}
161
162impl TryFrom<Box<Expression>> for ACOperatorKind {
163 type Error = ();
164
165 fn try_from(value: Box<Expression>) -> Result<Self, Self::Error> {
166 TryFrom::try_from(value.as_ref())
167 }
168}