1
use super::categories::{Category, CategoryOf};
2
use super::name::Name;
3
use super::serde::{DefaultWithId, HasId, IdPtr, ObjId, PtrAsInner};
4
use super::{
5
    DecisionVariable, DomainPtr, Expression, GroundDomain, HasDomain, Moo, RecordEntry, Reference,
6
    ReturnType, Typeable,
7
};
8
use parking_lot::{
9
    MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard,
10
};
11
use serde::{Deserialize, Serialize};
12
use serde_with::serde_as;
13
use std::any::TypeId;
14
use std::collections::VecDeque;
15
use std::fmt::{Debug, Display};
16
use std::mem;
17
use std::sync::Arc;
18
use std::sync::atomic::{AtomicU32, Ordering};
19
use uniplate::{Biplate, Tree, Uniplate};
20

            
21
/// Global counter of declarations.
22
/// Note that the counter is shared between all threads
23
/// Thus, when running multiple models in parallel, IDs may
24
/// be different with every run depending on scheduling order
25
static DECLARATION_PTR_ID_COUNTER: AtomicU32 = const { AtomicU32::new(0) };
26

            
27
#[doc(hidden)]
28
/// Resets the id counter of `DeclarationPtr` to 0.
29
///
30
/// This is probably always a bad idea.
31
pub fn reset_declaration_id_unchecked() {
32
    let _ = DECLARATION_PTR_ID_COUNTER.swap(0, Ordering::Relaxed);
33
}
34

            
35
/// A shared pointer to a [`Declaration`].
36
///
37
/// Two declaration pointers are equal if they point to the same underlying declaration.
38
///
39
/// # Id
40
///
41
///  The id of `DeclarationPtr` obeys the following invariants:
42
///
43
/// 1. Declaration pointers have the same id if they point to the same
44
///    underlying declaration.
45
///
46
/// 2. The id is immutable.
47
///
48
/// 3. Changing the declaration pointed to by the declaration pointer does not change the id. This
49
///    allows declarations to be updated by replacing them with a newer version of themselves.
50
///
51
/// `Ord`, `Hash`, and `Eq` use id for comparisons.
52
/// # Serde
53
///
54
/// Declaration pointers can be serialised using the following serializers:
55
///
56
/// + [`DeclarationPtrFull`](serde::DeclarationPtrFull)
57
/// + [`DeclarationPtrAsId`](serde::DeclarationPtrAsId)
58
///
59
/// See their documentation for more information.
60
#[derive(Clone, Debug)]
61
pub struct DeclarationPtr
62
where
63
    Self: Send + Sync,
