1use super::categories::{Category, CategoryOf};
2use super::name::Name;
3use super::serde::{DefaultWithId, HasId, IdPtr, ObjId, PtrAsInner};
4use super::{
5 DecisionVariable, DomainPtr, Expression, GroundDomain, HasDomain, Moo, RecordEntry, Reference,
6 ReturnType, Typeable,
7};
8use parking_lot::{
9 MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard,
10};
11use serde::{Deserialize, Serialize};
12use serde_with::serde_as;
13use std::any::TypeId;
14use std::collections::VecDeque;
15use std::fmt::{Debug, Display};
16use std::mem;
17use std::sync::Arc;
18use std::sync::atomic::{AtomicU32, Ordering};
19use uniplate::{Biplate, Tree, Uniplate};
20
21static DECLARATION_PTR_ID_COUNTER: AtomicU32 = const { AtomicU32::new(0) };
26
27#[doc(hidden)]
28pub fn reset_declaration_id_unchecked() {
32 let _ = DECLARATION_PTR_ID_COUNTER.swap(0, Ordering::Relaxed);
33}
34
35#[derive(Clone, Debug)]
61pub struct DeclarationPtr
62where
63 Self: Send + Sync,
64{
65 inner: Arc<DeclarationPtrInner>,
67}
68
69#[derive(Debug)]
71struct DeclarationPtrInner {
72 id: ObjId,
77
78 value: RwLock<Declaration>,
80}
81
82impl DeclarationPtrInner {
83 fn new(value: RwLock<Declaration>) -> Arc<DeclarationPtrInner> {
84 Arc::new(DeclarationPtrInner {
85 id: ObjId {
86 type_name: ustr::ustr(DeclarationPtr::TYPE_NAME),
87 object_id: DECLARATION_PTR_ID_COUNTER.fetch_add(1, Ordering::Relaxed),
88 },
89 value,
90 })
91 }
92
93 fn new_with_id_unchecked(value: RwLock<Declaration>, id: ObjId) -> Arc<DeclarationPtrInner> {
96 Arc::new(DeclarationPtrInner { id, value })
97 }
98}
99
100#[allow(dead_code)]
101impl DeclarationPtr {
102 fn from_declaration(declaration: Declaration) -> DeclarationPtr {
108 DeclarationPtr {
109 inner: DeclarationPtrInner::new(RwLock::new(declaration)),
110 }
111 }
112
113 pub fn new(name: Name, kind: DeclarationKind) -> DeclarationPtr {
127 DeclarationPtr::from_declaration(Declaration::new(name, kind))
128 }
129
130 pub fn new_find(name: Name, domain: DomainPtr) -> DeclarationPtr {
144 let kind = DeclarationKind::Find(DecisionVariable::new(domain));
145 DeclarationPtr::new(name, kind)
146 }
147
148 pub fn new_given(name: Name, domain: DomainPtr) -> DeclarationPtr {
162 let kind = DeclarationKind::Given(domain);
163 DeclarationPtr::new(name, kind)
164 }
165
166 pub fn new_quantified(name: Name, domain: DomainPtr) -> DeclarationPtr {
170 DeclarationPtr::new(
171 name,
172 DeclarationKind::Quantified(Quantified {
173 domain,
174 generator: None,
175 }),
176 )
177 }
178
179 pub fn new_quantified_from_generator(decl: &DeclarationPtr) -> Option<DeclarationPtr> {
183 let kind = DeclarationKind::Quantified(Quantified {
184 domain: decl.domain()?,
185 generator: Some(decl.clone()),
186 });
187 Some(DeclarationPtr::new(decl.name().clone(), kind))
188 }
189
190 pub fn new_value_letting(name: Name, expression: Expression) -> DeclarationPtr {
208 let kind = DeclarationKind::ValueLetting(expression, None);
209 DeclarationPtr::new(name, kind)
210 }
211
212 pub fn new_value_letting_with_domain(
232 name: Name,
233 expression: Expression,
234 domain: DomainPtr,
235 ) -> DeclarationPtr {
236 let kind = DeclarationKind::ValueLetting(expression, Some(domain));
237 DeclarationPtr::new(name, kind)
238 }
239
240 pub fn new_domain_letting(name: Name, domain: DomainPtr) -> DeclarationPtr {
254 let kind = DeclarationKind::DomainLetting(domain);
255 DeclarationPtr::new(name, kind)
256 }
257
258 pub fn new_record_field(entry: RecordEntry) -> DeclarationPtr {
275 let kind = DeclarationKind::RecordField(entry.domain);
276 DeclarationPtr::new(entry.name, kind)
277 }
278
279 pub fn domain(&self) -> Option<DomainPtr> {
297 match &self.kind() as &DeclarationKind {
298 DeclarationKind::Find(var) => Some(var.domain_of()),
299 DeclarationKind::ValueLetting(e, _) | DeclarationKind::TemporaryValueLetting(e) => {
300 e.domain_of()
301 }
302 DeclarationKind::DomainLetting(domain) => Some(domain.clone()),
303 DeclarationKind::Given(domain) => Some(domain.clone()),
304 DeclarationKind::Quantified(inner) => Some(inner.domain.clone()),
305 DeclarationKind::RecordField(domain) => Some(domain.clone()),
306 }
307 }
308
309 pub fn resolved_domain(&self) -> Option<Moo<GroundDomain>> {
311 self.domain()?.resolve()
312 }
313
314 pub fn kind(&self) -> MappedRwLockReadGuard<'_, DeclarationKind> {
326 self.map(|x| &x.kind)
327 }
328
329 pub fn name(&self) -> MappedRwLockReadGuard<'_, Name> {
342 self.map(|x| &x.name)
343 }
344
345 pub fn as_find(&self) -> Option<MappedRwLockReadGuard<'_, DecisionVariable>> {
347 RwLockReadGuard::try_map(self.read(), |x| {
348 if let DeclarationKind::Find(var) = &x.kind {
349 Some(var)
350 } else {
351 None
352 }
353 })
354 .ok()
355 }
356
357 pub fn as_find_mut(&mut self) -> Option<MappedRwLockWriteGuard<'_, DecisionVariable>> {
359 RwLockWriteGuard::try_map(self.write(), |x| {
360 if let DeclarationKind::Find(var) = &mut x.kind {
361 Some(var)
362 } else {
363 None
364 }
365 })
366 .ok()
367 }
368
369 pub fn as_domain_letting(&self) -> Option<MappedRwLockReadGuard<'_, DomainPtr>> {
371 RwLockReadGuard::try_map(self.read(), |x| {
372 if let DeclarationKind::DomainLetting(domain) = &x.kind {
373 Some(domain)
374 } else {
375 None
376 }
377 })
378 .ok()
379 }
380
381 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 pub fn as_value_letting(&self) -> Option<MappedRwLockReadGuard<'_, Expression>> {
395 RwLockReadGuard::try_map(self.read(), |x| {
396 if let DeclarationKind::ValueLetting(expression, _)
397 | DeclarationKind::TemporaryValueLetting(expression) = &x.kind
398 {
399 Some(expression)
400 } else {
401 None
402 }
403 })
404 .ok()
405 }
406
407 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 pub fn as_given(&self) -> Option<MappedRwLockReadGuard<'_, DomainPtr>> {
423 RwLockReadGuard::try_map(self.read(), |x| {
424 if let DeclarationKind::Given(domain) = &x.kind {
425 Some(domain)
426 } else {
427 None
428 }
429 })
430 .ok()
431 }
432
433 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 pub fn replace_name(&mut self, name: Name) -> Name {
460 let mut decl = self.write();
461 std::mem::replace(&mut decl.name, name)
462 }
463
464 pub fn replace_kind(&mut self, kind: DeclarationKind) -> DeclarationKind {
467 let mut decl = self.write();
468 std::mem::replace(&mut decl.kind, kind)
469 }
470
471 fn read(&self) -> RwLockReadGuard<'_, Declaration> {
485 self.inner.value.read()
486 }
487
488 fn write(&mut self) -> RwLockWriteGuard<'_, Declaration> {
493 self.inner.value.write()
494 }
495
496 pub fn detach(self) -> DeclarationPtr {
526 let value = self.inner.value.read().clone();
529 DeclarationPtr {
530 inner: DeclarationPtrInner::new(RwLock::new(value)),
531 }
532 }
533
534 fn map<U>(&self, f: impl FnOnce(&Declaration) -> &U) -> MappedRwLockReadGuard<'_, U> {
536 RwLockReadGuard::map(self.read(), f)
537 }
538
539 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 pub fn replace(&mut self, declaration: Declaration) -> Declaration {
550 let mut guard = self.write();
551 let ans = mem::replace(&mut *guard, declaration);
552 drop(guard);
553 ans
554 }
555}
556
557impl CategoryOf for DeclarationPtr {
558 fn category_of(&self) -> Category {
559 match &self.kind() as &DeclarationKind {
560 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 DeclarationKind::Quantified(..) => Category::Quantified,
566 DeclarationKind::RecordField(_) => Category::Bottom,
567 }
568 }
569}
570impl HasId for DeclarationPtr {
571 const TYPE_NAME: &'static str = "DeclarationPtrInner";
572 fn id(&self) -> ObjId {
573 self.inner.id.clone()
574 }
575}
576
577impl DefaultWithId for DeclarationPtr {
578 fn default_with_id(id: ObjId) -> Self {
579 DeclarationPtr {
580 inner: DeclarationPtrInner::new_with_id_unchecked(
581 RwLock::new(Declaration {
582 name: Name::User("_UNKNOWN".into()),
583 kind: DeclarationKind::ValueLetting(false.into(), None),
584 }),
585 id,
586 ),
587 }
588 }
589}
590
591impl 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
605impl Uniplate for DeclarationPtr {
606 fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
607 let decl = self.read();
608 let (tree, recons) = Biplate::<DeclarationPtr>::biplate(&decl as &Declaration);
609
610 let self2 = self.clone();
611 (
612 tree,
613 Box::new(move |x| {
614 let mut self3 = self2.clone();
615 let inner = recons(x);
616 *(&mut self3.write() as &mut Declaration) = inner;
617 self3
618 }),
619 )
620 }
621}
622
623impl<To> Biplate<To> for DeclarationPtr
624where
625 Declaration: Biplate<To>,
626 To: Uniplate,
627{
628 fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
629 if TypeId::of::<To>() == TypeId::of::<Self>() {
630 unsafe {
631 let self_as_to = std::mem::transmute::<&Self, &To>(self).clone();
632 (
633 Tree::One(self_as_to),
634 Box::new(move |x| {
635 let Tree::One(x) = x else { panic!() };
636
637 let x_as_self = std::mem::transmute::<&To, &Self>(&x);
638 x_as_self.clone()
639 }),
640 )
641 }
642 } else {
643 let decl = self.read();
645 let (tree, recons) = Biplate::<To>::biplate(&decl as &Declaration);
646
647 let self2 = self.clone();
648 (
649 tree,
650 Box::new(move |x| {
651 let mut self3 = self2.clone();
652 let inner = recons(x);
653 *(&mut self3.write() as &mut Declaration) = inner;
654 self3
655 }),
656 )
657 }
658 }
659}
660
661type ReferenceTree = Tree<Reference>;
662type ReferenceReconstructor<T> = Box<dyn Fn(ReferenceTree) -> T>;
663
664impl Biplate<Reference> for DeclarationPtr {
665 fn biplate(&self) -> (ReferenceTree, ReferenceReconstructor<Self>) {
666 let (tree, recons_kind) = biplate_declaration_kind_references(self.kind().clone());
667
668 let self2 = self.clone();
669 (
670 tree,
671 Box::new(move |x| {
672 let mut self3 = self2.clone();
673 let _ = self3.replace_kind(recons_kind(x));
674 self3
675 }),
676 )
677 }
678}
679
680fn biplate_domain_ptr_references(
681 domain: DomainPtr,
682) -> (ReferenceTree, ReferenceReconstructor<DomainPtr>) {
683 let domain_inner = domain.as_ref().clone();
684 let (tree, recons_domain) = Biplate::<Reference>::biplate(&domain_inner);
685 (tree, Box::new(move |x| Moo::new(recons_domain(x))))
686}
687
688fn biplate_declaration_kind_references(
689 kind: DeclarationKind,
690) -> (ReferenceTree, ReferenceReconstructor<DeclarationKind>) {
691 match kind {
692 DeclarationKind::Find(var) => {
693 let (tree, recons_domain) = biplate_domain_ptr_references(var.domain.clone());
694 (
695 tree,
696 Box::new(move |x| {
697 let mut var2 = var.clone();
698 var2.domain = recons_domain(x);
699 DeclarationKind::Find(var2)
700 }),
701 )
702 }
703 DeclarationKind::Given(domain) => {
704 let (tree, recons_domain) = biplate_domain_ptr_references(domain);
705 (
706 tree,
707 Box::new(move |x| DeclarationKind::Given(recons_domain(x))),
708 )
709 }
710 DeclarationKind::DomainLetting(domain) => {
711 let (tree, recons_domain) = biplate_domain_ptr_references(domain);
712 (
713 tree,
714 Box::new(move |x| DeclarationKind::DomainLetting(recons_domain(x))),
715 )
716 }
717 DeclarationKind::RecordField(domain) => {
718 let (tree, recons_domain) = biplate_domain_ptr_references(domain);
719 (
720 tree,
721 Box::new(move |x| DeclarationKind::RecordField(recons_domain(x))),
722 )
723 }
724 DeclarationKind::ValueLetting(expression, domain) => {
725 let (tree, recons_expr) = Biplate::<Reference>::biplate(&expression);
726 (
727 tree,
728 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}
777
778impl IdPtr for DeclarationPtr {
779 type Data = Declaration;
780
781 fn get_data(&self) -> Self::Data {
782 self.read().clone()
783 }
784
785 fn with_id_and_data(id: ObjId, data: Self::Data) -> Self {
786 Self {
787 inner: DeclarationPtrInner::new_with_id_unchecked(RwLock::new(data), id),
788 }
789 }
790}
791
792impl Ord for DeclarationPtr {
793 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
794 self.inner.id.cmp(&other.inner.id)
795 }
796}
797
798impl PartialOrd for DeclarationPtr {
799 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
800 Some(self.cmp(other))
801 }
802}
803
804impl PartialEq for DeclarationPtr {
805 fn eq(&self, other: &Self) -> bool {
806 self.inner.id == other.inner.id
807 }
808}
809
810impl Eq for DeclarationPtr {}
811
812impl std::hash::Hash for DeclarationPtr {
813 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
814 self.inner.id.hash(state);
816 }
817}
818
819impl 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)]
830pub struct Declaration {
832 name: Name,
834
835 kind: DeclarationKind,
837}
838
839impl Declaration {
840 pub fn new(name: Name, kind: DeclarationKind) -> Declaration {
842 Declaration { name, kind }
843 }
844}
845
846#[non_exhaustive]
848#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
849#[biplate(to=Expression)]
850#[biplate(to=DeclarationPtr)]
851#[biplate(to=Declaration)]
852pub enum DeclarationKind {
853 Find(DecisionVariable),
854 Given(DomainPtr),
855 Quantified(Quantified),
856
857 ValueLetting(Expression, Option<DomainPtr>),
859 DomainLetting(DomainPtr),
860
861 TemporaryValueLetting(Expression),
865
866 RecordField(DomainPtr),
869}
870
871#[serde_as]
872#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Uniplate)]
873pub struct Quantified {
874 domain: DomainPtr,
875
876 #[serde_as(as = "Option<PtrAsInner>")]
877 generator: Option<DeclarationPtr>,
878}
879
880impl Quantified {
881 pub fn domain(&self) -> &DomainPtr {
882 &self.domain
883 }
884
885 pub fn generator(&self) -> Option<&DeclarationPtr> {
886 self.generator.as_ref()
887 }
888}