module Language.Haskell.Names.Environment
(
Environment
, loadBase
, readSymbols
, writeSymbols
, SymbolsFileException(..)
) where
import Language.Haskell.Names.Types (Environment, Symbol(..))
import Language.Haskell.Exts (ModuleName(ModuleName),Name,prettyPrint)
import Language.Haskell.Names.SyntaxUtils (stringToName,nameToString,dropAnn, annName)
import qualified Data.ByteString.Lazy as BS (readFile, writeFile, pack)
import Data.Aeson
import Data.Char
import Data.Typeable
import Control.Exception
import Control.Monad
import System.FilePath ((</>), (<.>))
import qualified Data.Map as Map (fromList)
import Data.Traversable (for)
import Paths_haskell_names (getDataDir)
readSymbols :: FilePath -> IO [Symbol]
readSymbols path =
either (throwIO . BadSymbolsFile path) return =<<
eitherDecode <$> BS.readFile path
writeSymbols :: FilePath -> [Symbol] -> IO ()
writeSymbols path symbols =
BS.writeFile path $
encode symbols `mappend` BS.pack [fromIntegral $ ord '\n']
data SymbolsFileException =
BadSymbolsFile FilePath String
deriving (Typeable, Show)
instance Exception SymbolsFileException
prettyName :: Name () -> String
prettyName = nameToString . annName
instance ToJSON Symbol where
toJSON symbol =
object ([
"entity" .= symbolEntity symbol,
"module" .= prettyPrint (symbolModule symbol),
"name" .= prettyName (symbolName symbol)] ++ additionalInfo symbol)
where
additionalInfo symbol = case symbol of
Method { className = cls } ->
["class" .= prettyName cls]
Selector { typeName = ty, constructors = cons } ->
["type" .= prettyName ty
,"constructors".= map prettyName cons]
Constructor { typeName = ty } ->
["type" .= prettyName ty]
TypeFam { associate = as } ->
["associate" .= fmap prettyName as]
DataFam { associate = as } ->
["associate" .= fmap prettyName as]
PatternConstructor { patternTypeName = mty } ->
["patternTypeName" .= fmap prettyName mty]
PatternSelector { patternTypeName = mty, patternConstructorName = pn } ->
["patternTypeName" .= fmap prettyName mty
,"patternConstructorName" .= prettyName pn]
_ -> []
symbolEntity :: Symbol -> String
symbolEntity i = case i of
Value {} -> "value"
Method {} -> "method"
Selector {} -> "selector"
Constructor {} -> "constructor"
Type {} -> "type"
Data {} -> "data"
NewType {} -> "newtype"
TypeFam {} -> "typeFamily"
DataFam {} -> "dataFamily"
Class {} -> "class"
PatternConstructor {} -> "patternConstructor"
PatternSelector {} -> "patternSelector"
parseName :: String -> Name ()
parseName = dropAnn . stringToName
instance FromJSON Symbol where
parseJSON (Object v) = do
entity <- v .: "entity"
symbolmodule <- ModuleName () <$> v .: "module"
symbolname <- parseName <$> v .: "name"
case entity :: String of
"value" -> return $ Value symbolmodule symbolname
"method" -> do
cls <- v .: "class"
return (Method symbolmodule symbolname (parseName cls))
"selector" -> do
typ <- v .: "type"
cons <- v .: "constructors"
return (Selector symbolmodule symbolname (parseName typ) (map parseName cons))
"constructor" -> do
typ <- v .: "type"
return (Constructor symbolmodule symbolname (parseName typ))
"type" -> return $ Type symbolmodule symbolname
"data" -> return $ Data symbolmodule symbolname
"newtype" -> return $ NewType symbolmodule symbolname
"typeFamily" -> do
associate <- fmap parseName <$> v .: "associate"
return $ TypeFam symbolmodule symbolname associate
"dataFamily" -> do
associate <- fmap parseName <$> v .: "associate"
return $ DataFam symbolmodule symbolname associate
"class" -> return $ Class symbolmodule symbolname
"patternConstructor" -> do
typ <- fmap parseName <$> v .: "patternTypeName"
return (PatternConstructor symbolmodule symbolname typ)
"patternSelector" -> do
typ <- fmap parseName <$> v .: "patternTypeName"
patternname <- parseName <$> v .: "patternConstructorName"
return (PatternSelector symbolmodule symbolname typ patternname)
_ -> mzero
parseJSON _ = mzero
loadBase :: IO Environment
loadBase = do
moduleSymbols <- for baseModules (\moduleName -> do
dataDir <- getDataDir
let path = dataDir </> "data" </> "baseEnvironment" </>
prettyPrint moduleName <.> "symbols"
symbols <- readSymbols path
return (moduleName, symbols))
return (Map.fromList moduleSymbols)
baseModules :: [ModuleName ()]
baseModules = map (ModuleName ()) ["Control.Applicative","Control.Arrow","Control.Category","Control.Concurrent.Chan","Control.Concurrent.MVar","Control.Concurrent.QSem","Control.Concurrent.QSemN","Control.Concurrent","Control.Exception.Base","Control.Exception","Control.Monad.Fix","Control.Monad.Instances","Control.Monad.ST.Imp","Control.Monad.ST.Lazy.Imp","Control.Monad.ST.Lazy.Safe","Control.Monad.ST.Lazy.Unsafe","Control.Monad.ST.Lazy","Control.Monad.ST.Safe","Control.Monad.ST.Strict","Control.Monad.ST.Unsafe","Control.Monad.ST","Control.Monad.Zip","Control.Monad","Data.Bits","Data.Bool","Data.Char","Data.Complex","Data.Data","Data.Dynamic","Data.Either","Data.Eq","Data.Fixed","Data.Foldable","Data.Function","Data.Functor","Data.IORef","Data.Int","Data.Ix","Data.List","Data.Maybe","Data.Monoid","Data.OldTypeable.Internal","Data.OldTypeable","Data.Ord","Data.Ratio","Data.STRef.Lazy","Data.STRef.Strict","Data.STRef","Data.String","Data.Traversable","Data.Tuple","Data.Typeable.Internal","Data.Typeable","Data.Unique","Data.Version","Data.Word","Debug.Trace","Foreign.C.Error","Foreign.C.String","Foreign.C.Types","Foreign.C","Foreign.Concurrent","Foreign.ForeignPtr.Imp","Foreign.ForeignPtr.Safe","Foreign.ForeignPtr.Unsafe","Foreign.ForeignPtr","Foreign.Marshal.Alloc","Foreign.Marshal.Array","Foreign.Marshal.Error","Foreign.Marshal.Pool","Foreign.Marshal.Safe","Foreign.Marshal.Unsafe","Foreign.Marshal.Utils","Foreign.Marshal","Foreign.Ptr","Foreign.Safe","Foreign.StablePtr","Foreign.Storable","Foreign","GHC.Arr","GHC.Base","GHC.Char","GHC.Conc.IO","GHC.Conc.Signal","GHC.Conc.Sync","GHC.Conc","GHC.ConsoleHandler","GHC.Constants","GHC.Desugar","GHC.Enum","GHC.Environment","GHC.Err","GHC.Event.Array","GHC.Event.Clock","GHC.Event.Control","GHC.Event.EPoll","GHC.Event.IntMap","GHC.Event.Internal","GHC.Event.KQueue","GHC.Event.Manager","GHC.Event.PSQ","GHC.Event.Poll","GHC.Event.Thread","GHC.Event.TimerManager","GHC.Event.Unique","GHC.Event","GHC.Exception","GHC.Exts","GHC.Fingerprint.Type","GHC.Fingerprint","GHC.Float.ConversionUtils","GHC.Float.RealFracMethods","GHC.Float","GHC.Foreign","GHC.ForeignPtr","GHC.GHCi","GHC.Generics","GHC.IO.Buffer","GHC.IO.BufferedIO","GHC.IO.Device","GHC.IO.Encoding.CodePage","GHC.IO.Encoding.Failure","GHC.IO.Encoding.Iconv","GHC.IO.Encoding.Latin1","GHC.IO.Encoding.Types","GHC.IO.Encoding.UTF16","GHC.IO.Encoding.UTF32","GHC.IO.Encoding.UTF8","GHC.IO.Encoding","GHC.IO.Exception","GHC.IO.FD","GHC.IO.Handle.FD","GHC.IO.Handle.Internals","GHC.IO.Handle.Text","GHC.IO.Handle.Types","GHC.IO.Handle","GHC.IO.IOMode","GHC.IO","GHC.IOArray","GHC.IORef","GHC.IP","GHC.Int","GHC.List","GHC.MVar","GHC.Num","GHC.PArr","GHC.Pack","GHC.Profiling","GHC.Ptr","GHC.Read","GHC.Real","GHC.ST","GHC.STRef","GHC.Show","GHC.Stable","GHC.Stack","GHC.Stats","GHC.Storable","GHC.TopHandler","GHC.TypeLits","GHC.Unicode","GHC.Weak","GHC.Word","Numeric","Prelude","System.CPUTime","System.Console.GetOpt","System.Environment.ExecutablePath","System.Environment","System.Exit","System.IO.Error","System.IO.Unsafe","System.IO","System.Info","System.Mem.StableName","System.Mem.Weak","System.Mem","System.Posix.Internals","System.Posix.Types","System.Timeout","Text.ParserCombinators.ReadP","Text.ParserCombinators.ReadPrec","Text.Printf","Text.Read.Lex","Text.Read","Text.Show.Functions","Text.Show","Unsafe.Coerce","GHC.CString","GHC.Classes","GHC.Debug","GHC.IntWord64","GHC.Magic","GHC.Prim","GHC.PrimopWrappers","GHC.Tuple","GHC.Types","GHC.Integer.Logarithms.Internals","GHC.Integer.Logarithms","GHC.Integer.Simple.Internals","GHC.Integer.Type","GHC.Integer"]