{-# OPTIONS_GHC -fno-warn-orphans -fno-warn-name-shadowing #-}
{-# LANGUAGE UndecidableInstances #-}
module Darcs.Patch.V2.Non
( Non(..)
, Nonable(..)
, unNon
, showNon
, showNons
, readNon
, readNons
, commutePrimsOrAddToCtx
, commuteOrAddToCtx
, commuteOrRemFromCtx
, commuteOrAddToCtxRL
, commuteOrRemFromCtxFL
, remNons
, (*>)
, (>*)
, (*>>)
, (>>*)
) where
import Darcs.Prelude hiding ( (*>) )
import Data.List ( delete )
import Control.Monad ( liftM, mzero )
import Darcs.Patch.Apply ( Apply(..) )
import Darcs.Patch.Commute ( commuteFL )
import Darcs.Patch.Effect ( Effect(..) )
import Darcs.Patch.Format ( PatchListFormat )
import Darcs.Patch.Invert ( Invert, invertFL, invertRL )
import Darcs.Patch.FromPrim
( FromPrim(..), ToFromPrim
, PrimOf, PrimPatchBase, toPrim
)
import Darcs.Patch.Prim ( sortCoalesceFL )
import Darcs.Patch.Commute ( Commute(..) )
import Darcs.Patch.Invert ( Invert(invert) )
import Darcs.Patch.Read ( ReadPatch(..) )
import Darcs.Patch.Show ( showPatch )
import Darcs.Util.Parser ( Parser, lexChar )
import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) )
import Darcs.Patch.Witnesses.Ordered
( FL(..), RL(..), (+>+), mapRL_RL
, (:>)(..), reverseFL, reverseRL )
import Darcs.Patch.Witnesses.Show ( Show1, Show2, appPrec, showsPrec2 )
import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed) )
import Darcs.Patch.Read ( peekfor )
import Darcs.Patch.Show ( ShowPatchBasic, ShowPatchFor )
import Darcs.Patch.Viewing ()
import Darcs.Patch.Permutations ( removeFL, commuteWhatWeCanFL )
import Darcs.Util.Printer ( Doc, empty, vcat, hiddenPrefix, blueText, ($$) )
import qualified Data.ByteString.Char8 as BC ( pack, singleton )
data Non p wX where
Non :: FL p wX wY -> PrimOf p wY wZ -> Non p wX
unNon :: FromPrim p => Non p wX -> Sealed (FL p wX)
unNon (Non c x) = Sealed (c +>+ fromAnonymousPrim x :>: NilFL)
instance (Show2 p, Show2 (PrimOf p)) => Show (Non p wX) where
showsPrec d (Non cs p) = showParen (d > appPrec) $ showString "Non " .
showsPrec2 (appPrec + 1) cs . showString " " .
showsPrec2 (appPrec + 1) p
instance (Show2 p, Show2 (PrimOf p)) => Show1 (Non p)
showNons :: (ShowPatchBasic p, PatchListFormat p, PrimPatchBase p)
=> ShowPatchFor -> [Non p wX] -> Doc
showNons _ [] = empty
showNons f xs = blueText "{{" $$ vcat (map (showNon f) xs) $$ blueText "}}"
showNon :: (ShowPatchBasic p, PatchListFormat p, PrimPatchBase p)
=> ShowPatchFor
-> Non p wX
-> Doc
showNon f (Non c p) = hiddenPrefix "|" (showPatch f c)
$$ hiddenPrefix "|" (blueText ":")
$$ showPatch f p
readNons :: (ReadPatch p, PatchListFormat p, PrimPatchBase p)
=> Parser [Non p wX]
readNons = peekfor (BC.pack "{{") rns (return [])
where rns = peekfor (BC.pack "}}") (return []) $
do Sealed ps <- readPatch'
lexChar ':'
Sealed p <- readPatch'
(Non ps p :) `liftM` rns
readNon :: (ReadPatch p, PatchListFormat p, PrimPatchBase p)
=> Parser (Non p wX)
readNon = do Sealed ps <- readPatch'
let doReadPrim = do Sealed p <- readPatch'
return $ Non ps p
peekfor (BC.singleton ':') doReadPrim mzero
instance (Commute p, Eq2 p, Eq2 (PrimOf p)) => Eq (Non p wX) where
Non (cx :: FL p wX wY1) (x :: PrimOf p wY1 wZ1)
== Non (cy :: FL p wX wY2) (y :: PrimOf p wY2 wZ2) =
case cx =\/= cy of
IsEq -> case x =\/= y :: EqCheck wZ1 wZ2 of
IsEq -> True
NotEq -> False
NotEq -> False
class Nonable p where
non :: p wX wY -> Non p wX
commuteOrAddToCtx :: (Commute p, ToFromPrim p) => p wX wY -> Non p wY
-> Non p wX
commuteOrAddToCtx p n | Just n' <- p >* n = n'
commuteOrAddToCtx p (Non c x) = Non (p:>:c) x
commuteOrAddToCtxRL :: (Apply p, Commute p, Invert p, ToFromPrim p) => RL p wX wY -> Non p wY
-> Non p wX
commuteOrAddToCtxRL NilRL n = n
commuteOrAddToCtxRL (ps:<:p) n = commuteOrAddToCtxRL ps $ commuteOrAddToCtx p n
class WL l where
toRL :: l p wX wY -> RL p wX wY
invertWL :: Invert p => l p wX wY -> l p wY wX
instance WL FL where
toRL = reverseFL
invertWL = reverseRL . invertFL
instance WL RL where
toRL = id
invertWL = reverseFL . invertRL
commutePrimsOrAddToCtx :: (WL l, Apply p, Commute p, Invert p, ToFromPrim p) => l (PrimOf p) wX wY
-> Non p wY -> Non p wX
commutePrimsOrAddToCtx q = commuteOrAddToCtxRL (mapRL_RL fromAnonymousPrim $ toRL q)
remNons :: (Nonable p, Effect p, Apply p, Commute p, Invert p, Eq2 p, ToFromPrim p, PrimPatchBase p)
=> [Non p wX] -> Non p wX -> Non p wX
remNons ns n@(Non c x) = case remNonHelper ns c of
NilFL :> c' -> Non c' x
_ -> n
where
remNonHelper :: (Nonable p, Effect p, Apply p, Commute p, Invert p, Eq2 p, ToFromPrim p,
PrimPatchBase p) => [Non p wX]
-> FL p wX wY -> (FL (PrimOf p) :> FL p) wX wY
remNonHelper [] x = NilFL :> x
remNonHelper _ NilFL = NilFL :> NilFL
remNonHelper ns (c:>:cs)
| non c `elem` ns =
let nsWithoutC = delete (non c) ns in
let commuteOrAddInvC = commuteOrAddToCtx $ invert c in
case remNonHelper (map commuteOrAddInvC nsWithoutC) cs of
a :> z -> sortCoalesceFL (effect c +>+ a) :> z
| otherwise = case commuteWhatWeCanFL (c :> cs) of
b :> c' :> d -> case remNonHelper ns b of
a :> b' -> a :> (b' +>+ c' :>: d)
commuteOrRemFromCtx :: (Commute p, Invert p, Eq2 p, ToFromPrim p) => p wX wY -> Non p wX
-> Maybe (Non p wY)
commuteOrRemFromCtx p n | n'@(Just _) <- n *> p = n'
commuteOrRemFromCtx p (Non pc x) = removeFL p pc >>= \c -> return (Non c x)
commuteOrRemFromCtxFL :: (Apply p, Commute p, Invert p, Eq2 p, ToFromPrim p) => FL p wX wY -> Non p wX
-> Maybe (Non p wY)
commuteOrRemFromCtxFL NilFL n = Just n
commuteOrRemFromCtxFL (p:>:ps) n = do n' <- commuteOrRemFromCtx p n
commuteOrRemFromCtxFL ps n'
(*>) :: (Commute p, Invert p, ToFromPrim p) => Non p wX -> p wX wY
-> Maybe (Non p wY)
n *> p = invert p >* n
(>*) :: (Commute p, ToFromPrim p) => p wX wY -> Non p wY
-> Maybe (Non p wX)
y >* (Non c x) = do
c' :> y' <- commuteFL (y :> c)
px' :> _ <- commute (y' :> fromAnonymousPrim x)
x' <- toPrim px'
return (Non c' x')
(*>>) :: (WL l, Apply p, Commute p, Invert p, ToFromPrim p, PrimPatchBase p) => Non p wX
-> l (PrimOf p) wX wY -> Maybe (Non p wY)
n *>> p = invertWL p >>* n
(>>*) :: (WL l, Apply p, Commute p, Invert p, ToFromPrim p) => l (PrimOf p) wX wY -> Non p wY
-> Maybe (Non p wX)
ps >>* n = commuteRLPastNon (toRL ps) n
where
commuteRLPastNon :: (Apply p, Commute p, Invert p, ToFromPrim p) => RL (PrimOf p) wX wY
-> Non p wY -> Maybe (Non p wX)
commuteRLPastNon NilRL n = Just n
commuteRLPastNon (xs:<:x) n = fromAnonymousPrim x >* n >>= commuteRLPastNon xs