options :: [OptDescr (CompilerOpts -> CompilerOpts)]
options =
  [ Option ['o'] ["out"] (ReqArg unitName' "NAME")  "Output unit NAME"
  , Option [] ["cdir"] (ReqArg cFilePrefix' "DIR")
      "Directory to place generated .c files"
  , Option [] ["hdir"] (ReqArg hFilePrefix' "DIR")
      "Directory to place generated .h files"
  , Option [] ["libprefix"] (ReqArg libPrefix' "STRING")
      "Library prefix to prefix includes with"
  , Option "I" [] (ReqArg includePaths' "DIRS")
      "List of module search paths"
  , Option ['t'] ["target"] (ReqArg target' "TARGET")
      ("Set target type:\n" ++
       "\t     parse : Parses the input file\n" ++
       "\t   convert : Converts the input file to core\n" ++
       "\t typecheck : Typechecks the file\n" ++
       "\t   codegen : Outputs the generated C" )
  , Option ['d'] ["debug"] (NoArg debug') "Enables debug mode"
  , Option ['h'] ["help"] (NoArg help') "Prints this usage information"
  , Option ['O'] ["opt"] (ReqArg optimize' "OPTIMIZATION")
      ("Enables optimizations:\n"
       ++ showOptimizations
       ++ "\nPrefixing an optimization with '-' disables it."
       ++ "\nall/none enables/disables ALL optimizations.")
  ]
  where unitName' s opts = opts { unitName = Just s }
        cFilePrefix' s opts = opts { cFilePrefix = Just s }
        hFilePrefix' s opts = opts { hFilePrefix = Just s }
        libPrefix' s opts = opts { libPrefix = Just s }
        includePaths' s opts = opts { includePaths = splitColon s ++ includePaths opts }
        target' t opts = opts { target = targetOpt t }
        debug' opts = opts { debugMode = True }
        help' opts = opts { helpMode = True }
        optimize' t opts
          = opts { optMode = foldl (flip id) (optMode opts)
                             [optOpt p | p <- splitOn ',' t] }
        splitOn :: Char -> String -> [String]
        splitOn delim = foldr split' [""]
          where split' c l@(x:xs) | c == delim  = []:l
                                  | otherwise   = (c:x):xs
options :: [OptDescr (CompilerOpts -> CompilerOpts)]
options =
  [ Option ['o'] ["out"] (ReqArg unitName' "NAME")  "Output unit NAME"
  , Option [] ["cdir"] (ReqArg cFilePrefix' "DIR")
      "Directory to place generated .c files"
  , Option [] ["hdir"] (ReqArg hFilePrefix' "DIR")
      "Directory to place generated .h files"
  , Option [] ["libprefix"] (ReqArg libPrefix' "STRING")
      "Library prefix to prefix includes with"
  , Option "I" [] (ReqArg includePaths' "DIRS")
      "List of module search paths"
  , Option ['t'] ["target"] (ReqArg target' "TARGET")
      ("Set target type:\n" ++
       "\t     parse : Parses the input file\n" ++
       "\t   convert : Converts the input file to core\n" ++
       "\t typecheck : Typechecks the file\n" ++
       "\t   codegen : Outputs the generated C" )
  , Option ['d'] ["debug"] (NoArg debug') "Enables debug mode"
  , Option ['h'] ["help"] (NoArg help') "Prints this usage information"
  , Option ['O'] ["opt"] (ReqArg optimize' "OPTIMIZATION")
      ("Enables optimizations:\n"
       ++ showOptimizations
       ++ "\nPrefixing an optimization with '-' disables it."
       ++ "\nall/none enables/disables ALL optimizations.")
  ]
  where unitName' s opts = opts { unitName = Just s }
        cFilePrefix' s opts = opts { cFilePrefix = Just s }
        hFilePrefix' s opts = opts { hFilePrefix = Just s }
        libPrefix' s opts = opts { libPrefix = Just s }
        includePaths' s opts = opts { includePaths = splitColon s ++ includePaths opts }
        target' t opts = opts { target = targetOpt t }
        debug' opts = opts { debugMode = True }
        help' opts = opts { helpMode = True }
        optimize' t opts
          = opts { optMode = foldl (flip id) (optMode opts)
                             [optOpt p | p <- splitOn ',' t] }
        splitOn :: Char -> String -> [String]
        splitOn delim = foldr split' [""]
          where split' c l@(x:xs) | c == delim  = []:l
                                  | otherwise   = (c:x):xs
options =
  [ Option ['o'] ["out"] (ReqArg unitName' "NAME")  "Output unit NAME"
  , Option [] ["cdir"] (ReqArg cFilePrefix' "DIR")
      "Directory to place generated .c files"
  , Option [] ["hdir"] (ReqArg hFilePrefix' "DIR")
      "Directory to place generated .h files"
  , Option [] ["libprefix"] (ReqArg libPrefix' "STRING")
      "Library prefix to prefix includes with"
  , Option "I" [] (ReqArg includePaths' "DIRS")
      "List of module search paths"
  , Option ['t'] ["target"] (ReqArg target' "TARGET")
      ("Set target type:\n" ++
       "\t     parse : Parses the input file\n" ++
       "\t   convert : Converts the input file to core\n" ++
       "\t typecheck : Typechecks the file\n" ++
       "\t   codegen : Outputs the generated C" )
  , Option ['d'] ["debug"] (NoArg debug') "Enables debug mode"
  , Option ['h'] ["help"] (NoArg help') "Prints this usage information"
  , Option ['O'] ["opt"] (ReqArg optimize' "OPTIMIZATION")
      ("Enables optimizations:\n"
       ++ showOptimizations
       ++ "\nPrefixing an optimization with '-' disables it."
       ++ "\nall/none enables/disables ALL optimizations.")
  ]
  where unitName' s opts = opts { unitName = Just s }
        cFilePrefix' s opts = opts { cFilePrefix = Just s }
        hFilePrefix' s opts = opts { hFilePrefix = Just s }
        libPrefix' s opts = opts { libPrefix = Just s }
        includePaths' s opts = opts { includePaths = splitColon s ++ includePaths opts }
        target' t opts = opts { target = targetOpt t }
        debug' opts = opts { debugMode = True }
        help' opts = opts { helpMode = True }
        optimize' t opts
          = opts { optMode = foldl (flip id) (optMode opts)
                             [optOpt p | p <- splitOn ',' t] }
        splitOn :: Char -> String -> [String]
        splitOn delim = foldr split' [""]
          where split' c l@(x:xs) | c == delim  = []:l
                                  | otherwise   = (c:x):xs