Gidl.hs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. module Gidl
  2. ( run
  3. ) where
  4. import Data.Char
  5. import Data.Monoid
  6. import Data.Maybe (catMaybes)
  7. import Control.Monad
  8. import System.Console.GetOpt
  9. import System.Environment
  10. import System.Exit
  11. import Text.Show.Pretty
  12. import Ivory.Artifact
  13. import Gidl.Parse
  14. import Gidl.Backend.Haskell
  15. --import Gidl.Backend.Ivory
  16. data OptParser opt = OptParser [String] (opt -> opt)
  17. instance Monoid (OptParser opt) where
  18. mempty = OptParser [] id
  19. OptParser as f `mappend` OptParser bs g = OptParser (as ++ bs) (f . g)
  20. success :: (opt -> opt) -> OptParser opt
  21. success = OptParser []
  22. invalid :: String -> OptParser opt
  23. invalid e = OptParser [e] id
  24. parseOptions :: [OptDescr (OptParser opt)] -> [String]
  25. -> Either [String] (opt -> opt)
  26. parseOptions opts args = case getOpt Permute opts args of
  27. (fs,[],[]) -> case mconcat fs of
  28. OptParser [] f -> Right f
  29. OptParser es _ -> Left es
  30. (_,_,es) -> Left es
  31. data Backend
  32. = HaskellBackend
  33. | IvoryBackend
  34. deriving (Eq, Show)
  35. data Opts = Opts
  36. { backend :: Backend
  37. , idlpath :: FilePath
  38. , outpath :: FilePath
  39. , packagename :: String
  40. , namespace :: String
  41. , debug :: Bool
  42. , help :: Bool
  43. }
  44. initialOpts :: Opts
  45. initialOpts = Opts
  46. { backend = error (usage ["must specify a backend"])
  47. , idlpath = error (usage ["must specify an idl file"])
  48. , outpath = error (usage ["must specify an output path"])
  49. , packagename = error (usage ["must specify a package name"])
  50. , namespace = ""
  51. , debug = False
  52. , help = False
  53. }
  54. setBackend :: String -> OptParser Opts
  55. setBackend b = case map toUpper b of
  56. "HASKELL" -> success (\o -> o { backend = HaskellBackend })
  57. "IVORY" -> success (\o -> o { backend = IvoryBackend })
  58. _ -> invalid ("\"" ++ b ++ "\" is not a valid backend.\n"
  59. ++ "Supported backends: haskell, ivory")
  60. setIdlPath :: String -> OptParser Opts
  61. setIdlPath p = success (\o -> o { idlpath = p })
  62. setOutPath :: String -> OptParser Opts
  63. setOutPath p = success (\o -> o { outpath = p })
  64. setPackageName :: String -> OptParser Opts
  65. setPackageName p = success (\o -> o { packagename = p })
  66. setNamespace :: String -> OptParser Opts
  67. setNamespace p = success (\o -> o { namespace = p })
  68. setDebug :: OptParser Opts
  69. setDebug = success (\o -> o { debug = True })
  70. setHelp :: OptParser Opts
  71. setHelp = success (\o -> o { help = True })
  72. options :: [OptDescr (OptParser Opts)]
  73. options =
  74. [ Option "b" ["backend"] (ReqArg setBackend "BACKEND")
  75. "code generator backend"
  76. , Option "i" ["idl"] (ReqArg setIdlPath "FILE")
  77. "IDL file"
  78. , Option "o" ["out"] (ReqArg setOutPath "DIR")
  79. "root directory for output"
  80. , Option "p" ["package"] (ReqArg setPackageName "NAME")
  81. "package name for output"
  82. , Option "n" ["namespace"] (ReqArg setNamespace "NAME")
  83. "namespace for output"
  84. , Option "" ["debug"] (NoArg setDebug)
  85. "enable debugging output"
  86. , Option "h" ["help"] (NoArg setHelp)
  87. "display this message and exit"
  88. ]
  89. parseOpts :: [String] -> IO Opts
  90. parseOpts args = case parseOptions options args of
  91. Right f -> let opts = f initialOpts in
  92. if help opts then putStrLn (usage []) >> exitSuccess
  93. else return opts
  94. Left errs -> putStrLn (usage errs) >> exitFailure
  95. usage :: [String] -> String
  96. usage errs = usageInfo banner options
  97. where
  98. banner = unlines (errs ++ ["", "Usage: gidl OPTIONS"])
  99. run :: IO ()
  100. run = do
  101. args <- getArgs
  102. opts <- parseOpts args
  103. idl <- readFile (idlpath opts)
  104. case parseDecls idl of
  105. Left e -> print e >> exitFailure
  106. Right (te, ie) -> do
  107. when (debug opts) $ do
  108. putStrLn (ppShow te)
  109. putStrLn (ppShow ie)
  110. case backend opts of
  111. HaskellBackend -> artifactBackend opts $
  112. haskellBackend te ie (packagename opts) (namespace opts)
  113. IvoryBackend -> artifactBackend opts $
  114. []
  115. --ivoryBackend te ie (packagename opts) (namespace opts)
  116. where
  117. artifactBackend :: Opts -> [Artifact] -> IO ()
  118. artifactBackend opts as = do
  119. when (debug opts) $ mapM_ printArtifact as
  120. es <- mapM (putArtifact (outpath opts)) as
  121. case catMaybes es of
  122. [] -> exitSuccess
  123. ees -> putStrLn (unlines ees) >> exitFailure