runGhcBWrap-core-0.1.0.0: src/RunGhc/Executable.hs
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
module RunGhc.Executable where
import RunGhc.SystemModule
import RunGhc.LocatedModule
import RunGhc.Locate
import System.FilePath
import Data.Aeson
import GHC.Generics
import qualified Data.Text as T
import qualified Data.Text.IO as T
-- NOTE: we are going to need functionality to get from github
-- or at least from .tar.gz
data Executable = Executable
{ _main :: LocatedModule
, _library :: [LocatedModule]
} deriving Generic
instance ToJSON Executable
instance FromJSON Executable
data ExecutableWithDeps = ExecutableWithDeps
{ _exe :: Executable
, _packages :: [PackageName]
}
data ExecutableWithDepsWithCommand = ExecutableWithDepsWithCommand
{ _exeWithDeps :: ExecutableWithDeps
, _commandWithArgs :: [T.Text] -- default would be runghc
}
newtype PackageName = PackageName { getPackageName :: T.Text }
getTargetModule :: Executable -> [PathSegment]
getTargetModule = getPathSegments . _main
getTargetModulePath :: T.Text -> Executable -> FilePath
getTargetModulePath fext = pathSegsToPath fext . getTargetModule
-- Perhaps Executable becomes own module
writeExecutable :: FilePath -> Executable -> IO ()
writeExecutable baseDir exe =
writeLocatedFiles baseDir $ _main exe : _library exe
writeLocatedFiles :: FilePath -> [LocatedModule] -> IO ()
writeLocatedFiles baseDir modules = do
mapM_ (writeLocatedFile baseDir) modules
where
fileExt = ".hs"
writeLocatedFile baseDir_ = \case
FromLocatedScript (LocatedScript pathSegs (Script script)) ->
T.writeFile (baseDir_ </> pathSegsToPath fileExt pathSegs) script
FromSystemModule pathSegs systemModule -> do
T.writeFile (baseDir </> pathSegsToPath fileExt pathSegs) $ getScript $ systemModuleToScript pathSegs systemModule
-- So that we can write to file
makeModuleDeclaration :: [PathSegment] -> Script
makeModuleDeclaration pathSegs = Script ("module " <> (pathSegsToModuleName pathSegs) <> " where\n")
mkImport :: Import -> T.Text
mkImport imp = case _import_qualifiedName imp of
Nothing -> "import " <> pathSegsToModuleName (_import_pathSeg imp)
Just qName -> "import qualified " <> pathSegsToModuleName (_import_pathSeg imp) <> " as " <> qName
makeImports (Imports importList) = Script $ T.unlines $ mkImport <$> importList
fromExpressions :: Expressions -> Script
fromExpressions = Script . getExpressions
makeExtensions (Extensions (exts)) = Script $
"{-# LANGUAGE" <> T.intercalate ", " exts <> " #-}"
systemModuleToScript :: [PathSegment] -> SystemModule -> Script
systemModuleToScript pathSegs = \case
ExpressionsOnly (Expressions rawSource) ->
makeModuleDeclaration pathSegs -- Script ("module " <> T.pack (pathSegsToModuleName pathSegs) <> " where\n")
<> Script rawSource
ExpressionsImportsOnly imports (Expressions rawSource) ->
makeModuleDeclaration pathSegs
<> makeImports imports
<> Script rawSource
ExpressionsImportsExtensionsOnly extensions imports (Expressions rawSource) ->
makeExtensions extensions
<> makeModuleDeclaration pathSegs
<> makeImports imports
<> Script rawSource
-- attachLibraryToUserModule :: LocatedUserModule -> Located-> [LocatedModule] -> Executable
-- attachLibraryToUserModule
addUserLibraryToExecutable :: LocatedUserModule -> Executable -> Executable
addUserLibraryToExecutable (LocatedUserModule loc) exe = Executable (addImports (Imports [toSimpleImport $ getPathSegments loc]) (_main exe)) [loc]
addSystemLibraryToExecutable :: LocatedTestModule -> Executable -> Executable
addSystemLibraryToExecutable (LocatedTestModule locs) exe = Executable (_main exe) $ locs : (_library exe)
addSystemLibrariesToExecutable :: [LocatedModule] -> Executable -> Executable
addSystemLibrariesToExecutable locs exe = Executable (_main exe) $ locs <> (_library exe)