64
{
65
    // the shared bits of the pointer
66
    inner: Arc<DeclarationPtrInner>,
67
}
68

            
69
// The bits of a declaration that are shared between all pointers.
70
#[derive(Debug)]
71
struct DeclarationPtrInner {
72
    // We don't want this to be mutable, as `HashMap` and `BTreeMap` rely on the hash or order of
73
    // keys to be unchanging.
74
    //
75
    // See:  https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type
76
    id: ObjId,
77

            
78
    // The contents of the declaration itself should be mutable.
79
    value: RwLock<Declaration>,
80
}
81

            
82
impl DeclarationPtrInner {
83
919924
    fn new(value: RwLock<Declaration>) -> Arc<DeclarationPtrInner> {
84
919924
        Arc::new(DeclarationPtrInner {
85
919924
            id: ObjId {
86
919924
                type_name: ustr::ustr(DeclarationPtr::TYPE_NAME),
87
919924
                object_id: DECLARATION_PTR_ID_COUNTER.fetch_add(1, Ordering::Relaxed),
88
919924
            },
89
919924
            value,
90
919924
        })
91
919924
    }
92

            
93
    // SAFETY: only use if you are really really sure you arn't going to break the id invariants of
94
    // DeclarationPtr and HasId!
95
2560
    fn new_with_id_unchecked(value: RwLock<Declaration>, id: ObjId) -> Arc<DeclarationPtrInner> {
96
2560
        Arc::new(DeclarationPtrInner { id, value })
97
2560
    }
98
}
99

            
100
#[allow(dead_code)]
101
impl DeclarationPtr {
102
    /******************************/
103
    /*        Constructors        */
104
    /******************************/
105

            
106
    /// Creates a `DeclarationPtr` for the given `Declaration`.
107
919384
    fn from_declaration(declaration: Declaration) -> DeclarationPtr {
108
919384
        DeclarationPtr {
109
919384
            inner: DeclarationPtrInner::new(RwLock::new(declaration)),
110
919384
        }
111
919384
    }
112

            
113
    /// Creates a new declaration.
114
    ///
115
    /// # Examples
116
    ///
117
    /// ```
118
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
119
    ///
120
    /// // letting MyDomain be int(1..5)
121
    /// let declaration = DeclarationPtr::new(
122
    ///     Name::User("MyDomain".into()),
123
    ///     DeclarationKind::DomainLetting(Domain::int(vec![
124
    ///         Range::Bounded(1,5)])));
125
    /// ```
126
919384
    pub fn new(name: Name, kind: DeclarationKind) -> DeclarationPtr {
127
919384
        DeclarationPtr::from_declaration(Declaration::new(name, kind))
128
919384
    }
129

            
130
    /// Creates a new find declaration.
131
    ///
132
    /// # Examples
133
    ///
134
    /// ```
135
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
136
    ///
137
    /// // find x: int(1..5)
138
    /// let declaration = DeclarationPtr::new_find(
139
    ///     Name::User("x".into()),
140
    ///     Domain::int(vec![Range::Bounded(1,5)]));
141
    ///
142
    /// ```
143
909632
    pub fn new_find(name: Name, domain: DomainPtr) -> DeclarationPtr {
144
909632
        let kind = DeclarationKind::Find(DecisionVariable::new(domain));
145
909632
        DeclarationPtr::new(name, kind)
146
909632
    }
147

            
148
    /// Creates a new given declaration.
149
    ///
150
    /// # Examples
151
    ///
152
    /// ```
153
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
154
    ///
155
    /// // given n: int(1..5)
156
    /// let declaration = DeclarationPtr::new_given(
157
    ///     Name::User("n".into()),
158
    ///     Domain::int(vec![Range::Bounded(1,5)]));
159
    ///
160
    /// ```
161
20
    pub fn new_given(name: Name, domain: DomainPtr) -> DeclarationPtr {
162
20
        let kind = DeclarationKind::Given(domain);
163
20
        DeclarationPtr::new(name, kind)
164
20
    }
165

            
166
    /// Creates a new quantified declaration for local comprehension scopes.
167
    ///
168
    /// Used when creating the quantified variable in a generator.
169
4704
    pub fn new_quantified(name: Name, domain: DomainPtr) -> DeclarationPtr {
170
4704
        DeclarationPtr::new(
171
4704
            name,
172
4704
            DeclarationKind::Quantified(Quantified {
173
4704
                domain,
174
4704
                generator: None,
175
4704
            }),
176
        )
177
4704
    }
178

            
179
    /// Creates a quantified declaration backed by a generator declaration.
180
    ///
181
    /// This is used in comprehensions to refer to a quantified variable that is already defined using a generator.
182
40
    pub fn new_quantified_from_generator(decl: &DeclarationPtr) -> Option<DeclarationPtr> {
183
40
        let kind = DeclarationKind::Quantified(Quantified {
184
40
            domain: decl.domain()?,
185
40
            generator: Some(decl.clone()),
186
        });
187
40
        Some(DeclarationPtr::new(decl.name().clone(), kind))
188
40
    }
189

            
190
    /// Creates a new value letting declaration.
191
    ///
192
    /// # Examples
193
    ///
194
    /// ```
195
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range, Expression,
196
    /// Literal,Atom,Moo};
197
    /// use conjure_cp_core::{matrix_expr,ast::Metadata};
198
    ///
199
    /// // letting n be 10 + 10
200
    /// let ten = Expression::Atomic(Metadata::new(),Atom::Literal(Literal::Int(10)));
201
    /// let expression = Expression::Sum(Metadata::new(),Moo::new(matrix_expr![ten.clone(),ten]));
202
    /// let declaration = DeclarationPtr::new_value_letting(
203
    ///     Name::User("n".into()),
204
    ///     expression);
205
    ///
206
    /// ```
207
4208
    pub fn new_value_letting(name: Name, expression: Expression) -> DeclarationPtr {
208
4208
        let kind = DeclarationKind::ValueLetting(expression);
209
4208
        DeclarationPtr::new(name, kind)
210
4208
    }
211

            
212
    /// Creates a new domain letting declaration.
213
    ///
214
    /// # Examples
215
    ///
216
    /// ```
217
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
218
    ///
219
    /// // letting MyDomain be int(1..5)
220
    /// let declaration = DeclarationPtr::new_domain_letting(
221
    ///     Name::User("MyDomain".into()),
222
    ///     Domain::int(vec![Range::Bounded(1,5)]));
223
    ///
224
    /// ```
225
660
    pub fn new_domain_letting(name: Name, domain: DomainPtr) -> DeclarationPtr {
226
660
        let kind = DeclarationKind::DomainLetting(domain);
227
660
        DeclarationPtr::new(name, kind)
228
660
    }
229

            
230
    /// Creates a new record field declaration.
231
    ///
232
    /// # Examples
233
    ///
234
    /// ```
235
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,RecordEntry,Domain,Range};
236
    ///
