conjure_core/ast/
declaration.rs1use std::sync::atomic::{AtomicU32, Ordering};
2
3use derivative::Derivative;
4use serde::{Deserialize, Serialize};
5use uniplate::derive::Uniplate;
6use uniplate::{Biplate, Tree};
7
8use super::name::Name;
9use super::serde::{DefaultWithId, HasId, ObjId};
10use super::types::Typeable;
11use super::{DecisionVariable, Domain, Expression, ReturnType};
12
13static ID_COUNTER: AtomicU32 = AtomicU32::new(0);
14
15#[derive(Derivative)]
16#[derivative(PartialEq)]
17#[derive(Debug, Serialize, Deserialize, Eq, Uniplate)]
18#[biplate(to=Expression)]
19#[uniplate(walk_into=[DeclarationKind])]
20pub struct Declaration {
21 name: Name,
23
24 kind: DeclarationKind,
26
27 #[derivative(PartialEq = "ignore")] id: ObjId,
32}
33
34impl Biplate<Declaration> for DeclarationKind {
38 fn biplate(&self) -> (Tree<Declaration>, Box<dyn Fn(Tree<Declaration>) -> Self>) {
39 let self2 = self.clone();
40 (Tree::Zero, Box::new(move |_| self2.clone()))
41 }
42}
43
44#[non_exhaustive]
46#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
47#[biplate(to=Expression)]
48pub enum DeclarationKind {
49 DecisionVariable(DecisionVariable),
50 ValueLetting(Expression),
51 DomainLetting(Domain),
52 Given(Domain),
53}
54
55impl Declaration {
56 pub fn new(name: Name, kind: DeclarationKind) -> Declaration {
58 let id = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
59 Declaration { name, kind, id }
60 }
61
62 pub fn new_var(name: Name, domain: Domain) -> Declaration {
64 let id = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
65 Declaration {
66 name,
67 kind: DeclarationKind::DecisionVariable(DecisionVariable::new(domain)),
68 id,
69 }
70 }
71
72 pub fn new_domain_letting(name: Name, domain: Domain) -> Declaration {
74 let id = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
75 Declaration {
76 name,
77 kind: DeclarationKind::DomainLetting(domain),
78 id,
79 }
80 }
81
82 pub fn new_value_letting(name: Name, value: Expression) -> Declaration {
84 let id = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
85 Declaration {
86 name,
87 kind: DeclarationKind::ValueLetting(value),
88 id,
89 }
90 }
91
92 pub fn new_given(name: Name, domain: Domain) -> Declaration {
94 let id = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
95 Declaration {
96 name,
97 kind: DeclarationKind::Given(domain),
98 id,
99 }
100 }
101
102 pub fn name(&self) -> &Name {
104 &self.name
105 }
106
107 pub fn kind(&self) -> &DeclarationKind {
109 &self.kind
110 }
111
112 pub fn domain(&self) -> Option<&Domain> {
114 match self.kind() {
115 DeclarationKind::DecisionVariable(var) => Some(&var.domain),
116 DeclarationKind::ValueLetting(_) => None,
117 DeclarationKind::DomainLetting(domain) => Some(domain),
118 DeclarationKind::Given(domain) => Some(domain),
119 }
120 }
121
122 pub fn as_var(&self) -> Option<&DecisionVariable> {
124 if let DeclarationKind::DecisionVariable(var) = self.kind() {
125 Some(var)
126 } else {
127 None
128 }
129 }
130
131 pub fn as_var_mut(&mut self) -> Option<&mut DecisionVariable> {
133 if let DeclarationKind::DecisionVariable(var) = &mut self.kind {
134 Some(var)
135 } else {
136 None
137 }
138 }
139
140 pub fn as_domain_letting(&self) -> Option<&Domain> {
142 if let DeclarationKind::DomainLetting(domain) = self.kind() {
143 Some(domain)
144 } else {
145 None
146 }
147 }
148
149 pub fn as_domain_letting_mut(&mut self) -> Option<&mut Domain> {
151 if let DeclarationKind::DomainLetting(domain) = &mut self.kind {
152 Some(domain)
153 } else {
154 None
155 }
156 }
157
158 pub fn as_value_letting(&self) -> Option<&Expression> {
160 if let DeclarationKind::ValueLetting(expr) = &self.kind {
161 Some(expr)
162 } else {
163 None
164 }
165 }
166
167 pub fn as_value_letting_mut(&mut self) -> Option<&mut Expression> {
169 if let DeclarationKind::ValueLetting(expr) = &mut self.kind {
170 Some(expr)
171 } else {
172 None
173 }
174 }
175
176 pub fn with_new_name(mut self, name: Name) -> Declaration {
178 self.name = name;
179 self
180 }
181}
182
183impl HasId for Declaration {
184 fn id(&self) -> ObjId {
185 self.id
186 }
187}
188
189impl DefaultWithId for Declaration {
190 fn default_with_id(id: ObjId) -> Self {
191 Self {
192 name: Name::User("_UNKNOWN".into()),
193 kind: DeclarationKind::ValueLetting(false.into()),
194 id,
195 }
196 }
197}
198
199impl Clone for Declaration {
200 fn clone(&self) -> Self {
201 Self {
202 name: self.name.clone(),
203 kind: self.kind.clone(),
204 id: ID_COUNTER.fetch_add(1, Ordering::Relaxed),
205 }
206 }
207}
208
209impl Typeable for Declaration {
210 fn return_type(&self) -> Option<ReturnType> {
211 match self.kind() {
212 DeclarationKind::DecisionVariable(var) => var.return_type(),
213 DeclarationKind::ValueLetting(expression) => expression.return_type(),
214 DeclarationKind::DomainLetting(domain) => domain.return_type(),
215 DeclarationKind::Given(domain) => domain.return_type(),
216 }
217 }
218}