conjure_cp_core/representation/
util.rs1use super::errors::ReprUpError;
2use super::types::LookupFn;
3use crate::ast::{GroundDomain, Literal, Name};
4use conjure_cp_core::ast::DeclarationPtr;
5use std::collections::HashMap;
6
7pub fn try_up_via(decl: DeclarationPtr, lu: &LookupFn<'_>) -> Result<Literal, ReprUpError> {
8 if let Some(mut result) = lu(&decl) {
10 if decl
11 .domain()
12 .and_then(|domain| domain.resolve().ok())
13 .is_some_and(|domain| domain.as_ref() == &GroundDomain::Bool)
14 {
15 result = match result {
16 Literal::Int(0) => Literal::Bool(false),
17 Literal::Int(1) => Literal::Bool(true),
18 result => result,
19 };
20 }
21 return Ok(result);
22 }
23
24 let reprs = decl.reprs();
26 if reprs.is_empty() {
27 return Err(ReprUpError::NotFound(decl.clone()));
28 }
29
30 let mut itr = reprs.iter();
32 let (_fst_name, fst) = itr.next().expect("checked that reprs is non-empty");
33 let fst_res = fst.up_via(lu)?;
34
35 #[cfg(debug_assertions)]
37 for (repr_name, repr) in itr {
38 let res = repr.up_via(lu)?;
39 assert_eq!(
40 res,
41 fst_res,
42 "representations `{}` and `{}` disagree for variable `{}`",
43 _fst_name,
44 repr_name,
45 decl.name()
46 );
47 }
48
49 Ok(fst_res)
50}
51
52pub fn try_up(
53 decl: DeclarationPtr,
54 raw_assignment: &HashMap<Name, Literal>,
55) -> Result<Literal, ReprUpError> {
56 let lu: LookupFn<'_> =
57 Box::new(|decl: &DeclarationPtr| raw_assignment.get(&decl.name()).cloned());
58 try_up_via(decl, &lu)
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64 use crate::ast::{DeclarationPtr, Domain};
65 use crate::{domain_int, range};
66
67 #[test]
68 fn represented_boolean_leaf_coerces_minion_zero_one_values() {
69 let declaration = DeclarationPtr::new_find(Name::user("flag"), Domain::bool());
70 let lookup: LookupFn<'_> = Box::new(|_| Some(Literal::Int(1)));
71 assert_eq!(
72 try_up_via(declaration, &lookup).unwrap(),
73 Literal::Bool(true)
74 );
75 }
76
77 #[test]
78 fn integer_zero_one_leaf_remains_an_integer() {
79 let declaration = DeclarationPtr::new_find(Name::user("value"), domain_int!(0..1));
80 let lookup: LookupFn<'_> = Box::new(|_| Some(Literal::Int(1)));
81 assert_eq!(try_up_via(declaration, &lookup).unwrap(), Literal::Int(1));
82 }
83}