237
    /// // create declaration for field A in `find rec: record {A: int(0..1), B: int(0..2)}`
238
    ///
239
    /// let field = RecordEntry {
240
    ///     name: Name::User("n".into()),
241
    ///     domain: Domain::int(vec![Range::Bounded(1,5)])
242
    /// };
243
    ///
244
    /// let declaration = DeclarationPtr::new_record_field(field);
245
    /// ```
246
100
    pub fn new_record_field(entry: RecordEntry) -> DeclarationPtr {
247
100
        let kind = DeclarationKind::RecordField(entry.domain);
248
100
        DeclarationPtr::new(entry.name, kind)
249
100
    }
250

            
251
    /**********************************************/
252
    /*        Declaration accessor methods        */
253
    /**********************************************/
254

            
255
    /// Gets the domain of the declaration, if it has one.
256
    ///
257
    /// # Examples
258
    ///
259
    /// ```
260
    /// use conjure_cp_core::ast::{DeclarationPtr, Name, Domain, Range, GroundDomain};
261
    ///
262
    /// // find a: int(1..5)
263
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
264
    ///
265
    /// assert!(declaration.domain().is_some_and(|x| x.as_ground().unwrap() == &GroundDomain::Int(vec![Range::Bounded(1,5)])))
266
    ///
267
    /// ```
268
35927532
    pub fn domain(&self) -> Option<DomainPtr> {
269
35927532
        match &self.kind() as &DeclarationKind {
270
35106672
            DeclarationKind::Find(var) => Some(var.domain_of()),
271
672332
            DeclarationKind::ValueLetting(e) | DeclarationKind::TemporaryValueLetting(e) => {
272
672332
                e.domain_of()
273
            }
274
70840
            DeclarationKind::DomainLetting(domain) => Some(domain.clone()),
275
            DeclarationKind::Given(domain) => Some(domain.clone()),
276
73928
            DeclarationKind::Quantified(inner) => Some(inner.domain.clone()),
277
3760
            DeclarationKind::RecordField(domain) => Some(domain.clone()),
278
        }
279
35927532
    }
280

            
281
    /// Gets the domain of the declaration and fully resolve it
282
10080
    pub fn resolved_domain(&self) -> Option<Moo<GroundDomain>> {
283
10080
        self.domain()?.resolve()
284
10080
    }
285

            
286
    /// Gets the kind of the declaration.
287
    ///
288
    /// # Examples
289
    ///
290
    /// ```
291
    /// use conjure_cp_core::ast::{DeclarationPtr,DeclarationKind,Name,Domain,Range};
292
    ///
293
    /// // find a: int(1..5)
294
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
295
    /// assert!(matches!(&declaration.kind() as &DeclarationKind, DeclarationKind::Find(_)))
296
    /// ```
297
210542168
    pub fn kind(&self) -> MappedRwLockReadGuard<'_, DeclarationKind> {
298
210542168
        self.map(|x| &x.kind)
299
210542168
    }
300

            
301
    /// Gets the name of the declaration.
302
    ///
303
    /// # Examples
304
    ///
305
    /// ```
306
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,Domain,Range};
307
    ///
308
    /// // find a: int(1..5)
