Gidl.hs 3.5 KB

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