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

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

            
106
    /// Creates a `DeclarationPtr` for the given `Declaration`.
107
454270
    fn from_declaration(declaration: Declaration) -> DeclarationPtr {
108
454270
        DeclarationPtr {
109
454270
            inner: DeclarationPtrInner::new(RwLock::new(declaration)),
110
454270
        }
111
454270
    }
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
454270
    pub fn new(name: Name, kind: DeclarationKind) -> DeclarationPtr {
127
454270
        DeclarationPtr::from_declaration(Declaration::new(name, kind))
128
454270
    }
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
448988
    pub fn new_find(name: Name, domain: DomainPtr) -> DeclarationPtr {
144
448988
        let kind = DeclarationKind::Find(DecisionVariable::new(domain));
145
448988
        DeclarationPtr::new(name, kind)
146
448988
    }
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
72
    pub fn new_given(name: Name, domain: DomainPtr) -> DeclarationPtr {
162
72
        let kind = DeclarationKind::Given(domain);
163
72
        DeclarationPtr::new(name, kind)
164
72
    }
165

            
166
    /// Creates a new quantified declaration for local comprehension scopes.
167
    ///
168
    /// Used when creating the quantified variable in a generator.
169
2392
    pub fn new_quantified(name: Name, domain: DomainPtr) -> DeclarationPtr {
170
2392
        DeclarationPtr::new(
171
2392
            name,
172
2392
            DeclarationKind::Quantified(Quantified {
173
2392
                domain,
174
2392
                generator: None,
175
2392
            }),
176
        )
177
2392
    }
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
20
    pub fn new_quantified_from_generator(decl: &DeclarationPtr) -> Option<DeclarationPtr> {
183
20
        let kind = DeclarationKind::Quantified(Quantified {
184
20
            domain: decl.domain()?,
185
20
            generator: Some(decl.clone()),
186
        });
187
20
        Some(DeclarationPtr::new(decl.name().clone(), kind))
188
20
    }
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
2318
    pub fn new_value_letting(name: Name, expression: Expression) -> DeclarationPtr {
208
2318
        let kind = DeclarationKind::ValueLetting(expression, None);
209
2318
        DeclarationPtr::new(name, kind)
210
2318
    }
211

            
212
    /// Creates a new value letting declaration with domain.
213
    ///
214
    /// # Examples
215
    ///
216
    /// ```
217
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range, Expression,
218
    /// Literal,Atom,Moo,DomainPtr,Metadata};
219
    /// use conjure_cp_core::{matrix_expr};
220
    ///
221
    /// // letting n be 10 + 10
222
    /// let ten = Expression::Atomic(Metadata::new(),Atom::Literal(Literal::Int(10)));
223
    /// let expression = Expression::Sum(Metadata::new(),Moo::new(matrix_expr![ten.clone(),ten]));
224
    /// let domain = Domain::bool();
225
    /// let declaration = DeclarationPtr::new_value_letting_with_domain(
226
    ///     Name::User("n".into()),
227
    ///     expression,
228
    ///     domain,
229
    /// );
230
    /// ```
231
20
    pub fn new_value_letting_with_domain(
232
20
        name: Name,
233
20
        expression: Expression,
234
20
        domain: DomainPtr,
235
20
    ) -> DeclarationPtr {
236
20
        let kind = DeclarationKind::ValueLetting(expression, Some(domain));
237
20
        DeclarationPtr::new(name, kind)
238
20
    }
239

            
240
    /// Creates a new domain letting declaration.
241
    ///
242
    /// # Examples
243
    ///
244
    /// ```
245
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,DeclarationKind,Domain,Range};
246
    ///
247
    /// // letting MyDomain be int(1..5)
248
    /// let declaration = DeclarationPtr::new_domain_letting(
249
    ///     Name::User("MyDomain".into()),
250
    ///     Domain::int(vec![Range::Bounded(1,5)]));
251
    ///
252
    /// ```
253
380
    pub fn new_domain_letting(name: Name, domain: DomainPtr) -> DeclarationPtr {
254
380
        let kind = DeclarationKind::DomainLetting(domain);
255
380
        DeclarationPtr::new(name, kind)
256
380
    }
257

            
258
    /// Creates a new record field declaration.
