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}