{-# LANGUAGE LambdaCase, ViewPatterns #-}
module TypeLevel.Rewrite.Internal.Lookup where
import Control.Arrow ((***), first)
import Data.Tuple (swap)
import qualified GHC.TcPluginM.Extra as TcPluginM
import DataCon (DataCon, promoteDataCon)
import DynFlags (getDynFlags)
import Finder (cannotFindModule)
import Module (Module, ModuleName, mkModuleName)
import OccName (mkDataOcc, mkTcOcc)
import Panic (panicDoc)
import TcPluginM
( FindResult(Found), TcPluginM, findImportedModule, tcLookupDataCon, tcLookupTyCon
, unsafeTcPluginTcM
)
import TyCon (TyCon)
lookupModule
:: String
-> TcPluginM Module
lookupModule moduleNameStr = do
let moduleName :: ModuleName
moduleName = mkModuleName moduleNameStr
findImportedModule moduleName Nothing >>= \case
Found _ module_ -> do
pure module_
findResult -> do
dynFlags <- unsafeTcPluginTcM getDynFlags
panicDoc ("TypeLevel.Lookup.lookupModule " ++ show moduleNameStr)
$ cannotFindModule dynFlags moduleName findResult
lookupTyCon
:: String
-> String
-> TcPluginM TyCon
lookupTyCon moduleNameStr tyConNameStr = do
module_ <- lookupModule moduleNameStr
tyConName <- TcPluginM.lookupName module_ (mkTcOcc tyConNameStr)
tyCon <- tcLookupTyCon tyConName
pure tyCon
lookupDataCon
:: String
-> String
-> TcPluginM DataCon
lookupDataCon moduleNameStr dataConNameStr = do
module_ <- lookupModule moduleNameStr
dataConName <- TcPluginM.lookupName module_ (mkDataOcc dataConNameStr)
dataCon <- tcLookupDataCon dataConName
pure dataCon
splitFirstDot
:: String -> Maybe (String, String)
splitFirstDot ('.' : rhs)
= Just ("", rhs)
splitFirstDot (x : xs)
= first (x:) <$> splitFirstDot xs
splitFirstDot _
= Nothing
splitLastDot
:: String -> Maybe (String, String)
splitLastDot
= fmap swap
. fmap (reverse *** reverse)
. splitFirstDot
. reverse
lookupFQN
:: String
-> TcPluginM TyCon
lookupFQN ('\'' : (splitLastDot -> Just (moduleNameStr, dataConNameStr)))
= promoteDataCon <$> lookupDataCon moduleNameStr dataConNameStr
lookupFQN (splitLastDot -> Just (moduleNameStr, tyConNameStr))
= lookupTyCon moduleNameStr tyConNameStr
lookupFQN fqn
= error $ "expected " ++ show "ModuleName.TypeName"
++ ", got " ++ show fqn