259
    ///
260
    /// # Examples
261
    ///
262
    /// ```
263
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,RecordEntry,Domain,Range};
264
    ///
265
    /// // create declaration for field A in `find rec: record {A: int(0..1), B: int(0..2)}`
266
    ///
267
    /// let field = RecordEntry {
268
    ///     name: Name::User("n".into()),
269
    ///     domain: Domain::int(vec![Range::Bounded(1,5)])
270
    /// };
271
    ///
272
    /// let declaration = DeclarationPtr::new_record_field(field);
273
    /// ```
274
60
    pub fn new_record_field(entry: RecordEntry) -> DeclarationPtr {
275
60
        let kind = DeclarationKind::RecordField(entry.domain);
276
60
        DeclarationPtr::new(entry.name, kind)
277
60
    }
278

            
279
    /**********************************************/
280
    /*        Declaration accessor methods        */
281
    /**********************************************/
282

            
283
    /// Gets the domain of the declaration, if it has one.
284
    ///
285
    /// # Examples
286
    ///
287
    /// ```
288
    /// use conjure_cp_core::ast::{DeclarationPtr, Name, Domain, Range, GroundDomain};
289
    ///
290
    /// // find a: int(1..5)
291
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
292
    ///
293
    /// assert!(declaration.domain().is_some_and(|x| x.as_ground().unwrap() == &GroundDomain::Int(vec![Range::Bounded(1,5)])))
294
    ///
295
    /// ```
296
20250582
    pub fn domain(&self) -> Option<DomainPtr> {
297
20250582
        match &self.kind() as &DeclarationKind {
298
17167872
            DeclarationKind::Find(var) => Some(var.domain_of()),
299
336386
            DeclarationKind::ValueLetting(e, _) | DeclarationKind::TemporaryValueLetting(e) => {
300
336386
                e.domain_of()
301
            }
302
35440
            DeclarationKind::DomainLetting(domain) => Some(domain.clone()),
303
40
            DeclarationKind::Given(domain) => Some(domain.clone()),
304
2708964
            DeclarationKind::Quantified(inner) => Some(inner.domain.clone()),
305
1880
            DeclarationKind::RecordField(domain) => Some(domain.clone()),
306
        }
307
20250582
    }
308

            
309
    /// Gets the domain of the declaration and fully resolve it
310
5440
    pub fn resolved_domain(&self) -> Option<Moo<GroundDomain>> {
311
5440
        self.domain()?.resolve()
312
5440
    }
313

            
314
    /// Gets the kind of the declaration.
315
    ///
316
    /// # Examples
317
    ///
318
    /// ```
319
    /// use conjure_cp_core::ast::{DeclarationPtr,DeclarationKind,Name,Domain,Range};
320
    ///
321
    /// // find a: int(1..5)
322
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
323
    /// assert!(matches!(&declaration.kind() as &DeclarationKind, DeclarationKind::Find(_)))
324
    /// ```
325
106351140
    pub fn kind(&self) -> MappedRwLockReadGuard<'_, DeclarationKind> {
326
106351140
        self.map(|x| &x.kind)
327
106351140
    }
328

            
329
    /// Gets the name of the declaration.
330
    ///
331
    /// # Examples
332
    ///
333
    /// ```
334
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,Domain,Range};
335
    ///
336
    /// // find a: int(1..5)
337
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
338
    ///
339
    /// assert_eq!(&declaration.name() as &Name, &Name::User("a".into()))
340
    /// ```
341
528260782
    pub fn name(&self) -> MappedRwLockReadGuard<'_, Name> {
342
528260782
        self.map(|x| &x.name)
343
528260782
    }
344

            
345
    /// This declaration as a decision variable, if it is one.
346
317364090
    pub fn as_find(&self) -> Option<MappedRwLockReadGuard<'_, DecisionVariable>> {
347
317364090
        RwLockReadGuard::try_map(self.read(), |x| {
348
317364090
            if let DeclarationKind::Find(var) = &x.kind {
349
315414264
                Some(var)
350
            } else {
351
1949826
                None
352
            }
353
317364090
        })
354
317364090
        .ok()
355
317364090
    }
356

            
357
    /// This declaration as a mutable decision variable, if it is one.
