-- | Contains the high-level functionality to create 'Code' and then produce the actual generated code files.
module Language.Drasil.Code.CodeGeneration (
  -- * Preparing the code files
  makeCode,
  -- * Creating the code files
  createCodeFiles
) where

import Language.Drasil.Code.Code (Code(..))
import Language.Drasil.Code.Imperative.GOOL.Data (AuxData(..))

import GOOL.Drasil (FileData(..), ModData(modDoc))

import Text.PrettyPrint.HughesPJ (Doc,render)
import System.Directory (createDirectoryIfMissing)
import System.FilePath.Posix (takeDirectory)
import System.IO (hPutStrLn, hClose, openFile, IOMode(WriteMode))

-- | Makes code from 'FileData' ('FilePath's with module data) and 'AuxData' ('FilePath's with auxiliary document information).
makeCode :: [FileData] -> [AuxData] -> Code
makeCode :: [FileData] -> [AuxData] -> Code
makeCode [FileData]
files [AuxData]
aux = [(FilePath, Doc)] -> Code
Code forall a b. (a -> b) -> a -> b
$ forall a b. [a] -> [b] -> [(a, b)]
zip (forall a b. (a -> b) -> [a] -> [b]
map FileData -> FilePath
filePath [FileData]
files forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map AuxData -> FilePath
auxFilePath [AuxData]
aux)
  (forall a b. (a -> b) -> [a] -> [b]
map (ModData -> Doc
modDoc forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileData -> ModData
fileMod) [FileData]
files forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map AuxData -> Doc
auxDoc [AuxData]
aux)

------------------
-- IO Functions --
------------------

-- | Creates the requested 'Code' by producing files.
createCodeFiles :: Code -> IO () -- [(FilePath, Doc)] -> IO ()
createCodeFiles :: Code -> IO ()
createCodeFiles (Code [(FilePath, Doc)]
cs) = forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (FilePath, Doc) -> IO ()
createCodeFile [(FilePath, Doc)]
cs

-- | Helper that uses pairs of 'Code' to create a file written with the given document at the given 'FilePath'.
createCodeFile :: (FilePath, Doc) -> IO ()
createCodeFile :: (FilePath, Doc) -> IO ()
createCodeFile (FilePath
path, Doc
code) = do
  Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
True (FilePath -> FilePath
takeDirectory FilePath
path)
  Handle
h <- FilePath -> IOMode -> IO Handle
openFile FilePath
path IOMode
WriteMode
  Handle -> FilePath -> IO ()
hPutStrLn Handle
h (Doc -> FilePath
render Doc
code)
  Handle -> IO ()
hClose Handle
h