{-# LANGUAGE UnicodeSyntax #-} module Network.HTTP.Lucu.Implant.Rewrite ( ModMap , rewriteNames ) where import Control.Applicative import Control.Monad.State import Data.Data import Data.Generics.Aliases import Data.Generics.Schemes import Data.Map (Map) import qualified Data.Map as M import Data.Monoid.Unicode import Language.Haskell.TH.Syntax import Prelude.Unicode -- FIXME: Document at least these data types. type ModMap = Map ModName (Maybe ModName) data RewriteTo = Qual (Maybe ModName) ModName | UnQual (Maybe ModName) rewriteNames ∷ Data d ⇒ d → (d, ModMap) rewriteNames = flip runState (∅) ∘ gmapM (everywhereM (mkM rewriteName)) rewriteName ∷ (Functor m, Monad m) ⇒ Name → StateT ModMap m Name rewriteName (Name o fl) = Name o <$> rewriteNameFlavour fl rewriteNameFlavour ∷ (Functor m, Monad m) ⇒ NameFlavour → StateT ModMap m NameFlavour rewriteNameFlavour fl = case getModName fl of Nothing → return fl Just m → do let r = M.lookup m modules insertIntoModMap m r return $ setModName r fl insertIntoModMap ∷ Monad m ⇒ ModName → Maybe RewriteTo → StateT ModMap m () insertIntoModMap _ (Just (Qual (Just m) m')) = modify $ M.insert m (Just m') insertIntoModMap m (Just (Qual Nothing m')) = modify $ M.insert m (Just m') insertIntoModMap _ (Just (UnQual (Just m) )) = modify $ M.insert m Nothing insertIntoModMap _ (Just (UnQual Nothing )) = return () insertIntoModMap m Nothing = modify $ M.insert m Nothing getModName ∷ NameFlavour → Maybe ModName getModName (NameQ m) = Just m getModName (NameG _ _ m) = Just m getModName _ = Nothing setModName ∷ Maybe RewriteTo → NameFlavour → NameFlavour setModName (Just (Qual _ m)) (NameQ _ ) = NameQ m setModName (Just (Qual _ m)) (NameG _ _ _) = NameQ m setModName (Just (UnQual _)) (NameQ _ ) = NameS setModName (Just (UnQual _)) (NameG _ _ _) = NameS setModName Nothing (NameQ _ ) = NameS setModName Nothing (NameG _ _ _) = NameS setModName _ _ = error "setModName: internal error" modules ∷ Map ModName RewriteTo modules = M.fromList [ ( mkModName "Codec.Compression.GZip" , Qual Nothing $ mkModName "G" ) , ( mkModName "Data.Ascii" , Qual Nothing $ mkModName "A" ) , ( mkModName "Data.ByteString.Char8" , Qual Nothing $ mkModName "B" ) , ( mkModName "Data.ByteString.Lazy.Internal" , Qual Nothing $ mkModName "L" ) , ( mkModName "Data.ByteString.Unsafe" , Qual Nothing $ mkModName "B" ) , ( mkModName "Data.Map" , Qual Nothing $ mkModName "M" ) , ( mkModName "Data.Maybe" , UnQual Nothing ) , ( mkModName "Data.Text" , Qual Nothing $ mkModName "T" ) , ( mkModName "Data.Time.Calendar.Days" , UnQual $ Just $ mkModName "Data.Time" ) , ( mkModName "Data.Time.Clock.Scale" , UnQual $ Just $ mkModName "Data.Time" ) , ( mkModName "Data.Time.Clock.UTC" , UnQual $ Just $ mkModName "Data.Time" ) , ( mkModName "GHC.Base" , UnQual Nothing ) , ( mkModName "GHC.Bool" , UnQual Nothing ) , ( mkModName "GHC.IO" -- for 'unsafePerformIO', but rather problematic... , UnQual $ Just $ mkModName "System.IO.Unsafe" ) , ( mkModName "GHC.Real" -- for '%', but rather problematic... , UnQual $ Just $ mkModName "Data.Ratio" ) , ( mkModName "Network.HTTP.Lucu.ETag" , UnQual $ Just $ mkModName "Network.HTTP.Lucu" ) , ( mkModName "Network.HTTP.Lucu.MIMEType" , UnQual $ Just $ mkModName "Network.HTTP.Lucu" ) , ( mkModName "Network.HTTP.Lucu.Resource" , UnQual $ Just $ mkModName "Network.HTTP.Lucu" ) , ( mkModName "Network.HTTP.Lucu.Resource.Internal" , UnQual $ Just $ mkModName "Network.HTTP.Lucu" ) ]