@@ -997,6 +997,12 @@ impl Pred {
997997/// An atom is a predicate applied to a list of terms.
998998#[ derive( Debug , Clone ) ]
999999pub struct Atom < V = TermVarIdx > {
1000+ /// With `guard`, this represents `guard => pred(args)`.
1001+ ///
1002+ /// As long as there is no pvar in the `guard`, it forms a valid CHC. However, in that case,
1003+ /// it becomes odd to call this an `Atom`... It is our TODO to clean this up by either
1004+ /// getting rid of the `guard` or renaming `Atom`.
1005+ pub guard : Option < Box < Formula < V > > > ,
10001006 pub pred : Pred ,
10011007 pub args : Vec < Term < V > > ,
10021008}
@@ -1008,7 +1014,12 @@ where
10081014 D :: Doc : Clone ,
10091015{
10101016 fn pretty ( self , allocator : & ' a D ) -> pretty:: DocBuilder < ' a , D , termcolor:: ColorSpec > {
1011- if self . pred . is_infix ( ) {
1017+ let guard = if let Some ( guard) = & self . guard {
1018+ guard. pretty ( allocator) . append ( allocator. text ( " ⇒" ) )
1019+ } else {
1020+ allocator. nil ( )
1021+ } ;
1022+ let atom = if self . pred . is_infix ( ) {
10121023 self . args [ 0 ]
10131024 . pretty_atom ( allocator)
10141025 . append ( allocator. line ( ) )
@@ -1027,42 +1038,58 @@ where
10271038 } else {
10281039 p. append ( allocator. line ( ) ) . append ( inner. nest ( 2 ) ) . group ( )
10291040 }
1030- }
1041+ } ;
1042+ guard. append ( allocator. line ( ) ) . append ( atom) . group ( )
10311043 }
10321044}
10331045
10341046impl < V > Atom < V > {
10351047 pub fn new ( pred : Pred , args : Vec < Term < V > > ) -> Self {
1036- Atom { pred, args }
1048+ Atom {
1049+ guard : None ,
1050+ pred,
1051+ args,
1052+ }
10371053 }
10381054
1039- pub fn top ( ) -> Self {
1055+ pub fn with_guard ( guard : Formula < V > , pred : Pred , args : Vec < Term < V > > ) -> Self {
10401056 Atom {
1041- pred : KnownPred :: TOP . into ( ) ,
1042- args : vec ! [ ] ,
1057+ guard : Some ( Box :: new ( guard) ) ,
1058+ pred,
1059+ args,
10431060 }
10441061 }
10451062
1063+ pub fn top ( ) -> Self {
1064+ Atom :: new ( KnownPred :: TOP . into ( ) , vec ! [ ] )
1065+ }
1066+
10461067 pub fn bottom ( ) -> Self {
1047- Atom {
1048- pred : KnownPred :: BOTTOM . into ( ) ,
1049- args : vec ! [ ] ,
1050- }
1068+ Atom :: new ( KnownPred :: BOTTOM . into ( ) , vec ! [ ] )
10511069 }
10521070
10531071 pub fn is_top ( & self ) -> bool {
1054- self . pred . is_top ( )
1072+ if let Some ( guard) = & self . guard {
1073+ guard. is_bottom ( ) || self . pred . is_top ( )
1074+ } else {
1075+ self . pred . is_top ( )
1076+ }
10551077 }
10561078
10571079 pub fn is_bottom ( & self ) -> bool {
1058- self . pred . is_bottom ( )
1080+ if let Some ( guard) = & self . guard {
1081+ guard. is_top ( ) && self . pred . is_bottom ( )
1082+ } else {
1083+ self . pred . is_bottom ( )
1084+ }
10591085 }
10601086
10611087 pub fn subst_var < F , W > ( self , mut f : F ) -> Atom < W >
10621088 where
10631089 F : FnMut ( V ) -> Term < W > ,
10641090 {
10651091 Atom {
1092+ guard : self . guard . map ( |fo| Box :: new ( fo. subst_var ( & mut f) ) ) ,
10661093 pred : self . pred ,
10671094 args : self . args . into_iter ( ) . map ( |t| t. subst_var ( & mut f) ) . collect ( ) ,
10681095 }
@@ -1073,13 +1100,37 @@ impl<V> Atom<V> {
10731100 F : FnMut ( V ) -> W ,
10741101 {
10751102 Atom {
1103+ guard : self . guard . map ( |fo| Box :: new ( fo. map_var ( & mut f) ) ) ,
10761104 pred : self . pred ,
10771105 args : self . args . into_iter ( ) . map ( |t| t. map_var ( & mut f) ) . collect ( ) ,
10781106 }
10791107 }
10801108
10811109 pub fn fv ( & self ) -> impl Iterator < Item = & V > {
1082- self . args . iter ( ) . flat_map ( |t| t. fv ( ) )
1110+ let guard_fvs: Box < dyn Iterator < Item = & V > > = if let Some ( guard) = & self . guard {
1111+ Box :: new ( guard. fv ( ) )
1112+ } else {
1113+ Box :: new ( std:: iter:: empty ( ) )
1114+ } ;
1115+ self . args . iter ( ) . flat_map ( |t| t. fv ( ) ) . chain ( guard_fvs)
1116+ }
1117+
1118+ pub fn guarded ( self , new_guard : Formula < V > ) -> Atom < V > {
1119+ let Atom {
1120+ guard : self_guard,
1121+ pred,
1122+ args,
1123+ } = self ;
1124+ let guard = if let Some ( self_guard) = self_guard {
1125+ self_guard. and ( new_guard)
1126+ } else {
1127+ new_guard
1128+ } ;
1129+ Atom {
1130+ guard : Some ( Box :: new ( guard) ) ,
1131+ pred,
1132+ args,
1133+ }
10831134 }
10841135}
10851136
@@ -1456,6 +1507,22 @@ impl<V> Body<V> {
14561507 }
14571508}
14581509
1510+ impl < V > Body < V >
1511+ where
1512+ V : Var ,
1513+ {
1514+ pub fn guarded ( self , guard : Formula < V > ) -> Body < V > {
1515+ let Body { atoms, formula } = self ;
1516+ Body {
1517+ atoms : atoms
1518+ . into_iter ( )
1519+ . map ( |a| a. guarded ( guard. clone ( ) ) )
1520+ . collect ( ) ,
1521+ formula : guard. not ( ) . or ( formula) ,
1522+ }
1523+ }
1524+ }
1525+
14591526impl < ' a , ' b , D , V > Pretty < ' a , D , termcolor:: ColorSpec > for & ' b Body < V >
14601527where
14611528 V : Var ,
0 commit comments