309
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
310
    ///
311
    /// assert_eq!(&declaration.name() as &Name, &Name::User("a".into()))
312
    /// ```
313
1060358600
    pub fn name(&self) -> MappedRwLockReadGuard<'_, Name> {
314
1060358600
        self.map(|x| &x.name)
315
1060358600
    }
316

            
317
    /// This declaration as a decision variable, if it is one.
318
650571168
    pub fn as_find(&self) -> Option<MappedRwLockReadGuard<'_, DecisionVariable>> {
319
650571168
        RwLockReadGuard::try_map(self.read(), |x| {
320
650571168
            if let DeclarationKind::Find(var) = &x.kind {
321
646672324
                Some(var)
322
            } else {
323
3898844
                None
324
            }
325
650571168
        })
326
650571168
        .ok()
327
650571168
    }
328

            
329
    /// This declaration as a mutable decision variable, if it is one.
330
13256
    pub fn as_find_mut(&mut self) -> Option<MappedRwLockWriteGuard<'_, DecisionVariable>> {
331
13256
        RwLockWriteGuard::try_map(self.write(), |x| {
332
13256
            if let DeclarationKind::Find(var) = &mut x.kind {
333
13256
                Some(var)
334
            } else {
335
                None
336
            }
337
13256
        })
338
13256
        .ok()
339
13256
    }
340

            
341
    /// This declaration as a domain letting, if it is one.
342
354540
    pub fn as_domain_letting(&self) -> Option<MappedRwLockReadGuard<'_, DomainPtr>> {
343
354540
        RwLockReadGuard::try_map(self.read(), |x| {
344
354540
            if let DeclarationKind::DomainLetting(domain) = &x.kind {
345
354520
                Some(domain)
346
            } else {
347
20
                None
348
            }
349
354540
        })
350
354540
        .ok()
351
354540
    }
352

            
353
    /// This declaration as a mutable domain letting, if it is one.
354
    pub fn as_domain_letting_mut(&mut self) -> Option<MappedRwLockWriteGuard<'_, DomainPtr>> {
355
        RwLockWriteGuard::try_map(self.write(), |x| {
356
            if let DeclarationKind::DomainLetting(domain) = &mut x.kind {
357
                Some(domain)
358
            } else {
359
                None
360
            }
361
        })
362
        .ok()
363
    }
364

            
365
    /// This declaration as a value letting, if it is one.
366
28575492
    pub fn as_value_letting(&self) -> Option<MappedRwLockReadGuard<'_, Expression>> {
367
28575492
        RwLockReadGuard::try_map(self.read(), |x| {
368
284396
            if let DeclarationKind::ValueLetting(expression)
369
28575492
            | DeclarationKind::TemporaryValueLetting(expression) = &x.kind
370
            {
371
1353992
                Some(expression)
372
            } else {
373
27221500
                None
374
            }
375
28575492
        })
376
28575492
        .ok()
377
28575492
    }
378

            
379
    /// This declaration as a mutable value letting, if it is one.
380
    pub fn as_value_letting_mut(&mut self) -> Option<MappedRwLockWriteGuard<'_, Expression>> {
381
        RwLockWriteGuard::try_map(self.write(), |x| {
382
            if let DeclarationKind::ValueLetting(expression)
383
            | DeclarationKind::TemporaryValueLetting(expression) = &mut x.kind
384
            {
385
                Some(expression)
386
            } else {
387
                None
388
            }
389
        })
390
        .ok()
391
    }
392

            
393
    /// Changes the name in this declaration, returning the old one.
394
    ///
395
    /// # Examples
396
    ///
397
    /// ```
398
    /// use conjure_cp_core::ast::{DeclarationPtr, Domain, Range, Name};
399
    ///
400
    /// // find a: int(1..5)
401
    /// let mut declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
402
    ///
403
    /// let old_name = declaration.replace_name(Name::User("b".into()));
404
    /// assert_eq!(old_name,Name::User("a".into()));
405
    /// assert_eq!(&declaration.name() as &Name,&Name::User("b".into()));
406
    /// ```
407
580
    pub fn replace_name(&mut self, name: Name) -> Name {
408
580
        let mut decl = self.write();
409
580
        std::mem::replace(&mut decl.name, name)
410
580
    }
