conjure_core/rules/
select_representation.rs
1use conjure_core::ast::Expression as Expr;
2use conjure_core::ast::SymbolTable;
3use conjure_core::rule_engine::{
4 register_rule, ApplicationError::RuleNotApplicable, ApplicationResult, Reduction,
5};
6use itertools::Itertools;
7
8use crate::ast::Atom;
9use crate::ast::Domain;
10use crate::ast::Name;
11use crate::bug;
12use crate::metadata::Metadata;
13use crate::representation::Representation;
14
15#[register_rule(("Base", 8000))]
16fn select_representation(expr: &Expr, symbols: &SymbolTable) -> ApplicationResult {
17 let Expr::Atomic(_, Atom::Reference(name)) = expr else {
19 return Err(RuleNotApplicable);
20 };
21
22 symbols
24 .lookup(name)
25 .ok_or(RuleNotApplicable)?
26 .as_var()
27 .ok_or(RuleNotApplicable)?;
28
29 if !needs_representation(name, symbols) {
30 return Err(RuleNotApplicable);
31 }
32
33 let mut symbols = symbols.clone();
34 let representation =
35 get_or_create_representation(name, &mut symbols).ok_or(RuleNotApplicable)?;
36
37 let representation_names = representation
38 .into_iter()
39 .map(|x| x.repr_name().to_string())
40 .collect_vec();
41
42 let new_name = Name::WithRepresentation(Box::new(name.clone()), representation_names);
43
44 Ok(Reduction::with_symbols(
45 Expr::Atomic(Metadata::new(), Atom::Reference(new_name)),
46 symbols,
47 ))
48}
49
50fn needs_representation(name: &Name, symbols: &SymbolTable) -> bool {
56 domain_needs_representation(&symbols.resolve_domain(name).unwrap())
58}
59
60fn domain_needs_representation(domain: &Domain) -> bool {
62 match domain {
64 Domain::BoolDomain | Domain::IntDomain(_) => false,
65 Domain::DomainSet(_, _) | Domain::DomainMatrix(_, _) => true,
66 Domain::DomainReference(_) => unreachable!("domain should be resolved"),
67 }
68}
69
70fn get_or_create_representation(
79 name: &Name,
80 symbols: &mut SymbolTable,
81) -> Option<Vec<Box<dyn Representation>>> {
82 match symbols.resolve_domain(name).unwrap() {
85 Domain::DomainSet(_, _) => None,
86 Domain::DomainMatrix(elem_domain, _) => {
87 if domain_needs_representation(elem_domain.as_ref()) {
90 bug!("representing nested abstract domains is not implemented");
91 }
92
93 symbols.get_or_add_representation(name, &["matrix_to_atom"])
94 }
95 _ => unreachable!("non abstract domains should never need representations"),
96 }
97}