358
6488
    pub fn as_find_mut(&mut self) -> Option<MappedRwLockWriteGuard<'_, DecisionVariable>> {
359
6488
        RwLockWriteGuard::try_map(self.write(), |x| {
360
6488
            if let DeclarationKind::Find(var) = &mut x.kind {
361
6488
                Some(var)
362
            } else {
363
                None
364
            }
365
6488
        })
366
6488
        .ok()
367
6488
    }
368

            
369
    /// This declaration as a domain letting, if it is one.
370
177380
    pub fn as_domain_letting(&self) -> Option<MappedRwLockReadGuard<'_, DomainPtr>> {
371
177380
        RwLockReadGuard::try_map(self.read(), |x| {
372
177380
            if let DeclarationKind::DomainLetting(domain) = &x.kind {
373
177360
                Some(domain)
374
            } else {
375
20
                None
376
            }
377
177380
        })
378
177380
        .ok()
379
177380
    }
380

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

            
393
    /// This declaration as a value letting, if it is one.
394
14063370
    pub fn as_value_letting(&self) -> Option<MappedRwLockReadGuard<'_, Expression>> {
395
14063370
        RwLockReadGuard::try_map(self.read(), |x| {
396
142456
            if let DeclarationKind::ValueLetting(expression, _)
397
14063370
            | DeclarationKind::TemporaryValueLetting(expression) = &x.kind
398
            {
399
677254
                Some(expression)
400
            } else {
401
13386116
                None
402
            }
403
14063370
        })
404
14063370
        .ok()
405
14063370
    }
406

            
407
    /// This declaration as a mutable value letting, if it is one.
408
    pub fn as_value_letting_mut(&mut self) -> Option<MappedRwLockWriteGuard<'_, Expression>> {
409
        RwLockWriteGuard::try_map(self.write(), |x| {
410
            if let DeclarationKind::ValueLetting(expression, _)
411
            | DeclarationKind::TemporaryValueLetting(expression) = &mut x.kind
412
            {
413
                Some(expression)
414
            } else {
415
                None
416
            }
417
        })
418
        .ok()
419
    }
420

            
421
    /// This declaration as a given statement, if it is one.
422
104
    pub fn as_given(&self) -> Option<MappedRwLockReadGuard<'_, DomainPtr>> {
423
104
        RwLockReadGuard::try_map(self.read(), |x| {
424
104
            if let DeclarationKind::Given(domain) = &x.kind {
425
52
                Some(domain)
426
            } else {
427
52
                None
428
            }
429
104
        })
430
104
        .ok()
431
104
    }
432

            
433
    /// This declaration as a mutable given statement, if it is one.
434
    pub fn as_given_mut(&mut self) -> Option<MappedRwLockWriteGuard<'_, DomainPtr>> {
435
        RwLockWriteGuard::try_map(self.write(), |x| {
436
            if let DeclarationKind::Given(domain) = &mut x.kind {
437
                Some(domain)
438
            } else {
439
                None
440
            }
441
        })
442
        .ok()
443
    }
444

            
445
    /// Changes the name in this declaration, returning the old one.
446
    ///
447
    /// # Examples
448
    ///
449
    /// ```
450
    /// use conjure_cp_core::ast::{DeclarationPtr, Domain, Range, Name};
451
    ///
452
    /// // find a: int(1..5)
453
    /// let mut declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
454
    ///
455
    /// let old_name = declaration.replace_name(Name::User("b".into()));
456
    /// assert_eq!(old_name,Name::User("a".into()));
457
    /// assert_eq!(&declaration.name() as &Name,&Name::User("b".into()));
458
    /// ```
459
320
    pub fn replace_name(&mut self, name: Name) -> Name {
460
320
        let mut decl = self.write();
461
320
        std::mem::replace(&mut decl.name, name)
462
320
    }
463

            
464
    /// Replaces the underlying declaration kind and returns the previous kind.
465
    /// Note: this affects all cloned `DeclarationPtr`s pointing to the same declaration.
466
186740
    pub fn replace_kind(&mut self, kind: DeclarationKind) -> DeclarationKind {
467
186740
        let mut decl = self.write();
468
186740
        std::mem::replace(&mut decl.kind, kind)
469
186740
    }
470

            
471
    /*****************************************/
