import Data.Functor (($>)) import Data.Maybe (catMaybes) import System.Environment (getArgs) import System.Exit (exitFailure) import System.Directory (listDirectory, createDirectoryIfMissing) import System.FilePath ((), takeExtension) import Wayland.CodeGen.Types import Wayland.CodeGen.Parser import Wayland.CodeGen.Utils import Wayland.CodeGen.BuildGen import Wayland.CodeGen.CodeGen main :: IO () main = do args <- getArgs case args of [dir] -> generate dir _ -> do putStrLn "Usage: highway-protocols-codegen " exitFailure generate :: FilePath -> IO () generate dir = do let srcDir = dir "src" let codeDir = dir "Wayland" "Protocols" let buildPath = dir "protocols.cabal" protocolSpecs <- filter (\p -> takeExtension p == ".xml") . fmap (srcDir ) <$> listDirectory srcDir protocols <- catMaybes <$> mapM readProtocol protocolSpecs let typedProtocols = fmap resolveTypes protocols mapM_ (writeProtocol (flattenModules typedProtocols) codeDir) typedProtocols writeBuild buildPath protocols readProtocol :: FilePath -> IO (Maybe Protocol) readProtocol path = readFile path >>= handleError . parseProtocolSpec where handleError :: Either String Protocol -> IO (Maybe Protocol) handleError (Left err) = putStrLn (show path ++ ": " ++ err) $> Nothing handleError (Right prot) = pure (Just prot) writeProtocol :: FlatModules -> FilePath -> TypedProtocol -> IO () writeProtocol flat baseDir p = do let dir = baseDir protocolModule p createDirectoryIfMissing True dir mapM_ (writeInterface flat dir p) (protInterfaces p) writeInterface :: FlatModules -> FilePath -> TypedProtocol -> TypedInterfaceDesc -> IO () writeInterface flat dir p i = do let path = dir (interfaceModule (fst i) ++ ".hs") let bootPath = dir (interfaceModule (fst i) ++ ".hs-boot") writeFile path (generateInterface flat p i) writeFile bootPath (generateInterfaceBoot flat p i) writeBuild :: FilePath -> [Protocol] -> IO () writeBuild path ps = writeFile path $ generateBuild ps