411

            
412
    /// Replaces the underlying declaration kind and returns the previous kind.
413
    /// Note: this affects all cloned `DeclarationPtr`s pointing to the same declaration.
414
373480
    pub fn replace_kind(&mut self, kind: DeclarationKind) -> DeclarationKind {
415
373480
        let mut decl = self.write();
416
373480
        std::mem::replace(&mut decl.kind, kind)
417
373480
    }
418

            
419
    /*****************************************/
420
    /*        Pointer utility methods        */
421
    /*****************************************/
422

            
423
    // These are mostly wrappers over RefCell, Ref, and RefMut methods, re-exported here for
424
    // convenience.
425

            
426
    /// Read the underlying [Declaration].
427
    ///
428
    /// Will block the current thread until no other thread has a write lock.
429
    /// Attempting to get a read lock if the current thread already has one
430
    /// **will** cause it to deadlock.
431
    /// The lock is released when the returned guard goes out of scope.
432
1987238312
    fn read(&self) -> RwLockReadGuard<'_, Declaration> {
433
1987238312
        self.inner.value.read()
434
1987238312
    }
435

            
436
    /// Write the underlying [Declaration].
437
    ///
438
    /// Will block the current thread until no other thread has a read or write lock.
439
    /// The lock is released when the returned guard goes out of scope.
440
1544596
    fn write(&mut self) -> RwLockWriteGuard<'_, Declaration> {
441
1544596
        self.inner.value.write()
442
1544596
    }
443

            
444
    /// Creates a new declaration pointer with the same contents as `self` that is not shared with
445
    /// anyone else.
446
    ///
447
    /// As the resulting pointer is unshared, it will have a new id.
448
    ///
449
    /// # Examples
450
    ///
451
    /// ```
452
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,Domain,Range};
453
    ///
454
    /// // find a: int(1..5)
455
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
456
    ///
457
    /// let mut declaration2 = declaration.clone();
458
    ///
459
    /// declaration2.replace_name(Name::User("b".into()));
460
    ///
461
    /// assert_eq!(&declaration.name() as &Name, &Name::User("b".into()));
462
    /// assert_eq!(&declaration2.name() as &Name, &Name::User("b".into()));
463
    ///
464
    /// declaration2 = declaration2.detach();
465
    ///
466
    /// assert_eq!(&declaration2.name() as &Name, &Name::User("b".into()));
467
    ///
468
    /// declaration2.replace_name(Name::User("c".into()));
469
    ///
470
    /// assert_eq!(&declaration.name() as &Name, &Name::User("b".into()));
471
    /// assert_eq!(&declaration2.name() as &Name, &Name::User("c".into()));
472
    /// ```
473
540
    pub fn detach(self) -> DeclarationPtr {
474
        // despite having the same contents, the new declaration pointer is unshared, so it should
475
        // get a new id.
476
540
        let value = self.inner.value.read().clone();
477
540
        DeclarationPtr {
478
540
            inner: DeclarationPtrInner::new(RwLock::new(value)),
479
540
        }
480
540
    }
481

            
482
    /// Applies `f` to the declaration, returning the result as a reference.
483
1270900768
    fn map<U>(&self, f: impl FnOnce(&Declaration) -> &U) -> MappedRwLockReadGuard<'_, U> {
484
1270900768
        RwLockReadGuard::map(self.read(), f)
485
1270900768
    }
486

            
487
    /// Applies mutable function `f` to the declaration, returning the result as a mutable reference.
488
    fn map_mut<U>(
489
        &mut self,
490
        f: impl FnOnce(&mut Declaration) -> &mut U,
491
    ) -> MappedRwLockWriteGuard<'_, U> {
492
        RwLockWriteGuard::map(self.write(), f)
493
    }
494

            
495
    /// Replaces the declaration with a new one, returning the old value, without deinitialising
496
    /// either one.
497
    fn replace(&mut self, declaration: Declaration) -> Declaration {
498
        let mut guard = self.write();
499
        let ans = mem::replace(&mut *guard, declaration);
500
        drop(guard);
501
        ans
502
    }
