module Darcs.Patch.Invertible
( Invertible
, mkInvertible
, fromPositiveInvertible
, withInvertible
) where
import Darcs.Prelude
import Darcs.Patch.CommuteFn ( invertCommuter )
import Darcs.Patch.Ident
( Ident(..), PatchId, SignedId(..) )
import Darcs.Patch.Invert ( Invert(..) )
import Darcs.Patch.RepoPatch
( Apply(..)
, Commute(..)
, Eq2(..)
, PrimPatchBase(..)
, PatchInspect(..)
, ShowContextPatch(..)
, ShowPatch(..)
, ShowPatchBasic(..)
)
import Darcs.Patch.Show ( ShowPatchFor(..) )
import Darcs.Patch.Witnesses.Ordered ((:>)(..))
data Invertible p wX wY where
Fwd :: p wX wY -> Invertible p wX wY
Rev :: p wX wY -> Invertible p wY wX
mkInvertible :: p wX wY -> Invertible p wX wY
mkInvertible = Fwd
fromPositiveInvertible :: Invertible p wX wY -> p wX wY
fromPositiveInvertible (Fwd p) = p
fromPositiveInvertible (Rev _) = error "precondition of fromPositiveInvertible"
withInvertible :: (forall wA wB. p wA wB -> r) -> Invertible p wX wY -> r
withInvertible f (Fwd p) = f p
withInvertible f (Rev p) = f p
instance Invert (Invertible p) where
invert (Fwd p) = Rev p
invert (Rev p) = Fwd p
instance Commute p => Commute (Invertible p) where
commute (Fwd p :> Fwd q) = do
q' :> p' <- commute (p :> q)
return (Fwd q' :> Fwd p')
commute pair@(Rev _ :> Rev _) = invertCommuter commute pair
commute _ = error "cannote commute mixed Fwd/Rev"
instance Eq2 p => Eq2 (Invertible p) where
Fwd p =\/= Fwd q = p =\/= q
Rev p =\/= Rev q = p =/\= q
_ =\/= _ = error "cannot compare mixed Fwd/Rev"
instance Apply p => Apply (Invertible p) where
type ApplyState (Invertible p) = ApplyState p
apply (Fwd p) = apply p
apply (Rev p) = unapply p
unapply (Fwd p) = unapply p
unapply (Rev p) = apply p
data InvertibleId ident = InvertibleId Bool ident
deriving (Eq, Ord)
instance Ord ident => SignedId (InvertibleId ident) where
positiveId (InvertibleId inverted _) = inverted
invertId (InvertibleId inverted theid) =
InvertibleId (not inverted) theid
type instance PatchId (Invertible p) = InvertibleId (PatchId p)
instance Ident p => Ident (Invertible p) where
ident (Fwd p) = InvertibleId False (ident p)
ident (Rev p) = InvertibleId True (ident p)
instance PatchInspect p => PatchInspect (Invertible p) where
listTouchedFiles (Fwd p) = listTouchedFiles p
listTouchedFiles (Rev p) = listTouchedFiles p
hunkMatches f (Fwd p) = hunkMatches f p
hunkMatches f (Rev p) = hunkMatches f p
instance PrimPatchBase p => PrimPatchBase (Invertible p) where
type PrimOf (Invertible p) = PrimOf p
instance ShowPatchBasic p => ShowPatchBasic (Invertible p) where
showPatch ForStorage = error "Invertible patches must not be stored"
showPatch ForDisplay = withInvertible (showPatch ForDisplay)
instance ShowPatch p => ShowPatch (Invertible p) where
description = withInvertible description
summary = withInvertible summary
content = withInvertible content
instance ShowContextPatch p => ShowContextPatch (Invertible p) where
showContextPatch ForStorage = error "Invertible patches must not be stored"
showContextPatch ForDisplay = withInvertible (showContextPatch ForDisplay)