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
967016
    fn new(value: RwLock<Declaration>) -> Arc<DeclarationPtrInner> {
84
967016
        Arc::new(DeclarationPtrInner {
85
967016
            id: ObjId {
86
967016
                type_name: ustr::ustr(DeclarationPtr::TYPE_NAME),
87
967016
                object_id: DECLARATION_PTR_ID_COUNTER.fetch_add(1, Ordering::Relaxed),
88
967016
            },
89
967016
            value,
90
967016
        })
91
967016
    }
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
2320
    fn new_with_id_unchecked(value: RwLock<Declaration>, id: ObjId) -> Arc<DeclarationPtrInner> {
96
2320
        Arc::new(DeclarationPtrInner { id, value })
97
2320
    }
98
}
99

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

            
106
    /// Creates a `DeclarationPtr` for the given `Declaration`.
107
966216
    fn from_declaration(declaration: Declaration) -> DeclarationPtr {
108
966216
        DeclarationPtr {
109
966216
            inner: DeclarationPtrInner::new(RwLock::new(declaration)),
110
966216
        }
111
966216
    }
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
966216
    pub fn new(name: Name, kind: DeclarationKind) -> DeclarationPtr {
127
966216
        DeclarationPtr::from_declaration(Declaration::new(name, kind))
128
966216
    }
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
951836
    pub fn new_find(name: Name, domain: DomainPtr) -> DeclarationPtr {
144
951836
        let kind = DeclarationKind::Find(DecisionVariable::new(domain));
145
951836
        DeclarationPtr::new(name, kind)
146
951836
    }
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
7020
    pub fn new_quantified(name: Name, domain: DomainPtr) -> DeclarationPtr {
170
7020
        DeclarationPtr::new(
171
7020
            name,
172
7020
            DeclarationKind::Quantified(Quantified {
173
7020
                domain,
174
7020
                generator: None,
175
7020
            }),
176
        )
177
7020
    }
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
60
    pub fn new_quantified_from_generator(decl: &DeclarationPtr) -> Option<DeclarationPtr> {
183
60
        let kind = DeclarationKind::Quantified(Quantified {
184
60
            domain: decl.domain()?,
185
60
            generator: Some(decl.clone()),
186
        });
187
60
        Some(DeclarationPtr::new(decl.name().clone(), kind))
188
60
    }
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
6160
    pub fn new_value_letting(name: Name, expression: Expression) -> DeclarationPtr {
208
6160
        let kind = DeclarationKind::ValueLetting(expression);
209
6160
        DeclarationPtr::new(name, kind)
210
6160
    }
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
960
    pub fn new_domain_letting(name: Name, domain: DomainPtr) -> DeclarationPtr {
226
960
        let kind = DeclarationKind::DomainLetting(domain);
227
960
        DeclarationPtr::new(name, kind)
228
960
    }
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
140
    pub fn new_record_field(entry: RecordEntry) -> DeclarationPtr {
247
140
        let kind = DeclarationKind::RecordField(entry.domain);
248
140
        DeclarationPtr::new(entry.name, kind)
249
140
    }
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
36375290
    pub fn domain(&self) -> Option<DomainPtr> {
269
36375290
        match &self.kind() as &DeclarationKind {
270
35145890
            DeclarationKind::Find(var) => Some(var.domain_of()),
271
1006740
            DeclarationKind::ValueLetting(e) | DeclarationKind::TemporaryValueLetting(e) => {
272
1006740
                e.domain_of()
273
            }
274
106240
            DeclarationKind::DomainLetting(domain) => Some(domain.clone()),
275
            DeclarationKind::Given(domain) => Some(domain.clone()),
276
110780
            DeclarationKind::Quantified(inner) => Some(inner.domain.clone()),
277
5640
            DeclarationKind::RecordField(domain) => Some(domain.clone()),
278
        }
279
36375290
    }
280

            
281
    /// Gets the domain of the declaration and fully resolve it
282
14880
    pub fn resolved_domain(&self) -> Option<Moo<GroundDomain>> {
283
14880
        self.domain()?.resolve()
284
14880
    }
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
145469074
    pub fn kind(&self) -> MappedRwLockReadGuard<'_, DeclarationKind> {
298
145469074
        self.map(|x| &x.kind)
299
145469074
    }
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
123016376
    pub fn name(&self) -> MappedRwLockReadGuard<'_, Name> {
314
123016376
        self.map(|x| &x.name)
315
123016376
    }
316

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

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

            
341
    /// This declaration as a domain letting, if it is one.
342
531780
    pub fn as_domain_letting(&self) -> Option<MappedRwLockReadGuard<'_, DomainPtr>> {
343
531780
        RwLockReadGuard::try_map(self.read(), |x| {
344
531780
            if let DeclarationKind::DomainLetting(domain) = &x.kind {
345
531760
                Some(domain)
346
            } else {
347
20
                None
348
            }
349
531780
        })
350
531780
        .ok()
351
531780
    }
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
32548920
    pub fn as_value_letting(&self) -> Option<MappedRwLockReadGuard<'_, Expression>> {