472
    /*        Pointer utility methods        */
473
    /*****************************************/
474

            
475
    // These are mostly wrappers over RefCell, Ref, and RefMut methods, re-exported here for
476
    // convenience.
477

            
478
    /// Read the underlying [Declaration].
479
    ///
480
    /// Will block the current thread until no other thread has a write lock.
481
    /// Attempting to get a read lock if the current thread already has one
482
    /// **will** cause it to deadlock.
483
    /// The lock is released when the returned guard goes out of scope.
484
984509678
    fn read(&self) -> RwLockReadGuard<'_, Declaration> {
485
984509678
        self.inner.value.read()
486
984509678
    }
487

            
488
    /// Write the underlying [Declaration].
489
    ///
490
    /// Will block the current thread until no other thread has a read or write lock.
491
    /// The lock is released when the returned guard goes out of scope.
492
773372
    fn write(&mut self) -> RwLockWriteGuard<'_, Declaration> {
493
773372
        self.inner.value.write()
494
773372
    }
495

            
496
    /// Creates a new declaration pointer with the same contents as `self` that is not shared with
497
    /// anyone else.
498
    ///
499
    /// As the resulting pointer is unshared, it will have a new id.
500
    ///
501
    /// # Examples
502
    ///
503
    /// ```
504
    /// use conjure_cp_core::ast::{DeclarationPtr,Name,Domain,Range};
505
    ///
506
    /// // find a: int(1..5)
507
    /// let declaration = DeclarationPtr::new_find(Name::User("a".into()),Domain::int(vec![Range::Bounded(1,5)]));
508
    ///
509
    /// let mut declaration2 = declaration.clone();
510
    ///
511
    /// declaration2.replace_name(Name::User("b".into()));
512
    ///
513
    /// assert_eq!(&declaration.name() as &Name, &Name::User("b".into()));
514
    /// assert_eq!(&declaration2.name() as &Name, &Name::User("b".into()));
515
    ///
516
    /// declaration2 = declaration2.detach();
517
    ///
518
    /// assert_eq!(&declaration2.name() as &Name, &Name::User("b".into()));
519
    ///
520
    /// declaration2.replace_name(Name::User("c".into()));
521
    ///
522
    /// assert_eq!(&declaration.name() as &Name, &Name::User("b".into()));
523
    /// assert_eq!(&declaration2.name() as &Name, &Name::User("c".into()));
524
    /// ```
525
280
    pub fn detach(self) -> DeclarationPtr {
526
        // despite having the same contents, the new declaration pointer is unshared, so it should
527
        // get a new id.
528
280
        let value = self.inner.value.read().clone();
529
280
        DeclarationPtr {
530
280
            inner: DeclarationPtrInner::new(RwLock::new(value)),
531
280
        }
532
280
    }
533

            
534
    /// Applies `f` to the declaration, returning the result as a reference.
535
634611922
    fn map<U>(&self, f: impl FnOnce(&Declaration) -> &U) -> MappedRwLockReadGuard<'_, U> {
536
634611922
        RwLockReadGuard::map(self.read(), f)
537
634611922
    }
538

            
539
    /// Applies mutable function `f` to the declaration, returning the result as a mutable reference.
540
    fn map_mut<U>(
541
        &mut self,
542
        f: impl FnOnce(&mut Declaration) -> &mut U,
543
    ) -> MappedRwLockWriteGuard<'_, U> {
544
        RwLockWriteGuard::map(self.write(), f)
545
    }
546

            
547
    /// Replaces the declaration with a new one, returning the old value, without deinitialising
548
    /// either one.
549
24
    pub fn replace(&mut self, declaration: Declaration) -> Declaration {
550
24
        let mut guard = self.write();
551
24
        let ans = mem::replace(&mut *guard, declaration);
552
24
        drop(guard);
553
24
        ans
554
24
    }
