run :: IO ()
run = do
  args <- getArgs
  opts <- parseOpts args
  idl <- readFile (idlpath opts)
  case parseDecls idl of
    Left e -> putStrLn ("Error parsing " ++ (idlpath opts) ++ ": " ++ e)
              >> exitFailure
    Right (te, ie) -> do
      when (debug opts) $ do
        putStrLn (ppShow te)
        putStrLn (ppShow ie)
      let InterfaceEnv ie' = ie
          interfaces = map snd ie'
          absolutize p name = do
            pAbs <- fmap normalise $
                      if isRelative p
                      then fmap (</> p) getCurrentDirectory
                      else return p
            ex <- doesDirectoryExist pAbs
            when (not ex) $
              error (usage [ "Directory \"" ++ p ++ "\" does not exist."
                           , "Make sure that the " ++ name
                             ++ " repository is checked out." ])
            return pAbs
      b <- case backend opts of
             HaskellBackend -> return haskellBackend
             IvoryBackend -> do
               ivoryAbs <- absolutize (ivoryrepo opts) "Ivory"
               return (ivoryBackend ivoryAbs)
             TowerBackend -> do
               ivoryAbs           <- absolutize (ivoryrepo opts) "Ivory"
               towerAbs           <- absolutize (towerrepo opts) "Tower"
               ivoryTowerSTM32Abs <- absolutize (ivorytowerstm32repo opts)
                                                "ivory-tower-stm32"
               return (towerBackend ivoryAbs towerAbs ivoryTowerSTM32Abs)
             RpcBackend -> return rpcBackend
             ElmBackend -> return elmBackend
      artifactBackend opts (b interfaces (packagename opts) (namespace opts))

  where
  artifactBackend :: Opts -> [Artifact] -> IO ()
  artifactBackend opts as = do
    when (debug opts) $ mapM_ printArtifact as
    es <- mapM (putArtifact (outpath opts)) as
    case catMaybes es of
      [] -> exitSuccess
      ees -> putStrLn (unlines ees) >> exitFailure
run :: IO ()
run = do
  args <- getArgs
  opts <- parseOpts args
  idl <- readFile (idlpath opts)
  case parseDecls idl of
    Left e -> putStrLn ("Error parsing " ++ (idlpath opts) ++ ": " ++ e)
              >> exitFailure
    Right (te, ie) -> do
      when (debug opts) $ do
        putStrLn (ppShow te)
        putStrLn (ppShow ie)
      let InterfaceEnv ie' = ie
          interfaces = map snd ie'
          absolutize p name = do
            pAbs <- fmap normalise $
                      if isRelative p
                      then fmap (</> p) getCurrentDirectory
                      else return p
            ex <- doesDirectoryExist pAbs
            when (not ex) $
              error (usage [ "Directory \"" ++ p ++ "\" does not exist."
                           , "Make sure that the " ++ name
                             ++ " repository is checked out." ])
            return pAbs
      b <- case backend opts of
             HaskellBackend -> return haskellBackend
             IvoryBackend -> do
               ivoryAbs <- absolutize (ivoryrepo opts) "Ivory"
               return (ivoryBackend ivoryAbs)
             TowerBackend -> do
               ivoryAbs           <- absolutize (ivoryrepo opts) "Ivory"
               towerAbs           <- absolutize (towerrepo opts) "Tower"
               ivoryTowerSTM32Abs <- absolutize (ivorytowerstm32repo opts)
                                                "ivory-tower-stm32"
               return (towerBackend ivoryAbs towerAbs ivoryTowerSTM32Abs)
             RpcBackend -> return rpcBackend
             ElmBackend -> return elmBackend
      artifactBackend opts (b interfaces (packagename opts) (namespace opts))

  where
  artifactBackend :: Opts -> [Artifact] -> IO ()
  artifactBackend opts as = do
    when (debug opts) $ mapM_ printArtifact as
    es <- mapM (putArtifact (outpath opts)) as
    case catMaybes es of
      [] -> exitSuccess
      ees -> putStrLn (unlines ees) >> exitFailure
run = do
  args <- getArgs
  opts <- parseOpts args
  idl <- readFile (idlpath opts)
  case parseDecls idl of
    Left e -> putStrLn ("Error parsing " ++ (idlpath opts) ++ ": " ++ e)
              >> exitFailure
    Right (te, ie) -> do
      when (debug opts) $ do
        putStrLn (ppShow te)
        putStrLn (ppShow ie)
      let InterfaceEnv ie' = ie
          interfaces = map snd ie'
          absolutize p name = do
            pAbs <- fmap normalise $
                      if isRelative p
                      then fmap (</> p) getCurrentDirectory
                      else return p
            ex <- doesDirectoryExist pAbs
            when (not ex) $
              error (usage [ "Directory \"" ++ p ++ "\" does not exist."
                           , "Make sure that the " ++ name
                             ++ " repository is checked out." ])
            return pAbs
      b <- case backend opts of
             HaskellBackend -> return haskellBackend
             IvoryBackend -> do
               ivoryAbs <- absolutize (ivoryrepo opts) "Ivory"
               return (ivoryBackend ivoryAbs)
             TowerBackend -> do
               ivoryAbs           <- absolutize (ivoryrepo opts) "Ivory"
               towerAbs           <- absolutize (towerrepo opts) "Tower"
               ivoryTowerSTM32Abs <- absolutize (ivorytowerstm32repo opts)
                                                "ivory-tower-stm32"
               return (towerBackend ivoryAbs towerAbs ivoryTowerSTM32Abs)
             RpcBackend -> return rpcBackend
             ElmBackend -> return elmBackend
      artifactBackend opts (b interfaces (packagename opts) (namespace opts))

  where
  artifactBackend :: Opts -> [Artifact] -> IO ()
  artifactBackend opts as = do
    when (debug opts) $ mapM_ printArtifact as
    es <- mapM (putArtifact (outpath opts)) as
    case catMaybes es of
      [] -> exitSuccess
      ees -> putStrLn (unlines ees) >> exitFailure