{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE CPP #-}
module Camfort.Helpers
(
Directory
, FileOrDir
, Filename
, SourceText
, checkDir
, getDir
, isDirectory
, collect
, descendBiReverseM
, descendReverseM
) where
import Data.Generics.Uniplate.Operations
import qualified Data.Generics.Str as Str
import Data.Data
import Data.List (elemIndices, union)
import qualified Data.ByteString.Char8 as B
import System.Directory
import qualified Data.Map.Lazy as Map hiding (map, (\\))
import Control.Monad.Writer
collect :: (Eq a, Ord k) => [(k, a)] -> Map.Map k [a]
collect :: [(k, a)] -> Map k [a]
collect = ([a] -> [a] -> [a]) -> [(k, [a])] -> Map k [a]
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith [a] -> [a] -> [a]
forall a. Eq a => [a] -> [a] -> [a]
union ([(k, [a])] -> Map k [a])
-> ([(k, a)] -> [(k, [a])]) -> [(k, a)] -> Map k [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((k, a) -> (k, [a])) -> [(k, a)] -> [(k, [a])]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> [a]) -> (k, a) -> (k, [a])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> [a] -> [a]
forall a. a -> [a] -> [a]
:[]))
type Filename = String
type Directory = String
type SourceText = B.ByteString
type FileOrDir = String
getDir :: Filename -> Directory
getDir :: Filename -> Filename
getDir Filename
file = let ixs :: [Int]
ixs = Char -> Filename -> [Int]
forall a. Eq a => a -> [a] -> [Int]
elemIndices Char
'/' Filename
file
in if [Int] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
ixs then Filename
file
else Int -> Filename -> Filename
forall a. Int -> [a] -> [a]
take ([Int] -> Int
forall a. [a] -> a
last ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ [Int]
ixs) Filename
file
checkDir :: Directory -> IO ()
checkDir :: Filename -> IO ()
checkDir Filename
f = case (Char -> Filename -> [Int]
forall a. Eq a => a -> [a] -> [Int]
elemIndices Char
'/' Filename
f) of
[] -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
[Int]
ix -> let d :: Filename
d = Int -> Filename -> Filename
forall a. Int -> [a] -> [a]
take ([Int] -> Int
forall a. [a] -> a
last [Int]
ix) Filename
f
in Bool -> Filename -> IO ()
createDirectoryIfMissing Bool
True Filename
d
isDirectory :: FileOrDir -> IO Bool
isDirectory :: Filename -> IO Bool
isDirectory Filename
s = Filename -> IO Bool
doesDirectoryExist Filename
s
#if __GLASGOW_HASKELL__ < 800
instance Monoid x => Monad ((,) x) where
return a = (mempty, a)
(x, a) >>= k = let (x', b) = k a
in (mappend x x', b)
#endif
data Reverse f a = Reverse { Reverse f a -> f a
unwrapReverse :: f a }
instance Functor (Reverse Str.Str) where
fmap :: (a -> b) -> Reverse Str a -> Reverse Str b
fmap a -> b
f (Reverse Str a
s) = Str b -> Reverse Str b
forall k (f :: k -> *) (a :: k). f a -> Reverse f a
Reverse ((a -> b) -> Str a -> Str b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Str a
s)
instance Foldable (Reverse Str.Str) where
foldMap :: (a -> m) -> Reverse Str a -> m
foldMap a -> m
f (Reverse Str a
x) = (a -> m) -> Str a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f Str a
x
instance Traversable (Reverse Str.Str) where
traverse :: (a -> f b) -> Reverse Str a -> f (Reverse Str b)
traverse a -> f b
_ (Reverse Str a
Str.Zero) = Reverse Str b -> f (Reverse Str b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Reverse Str b -> f (Reverse Str b))
-> Reverse Str b -> f (Reverse Str b)
forall a b. (a -> b) -> a -> b
$ Str b -> Reverse Str b
forall k (f :: k -> *) (a :: k). f a -> Reverse f a
Reverse Str b
forall a. Str a
Str.Zero
traverse a -> f b
f (Reverse (Str.One a
x)) = (Str b -> Reverse Str b
forall k (f :: k -> *) (a :: k). f a -> Reverse f a
Reverse (Str b -> Reverse Str b) -> (b -> Str b) -> b -> Reverse Str b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Str b
forall a. a -> Str a
Str.One) (b -> Reverse Str b) -> f b -> f (Reverse Str b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
x
traverse a -> f b
f (Reverse (Str.Two Str a
x Str a
y)) = (\Str b
y' Str b
x' -> Str b -> Reverse Str b
forall k (f :: k -> *) (a :: k). f a -> Reverse f a
Reverse (Str b -> Reverse Str b) -> Str b -> Reverse Str b
forall a b. (a -> b) -> a -> b
$ Str b -> Str b -> Str b
forall a. Str a -> Str a -> Str a
Str.Two Str b
x' Str b
y')
(Str b -> Str b -> Reverse Str b)
-> f (Str b) -> f (Str b -> Reverse Str b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Reverse Str b -> Str b) -> f (Reverse Str b) -> f (Str b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Reverse Str b -> Str b
forall k (f :: k -> *) (a :: k). Reverse f a -> f a
unwrapReverse (f (Reverse Str b) -> f (Str b))
-> (Str a -> f (Reverse Str b)) -> Str a -> f (Str b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> f b) -> Reverse Str a -> f (Reverse Str b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f (Reverse Str a -> f (Reverse Str b))
-> (Str a -> Reverse Str a) -> Str a -> f (Reverse Str b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Str a -> Reverse Str a
forall k (f :: k -> *) (a :: k). f a -> Reverse f a
Reverse (Str a -> f (Str b)) -> Str a -> f (Str b)
forall a b. (a -> b) -> a -> b
$ Str a
y)
f (Str b -> Reverse Str b) -> f (Str b) -> f (Reverse Str b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((Reverse Str b -> Str b) -> f (Reverse Str b) -> f (Str b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Reverse Str b -> Str b
forall k (f :: k -> *) (a :: k). Reverse f a -> f a
unwrapReverse (f (Reverse Str b) -> f (Str b))
-> (Str a -> f (Reverse Str b)) -> Str a -> f (Str b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> f b) -> Reverse Str a -> f (Reverse Str b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f (Reverse Str a -> f (Reverse Str b))
-> (Str a -> Reverse Str a) -> Str a -> f (Reverse Str b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Str a -> Reverse Str a
forall k (f :: k -> *) (a :: k). f a -> Reverse f a
Reverse (Str a -> f (Str b)) -> Str a -> f (Str b)
forall a b. (a -> b) -> a -> b
$ Str a
x)
descendReverseM :: (Data on, Monad m, Uniplate on) => (on -> m on) -> on -> m on
descendReverseM :: (on -> m on) -> on -> m on
descendReverseM on -> m on
f on
x =
(Str on -> on) -> m (Str on) -> m on
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Str on -> on
generate (m (Str on) -> m on) -> (Str on -> m (Str on)) -> Str on -> m on
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Reverse Str on -> Str on) -> m (Reverse Str on) -> m (Str on)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Reverse Str on -> Str on
forall k (f :: k -> *) (a :: k). Reverse f a -> f a
unwrapReverse (m (Reverse Str on) -> m (Str on))
-> (Str on -> m (Reverse Str on)) -> Str on -> m (Str on)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (on -> m on) -> Reverse Str on -> m (Reverse Str on)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse on -> m on
f (Reverse Str on -> m (Reverse Str on))
-> (Str on -> Reverse Str on) -> Str on -> m (Reverse Str on)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Str on -> Reverse Str on
forall k (f :: k -> *) (a :: k). f a -> Reverse f a
Reverse (Str on -> m on) -> Str on -> m on
forall a b. (a -> b) -> a -> b
$ Str on
current
where (Str on
current, Str on -> on
generate) = on -> (Str on, Str on -> on)
forall on. Uniplate on => on -> (Str on, Str on -> on)
uniplate on
x
descendBiReverseM :: (Data from, Data to, Monad m, Biplate from to) => (to -> m to) -> from -> m from
descendBiReverseM :: (to -> m to) -> from -> m from
descendBiReverseM to -> m to
f from
x =
(Str to -> from) -> m (Str to) -> m from
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Str to -> from
generate (m (Str to) -> m from)
-> (Str to -> m (Str to)) -> Str to -> m from
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Reverse Str to -> Str to) -> m (Reverse Str to) -> m (Str to)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Reverse Str to -> Str to
forall k (f :: k -> *) (a :: k). Reverse f a -> f a
unwrapReverse (m (Reverse Str to) -> m (Str to))
-> (Str to -> m (Reverse Str to)) -> Str to -> m (Str to)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (to -> m to) -> Reverse Str to -> m (Reverse Str to)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse to -> m to
f (Reverse Str to -> m (Reverse Str to))
-> (Str to -> Reverse Str to) -> Str to -> m (Reverse Str to)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Str to -> Reverse Str to
forall k (f :: k -> *) (a :: k). f a -> Reverse f a
Reverse (Str to -> m from) -> Str to -> m from
forall a b. (a -> b) -> a -> b
$ Str to
current
where (Str to
current, Str to -> from
generate) = from -> (Str to, Str to -> from)
forall from to. Biplate from to => from -> (Str to, Str to -> from)
biplate from
x