conjure_cp_core/ast/
ac_operators.rs1use crate::{
2 ast::{Domain, Moo, 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 = Moo::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 = Moo::new(tail_expr);
96 let guard_expr_boxed = Moo::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 Moo::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 = Moo::new(guard_expr);
115 Expression::UnsafeIndex(
116 Metadata::new(),
117 Moo::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 = Moo::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 Moo::new(matrix_expr![
132 Expression::ToInt(Metadata::new(), guard_expr_boxed),
133 tail_expr
134 ]),
135 )
136 }
137 }
138 }
139
140 pub fn return_type(&self) -> ReturnType {
142 match self {
143 ACOperatorKind::And | ACOperatorKind::Or => ReturnType::Bool,
144 ACOperatorKind::Product | ACOperatorKind::Sum => ReturnType::Int,
145 }
146 }
147}
148
149impl TryFrom<&Expression> for ACOperatorKind {
150 type Error = ();
151 fn try_from(expr: &Expression) -> Result<Self, Self::Error> {
152 match expr {
153 Expression::And(_, _) => Ok(ACOperatorKind::And),
154 Expression::Or(_, _) => Ok(ACOperatorKind::Or),
155 Expression::Product(_, _) => Ok(ACOperatorKind::Product),
156 Expression::Sum(_, _) => Ok(ACOperatorKind::Sum),
157 _ => Err(()),
158 }
159 }
160}
161
162impl TryFrom<Expression> for ACOperatorKind {
163 type Error = ();
164
165 fn try_from(value: Expression) -> Result<Self, Self::Error> {
166 TryFrom::try_from(&value)
167 }
168}
169
170impl TryFrom<Box<Expression>> for ACOperatorKind {
171 type Error = ();
172
173 fn try_from(value: Box<Expression>) -> Result<Self, Self::Error> {
174 TryFrom::try_from(value.as_ref())
175 }
176}