content: -- Copyright 2020 United States Government as represented by the Administrator
  -- of the National Aeronautics and Space Administration. All Rights Reserved.
  --
  -- Disclaimers
  --
  -- Licensed under the Apache License, Version 2.0 (the "License"); you may
  -- not use this file except in compliance with the License. You may obtain a
  -- copy of the License at
  --
  --      https://www.apache.org/licenses/LICENSE-2.0
  --
  -- Unless required by applicable law or agreed to in writing, software
  -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  -- License for the specific language governing permissions and limitations
  -- under the License.
  --
  -- | Generate Copilot struct definitions and instances from structs defined in
  -- a C header file.
  --
  -- Working with Copilot structs requires three definitions: the datatype, a
  -- @Struct@ instance, and a @Typed@ instance.
  --
  -- This module converts the C structs into 'Language.Copilot.CStruct.CStruct's,
  -- and then converts those 'Language.Copilot.CStruct.CStruct's into Copilot
  -- (i.e., Haskell) data type declarations and instance declarations. The result
  -- is then printed to a file. This module makes use of
  -- "Language.Trans.CStructs2Copilot", which does most of the work.
  module Command.CStructs2Copilot
      ( cstructs2Copilot
      , ErrorCode
      )
    where
  
  -- External imports: auxiliary
  import Data.String.Extra as S ( safeReadFile )
  
  -- Internal imports: auxiliary
  import Command.Result ( Result (..) )
  import Data.Location  ( Location (..) )
  
  -- Internal imports: C parsing and AST
  import qualified Language.C.AbsC as C ( TranslationUnit )
  import qualified Language.C.ParC as C ( myLexer, pTranslationUnit )
  
  -- Internal imports: transformation of C structs to Copilot structs
  import Language.Trans.CStructs2Copilot ( cstructs2CopilotDecls )
  
  -- | Generate Copilot struct definitions and instances from structs defined in
  -- a C header file.
  cstructs2Copilot :: FilePath -- ^ Path to a readable, valid C header file
                               -- containing struct definitions.
                   -> IO (Result ErrorCode)
  cstructs2Copilot fp = do
      source <- parseCFile fp
  
      case cstructs2CopilotDecls =<< source of
        Right decls -> printDecls decls >> return Success
        Left msg    -> return $ Error ecCStructError msg (LocationFile fp)
  
    where
  
      -- Parse a C file, returning 'Left' with some message when there is a parse
      -- error.
      --
      parseCFile :: FilePath -> IO (Either String C.TranslationUnit)
      parseCFile fp' = do
        content <- S.safeReadFile fp'
        return $ C.pTranslationUnit . C.myLexer =<< content
  
      -- Print several Haskell declarations to standard output.
      printDecls :: [ String ] -> IO ()
      printDecls = putStrLn . unlines
  
  -- * Error codes
  
  -- | Encoding of reasons why the command can fail.
  --
  -- The error code used is 1 for user error.
  type ErrorCode = Int
  
  -- | Error: the C header file cannot be read due to the file being unreadable
  -- or the format being incorrect.
  ecCStructError :: ErrorCode
  ecCStructError = 1
  