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}
53
54impl Declaration {
55 pub fn new(name: Name, kind: DeclarationKind) -> Declaration {
57 let id = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
58 Declaration { name, kind, id }
59 }
60
61 pub fn new_var(name: Name, domain: Domain) -> Declaration {
63 let id = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
64 Declaration {
65 name,
66 kind: DeclarationKind::DecisionVariable(DecisionVariable::new(domain)),
67 id,
68 }
69 }
70
71 pub fn new_domain_letting(name: Name, domain: Domain) -> Declaration {
73 let id = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
74 Declaration {
75 name,
76 kind: DeclarationKind::DomainLetting(domain),
77 id,
78 }
79 }
80
81 pub fn new_value_letting(name: Name, value: Expression) -> Declaration {
83 let id = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
84 Declaration {
85 name,
86 kind: DeclarationKind::ValueLetting(value),
87 id,
88 }
89 }
90
91 pub fn name(&self) -> &Name {
93 &self.name
94 }
95
96 pub fn kind(&self) -> &DeclarationKind {
98 &self.kind
99 }
100
101 pub fn domain(&self) -> Option<&Domain> {
103 match self.kind() {
104 DeclarationKind::DecisionVariable(var) => Some(&var.domain),
105 DeclarationKind::ValueLetting(_) => None,
107 DeclarationKind::DomainLetting(domain) => Some(domain),
108 }
109 }
110
111 pub fn as_var(&self) -> Option<&DecisionVariable> {
113 if let DeclarationKind::DecisionVariable(var) = self.kind() {
114 Some(var)
115 } else {
116 None
117 }
118 }
119
120 pub fn as_var_mut(&mut self) -> Option<&mut DecisionVariable> {
122 if let DeclarationKind::DecisionVariable(var) = &mut self.kind {
123 Some(var)
124 } else {
125 None
126 }
127 }
128
129 pub fn as_domain_letting(&self) -> Option<&Domain> {
131 if let DeclarationKind::DomainLetting(domain) = self.kind() {
132 Some(domain)
133 } else {
134 None
135 }
136 }
137
138 pub fn as_domain_letting_mut(&mut self) -> Option<&mut Domain> {
140 if let DeclarationKind::DomainLetting(domain) = &mut self.kind {
141 Some(domain)
142 } else {
143 None
144 }
145 }
146
147 pub fn as_value_letting(&self) -> Option<&Expression> {
149 if let DeclarationKind::ValueLetting(expr) = &self.kind {
150 Some(expr)
151 } else {
152 None
153 }
154 }
155
156 pub fn as_value_letting_mut(&mut self) -> Option<&mut Expression> {
158 if let DeclarationKind::ValueLetting(expr) = &mut self.kind {
159 Some(expr)
160 } else {
161 None
162 }
163 }
164}
165
166impl HasId for Declaration {
167 fn id(&self) -> ObjId {
168 self.id
169 }
170}
171
172impl DefaultWithId for Declaration {
173 fn default_with_id(id: ObjId) -> Self {
174 Self {
175 name: Name::UserName("_UNKNOWN".into()),
176 kind: DeclarationKind::ValueLetting(false.into()),
177 id,
178 }
179 }
180}
181
182impl Clone for Declaration {
183 fn clone(&self) -> Self {
184 Self {
185 name: self.name.clone(),
186 kind: self.kind.clone(),
187 id: ID_COUNTER.fetch_add(1, Ordering::Relaxed),
188 }
189 }
190}
191
192impl Typeable for Declaration {
193 fn return_type(&self) -> Option<ReturnType> {
194 match self.kind() {
195 DeclarationKind::DecisionVariable(var) => var.return_type(),
196 DeclarationKind::ValueLetting(expression) => expression.return_type(),
197 DeclarationKind::DomainLetting(domain) => domain.return_type(),
198 }
199 }
200}