503
}
504

            
505
impl CategoryOf for DeclarationPtr {
506
2464768
    fn category_of(&self) -> Category {
507
2464768
        match &self.kind() as &DeclarationKind {
508
2464528
            DeclarationKind::Find(decision_variable) => decision_variable.category_of(),
509
            DeclarationKind::ValueLetting(expression)
510
            | DeclarationKind::TemporaryValueLetting(expression) => expression.category_of(),
511
            DeclarationKind::DomainLetting(_) => Category::Constant,
512
            DeclarationKind::Given(_) => Category::Parameter,
513
240
            DeclarationKind::Quantified(..) => Category::Quantified,
514
            DeclarationKind::RecordField(_) => Category::Bottom,
515
        }
516
2464768
    }
517
}
518
impl HasId for DeclarationPtr {
519
    const TYPE_NAME: &'static str = "DeclarationPtrInner";
520
6127720
    fn id(&self) -> ObjId {
521
6127720
        self.inner.id.clone()
522
6127720
    }
523
}
524

            
525
impl DefaultWithId for DeclarationPtr {
526
920
    fn default_with_id(id: ObjId) -> Self {
527
920
        DeclarationPtr {
528
920
            inner: DeclarationPtrInner::new_with_id_unchecked(
529
920
                RwLock::new(Declaration {
530
920
                    name: Name::User("_UNKNOWN".into()),
531
920
                    kind: DeclarationKind::ValueLetting(false.into()),
532
920
                }),
533
920
                id,
534
920
            ),
535
920
        }
536
920
    }
537
}
538

            
539
impl Typeable for DeclarationPtr {
540
    fn return_type(&self) -> ReturnType {
541
        match &self.kind() as &DeclarationKind {
542
            DeclarationKind::Find(var) => var.return_type(),
543
            DeclarationKind::ValueLetting(expression)
544
            | DeclarationKind::TemporaryValueLetting(expression) => expression.return_type(),
545
            DeclarationKind::DomainLetting(domain) => domain.return_type(),
546
            DeclarationKind::Given(domain) => domain.return_type(),
547
            DeclarationKind::Quantified(inner) => inner.domain.return_type(),
548
            DeclarationKind::RecordField(domain) => domain.return_type(),
549
        }
550
    }
551
}
552

            
553
impl Uniplate for DeclarationPtr {
554
2039636
    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
555
2039636
        let decl = self.read();
556
2039636
        let (tree, recons) = Biplate::<DeclarationPtr>::biplate(&decl as &Declaration);
557

            
558
2039636
        let self2 = self.clone();
559
        (
560
2039636
            tree,
561
2039636
            Box::new(move |x| {
562
3160
                let mut self3 = self2.clone();
563
3160
                let inner = recons(x);
564
3160
                *(&mut self3.write() as &mut Declaration) = inner;
565
3160
                self3
566
3160
            }),
567
        )
568
2039636
    }
569
}
570

            
571
impl<To> Biplate<To> for DeclarationPtr
572
where
573
    Declaration: Biplate<To>,
574
    To: Uniplate,
575
{
576
36835236
    fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
577
36835236
        if TypeId::of::<To>() == TypeId::of::<Self>() {
578
            unsafe {
579
2039636
                let self_as_to = std::mem::transmute::<&Self, &To>(self).clone();
580
                (
581
2039636
                    Tree::One(self_as_to),
582
2039636
                    Box::new(move |x| {
583
1280
                        let Tree::One(x) = x else { panic!() };
584

            
585
1280
                        let x_as_self = std::mem::transmute::<&To, &Self>(&x);
586
1280
                        x_as_self.clone()
587
1280
                    }),
588
                )
589
            }
590
        } else {
591
            // call biplate on the enclosed declaration
592
34795600
            let decl = self.read();
593
34795600
            let (tree, recons) = Biplate::<To>::biplate(&decl as &Declaration);
594

            
595
34795600
            let self2 = self.clone();
596
            (
597
34795600
                tree,
598
34795600
                Box::new(move |x| {
599
1154120
                    let mut self3 = self2.clone();
600
1154120
                    let inner = recons(x);
601
1154120
                    *(&mut self3.write() as &mut Declaration) = inner;
602
1154120
                    self3
603
1154120
                }),
604
            )
605
        }
606
36835236
    }