367
32548920
        RwLockReadGuard::try_map(self.read(), |x| {
368
425180
            if let DeclarationKind::ValueLetting(expression)
369
32548920
            | DeclarationKind::TemporaryValueLetting(expression) = &x.kind
370
            {
371
2029340
                Some(expression)
372
            } else {
373
30519580
                None
374
            }
375
32548920
        })
376
32548920
        .ok()
377
32548920
    }
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
840
    pub fn replace_name(&mut self, name: Name) -> Name {
408
840
        let mut decl = self.write();
409
840
        std::mem::replace(&mut decl.name, name)
410
840
    }
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
560040
    pub fn replace_kind(&mut self, kind: DeclarationKind) -> DeclarationKind {
415
560040
        let mut decl = self.write();
416
560040
        std::mem::replace(&mut decl.kind, kind)
417
560040
    }
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
1017069604
    fn read(&self) -> RwLockReadGuard<'_, Declaration> {
433
1017069604
        self.inner.value.read()
434
1017069604
    }
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
2293800
    fn write(&mut self) -> RwLockWriteGuard<'_, Declaration> {
441
2293800
        self.inner.value.write()
442
2293800
    }
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
800
    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
800
        let value = self.inner.value.read().clone();
477
800
        DeclarationPtr {
478
800
            inner: DeclarationPtrInner::new(RwLock::new(value)),
479
800
        }
480
800
    }
481

            
482
    /// Applies `f` to the declaration, returning the result as a reference.
483
268485450
    fn map<U>(&self, f: impl FnOnce(&Declaration) -> &U) -> MappedRwLockReadGuard<'_, U> {
484
268485450
        RwLockReadGuard::map(self.read(), f)
485
268485450
    }
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
3673560
    fn category_of(&self) -> Category {
507
3673560
        match &self.kind() as &DeclarationKind {
508
3673200
            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
360
            DeclarationKind::Quantified(..) => Category::Quantified,
514
            DeclarationKind::RecordField(_) => Category::Bottom,
515
        }
516
3673560
    }
517
}
518
impl HasId for DeclarationPtr {
519
    const TYPE_NAME: &'static str = "DeclarationPtrInner";
520
8357746
    fn id(&self) -> ObjId {
521
8357746
        self.inner.id.clone()
522
8357746
    }
523
}
524

            
525
impl DefaultWithId for DeclarationPtr {
526
840
    fn default_with_id(id: ObjId) -> Self {
527
840
        DeclarationPtr {
528
840
            inner: DeclarationPtrInner::new_with_id_unchecked(
529
840
                RwLock::new(Declaration {
530
840
                    name: Name::User("_UNKNOWN".into()),
531
840
                    kind: DeclarationKind::ValueLetting(false.into()),
532
840
                }),
533
840
                id,
534
840
            ),
535
840
        }
536
840
    }
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
3045558
    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
555
3045558
        let decl = self.read();
556
3045558
        let (tree, recons) = Biplate::<DeclarationPtr>::biplate(&decl as &Declaration);
557

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

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

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

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

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

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

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

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

            
636
75927900
fn biplate_declaration_kind_references(
637
75927900
    kind: DeclarationKind,
638
75927900
) -> (ReferenceTree, ReferenceReconstructor<DeclarationKind>) {
639
75927900
    match kind {
640
74271900
        DeclarationKind::Find(var) => {
641
74271900
            let (tree, recons_domain) = biplate_domain_ptr_references(var.domain.clone());
642
            (
643
74271900
                tree,
644
74271900
                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
1167520
        DeclarationKind::DomainLetting(domain) => {
659
1167520
            let (tree, recons_domain) = biplate_domain_ptr_references(domain);
660
            (
661
1167520
                tree,
662
1167520
                Box::new(move |x| DeclarationKind::DomainLetting(recons_domain(x))),
663
            )
664
        }
665
540
        DeclarationKind::RecordField(domain) => {
666
540
            let (tree, recons_domain) = biplate_domain_ptr_references(domain);
667
            (
668
540
                tree,
669
540
                Box::new(move |x| DeclarationKind::RecordField(recons_domain(x))),
670
            )
671
        }
672
487940
        DeclarationKind::ValueLetting(expression) => {
673
487940
            let (tree, recons_expr) = Biplate::<Reference>::biplate(&expression);
674
            (
675
487940
                tree,
676
487940
                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
75927900
}
725

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

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

            
733
1480
    fn with_id_and_data(id: ObjId, data: Self::Data) -> Self {
734
1480
        Self {
735
1480
            inner: DeclarationPtrInner::new_with_id_unchecked(RwLock::new(data), id),
736
1480
        }
737
1480
    }
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
46196100
    fn eq(&self, other: &Self) -> bool {
754
46196100
        self.inner.id == other.inner.id
755
46196100
    }
756
}
757

            
758
impl Eq for DeclarationPtr {}
759

            
760
impl std::hash::Hash for DeclarationPtr {
761
4905
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
762
        // invariant: x == y -> hash(x) == hash(y)
763
4905
        self.inner.id.hash(state);
764
4905
    }
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
966216
    fn new(name: Name, kind: DeclarationKind) -> Declaration {
790
966216
        Declaration { name, kind }
791
966216
    }
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
120
    pub fn domain(&self) -> &DomainPtr {
829
120
        &self.domain
830
120
    }
831

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