555
}
556

            
557
impl CategoryOf for DeclarationPtr {
558
1232384
    fn category_of(&self) -> Category {
559
1232384
        match &self.kind() as &DeclarationKind {
560
1232264
            DeclarationKind::Find(decision_variable) => decision_variable.category_of(),
561
            DeclarationKind::ValueLetting(expression, _)
562
            | DeclarationKind::TemporaryValueLetting(expression) => expression.category_of(),
563
            DeclarationKind::DomainLetting(_) => Category::Constant,
564
            DeclarationKind::Given(_) => Category::Parameter,
565
120
            DeclarationKind::Quantified(..) => Category::Quantified,
566
            DeclarationKind::RecordField(_) => Category::Bottom,
567
        }
568
1232384
    }
569
}
570
impl HasId for DeclarationPtr {
571
    const TYPE_NAME: &'static str = "DeclarationPtrInner";
572
3046290
    fn id(&self) -> ObjId {
573
3046290
        self.inner.id.clone()
574
3046290
    }
575
}
576

            
577
impl DefaultWithId for DeclarationPtr {
578
1000
    fn default_with_id(id: ObjId) -> Self {
579
1000
        DeclarationPtr {
580
1000
            inner: DeclarationPtrInner::new_with_id_unchecked(
581
1000
                RwLock::new(Declaration {
582
1000
                    name: Name::User("_UNKNOWN".into()),
583
1000
                    kind: DeclarationKind::ValueLetting(false.into(), None),
584
1000
                }),
585
1000
                id,
586
1000
            ),
587
1000
        }
588
1000
    }
589
}
590

            
591
impl Typeable for DeclarationPtr {
592
    fn return_type(&self) -> ReturnType {
593
        match &self.kind() as &DeclarationKind {
594
            DeclarationKind::Find(var) => var.return_type(),
595
            DeclarationKind::ValueLetting(expression, _)
596
            | DeclarationKind::TemporaryValueLetting(expression) => expression.return_type(),
597
            DeclarationKind::DomainLetting(domain) => domain.return_type(),
598
            DeclarationKind::Given(domain) => domain.return_type(),
599
            DeclarationKind::Quantified(inner) => inner.domain.return_type(),
600
            DeclarationKind::RecordField(domain) => domain.return_type(),
601
        }
602
    }
603
}
604

            
605
impl Uniplate for DeclarationPtr {
606
1021308
    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
607
1021308
        let decl = self.read();
608
1021308
        let (tree, recons) = Biplate::<DeclarationPtr>::biplate(&decl as &Declaration);
609

            
610
1021308
        let self2 = self.clone();
611
        (
612
1021308
            tree,
613
1021308
            Box::new(move |x| {
614
2120
                let mut self3 = self2.clone();
615
2120
                let inner = recons(x);
616
2120
                *(&mut self3.write() as &mut Declaration) = inner;
617
2120
                self3
618
2120
            }),
619
        )
620
1021308
    }
621
}
622

            
623
impl<To> Biplate<To> for DeclarationPtr
624
where
625
    Declaration: Biplate<To>,
626
    To: Uniplate,
627
{
628
18291808
    fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
629
18291808
        if TypeId::of::<To>() == TypeId::of::<Self>() {
630
            unsafe {
631
1021308
                let self_as_to = std::mem::transmute::<&Self, &To>(self).clone();
632
                (
633
1021308
                    Tree::One(self_as_to),
634
1021308
                    Box::new(move |x| {
635
640
                        let Tree::One(x) = x else { panic!() };
636

            
637
640
                        let x_as_self = std::mem::transmute::<&To, &Self>(&x);
638
640
                        x_as_self.clone()
639
640
                    }),
640
                )
641
            }
642
        } else {
643
            // call biplate on the enclosed declaration
644
17270500
            let decl = self.read();
645
17270500
            let (tree, recons) = Biplate::<To>::biplate(&decl as &Declaration);
646

            
647
17270500
            let self2 = self.clone();
648
            (
649
17270500
                tree,
650
17270500
                Box::new(move |x| {
651
577680
                    let mut self3 = self2.clone();
652
577680
                    let inner = recons(x);
653
577680
                    *(&mut self3.write() as &mut Declaration) = inner;
654
577680
                    self3
655
577680
                }),
656
            )
657
        }
658
18291808
    }
