Skip to main content

conjure_cp_core/representation/
stored.rs

1use super::errors::ReprUpError;
2use super::types::{LookupFn, ReprAssignment, ReprDeclLevel, ReprGetOrInitResult, ReprResult};
3use crate::ast::{DeclarationPtr, Literal, Name};
4use crate::representation::ReprRule;
5use conjure_cp_core::representation::ReprError;
6use parking_lot::MappedRwLockReadGuard;
7use serde::Deserialize;
8use serde_json;
9use std::any::Any;
10use std::collections::{HashMap, VecDeque};
11use std::fmt::Debug;
12use std::hash::{Hash, Hasher};
13
14pub trait ReprStateStored: Any + Send + Sync + Debug {
15    fn rule(&self) -> &'static dyn ReprRuleStored;
16
17    fn up_via(&self, lu: &LookupFn<'_>) -> Result<Literal, ReprUpError>;
18
19    fn up(&self, raw_assignment: &HashMap<Name, Literal>) -> Result<Literal, ReprUpError> {
20        let lu: LookupFn<'_> =
21            Box::new(|decl: &DeclarationPtr| raw_assignment.get(&decl.name()).cloned());
22        self.up_via(&lu)
23    }
24
25    fn repr_vars(&self) -> VecDeque<DeclarationPtr>;
26
27    fn as_any(&self) -> &dyn Any;
28
29    fn as_any_mut(&mut self) -> &mut dyn Any;
30
31    fn clone_box(&self) -> Box<dyn ReprStateStored>;
32
33    fn serialise(&self) -> Result<serde_json::Value, serde_json::Error>;
34}
35
36impl<D: ReprDeclLevel> ReprStateStored for D {
37    fn rule(&self) -> &'static dyn ReprRuleStored {
38        D::RULE
39    }
40
41    fn up_via(&self, lu: &LookupFn<'_>) -> Result<Literal, ReprUpError> {
42        let res = self.lookup_via(lu)?;
43        Ok(res.up())
44    }
45
46    fn repr_vars(&self) -> VecDeque<DeclarationPtr> {
47        D::repr_vars(self)
48    }
49
50    fn as_any(&self) -> &dyn Any {
51        self
52    }
53
54    fn as_any_mut(&mut self) -> &mut dyn Any {
55        self
56    }
57
58    fn clone_box(&self) -> Box<dyn ReprStateStored> {
59        Box::new(self.clone())
60    }
61
62    fn serialise(&self) -> Result<serde_json::Value, serde_json::Error> {
63        serde_json::to_value(self)
64    }
65}
66
67pub trait ReprRuleStored: Send + Sync {
68    fn name(&self) -> &'static str;
69
70    fn short_name(&self) -> &'static str;
71
72    /// This representation's identity.
73    fn id(&self) -> super::ReprId;
74
75    /// Whether this representation is available when targeting `family`.
76    fn applies_to(&self, family: crate::settings::SolverFamily) -> bool;
77
78    fn init_for(&self, decl: &mut DeclarationPtr) -> ReprResult;
79
80    fn init_for_if_not_exists(&self, decl: &mut DeclarationPtr) -> ReprResult;
81
82    /// Checks applicability without mutating the source declaration and returns its compactness
83    /// score.
84    fn probe_for(&self, decl: &DeclarationPtr) -> Result<usize, ReprError>;
85
86    fn get_or_init_for<'a>(
87        &self,
88        decl: &'a mut DeclarationPtr,
89    ) -> ReprGetOrInitResult<'a, dyn ReprStateStored, ReprError>;
90
91    fn get_for<'a>(
92        &self,
93        decl: &'a DeclarationPtr,
94    ) -> Option<MappedRwLockReadGuard<'a, dyn ReprStateStored>>;
95
96    fn deserialize_state(
97        &self,
98        val: serde_json::Value,
99    ) -> Result<Box<dyn ReprStateStored>, serde_json::Error>;
100}
101
102impl<R: ReprRule> ReprRuleStored for R {
103    fn name(&self) -> &'static str {
104        R::NAME
105    }
106
107    fn id(&self) -> super::ReprId {
108        <R as ReprRule>::id()
109    }
110
111    fn short_name(&self) -> &'static str {
112        R::SHORT_NAME
113    }
114
115    fn applies_to(&self, family: crate::settings::SolverFamily) -> bool {
116        R::applies_to(family)
117    }
118
119    fn init_for(&self, decl: &mut DeclarationPtr) -> ReprResult {
120        R::init_for(decl)
121    }
122
123    fn init_for_if_not_exists(&self, decl: &mut DeclarationPtr) -> ReprResult {
124        R::init_for_if_not_exists(decl)
125    }
126
127    fn probe_for(&self, decl: &DeclarationPtr) -> Result<usize, ReprError> {
128        let domain = decl
129            .domain()
130            .ok_or_else(|| super::errors::ReprInstantiateError::NoDomain(decl.clone()))?;
131        let domain = domain.resolve().map(Into::into).unwrap_or(domain);
132        let mut detached = decl.clone().detach();
133        R::init_for(&mut detached)?;
134        R::compactness_score(domain).map_err(Into::into)
135    }
136
137    fn get_or_init_for<'a>(
138        &self,
139        decl: &'a mut DeclarationPtr,
140    ) -> ReprGetOrInitResult<'a, dyn ReprStateStored, ReprError> {
141        let (state, symbols, constraints) = R::get_or_init_for(decl)?;
142        let state_dyn = repr_state_as_dyn(state);
143        Ok((state_dyn, symbols, constraints))
144    }
145
146    fn get_for<'a>(
147        &self,
148        decl: &'a DeclarationPtr,
149    ) -> Option<MappedRwLockReadGuard<'a, dyn ReprStateStored>> {
150        let state = R::get_for(decl)?;
151        Some(repr_state_as_dyn(state))
152    }
153
154    fn deserialize_state(
155        &self,
156        val: serde_json::Value,
157    ) -> Result<Box<dyn ReprStateStored>, serde_json::Error> {
158        Ok(Box::new(R::DeclLevel::deserialize(val)?))
159    }
160}
161
162impl Debug for dyn ReprRuleStored {
163    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164        write!(fmt, "ReprRule({})", self.name())
165    }
166}
167
168impl PartialEq for dyn ReprRuleStored {
169    fn eq(&self, other: &Self) -> bool {
170        self.id() == other.id()
171    }
172}
173
174impl Eq for dyn ReprRuleStored {}
175
176impl PartialOrd for dyn ReprRuleStored {
177    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
178        Some(self.cmp(other))
179    }
180}
181
182impl Ord for dyn ReprRuleStored {
183    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
184        self.name().cmp(other.name())
185    }
186}
187
188impl Hash for dyn ReprRuleStored {
189    fn hash<H: Hasher>(&self, state: &mut H) {
190        self.name().hash(state)
191    }
192}
193
194fn repr_state_as_dyn<'a, D>(
195    guard: MappedRwLockReadGuard<'a, D>,
196) -> MappedRwLockReadGuard<'a, dyn ReprStateStored>
197where
198    D: ReprStateStored,
199{
200    MappedRwLockReadGuard::map(guard, |state| state as &dyn ReprStateStored)
201}