607
}
608

            
609
type ReferenceTree = Tree<Reference>;
610
type ReferenceReconstructor<T> = Box<dyn Fn(ReferenceTree) -> T>;
611

            
612
impl Biplate<Reference> for DeclarationPtr {
613
150606376
    fn biplate(&self) -> (ReferenceTree, ReferenceReconstructor<Self>) {
614
150606376
        let (tree, recons_kind) = biplate_declaration_kind_references(self.kind().clone());
615

            
616
150606376
        let self2 = self.clone();
617
        (
618
150606376
            tree,
619
150606376
            Box::new(move |x| {
620
                let mut self3 = self2.clone();
621
                let _ = self3.replace_kind(recons_kind(x));
622
                self3
623
            }),
624
        )
625
150606376
    }
626
}
627

            
628
150281056
fn biplate_domain_ptr_references(
629
150281056
    domain: DomainPtr,
630
150281056
) -> (ReferenceTree, ReferenceReconstructor<DomainPtr>) {
631
150281056
    let domain_inner = domain.as_ref().clone();
632
150281056
    let (tree, recons_domain) = Biplate::<Reference>::biplate(&domain_inner);
633
150281056
    (tree, Box::new(move |x| Moo::new(recons_domain(x))))
634
150281056
}
635

            
636
150606376
fn biplate_declaration_kind_references(
637
150606376
    kind: DeclarationKind,
638
150606376
) -> (ReferenceTree, ReferenceReconstructor<DeclarationKind>) {
639
150606376
    match kind {
640
149502336
        DeclarationKind::Find(var) => {
641
149502336
            let (tree, recons_domain) = biplate_domain_ptr_references(var.domain.clone());
642
            (
643
149502336
                tree,
644
149502336
                Box::new(move |x| {
645
                    let mut var2 = var.clone();
646
                    var2.domain = recons_domain(x);
647
                    DeclarationKind::Find(var2)
648
                }),
649
            )
650
        }
651
        DeclarationKind::Given(domain) => {
652
            let (tree, recons_domain) = biplate_domain_ptr_references(domain);
653
            (
654
                tree,
655
                Box::new(move |x| DeclarationKind::Given(recons_domain(x))),
656
            )
657
        }
658
778360
        DeclarationKind::DomainLetting(domain) => {
659
778360
            let (tree, recons_domain) = biplate_domain_ptr_references(domain);
660
            (
661
778360
                tree,
662
778360
                Box::new(move |x| DeclarationKind::DomainLetting(recons_domain(x))),
663
            )
664
        }
665
360
        DeclarationKind::RecordField(domain) => {
666
360
            let (tree, recons_domain) = biplate_domain_ptr_references(domain);
667
            (
668
360
                tree,
669
360
                Box::new(move |x| DeclarationKind::RecordField(recons_domain(x))),
670
            )
671
        }
672
325320
        DeclarationKind::ValueLetting(expression) => {
673
325320
            let (tree, recons_expr) = Biplate::<Reference>::biplate(&expression);
674
            (
675
325320
                tree,
676
325320
                Box::new(move |x| DeclarationKind::ValueLetting(recons_expr(x))),
677
            )
678
        }
679
        DeclarationKind::TemporaryValueLetting(expression) => {
680
            let (tree, recons_expr) = Biplate::<Reference>::biplate(&expression);
681
            (
682
                tree,
683
                Box::new(move |x| DeclarationKind::TemporaryValueLetting(recons_expr(x))),
684
            )
685
        }
686
        DeclarationKind::Quantified(quantified) => {
687
            let (domain_tree, recons_domain) =
688
                biplate_domain_ptr_references(quantified.domain.clone());
689

            
690
            let (generator_tree, recons_generator) = if let Some(generator) = quantified.generator()
691
            {
692
                let generator = generator.clone();
693
                let (tree, recons_declaration) = Biplate::<Reference>::biplate(&generator);
694
                (
695
                    tree,
696
                    Box::new(move |x| Some(recons_declaration(x)))
697
                        as ReferenceReconstructor<Option<DeclarationPtr>>,
698
                )
699
            } else {
700
                (
701
                    Tree::Zero,
702
                    Box::new(|_| None) as ReferenceReconstructor<Option<DeclarationPtr>>,
703
                )
704
            };
705

            
706
            (
707
                Tree::Many(VecDeque::from([domain_tree, generator_tree])),
708
                Box::new(move |x| {
709
                    let Tree::Many(mut children) = x else {
710
                        panic!("unexpected biplate tree shape for quantified declaration")
711
                    };
712

            
713
                    let domain = children.pop_front().unwrap_or(Tree::Zero);
714
                    let generator = children.pop_front().unwrap_or(Tree::Zero);
715

            
716
                    let mut quantified2 = quantified.clone();
717
                    quantified2.domain = recons_domain(domain);
718
                    quantified2.generator = recons_generator(generator);
719
                    DeclarationKind::Quantified(quantified2)
720
                }),
721
            )
722
        }
723
    }
724
150606376
}
725

            
726
impl IdPtr for DeclarationPtr {
727
    type Data = Declaration;
728

            
729
1108
    fn get_data(&self) -> Self::Data {
730
1108
        self.read().clone()
731
1108
    }
732

            
733
1640
    fn with_id_and_data(id: ObjId, data: Self::Data) -> Self {
734
1640
        Self {
735
1640
            inner: DeclarationPtrInner::new_with_id_unchecked(RwLock::new(data), id),
736
1640
        }
737
1640
    }
738
}
739

            
740
impl Ord for DeclarationPtr {
741
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
742
        self.inner.id.cmp(&other.inner.id)
743
    }