659
}
660

            
661
type ReferenceTree = Tree<Reference>;
662
type ReferenceReconstructor<T> = Box<dyn Fn(ReferenceTree) -> T>;
663

            
664
impl Biplate<Reference> for DeclarationPtr {
665
74147212
    fn biplate(&self) -> (ReferenceTree, ReferenceReconstructor<Self>) {
666
74147212
        let (tree, recons_kind) = biplate_declaration_kind_references(self.kind().clone());
667

            
668
74147212
        let self2 = self.clone();
669
        (
670
74147212
            tree,
671
74147212
            Box::new(move |x| {
672
                let mut self3 = self2.clone();
673
                let _ = self3.replace_kind(recons_kind(x));
674
                self3
675
            }),
676
        )
677
74147212
    }
678
}
679

            
680
73984492
fn biplate_domain_ptr_references(
681
73984492
    domain: DomainPtr,
682
73984492
) -> (ReferenceTree, ReferenceReconstructor<DomainPtr>) {
683
73984492
    let domain_inner = domain.as_ref().clone();
684
73984492
    let (tree, recons_domain) = Biplate::<Reference>::biplate(&domain_inner);
685
73984492
    (tree, Box::new(move |x| Moo::new(recons_domain(x))))
686
73984492
}
687

            
688
74147212
fn biplate_declaration_kind_references(
689
74147212
    kind: DeclarationKind,
690
74147212
) -> (ReferenceTree, ReferenceReconstructor<DeclarationKind>) {
691
74147212
    match kind {
692
73595072
        DeclarationKind::Find(var) => {
693
73595072
            let (tree, recons_domain) = biplate_domain_ptr_references(var.domain.clone());
694
            (
695
73595072
                tree,
696
73595072
                Box::new(move |x| {
697
                    let mut var2 = var.clone();
698
                    var2.domain = recons_domain(x);
699
                    DeclarationKind::Find(var2)
700
                }),
701
            )
702
        }
703
40
        DeclarationKind::Given(domain) => {
704
40
            let (tree, recons_domain) = biplate_domain_ptr_references(domain);
705
            (
706
40
                tree,
707
40
                Box::new(move |x| DeclarationKind::Given(recons_domain(x))),
708
            )
709
        }
710
389200
        DeclarationKind::DomainLetting(domain) => {
711
389200
            let (tree, recons_domain) = biplate_domain_ptr_references(domain);
712
            (
713
389200
                tree,
714
389200
                Box::new(move |x| DeclarationKind::DomainLetting(recons_domain(x))),
715
            )
716
        }
717
180
        DeclarationKind::RecordField(domain) => {
718
180
            let (tree, recons_domain) = biplate_domain_ptr_references(domain);
719
            (
720
180
                tree,
721
180
                Box::new(move |x| DeclarationKind::RecordField(recons_domain(x))),
722
            )
723
        }
724
162720
        DeclarationKind::ValueLetting(expression, domain) => {
725
162720
            let (tree, recons_expr) = Biplate::<Reference>::biplate(&expression);
726
            (
727
162720
                tree,
728
162720
                Box::new(move |x| DeclarationKind::ValueLetting(recons_expr(x), domain.clone())),
729
            )
730
        }
731
        DeclarationKind::TemporaryValueLetting(expression) => {
732
            let (tree, recons_expr) = Biplate::<Reference>::biplate(&expression);
733
            (
734
                tree,
735
                Box::new(move |x| DeclarationKind::TemporaryValueLetting(recons_expr(x))),
736
            )
737
        }
738
        DeclarationKind::Quantified(quantified) => {
739
            let (domain_tree, recons_domain) =
740
                biplate_domain_ptr_references(quantified.domain.clone());
741

            
742
            let (generator_tree, recons_generator) = if let Some(generator) = quantified.generator()
743
            {
744
                let generator = generator.clone();
745
                let (tree, recons_declaration) = Biplate::<Reference>::biplate(&generator);
746
                (
747
                    tree,
748
                    Box::new(move |x| Some(recons_declaration(x)))
749
                        as ReferenceReconstructor<Option<DeclarationPtr>>,
750
                )
751
            } else {
752
                (
753
                    Tree::Zero,
754
                    Box::new(|_| None) as ReferenceReconstructor<Option<DeclarationPtr>>,
755
                )
756
            };
757

            
758
            (
759
                Tree::Many(VecDeque::from([domain_tree, generator_tree])),
760
                Box::new(move |x| {
761
                    let Tree::Many(mut children) = x else {
762
                        panic!("unexpected biplate tree shape for quantified declaration")
763
                    };
764

            
765
                    let domain = children.pop_front().unwrap_or(Tree::Zero);
766
                    let generator = children.pop_front().unwrap_or(Tree::Zero);
767

            
768
                    let mut quantified2 = quantified.clone();
769
                    quantified2.domain = recons_domain(domain);
770
                    quantified2.generator = recons_generator(generator);
771
                    DeclarationKind::Quantified(quantified2)
772
                }),
773
            )
774
        }
775
    }
776
74147212
}
777

            
778
impl IdPtr for DeclarationPtr {
779
    type Data = Declaration;
780

            
781
1004
    fn get_data(&self) -> Self::Data {
782
1004
        self.read().clone()
783
1004
    }
784

            
785
1720
    fn with_id_and_data(id: ObjId, data: Self::Data) -> Self {
786
1720
        Self {
787
1720
            inner: DeclarationPtrInner::new_with_id_unchecked(RwLock::new(data), id),
788
1720
        }
789
1720
    }
790
}
791

            
792
impl Ord for DeclarationPtr {
793
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
794
        self.inner.id.cmp(&other.inner.id)
795
    }
