module Data.SBV.Utils.Lib (mlift2, mlift3, mlift4, mlift5, mlift6, mlift7, mlift8, joinArgs, splitArgs) where
import Data.Char (isSpace)
import Data.Maybe (fromJust, isNothing)
mlift2 :: Monad m => (a' -> b' -> r) -> (a -> m a') -> (b -> m b') -> (a, b) -> m r
mlift2 k f g (a, b) = f a >>= \a' -> g b >>= \b' -> return $ k a' b'
mlift3 :: Monad m => (a' -> b' -> c' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (a, b, c) -> m r
mlift3 k f g h (a, b, c) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> return $ k a' b' c'
mlift4 :: Monad m => (a' -> b' -> c' -> d' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (d -> m d') -> (a, b, c, d) -> m r
mlift4 k f g h i (a, b, c, d) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> return $ k a' b' c' d'
mlift5 :: Monad m => (a' -> b' -> c' -> d' -> e' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (d -> m d') -> (e -> m e') -> (a, b, c, d, e) -> m r
mlift5 k f g h i j (a, b, c, d, e) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> return $ k a' b' c' d' e'
mlift6 :: Monad m => (a' -> b' -> c' -> d' -> e' -> f' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (d -> m d') -> (e -> m e') -> (f -> m f') -> (a, b, c, d, e, f) -> m r
mlift6 k f g h i j l (a, b, c, d, e, y) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> l y >>= \y' -> return $ k a' b' c' d' e' y'
mlift7 :: Monad m => (a' -> b' -> c' -> d' -> e' -> f' -> g' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (d -> m d') -> (e -> m e') -> (f -> m f') -> (g -> m g') -> (a, b, c, d, e, f, g) -> m r
mlift7 k f g h i j l m (a, b, c, d, e, y, z) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> l y >>= \y' -> m z >>= \z' -> return $ k a' b' c' d' e' y' z'
mlift8 :: Monad m => (a' -> b' -> c' -> d' -> e' -> f' -> g' -> h' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (d -> m d') -> (e -> m e') -> (f -> m f') -> (g -> m g') -> (h -> m h') -> (a, b, c, d, e, f, g, h) -> m r
mlift8 k f g h i j l m n (a, b, c, d, e, y, z, w) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> l y >>= \y' -> m z >>= \z' -> n w >>= \w' -> return $ k a' b' c' d' e' y' z' w'
joinArgs :: [String] -> String
joinArgs = unwords . map f
where f x = q ++ g x ++ q
where hasSpace = any isSpace x
q = ['\"' | hasSpace || null x]
g ('\\':'\"':xs) = '\\':'\\':'\\':'\"': g xs
g "\\" | hasSpace = "\\\\"
g ('\"':xs) = '\\':'\"': g xs
g (x':xs) = x' : g xs
g [] = []
data State = Init
| Norm
| Quot
splitArgs :: String -> [String]
splitArgs = join . f Init
where
join :: [Maybe Char] -> [String]
join [] = []
join xs = map fromJust a : join (drop 1 b)
where (a,b) = break isNothing xs
f Init (x:xs) | isSpace x = f Init xs
f Init "\"\"" = [Nothing]
f Init "\"" = [Nothing]
f Init xs = f Norm xs
f m ('\"':'\"':'\"':xs) = Just '\"' : f m xs
f m ('\\':'\"':xs) = Just '\"' : f m xs
f m ('\\':'\\':'\"':xs) = Just '\\' : f m ('\"':xs)
f Norm ('\"':xs) = f Quot xs
f Quot ('\"':'\"':xs) = Just '\"' : f Norm xs
f Quot ('\"':xs) = f Norm xs
f Norm (x:xs) | isSpace x = Nothing : f Init xs
f m (x:xs) = Just x : f m xs
f _ [] = []