744
}
745

            
746
impl PartialOrd for DeclarationPtr {
747
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
748
        Some(self.cmp(other))
749
    }
750
}
751

            
752
impl PartialEq for DeclarationPtr {
753
34937592
    fn eq(&self, other: &Self) -> bool {
754
34937592
        self.inner.id == other.inner.id
755
34937592
    }
756
}
757

            
758
impl Eq for DeclarationPtr {}
759

            
760
impl std::hash::Hash for DeclarationPtr {
761
3334
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
762
        // invariant: x == y -> hash(x) == hash(y)
763
3334
        self.inner.id.hash(state);
764
3334
    }
765
}
766

            
767
impl Display for DeclarationPtr {
768
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
769
        let value: &Declaration = &self.read();
770
        value.fmt(f)
771
    }
772
}
773

            
774
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Eq, Uniplate)]
775
#[biplate(to=Expression)]
776
#[biplate(to=DeclarationPtr)]
777
#[biplate(to=Name)]
778
/// The contents of a declaration
779
pub(super) struct Declaration {
780
    /// The name of the declared symbol.
781
    name: Name,
782

            
783
    /// The kind of the declaration.
784
    kind: DeclarationKind,
785
}
786

            
787
impl Declaration {
788
    /// Creates a new declaration.
789
919384
    fn new(name: Name, kind: DeclarationKind) -> Declaration {
790
919384
        Declaration { name, kind }
791
919384
    }
792
}
793

            
794
/// A specific kind of declaration.
795
#[non_exhaustive]
796
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
797
#[biplate(to=Expression)]
798
#[biplate(to=DeclarationPtr)]
799
#[biplate(to=Declaration)]
800
pub enum DeclarationKind {
801
    Find(DecisionVariable),
802
    Given(DomainPtr),
803
    Quantified(Quantified),
804

            
805
    ValueLetting(Expression),
806
    DomainLetting(DomainPtr),
807

            
808
    /// A short-lived value binding used internally during rewrites (e.g. comprehension unrolling).
809
    ///
810
    /// Unlike `ValueLetting`, this is not intended to represent a user-visible top-level `letting`.
811
    TemporaryValueLetting(Expression),
812

            
813
    /// A named field inside a record type.
814
    /// e.g. A, B in record{A: int(0..1), B: int(0..2)}
815
    RecordField(DomainPtr),
816
}
817

            
818
#[serde_as]
819
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
820
pub struct Quantified {
821
    domain: DomainPtr,
822

            
823
    #[serde_as(as = "Option<PtrAsInner>")]
824
    generator: Option<DeclarationPtr>,
825
}
826

            
827
impl Quantified {
828
80
    pub fn domain(&self) -> &DomainPtr {
829
80
        &self.domain
830
80
    }
831

            
832
171280
    pub fn generator(&self) -> Option<&DeclarationPtr> {
833
171280
        self.generator.as_ref()
834
171280
    }
835
}