Skip to main content

conjure_cp_core/ast/
declaration.rs

1pub mod serde;
2
3use serde::DeclarationPtrFull;
4
5use std::any::TypeId;
6// allow use of Declaration in this file, and nowhere else
7use std::cell::{Cell, Ref, RefCell, RefMut};
8use std::fmt::{Debug, Display};
9use std::rc::Rc;
10
11use ::serde::{Deserialize, Serialize};
12use serde_with::serde_as;
13
14use super::categories::{Category, CategoryOf};
15use super::name::Name;
16use super::serde::{DefaultWithId, HasId, ObjId};
17use super::{
18    DecisionVariable, DomainPtr, Expression, GroundDomain, Moo, RecordEntry, ReturnType, Typeable,
19};
20use crate::ast::domains::HasDomain;
21use uniplate::{Biplate, Tree, Uniplate};
22
23thread_local! {
24    // make each thread have its own id counter.
25    static DECLARATION_PTR_ID_COUNTER: Cell<u32> = const { Cell::new(0) };
26
27    // We run integration tests in parallel threads - making this thread local ensures that
28    // declarations in a test always have the same id, instead of the ids depending on how many
29    // threads are running, how they are scheduled, etc.
30}
31
32#[doc(hidden)]
33/// Resets the id counter of `DeclarationPtr` to 0.
34///
35/// This is probably always a bad idea.
36pub fn reset_declaration_id_unchecked() {
37    DECLARATION_PTR_ID_COUNTER.set(0);
38}
39
40/// A shared pointer to a [`Declaration`].
41///
42/// Two declaration pointers are equal if they point to the same underlying declaration.
43///
44/// # Id
45///
46///  The id of `DeclarationPtr` obeys the following invariants:
47///
48/// 1. Declaration pointers have the same id if they point to the same
49///    underlying declaration.
50///
51/// 2. The id is immutable.
52///
53/// 3. Changing the declaration pointed to by the declaration pointer does not change the id. This
54///    allows declarations to be updated by replacing them with a newer version of themselves.
55///
56/// `Ord`, `Hash`, and `Eq` use id for comparisons.
57/// # Serde
58///
59/// Declaration pointers can be serialised using the following serializers:
60///
61/// + [`DeclarationPtrFull`](serde::DeclarationPtrFull)
62/// + [`DeclarationPtrAsId`](serde::DeclarationPtrAsId)
63///
64/// See their documentation for more information.
65#[derive(Clone, Debug)]
66pub struct DeclarationPtr {
67    // the shared bits of the pointer
68    inner: Rc<DeclarationPtrInner>,
69}
70
71// The bits of a declaration that are shared between all pointers.
72#[derive(Clone, Debug)]
73struct DeclarationPtrInner {
74    // We don't want this to be mutable, as `HashMap` and `BTreeMap` rely on the hash or order of
75    // keys to be unchanging.
76    //
77    // See:  https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type
78    id: ObjId,
79
80    // The contents of the declaration itself should be mutable.
81    value: RefCell<Declaration>,
82}
83
84impl DeclarationPtrInner {
85    fn new(value: RefCell<Declaration>) -> Rc<DeclarationPtrInner> {
86        Rc::new(DeclarationPtrInner {
87            id: ObjId {
88                type_name: ustr::ustr(DeclarationPtr::TYPE_NAME),
89                object_id: DECLARATION_PTR_ID_COUNTER.replace(DECLARATION_PTR_ID_COUNTER.get() + 1),
90            },
91            value,
92        })
93    }
94
95    // SAFETY: only use if you are really really sure you arn't going to break the id invariants of
96    // DeclarationPtr and HasId!
97    fn new_with_id_unchecked(value: RefCell<Declaration>, id: ObjId) -> Rc<DeclarationPtrInner> {
98        Rc::new(DeclarationPtrInner { id, value })
99    }
100}
101
102#[allow(dead_code)]
103impl DeclarationPtr {
104    /******************************/
105    /*        Constructors        */
106    /******************************/
107
108    /// Creates a `DeclarationPtr` for the given `Declaration`.
109    fn from_declaration(declaration: Declaration) -> DeclarationPtr {
110        DeclarationPtr {
111            inner: DeclarationPtrInner::new(RefCell::new(declaration)),
112        }
113    }
114
115    /// Creates a new declaration.
116    ///
117    /// # Examples
118    ///
119    /// ```
120    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
121    ///
122    /// // letting MyDomain be int(1..5)
123    /// let declaration = DeclarationPtr::new(
124    ///     Name::User("MyDomain".into()),
125    ///     DeclarationKind::DomainLetting(Domain::int(vec![
126    ///         Range::Bounded(1,5)])));
127    /// ```
128    pub fn new(name: Name, kind: DeclarationKind) -> DeclarationPtr {
129        DeclarationPtr::from_declaration(Declaration::new(name, kind))
130    }
131
132    /// Creates a new decision variable declaration with the decision category.
133    ///
134    /// # Examples
135    ///
136    /// ```
137    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
138    ///
139    /// // find x: int(1..5)
140    /// let declaration = DeclarationPtr::new_var(
141    ///     Name::User("x".into()),
142    ///     Domain::int(vec![Range::Bounded(1,5)]));
143    ///
144    /// ```
145    pub fn new_var(name: Name, domain: DomainPtr) -> DeclarationPtr {
146        let kind =
147            DeclarationKind::DecisionVariable(DecisionVariable::new(domain, Category::Decision));
148        DeclarationPtr::new(name, kind)
149    }
150
151    /// Creates a new decision variable with the quantified category.
152    ///
153    /// This is useful to represent a quantified / induction variable in a comprehension.
154    pub fn new_var_quantified(name: Name, domain: DomainPtr) -> DeclarationPtr {
155        let kind =
156            DeclarationKind::DecisionVariable(DecisionVariable::new(domain, Category::Quantified));
157
158        DeclarationPtr::new(name, kind)
159    }
160
161    /// Creates a new domain letting declaration.
162    ///
163    /// # Examples
164    ///
165    /// ```
166    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
167    ///
168    /// // letting MyDomain be int(1..5)
169    /// let declaration = DeclarationPtr::new_domain_letting(
170    ///     Name::User("MyDomain".into()),
171    ///     Domain::int(vec![Range::Bounded(1,5)]));
172    ///
173    /// ```
174    pub fn new_domain_letting(name: Name, domain: DomainPtr) -> DeclarationPtr {
175        let kind = DeclarationKind::DomainLetting(domain);
176        DeclarationPtr::new(name, kind)
177    }
178
179    /// Creates a new value letting declaration.
180    ///
181    /// # Examples
182    ///
183    /// ```
184    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range, Expression,
185    /// Literal,Atom,Moo};
186    /// use conjure_cp_core::{matrix_expr,ast::Metadata};
187    ///
188    /// // letting n be 10 + 10
189    /// let ten = Expression::Atomic(Metadata::new(),Atom::Literal(Literal::Int(10)));
190    /// let expression = Expression::Sum(Metadata::new(),Moo::new(matrix_expr![ten.clone(),ten]));
191    /// let declaration = DeclarationPtr::new_value_letting(
192    ///     Name::User("n".into()),
193    ///     expression);
194    ///
195    /// ```
196    pub fn new_value_letting(name: Name, expression: Expression) -> DeclarationPtr {
197        let kind = DeclarationKind::ValueLetting(expression);
198        DeclarationPtr::new(name, kind)
199    }
200
201    /// Creates a new given declaration.
202    ///
203    /// # Examples
204    ///
205    /// ```
206    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
207    ///
208    /// // given n: int(1..5)
209    /// let declaration = DeclarationPtr::new_given(
210    ///     Name::User("n".into()),
211    ///     Domain::int(vec![Range::Bounded(1,5)]));
212    ///
213    /// ```
214    pub fn new_given(name: Name, domain: DomainPtr) -> DeclarationPtr {
215        let kind = DeclarationKind::Given(domain);
216        DeclarationPtr::new(name, kind)
217    }
218
219    /// Creates a new given declaration backed by a quantified declaration.
220    ///
221    /// This is used in abstract comprehensions, where a variable in the return expression
222    /// is "given", but also references its counterpart in the generator.
223    pub fn new_given_quantified(decl: &DeclarationPtr) -> Option<DeclarationPtr> {
224        let kind = DeclarationKind::GivenQuantified(GivenQuantified {
225            domain: decl.domain()?,
226            generator: decl.clone(),
227        });
228        Some(DeclarationPtr::new(decl.name().clone(), kind))
229    }
230
231    /// Creates a new record field declaration.
232    ///
233    /// # Examples
234    ///
235    /// ```
236    /// use conjure_cp_core::ast::{DeclarationPtr,Name,RecordEntry,Domain,Range};
237    ///
238    /// // create declaration for field A in `find rec: record {A: int(0..1), B: int(0..2)}`
239    ///
240    /// let field = RecordEntry {
241    ///     name: Name::User("n".into()),
242    ///     domain: Domain::int(vec![Range::Bounded(1,5)])
243    /// };
244    ///
245    /// let declaration = DeclarationPtr::new_record_field(field);
246    /// ```
247    pub fn new_record_field(entry: RecordEntry) -> DeclarationPtr {
248        let kind = DeclarationKind::RecordField(entry.domain);
249        DeclarationPtr::new(entry.name, kind)
250    }
251
252    /**********************************************/
253    /*        Declaration accessor methods        */
254    /**********************************************/
255
256    /// Gets the domain of the declaration, if it has one.
257    ///
258    /// # Examples
259    ///
260    /// ```
261    /// use conjure_cp_core::ast::{DeclarationPtr, Name, Domain, Range, GroundDomain};
262    ///
263    /// // find a: int(1..5)
264    /// let declaration = DeclarationPtr::new_var(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
265    ///
266    /// assert!(declaration.domain().is_some_and(|x| x.as_ground().unwrap() == &GroundDomain::Int(vec![Range::Bounded(1,5)])))
267    ///
268    /// ```
269    pub fn domain(&self) -> Option<DomainPtr> {
270        match &self.kind() as &DeclarationKind {
271            DeclarationKind::DecisionVariable(var) => Some(var.domain_of()),
272            DeclarationKind::ValueLetting(e) => e.domain_of(),
273            DeclarationKind::DomainLetting(domain) => Some(domain.clone()),
274            DeclarationKind::Given(domain) => Some(domain.clone()),
275            DeclarationKind::GivenQuantified(inner) => Some(inner.domain.clone()),
276            DeclarationKind::RecordField(domain) => Some(domain.clone()),
277        }
278    }
279
280    /// Gets the domain of the declaration and fully resolve it
281    pub fn resolved_domain(&self) -> Option<Moo<GroundDomain>> {
282        self.domain()?.resolve()
283    }
284
285    /// Gets the kind of the declaration.
286    ///
287    /// # Examples
288    ///
289    /// ```
290    /// use conjure_cp_core::ast::{DeclarationPtr,DeclarationKind,Name,Domain,Range};
291    ///
292    /// // find a: int(1..5)
293    /// let declaration = DeclarationPtr::new_var(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
294    /// assert!(matches!(&declaration.kind() as &DeclarationKind, DeclarationKind::DecisionVariable(_)))
295    /// ```
296    pub fn kind(&self) -> Ref<'_, DeclarationKind> {
297        self.map(|x| &x.kind)
298    }
299
300    /// Gets the name of the declaration.
301    ///
302    /// # Examples
303    ///
304    /// ```
305    /// use conjure_cp_core::ast::{DeclarationPtr,Name,Domain,Range};
306    ///
307    /// // find a: int(1..5)
308    /// let declaration = DeclarationPtr::new_var(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
309    ///
310    /// assert_eq!(&declaration.name() as &Name, &Name::User("a".into()))
311    /// ```
312    pub fn name(&self) -> Ref<'_, Name> {
313        self.map(|x| &x.name)
314    }
315
316    /// This declaration as a decision variable, if it is one.
317    pub fn as_var(&self) -> Option<Ref<'_, DecisionVariable>> {
318        Ref::filter_map(self.borrow(), |x| {
319            if let DeclarationKind::DecisionVariable(var) = &x.kind {
320                Some(var)
321            } else {
322                None
323            }
324        })
325        .ok()
326    }
327
328    /// This declaration as a mutable decision variable, if it is one.
329    pub fn as_var_mut(&mut self) -> Option<RefMut<'_, DecisionVariable>> {
330        RefMut::filter_map(self.borrow_mut(), |x| {
331            if let DeclarationKind::DecisionVariable(var) = &mut x.kind {
332                Some(var)
333            } else {
334                None
335            }
336        })
337        .ok()
338    }
339
340    /// This declaration as a domain letting, if it is one.
341    pub fn as_domain_letting(&self) -> Option<Ref<'_, DomainPtr>> {
342        Ref::filter_map(self.borrow(), |x| {
343            if let DeclarationKind::DomainLetting(domain) = &x.kind {
344                Some(domain)
345            } else {
346                None
347            }
348        })
349        .ok()
350    }
351
352    /// This declaration as a mutable domain letting, if it is one.
353    pub fn as_domain_letting_mut(&mut self) -> Option<RefMut<'_, DomainPtr>> {
354        RefMut::filter_map(self.borrow_mut(), |x| {
355            if let DeclarationKind::DomainLetting(domain) = &mut x.kind {
356                Some(domain)
357            } else {
358                None
359            }
360        })
361        .ok()
362    }
363
364    /// This declaration as a value letting, if it is one.
365    pub fn as_value_letting(&self) -> Option<Ref<'_, Expression>> {
366        Ref::filter_map(self.borrow(), |x| {
367            if let DeclarationKind::ValueLetting(e) = &x.kind {
368                Some(e)
369            } else {
370                None
371            }
372        })
373        .ok()
374    }
375
376    /// This declaration as a mutable value letting, if it is one.
377    pub fn as_value_letting_mut(&mut self) -> Option<RefMut<'_, Expression>> {
378        RefMut::filter_map(self.borrow_mut(), |x| {
379            if let DeclarationKind::ValueLetting(e) = &mut x.kind {
380                Some(e)
381            } else {
382                None
383            }
384        })
385        .ok()
386    }
387
388    /// Changes the name in this declaration, returning the old one.
389    ///
390    /// # Examples
391    ///
392    /// ```
393    /// use conjure_cp_core::ast::{DeclarationPtr, Domain, Range, Name};
394    ///
395    /// // find a: int(1..5)
396    /// let mut declaration = DeclarationPtr::new_var(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
397    ///
398    /// let old_name = declaration.replace_name(Name::User("b".into()));
399    /// assert_eq!(old_name,Name::User("a".into()));
400    /// assert_eq!(&declaration.name() as &Name,&Name::User("b".into()));
401    /// ```
402    pub fn replace_name(&mut self, name: Name) -> Name {
403        let mut decl = self.borrow_mut();
404        std::mem::replace(&mut decl.name, name)
405    }
406
407    /*****************************************/
408    /*        Pointer utility methods        */
409    /*****************************************/
410
411    // These are mostly wrappers over RefCell, Ref, and RefMut methods, re-exported here for
412    // convenience.
413
414    /// Immutably borrows the declaration.
415    fn borrow(&self) -> Ref<'_, Declaration> {
416        // unlike refcell.borrow(), this never panics
417        self.inner.value.borrow()
418    }
419
420    /// Mutably borrows the declaration.
421    fn borrow_mut(&mut self) -> RefMut<'_, Declaration> {
422        // unlike refcell.borrow_mut(), this never panics
423        self.inner.value.borrow_mut()
424    }
425
426    /// Creates a new declaration pointer with the same contents as `self` that is not shared with
427    /// anyone else.
428    ///
429    /// As the resulting pointer is unshared, it will have a new id.
430    ///
431    /// # Examples
432    ///
433    /// ```
434    /// use conjure_cp_core::ast::{DeclarationPtr,Name,Domain,Range};
435    ///
436    /// // find a: int(1..5)
437    /// let declaration = DeclarationPtr::new_var(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
438    ///
439    /// let mut declaration2 = declaration.clone();
440    ///
441    /// declaration2.replace_name(Name::User("b".into()));
442    ///
443    /// assert_eq!(&declaration.name() as &Name, &Name::User("b".into()));
444    /// assert_eq!(&declaration2.name() as &Name, &Name::User("b".into()));
445    ///
446    /// declaration2 = declaration2.detach();
447    ///
448    /// assert_eq!(&declaration2.name() as &Name, &Name::User("b".into()));
449    ///
450    /// declaration2.replace_name(Name::User("c".into()));
451    ///
452    /// assert_eq!(&declaration.name() as &Name, &Name::User("b".into()));
453    /// assert_eq!(&declaration2.name() as &Name, &Name::User("c".into()));
454    /// ```
455    pub fn detach(self) -> DeclarationPtr {
456        // despite having the same contents, the new declaration pointer is unshared, so it should
457        // get a new id.
458        DeclarationPtr {
459            inner: DeclarationPtrInner::new(self.inner.value.clone()),
460        }
461    }
462
463    /// Applies `f` to the declaration, returning the result as a reference.
464    fn map<U>(&self, f: impl FnOnce(&Declaration) -> &U) -> Ref<'_, U> {
465        Ref::map(self.borrow(), f)
466    }
467
468    /// Applies mutable function `f` to the declaration, returning the result as a mutable reference.
469    fn map_mut<U>(&mut self, f: impl FnOnce(&mut Declaration) -> &mut U) -> RefMut<'_, U> {
470        RefMut::map(self.borrow_mut(), f)
471    }
472
473    /// Replaces the declaration with a new one, returning the old value, without deinitialising
474    /// either one.
475    fn replace(&mut self, declaration: Declaration) -> Declaration {
476        self.inner.value.replace(declaration)
477    }
478}
479
480impl CategoryOf for DeclarationPtr {
481    fn category_of(&self) -> Category {
482        match &self.kind() as &DeclarationKind {
483            DeclarationKind::DecisionVariable(decision_variable) => decision_variable.category_of(),
484            DeclarationKind::ValueLetting(expression) => expression.category_of(),
485            DeclarationKind::DomainLetting(_) => Category::Constant,
486            DeclarationKind::Given(_) => Category::Parameter,
487            DeclarationKind::GivenQuantified(..) => Category::Parameter,
488            DeclarationKind::RecordField(_) => Category::Bottom,
489        }
490    }
491}
492impl HasId for DeclarationPtr {
493    const TYPE_NAME: &'static str = "DeclarationPtrInner";
494    fn id(&self) -> ObjId {
495        self.inner.id.clone()
496    }
497}
498
499impl DefaultWithId for DeclarationPtr {
500    fn default_with_id(id: ObjId) -> Self {
501        DeclarationPtr {
502            inner: DeclarationPtrInner::new_with_id_unchecked(
503                RefCell::new(Declaration {
504                    name: Name::User("_UNKNOWN".into()),
505                    kind: DeclarationKind::ValueLetting(false.into()),
506                }),
507                id,
508            ),
509        }
510    }
511}
512
513impl Typeable for DeclarationPtr {
514    fn return_type(&self) -> ReturnType {
515        match &self.kind() as &DeclarationKind {
516            DeclarationKind::DecisionVariable(var) => var.return_type(),
517            DeclarationKind::ValueLetting(expression) => expression.return_type(),
518            DeclarationKind::DomainLetting(domain) => domain.return_type(),
519            DeclarationKind::Given(domain) => domain.return_type(),
520            DeclarationKind::GivenQuantified(inner) => inner.domain.return_type(),
521            DeclarationKind::RecordField(domain) => domain.return_type(),
522        }
523    }
524}
525
526impl Uniplate for DeclarationPtr {
527    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
528        let decl = self.borrow();
529        let (tree, recons) = Biplate::<DeclarationPtr>::biplate(&decl as &Declaration);
530
531        let self2 = self.clone();
532        (
533            tree,
534            Box::new(move |x| {
535                let mut self3 = self2.clone();
536                let inner = recons(x);
537                *(&mut self3.borrow_mut() as &mut Declaration) = inner;
538                self3
539            }),
540        )
541    }
542}
543
544impl<To> Biplate<To> for DeclarationPtr
545where
546    Declaration: Biplate<To>,
547    To: Uniplate,
548{
549    fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
550        if TypeId::of::<To>() == TypeId::of::<Self>() {
551            unsafe {
552                let self_as_to = std::mem::transmute::<&Self, &To>(self).clone();
553                (
554                    Tree::One(self_as_to),
555                    Box::new(move |x| {
556                        let Tree::One(x) = x else { panic!() };
557
558                        let x_as_self = std::mem::transmute::<&To, &Self>(&x);
559                        x_as_self.clone()
560                    }),
561                )
562            }
563        } else {
564            // call biplate on the enclosed declaration
565            let decl = self.borrow();
566            let (tree, recons) = Biplate::<To>::biplate(&decl as &Declaration);
567
568            let self2 = self.clone();
569            (
570                tree,
571                Box::new(move |x| {
572                    let mut self3 = self2.clone();
573                    let inner = recons(x);
574                    *(&mut self3.borrow_mut() as &mut Declaration) = inner;
575                    self3
576                }),
577            )
578        }
579    }
580}
581
582impl Ord for DeclarationPtr {
583    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
584        self.inner.id.cmp(&other.inner.id)
585    }
586}
587
588impl PartialOrd for DeclarationPtr {
589    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
590        Some(self.cmp(other))
591    }
592}
593
594impl PartialEq for DeclarationPtr {
595    fn eq(&self, other: &Self) -> bool {
596        self.inner.id == other.inner.id
597    }
598}
599
600impl Eq for DeclarationPtr {}
601
602impl std::hash::Hash for DeclarationPtr {
603    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
604        // invariant: x == y -> hash(x) == hash(y)
605        self.inner.id.hash(state);
606    }
607}
608
609impl Display for DeclarationPtr {
610    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
611        let value: &Declaration = &self.borrow();
612        value.fmt(f)
613    }
614}
615
616#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Eq, Uniplate)]
617#[biplate(to=Expression)]
618#[biplate(to=DeclarationPtr)]
619#[biplate(to=Name)]
620/// The contents of a declaration
621struct Declaration {
622    /// The name of the declared symbol.
623    name: Name,
624
625    /// The kind of the declaration.
626    kind: DeclarationKind,
627}
628
629impl Declaration {
630    /// Creates a new declaration.
631    fn new(name: Name, kind: DeclarationKind) -> Declaration {
632        Declaration { name, kind }
633    }
634}
635
636/// A specific kind of declaration.
637#[non_exhaustive]
638#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
639#[biplate(to=Expression)]
640#[biplate(to=DeclarationPtr)]
641#[biplate(to=Declaration)]
642pub enum DeclarationKind {
643    DecisionVariable(DecisionVariable),
644    ValueLetting(Expression),
645    DomainLetting(DomainPtr),
646    Given(DomainPtr),
647
648    GivenQuantified(GivenQuantified),
649
650    /// A named field inside a record type.
651    /// e.g. A, B in record{A: int(0..1), B: int(0..2)}
652    RecordField(DomainPtr),
653}
654
655#[serde_as]
656#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
657pub struct GivenQuantified {
658    domain: DomainPtr,
659
660    #[serde_as(as = "DeclarationPtrFull")]
661    generator: DeclarationPtr,
662}
663
664impl GivenQuantified {
665    pub fn domain(&self) -> &DomainPtr {
666        &self.domain
667    }
668
669    pub fn generator(&self) -> &DeclarationPtr {
670        &self.generator
671    }
672}