1
//! Default implementations of some Repr trait methods using functors;
2
//! These methods are used by the register_repr! macro
3

            
4
use super::errors::ReprUpError;
5
use super::types::{LookupFn, ReprDomainLevel, ReprInstantiateResult};
6
use super::util::try_up_via;
7
use crate::ast::{
8
    DeclarationKind, DeclarationPtr, DomainPtr, Expression, Literal, Name, SymbolTable,
9
    eval_constant,
10
};
11
use crate::representation::ReprInstantiateError;
12
use anyhow::anyhow;
13
use funcmap::{FuncMap, TryFuncMap};
14
/// Returns the number of values in a representation-variable domain.
15
/// Domains whose size is unknown or does not fit in `usize` rank as least compact.
16
8438712
pub fn domain_size(domain: &DomainPtr) -> usize {
17
8438712
    domain
18
8438712
        .length()
19
8438712
        .ok()
20
8422261
        .and_then(|size| usize::try_from(size).ok())
21
8438712
        .unwrap_or(usize::MAX)
22
8438712
}
23

            
24
/// Implement [ReprDeclLevel::lookup_via] as a functor `S<DeclarationPtr> -> S<Literal>`.
25
15097933
pub fn lookup_via_default_impl<DeclL, A>(
26
15097933
    decl_level: &DeclL,
27
15097933
    lookup: &LookupFn<'_>,
28
15097933
) -> Result<A, ReprUpError>
29
15097933
where
30
15097933
    DeclL: Clone + TryFuncMap<DeclarationPtr, Literal, Output = A>,
31
{
32
15097933
    decl_level
33
15097933
        .clone()
34
73791719
        .try_func_map(|decl: DeclarationPtr| try_up_via(decl, lookup))
35
15097933
}
36

            
37
/// Implement [ReprDeclLevel::to_domain_level] as a functor `S<DeclarationPtr> -> S<DomainPtr>`.
38
pub fn to_domain_level_default_impl<DomL, DecL>(decl_level: DecL) -> DomL
39
where
40
    DecL: FuncMap<DeclarationPtr, DomainPtr, Output = DomL>,
41
{
42
    let field_dom = |decl: DeclarationPtr| decl.domain().expect("variable must have a domain");
43
    decl_level.func_map(field_dom)
44
}
45

            
46
/// Implement [ReprDomainLevel::instantiate] as a functor `S<DomainPtr> -> S<DeclarationPtr>`.
47
/// Needs the following additional arguments:
48
/// - `structural` - function which takes `&S<DeclarationPtr>` and generates its structural constraints
49
3217998
pub fn instantiate_default_impl<DomL, DecL, A, SF>(
50
3217998
    dom_level: DomL,
51
3217998
    decl: DeclarationPtr,
52
3217998
    structural: SF,
53
3217998
) -> ReprInstantiateResult<DecL>
54
3217998
where
55
3217998
    DomL: ReprDomainLevel<Assignment = A, DeclLevel = DecL>
56
3217998
        + FuncMap<DomainPtr, DeclarationPtr, Output = DecL>,
57
3217998
    A: FuncMap<Literal, DeclarationPtr, Output = DecL>,
58
3217998
    SF: Fn(&DecL) -> Vec<Expression>,
59
{
60
3217998
    let src_name = decl.name();
61
3217998
    let repr_name = <DomL as ReprDomainLevel>::RULE.id();
62
3217998
    let mut symtab = SymbolTable::new();
63
3217998
    let mut counter = 1;
64
3217998
    let element_domains = decl.as_find().and_then(|var| var.element_domains.clone());
65

            
66
3217998
    match &decl.kind() as &DeclarationKind {
67
        DeclarationKind::Find(_) | DeclarationKind::FindAuxiliary(_) => {
68
12869914
            let declare_field_var = |dom: DomainPtr| {
69
12869914
                let dom = element_domains
70
12869914
                    .as_ref()
71
84
                    .and_then(|domains| domains.get(counter - 1))
72
                    .cloned()
73
12869914
                    .unwrap_or(dom);
74
12869914
                let name = Name::repr(src_name.clone(), repr_name, &counter.to_string());
75
12869914
                let mut field_decl = if decl.is_find_auxiliary() {
76
778136
                    DeclarationPtr::new_find_auxiliary(name, dom)
77
                } else {
78
12091778
                    DeclarationPtr::new_find(name, dom)
79
                };
80
12869914
                *(field_decl.source_mut()) = Some(decl.clone());
81
12869914
                symtab
82
12869914
                    .insert(field_decl.clone())
83
12869914
                    .expect("declaration already exists");
84
12869914
                counter += 1;
85
12869914
                field_decl
86
12869914
            };
87

            
88
3203204
            let decl_level = dom_level.func_map(declare_field_var);
89
3203204
            let constraints = structural(&decl_level);
90
3203204
            Ok((decl_level, symtab, constraints))
91
        }
92
        DeclarationKind::ValueLetting(expr, _) | DeclarationKind::TemporaryValueLetting(expr) => {
93
141055
            let declare_field_value_letting = |lit: Literal| {
94
141055
                let name = Name::repr(src_name.clone(), repr_name, &counter.to_string());
95
141055
                let mut field_decl = DeclarationPtr::new_value_letting(name, lit.into());
96
141055
                *(field_decl.source_mut()) = Some(decl.clone());
97
141055
                symtab
98
141055
                    .insert(field_decl.clone())
99
141055
                    .expect("declaration already exists");
100
141055
                counter += 1;
101
141055
                field_decl
102
141055
            };
103

            
104
14794
            let val = eval_constant(expr).ok_or(ReprInstantiateError::Other(anyhow!(
105
14794
                "expression {expr} is not constant"
106
14794
            )))?;
107
14794
            let val_down = dom_level.down(val).unwrap();
108
14794
            let decl_level = val_down.func_map(declare_field_value_letting);
109
            // no constraints for value letting reprs
110
14794
            let constraints = vec![];
111
14794
            Ok((decl_level, symtab, constraints))
112
        }
113
        _ => Err(ReprInstantiateError::BadKind(
114
            decl.clone(),
115
            String::from("expected a variable or value letting"),
116
        )),
117
    }
118
3217998
}