796
}
797

            
798
impl PartialOrd for DeclarationPtr {
799
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
800
        Some(self.cmp(other))
801
    }
802
}
803

            
804
impl PartialEq for DeclarationPtr {
805
17334756
    fn eq(&self, other: &Self) -> bool {
806
17334756
        self.inner.id == other.inner.id
807
17334756
    }
808
}
809

            
810
impl Eq for DeclarationPtr {}
811

            
812
impl std::hash::Hash for DeclarationPtr {
813
1667
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
814
        // invariant: x == y -> hash(x) == hash(y)
815
1667
        self.inner.id.hash(state);
816
1667
    }
817
}
818

            
819
impl Display for DeclarationPtr {
820
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
821
        let value: &Declaration = &self.read();
822
        value.fmt(f)
823
    }
824
}
825

            
826
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Eq, Uniplate)]
827
#[biplate(to=Expression)]
828
#[biplate(to=DeclarationPtr)]
829
#[biplate(to=Name)]
830
/// The contents of a declaration
831
pub struct Declaration {
832
    /// The name of the declared symbol.
833
    name: Name,
834

            
835
    /// The kind of the declaration.
836
    kind: DeclarationKind,
837
}
838

            
839
impl Declaration {
840
    /// Creates a new declaration.
841
454294
    pub fn new(name: Name, kind: DeclarationKind) -> Declaration {
842
454294
        Declaration { name, kind }
843
454294
    }
844
}
845

            
846
/// A specific kind of declaration.
847
#[non_exhaustive]
848
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
849
#[biplate(to=Expression)]
850
#[biplate(to=DeclarationPtr)]
851
#[biplate(to=Declaration)]
852
pub enum DeclarationKind {
853
    Find(DecisionVariable),
854
    Given(DomainPtr),
855
    Quantified(Quantified),
856

            
857
    /// Carries an optional domain so instantiated `given`s can retain their declared domain.
858
    ValueLetting(Expression, Option<DomainPtr>),
859
    DomainLetting(DomainPtr),
860

            
861
    /// A short-lived value binding used internally during rewrites (e.g. comprehension unrolling).
862
    ///
863
    /// Unlike `ValueLetting`, this is not intended to represent a user-visible top-level `letting`.
864
    TemporaryValueLetting(Expression),
865

            
866
    /// A named field inside a record type.
867
    /// e.g. A, B in record{A: int(0..1), B: int(0..2)}
868
    RecordField(DomainPtr),
869
}
870

            
871
#[serde_as]
872
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
873
pub struct Quantified {
874
    domain: DomainPtr,
875

            
876
    #[serde_as(as = "Option<PtrAsInner>")]
877
    generator: Option<DeclarationPtr>,
878
}
879

            
880
impl Quantified {
881
40
    pub fn domain(&self) -> &DomainPtr {
882
40
        &self.domain
883
40
    }
884

            
885
85640
    pub fn generator(&self) -> Option<&DeclarationPtr> {
886
85640
        self.generator.as_ref()
887
85640
    }
888
}