conjure_cp_core/
representation.rs

1use std::collections::BTreeMap;
2
3use core::fmt::Debug;
4use linkme::distributed_slice;
5
6//TODO: write good documentation on this! ~niklasdewally
7
8use crate::{
9    ast::{DeclarationPtr, Expression, Literal, Name, SymbolTable},
10    rule_engine::ApplicationError,
11};
12
13#[distributed_slice]
14#[doc(hidden)]
15pub static REPRESENTATION_RULES: [RepresentationRule];
16
17#[doc(hidden)]
18pub struct RepresentationRule {
19    pub name: &'static str,
20    pub init: fn(&Name, &SymbolTable) -> Option<Box<dyn Representation>>,
21}
22
23/// Gets the representation rule named `name`.
24#[allow(clippy::type_complexity)]
25pub fn get_repr_rule(
26    name: &str,
27) -> Option<fn(&Name, &SymbolTable) -> Option<Box<dyn Representation>>> {
28    REPRESENTATION_RULES
29        .iter()
30        .find(|x| x.name == name)
31        .map(|x| x.init)
32}
33
34#[macro_export]
35macro_rules! register_representation {
36    ($ruleType:ident, $ruleName:literal) => {
37        paste::paste!{
38        #[linkme::distributed_slice($crate::representation::REPRESENTATION_RULES)]
39        pub static [<__ $ruleType:snake:upper _REPRESENTATION_RULE>]: $crate::representation::RepresentationRule = $crate::representation::RepresentationRule {
40            name: $ruleName,
41            init: [<__create_representation_ $ruleType:snake>]
42        };
43
44
45        fn [<__create_representation_ $ruleType:snake>] (name: &$crate::ast::Name, symtab: &$crate::ast::SymbolTable) -> Option<Box<dyn Representation>>  {
46                $ruleType::init(name,symtab).map(|x| Box::new(x) as Box<dyn Representation>)
47            }
48        }
49    };
50}
51
52// This alongside Representation::box_clone() allows Representation to be a trait-object but still
53// cloneable.
54impl Clone for Box<dyn Representation> {
55    fn clone(&self) -> Self {
56        self.box_clone()
57    }
58}
59
60/// Encodes the two-way relationship between a non-atomic variable and multiple auxiliary variables.
61///
62/// For example, a 2x2 matrix X might be represented by a variable for each element X1_1 X1_2 X2_1 X2_2.
63/// The [`Representation`] for X then allows us to set the value of the matrix, and takes care of
64/// assigning the individual variables accordingly. Conversly, we can set the values of the elements, and
65/// the [`Representation`] will return an assignment for the matrix as a whole.
66pub trait Representation: Send + Sync + Debug {
67    /// Creates a representation object for the given name.
68    fn init(name: &Name, symtab: &SymbolTable) -> Option<Self>
69    where
70        Self: Sized;
71
72    /// The variable being represented.
73    fn variable_name(&self) -> &Name;
74
75    /// Given an assignment for `self`, creates assignments for its representation variables.
76    fn value_down(&self, value: Literal) -> Result<BTreeMap<Name, Literal>, ApplicationError>;
77
78    /// Given assignments for its representation variables, creates an assignment for `self`.
79    fn value_up(&self, values: &BTreeMap<Name, Literal>) -> Result<Literal, ApplicationError>;
80
81    /// Returns [`Expression`]s representing each representation variable.
82    fn expression_down(
83        &self,
84        symtab: &SymbolTable,
85    ) -> Result<BTreeMap<Name, Expression>, ApplicationError>;
86
87    /// Creates declarations for the representation variables of `self`.
88    fn declaration_down(&self) -> Result<Vec<DeclarationPtr>, ApplicationError>;
89
90    /// The rule name for this representaion.
91    fn repr_name(&self) -> &str;
92
93    /// Makes a clone of `self` into a `Representation` trait object.
94    fn box_clone(&self) -> Box<dyn Representation>;
95}