    {-# LANGUAGE ExistentialQuantification #-}
    {-# LANGUAGE DeriveGeneric             #-}
    {-# LANGUAGE MultiWayIf                #-}
    {-# LANGUAGE OverloadedStrings         #-}
    {-# LANGUAGE ScopedTypeVariables       #-}
    -- Copyright 2022 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.
    --
    -- | Create <https://github.com/nasa/fprime FPrime> components that subscribe
    -- to obtain data and call Copilot when new values arrive.

    {- HLINT ignore "Functor law" -}
    module Command.FPrimeApp
        ( command
        , CommandOptions(..)
        , ErrorCode
        )
      where

    -- External imports
    import           Control.Applicative    ( liftA2, (<|>) )
    import qualified Control.Exception      as E
    import           Control.Monad.Except   ( ExceptT(..), liftEither )
    import           Data.Aeson             ( ToJSON, toJSON )
    import           Data.Char              ( toUpper )
    import           Data.Maybe             ( fromMaybe, mapMaybe, maybeToList )
    import           GHC.Generics           ( Generic )

    -- External imports: auxiliary
    import System.Directory.Extra ( copyTemplate )

    import qualified Command.Standalone

    -- Internal imports: auxiliary
    import Command.Result (Result (..))

    -- Internal imports
    import Command.Common
    import Command.Errors     (ErrorCode, ErrorTriplet (..))
    import Command.VariableDB (InputDef (..), TypeDef (..), VariableDB, findInput,
                               findType, findTypeByType)

    -- | Generate a new FPrime component connected to Copilot.
    command :: CommandOptions -- ^ Options to the ROS backend.
            -> IO (Result ErrorCode)
    command :: CommandOptions -> IO (Result ErrorCode)
    command CommandOptions
    options = ExceptT ErrorTriplet IO () -> IO (Result ErrorCode)
    forall (m :: * -> *) a.
    Monad m =>
    ExceptT ErrorTriplet m a -> m (Result ErrorCode)
    processResult (ExceptT ErrorTriplet IO () -> IO (Result ErrorCode))
    -> ExceptT ErrorTriplet IO () -> IO (Result ErrorCode)
    forall a b. (a -> b) -> a -> b
    $ do
        -- Obtain template dir
        FilePath
    templateDir <- Maybe FilePath -> FilePath -> ExceptT ErrorTriplet IO FilePath
    forall e. Maybe FilePath -> FilePath -> ExceptT e IO FilePath
    locateTemplateDir Maybe FilePath
    mTemplateDir FilePath
    "fprime"

        Value
    templateVars <- Maybe FilePath -> ExceptT ErrorTriplet IO Value
    parseTemplateVarsFile Maybe FilePath
    templateVarsF

        AppData
    appData <- CommandOptions -> ExprPair -> ExceptT ErrorTriplet IO AppData
    command' CommandOptions
    options ExprPair
    functions

        let subst :: Value
    subst = Value -> Value -> Value
    mergeObjects (AppData -> Value
    forall a. ToJSON a => a -> Value
    toJSON AppData
    appData) Value
    templateVars

        -- Expand template
        IO (Either ErrorTriplet ()) -> ExceptT ErrorTriplet IO ()
    forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
    ExceptT (IO (Either ErrorTriplet ()) -> ExceptT ErrorTriplet IO ())
    -> IO (Either ErrorTriplet ()) -> ExceptT ErrorTriplet IO ()
    forall a b. (a -> b) -> a -> b
    $ (Either SomeException () -> Either ErrorTriplet ())
    -> IO (Either SomeException ()) -> IO (Either ErrorTriplet ())
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (ErrorTriplet -> Either SomeException () -> Either ErrorTriplet ()
    forall c b. c -> Either SomeException b -> Either c b
    makeLeftE ErrorTriplet
    cannotCopyTemplate) (IO (Either SomeException ()) -> IO (Either ErrorTriplet ()))
    -> IO (Either SomeException ()) -> IO (Either ErrorTriplet ())
    forall a b. (a -> b) -> a -> b
    $ IO () -> IO (Either SomeException ())
    forall e a. Exception e => IO a -> IO (Either e a)
    E.try (IO () -> IO (Either SomeException ()))
    -> IO () -> IO (Either SomeException ())
    forall a b. (a -> b) -> a -> b
    $
          FilePath -> Value -> FilePath -> IO ()
    copyTemplate FilePath
    templateDir Value
    subst FilePath
    targetDir

      where

        targetDir :: FilePath
    targetDir     = CommandOptions -> FilePath
    commandTargetDir CommandOptions
    options
        mTemplateDir :: Maybe FilePath
    mTemplateDir  = CommandOptions -> Maybe FilePath
    commandTemplateDir CommandOptions
    options
        functions :: ExprPair
    functions     = FilePath -> ExprPair
    exprPair (CommandOptions -> FilePath
    commandPropFormat CommandOptions
    options)
        templateVarsF :: Maybe FilePath
    templateVarsF = CommandOptions -> Maybe FilePath
    commandExtraVars CommandOptions
    options

    command' :: CommandOptions
             -> ExprPair
             -> ExceptT ErrorTriplet IO AppData
    command' :: CommandOptions -> ExprPair -> ExceptT ErrorTriplet IO AppData
    command' CommandOptions
    options (ExprPair ExprPairT a
    exprT) = do
        -- Open files needed to fill in details in the template.
        Maybe [FilePath]
    vs    <- Maybe FilePath -> ExceptT ErrorTriplet IO (Maybe [FilePath])
    parseVariablesFile Maybe FilePath
    varNameFile
        Maybe [FilePath]
    rs    <- Maybe FilePath -> ExceptT ErrorTriplet IO (Maybe [FilePath])
    parseRequirementsListFile Maybe FilePath
    handlersFile
        VariableDB
    varDB <- [FilePath] -> ExceptT ErrorTriplet IO VariableDB
    openVarDBFilesWithDefault [FilePath]
    varDBFile

        Maybe (Spec a)
    specT <- ExceptT ErrorTriplet IO (Maybe (Spec a))
    -> (FilePath -> ExceptT ErrorTriplet IO (Maybe (Spec a)))
    -> Maybe FilePath
    -> ExceptT ErrorTriplet IO (Maybe (Spec a))
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (Maybe (Spec a) -> ExceptT ErrorTriplet IO (Maybe (Spec a))
    forall a. a -> ExceptT ErrorTriplet IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (Spec a)
    forall a. Maybe a
    Nothing) (\FilePath
    e -> Spec a -> Maybe (Spec a)
    forall a. a -> Maybe a
    Just (Spec a -> Maybe (Spec a))
    -> ExceptT ErrorTriplet IO (Spec a)
    -> ExceptT ErrorTriplet IO (Maybe (Spec a))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> FilePath -> ExceptT ErrorTriplet IO (Spec a)
    parseInputExpr' FilePath
    e) Maybe FilePath
    cExpr
        Maybe (Spec a)
    specF <- ExceptT ErrorTriplet IO (Maybe (Spec a))
    -> (FilePath -> ExceptT ErrorTriplet IO (Maybe (Spec a)))
    -> Maybe FilePath
    -> ExceptT ErrorTriplet IO (Maybe (Spec a))
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (Maybe (Spec a) -> ExceptT ErrorTriplet IO (Maybe (Spec a))
    forall a. a -> ExceptT ErrorTriplet IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (Spec a)
    forall a. Maybe a
    Nothing) (\FilePath
    f -> Spec a -> Maybe (Spec a)
    forall a. a -> Maybe a
    Just (Spec a -> Maybe (Spec a))
    -> ExceptT ErrorTriplet IO (Spec a)
    -> ExceptT ErrorTriplet IO (Maybe (Spec a))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> FilePath -> ExceptT ErrorTriplet IO (Spec a)
    parseInputFile' FilePath
    f) Maybe FilePath
    fp

        let spec :: Maybe (Spec a)
    spec = Maybe (Spec a)
    specT Maybe (Spec a) -> Maybe (Spec a) -> Maybe (Spec a)
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Maybe (Spec a)
    specF

        Either ErrorTriplet () -> ExceptT ErrorTriplet IO ()
    forall e (m :: * -> *) a. MonadError e m => Either e a -> m a
    liftEither (Either ErrorTriplet () -> ExceptT ErrorTriplet IO ())
    -> Either ErrorTriplet () -> ExceptT ErrorTriplet IO ()
    forall a b. (a -> b) -> a -> b
    $ Maybe (Spec a)
    -> Maybe [FilePath] -> Maybe [FilePath] -> Either ErrorTriplet ()
    forall a.
    Maybe (Spec a)
    -> Maybe [FilePath] -> Maybe [FilePath] -> Either ErrorTriplet ()
    checkArguments Maybe (Spec a)
    spec Maybe [FilePath]
    vs Maybe [FilePath]
    rs

        Maybe AppData
    copilotM <- Maybe (ExceptT ErrorTriplet IO AppData)
    -> ExceptT ErrorTriplet IO (Maybe AppData)
    forall (t :: * -> *) (f :: * -> *) a.
    (Traversable t, Applicative f) =>
    t (f a) -> f (t a)
    forall (f :: * -> *) a. Applicative f => Maybe (f a) -> f (Maybe a)
    sequenceA (Maybe (ExceptT ErrorTriplet IO AppData)
     -> ExceptT ErrorTriplet IO (Maybe AppData))
    -> Maybe (ExceptT ErrorTriplet IO AppData)
    -> ExceptT ErrorTriplet IO (Maybe AppData)
    forall a b. (a -> b) -> a -> b
    $ (\Spec a
    spec' -> Spec a
    -> Maybe FilePath
    -> Maybe FilePath
    -> ExceptT ErrorTriplet IO AppData
    processSpec Spec a
    spec' Maybe FilePath
    fp Maybe FilePath
    cExpr) (Spec a -> ExceptT ErrorTriplet IO AppData)
    -> Maybe (Spec a) -> Maybe (ExceptT ErrorTriplet IO AppData)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe (Spec a)
    spec

        let varNames :: [FilePath]
    varNames = [FilePath] -> Maybe [FilePath] -> [FilePath]
    forall a. a -> Maybe a -> a
    fromMaybe (Maybe (Spec a) -> [FilePath]
    forall a. Maybe (Spec a) -> [FilePath]
    specExtractExternalVariables Maybe (Spec a)
    spec) Maybe [FilePath]
    vs
            monitors :: [(FilePath, Maybe FilePath)]
    monitors = [(FilePath, Maybe FilePath)]
    -> ([FilePath] -> [(FilePath, Maybe FilePath)])
    -> Maybe [FilePath]
    -> [(FilePath, Maybe FilePath)]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe
                         (Maybe (Spec a) -> [(FilePath, Maybe FilePath)]
    forall a. Maybe (Spec a) -> [(FilePath, Maybe FilePath)]
    specExtractHandlers Maybe (Spec a)
    spec)
                         ((FilePath -> (FilePath, Maybe FilePath))
    -> [FilePath] -> [(FilePath, Maybe FilePath)]
    forall a b. (a -> b) -> [a] -> [b]
    map (\FilePath
    x -> (FilePath
    x, Maybe FilePath
    forall a. Maybe a
    Nothing)))
                         Maybe [FilePath]
    rs

        let appData :: AppData
    appData   = [VarDecl] -> [Monitor] -> Maybe AppData -> AppData
    AppData [VarDecl]
    variables [Monitor]
    monitors' Maybe AppData
    copilotM
            variables :: [VarDecl]
    variables = (FilePath -> Maybe VarDecl) -> [FilePath] -> [VarDecl]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe (VariableDB -> FilePath -> Maybe VarDecl
    variableMap VariableDB
    varDB) [FilePath]
    varNames
            monitors' :: [Monitor]
    monitors' = ((FilePath, Maybe FilePath) -> Maybe Monitor)
    -> [(FilePath, Maybe FilePath)] -> [Monitor]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe (VariableDB -> (FilePath, Maybe FilePath) -> Maybe Monitor
    monitorMap VariableDB
    varDB) [(FilePath, Maybe FilePath)]
    monitors

        AppData -> ExceptT ErrorTriplet IO AppData
    forall a. a -> ExceptT ErrorTriplet IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return AppData
    appData

      where

        cExpr :: Maybe FilePath
    cExpr          = CommandOptions -> Maybe FilePath
    commandConditionExpr CommandOptions
    options
        fp :: Maybe FilePath
    fp             = CommandOptions -> Maybe FilePath
    commandInputFile CommandOptions
    options
        varNameFile :: Maybe FilePath
    varNameFile    = CommandOptions -> Maybe FilePath
    commandVariables CommandOptions
    options
        varDBFile :: [FilePath]
    varDBFile      = Maybe FilePath -> [FilePath]
    forall a. Maybe a -> [a]
    maybeToList (Maybe FilePath -> [FilePath]) -> Maybe FilePath -> [FilePath]
    forall a b. (a -> b) -> a -> b
    $ CommandOptions -> Maybe FilePath
    commandVariableDB CommandOptions
    options
        handlersFile :: Maybe FilePath
    handlersFile   = CommandOptions -> Maybe FilePath
    commandHandlers CommandOptions
    options
        formatName :: FilePath
    formatName     = CommandOptions -> FilePath
    commandFormat CommandOptions
    options
        propFormatName :: FilePath
    propFormatName = CommandOptions -> FilePath
    commandPropFormat CommandOptions
    options
        propVia :: Maybe FilePath
    propVia        = CommandOptions -> Maybe FilePath
    commandPropVia CommandOptions
    options

        parseInputExpr' :: FilePath -> ExceptT ErrorTriplet IO (Spec a)
    parseInputExpr' FilePath
    e =
          FilePath
    -> FilePath
    -> Maybe FilePath
    -> ExprPairT a
    -> ExceptT ErrorTriplet IO (Spec a)
    forall a.
    FilePath
    -> FilePath
    -> Maybe FilePath
    -> ExprPairT a
    -> ExceptT ErrorTriplet IO (Spec a)
    parseInputExpr FilePath
    e FilePath
    propFormatName Maybe FilePath
    propVia ExprPairT a
    exprT

        parseInputFile' :: FilePath -> ExceptT ErrorTriplet IO (Spec a)
    parseInputFile' FilePath
    f =
          FilePath
    -> FilePath
    -> FilePath
    -> Maybe FilePath
    -> ExprPairT a
    -> ExceptT ErrorTriplet IO (Spec a)
    forall a.
    FilePath
    -> FilePath
    -> FilePath
    -> Maybe FilePath
    -> ExprPairT a
    -> ExceptT ErrorTriplet IO (Spec a)
    parseInputFile FilePath
    f FilePath
    formatName FilePath
    propFormatName Maybe FilePath
    propVia ExprPairT a
    exprT

        processSpec :: Spec a
    -> Maybe FilePath
    -> Maybe FilePath
    -> ExceptT ErrorTriplet IO AppData
    processSpec Spec a
    spec' Maybe FilePath
    expr' Maybe FilePath
    fp' =
          Maybe FilePath
    -> Maybe FilePath
    -> FilePath
    -> [(FilePath, FilePath)]
    -> ExprPairT a
    -> Spec a
    -> ExceptT ErrorTriplet IO AppData
    forall a.
    Maybe FilePath
    -> Maybe FilePath
    -> FilePath
    -> [(FilePath, FilePath)]
    -> ExprPairT a
    -> Spec a
    -> ExceptT ErrorTriplet IO AppData
    Command.Standalone.commandLogic Maybe FilePath
    expr' Maybe FilePath
    fp' FilePath
    "copilot" [] ExprPairT a
    exprT Spec a
    spec'

    -- ** Argument processing

    -- | Options used to customize the conversion of specifications to F'
    -- applications.
    data CommandOptions = CommandOptions
      { CommandOptions -> Maybe FilePath
    commandConditionExpr :: Maybe String   -- ^ Trigger condition.
      , CommandOptions -> Maybe FilePath
    commandInputFile   :: Maybe FilePath -- ^ Input specification file.
      , CommandOptions -> FilePath
    commandTargetDir   :: FilePath       -- ^ Target directory where the
                                             -- component should be created.
      , CommandOptions -> Maybe FilePath
    commandTemplateDir :: Maybe FilePath -- ^ Directory where the template is
                                             -- to be found.
      , CommandOptions -> Maybe FilePath
    commandVariables   :: Maybe FilePath -- ^ File containing a list of
                                             -- variables to make available to
                                             -- Copilot.
      , CommandOptions -> Maybe FilePath
    commandVariableDB  :: Maybe FilePath -- ^ File containing a list of known
                                             -- variables with their types and the
                                             -- message IDs they can be obtained
                                             -- from.
      , CommandOptions -> Maybe FilePath
    commandHandlers    :: Maybe FilePath -- ^ File containing a list of
                                             -- handlers used in the Copilot
                                             -- specification. The handlers are
                                             -- assumed to receive no arguments.
      , CommandOptions -> FilePath
    commandFormat      :: String         -- ^ Format of the input file.
      , CommandOptions -> FilePath
    commandPropFormat  :: String         -- ^ Format used for input properties.
      , CommandOptions -> Maybe FilePath
    commandPropVia     :: Maybe String   -- ^ Use external command to
                                             -- pre-process system properties.
      , CommandOptions -> Maybe FilePath
    commandExtraVars   :: Maybe FilePath -- ^ File containing additional
                                             -- variables to make available to the
                                             -- template.
      }

    -- | Return the variable information needed to generate declarations
    -- and subscriptions for a given variable name and variable database.
    variableMap :: VariableDB
                -> String
                -> Maybe VarDecl
    variableMap :: VariableDB -> FilePath -> Maybe VarDecl
    variableMap VariableDB
    varDB FilePath
    varName = do
      InputDef
    inputDef     <- VariableDB -> FilePath -> Maybe InputDef
    findInput VariableDB
    varDB FilePath
    varName
      FilePath
    inputDefType <- InputDef -> Maybe FilePath
    inputType InputDef
    inputDef
      let typeDef :: Maybe TypeDef
    typeDef = VariableDB -> FilePath -> FilePath -> FilePath -> Maybe TypeDef
    findType VariableDB
    varDB FilePath
    varName FilePath
    "fprime/port" FilePath
    "C"

      FilePath
    portType <- Maybe FilePath
    -> (TypeDef -> Maybe FilePath) -> Maybe TypeDef -> Maybe FilePath
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (InputDef -> Maybe FilePath
    inputType InputDef
    inputDef) (FilePath -> Maybe FilePath
    forall a. a -> Maybe a
    Just (FilePath -> Maybe FilePath)
    -> (TypeDef -> FilePath) -> TypeDef -> Maybe FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . TypeDef -> FilePath
    typeFromType) Maybe TypeDef
    typeDef

      VarDecl -> Maybe VarDecl
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (VarDecl -> Maybe VarDecl) -> VarDecl -> Maybe VarDecl
    forall a b. (a -> b) -> a -> b
    $ FilePath -> FilePath -> FilePath -> VarDecl
    VarDecl FilePath
    varName FilePath
    inputDefType FilePath
    portType

    -- | Return the monitor information needed to generate declarations and
    -- publishers for the given monitor info, and variable database.
    monitorMap :: VariableDB
               -> (String, Maybe String)
               -> Maybe Monitor
    monitorMap :: VariableDB -> (FilePath, Maybe FilePath) -> Maybe Monitor
    monitorMap VariableDB
    varDB (FilePath
    monitorName, Maybe FilePath
    Nothing) =
      Monitor -> Maybe Monitor
    forall a. a -> Maybe a
    Just (Monitor -> Maybe Monitor) -> Monitor -> Maybe Monitor
    forall a b. (a -> b) -> a -> b
    $ FilePath -> FilePath -> Maybe FilePath -> Maybe FilePath -> Monitor
    Monitor FilePath
    monitorName ((Char -> Char) -> FilePath -> FilePath
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toUpper FilePath
    monitorName) Maybe FilePath
    forall a. Maybe a
    Nothing Maybe FilePath
    forall a. Maybe a
    Nothing
    monitorMap VariableDB
    varDB (FilePath
    monitorName, Just FilePath
    ty) = do
      let tyPort :: FilePath
    tyPort = FilePath -> (TypeDef -> FilePath) -> Maybe TypeDef -> FilePath
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe FilePath
    ty TypeDef -> FilePath
    typeFromType (Maybe TypeDef -> FilePath) -> Maybe TypeDef -> FilePath
    forall a b. (a -> b) -> a -> b
    $ VariableDB -> FilePath -> FilePath -> FilePath -> Maybe TypeDef
    findTypeByType VariableDB
    varDB FilePath
    "fprime/port" FilePath
    "C" FilePath
    ty
      Monitor -> Maybe Monitor
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Monitor -> Maybe Monitor) -> Monitor -> Maybe Monitor
    forall a b. (a -> b) -> a -> b
    $ FilePath -> FilePath -> Maybe FilePath -> Maybe FilePath -> Monitor
    Monitor FilePath
    monitorName ((Char -> Char) -> FilePath -> FilePath
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toUpper FilePath
    monitorName) (FilePath -> Maybe FilePath
    forall a. a -> Maybe a
    Just FilePath
    ty) (FilePath -> Maybe FilePath
    forall a. a -> Maybe a
    Just FilePath
    tyPort)

    -- | The declaration of a variable in C, with a given type and name.
    data VarDecl = VarDecl
        { VarDecl -> FilePath
    varDeclName       :: String
        , VarDecl -> FilePath
    varDeclType       :: String
        , VarDecl -> FilePath
    varDeclFPrimeType :: String
        }
      deriving (forall x. VarDecl -> Rep VarDecl x)
    -> (forall x. Rep VarDecl x -> VarDecl) -> Generic VarDecl
    forall x. Rep VarDecl x -> VarDecl
    forall x. VarDecl -> Rep VarDecl x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. VarDecl -> Rep VarDecl x
    from :: forall x. VarDecl -> Rep VarDecl x
    $cto :: forall x. Rep VarDecl x -> VarDecl
    to :: forall x. Rep VarDecl x -> VarDecl
    Generic

    instance ToJSON VarDecl

    data Monitor = Monitor
        { Monitor -> FilePath
    monitorName     :: String
        , Monitor -> FilePath
    monitorUC       :: String
        , Monitor -> Maybe FilePath
    monitorType     :: Maybe String
        , Monitor -> Maybe FilePath
    monitorPortType :: Maybe String
        }
      deriving (forall x. Monitor -> Rep Monitor x)
    -> (forall x. Rep Monitor x -> Monitor) -> Generic Monitor
    forall x. Rep Monitor x -> Monitor
    forall x. Monitor -> Rep Monitor x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. Monitor -> Rep Monitor x
    from :: forall x. Monitor -> Rep Monitor x
    $cto :: forall x. Rep Monitor x -> Monitor
    to :: forall x. Rep Monitor x -> Monitor
    Generic

    instance ToJSON Monitor

    -- | Data that may be relevant to generate a ROS application.
    data AppData = AppData
      { AppData -> [VarDecl]
    variables :: [VarDecl]
      , AppData -> [Monitor]
    monitors  :: [Monitor]
      , AppData -> Maybe AppData
    copilot   :: Maybe Command.Standalone.AppData
      }
      deriving ((forall x. AppData -> Rep AppData x)
    -> (forall x. Rep AppData x -> AppData) -> Generic AppData
    forall x. Rep AppData x -> AppData
    forall x. AppData -> Rep AppData x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. AppData -> Rep AppData x
    from :: forall x. AppData -> Rep AppData x
    $cto :: forall x. Rep AppData x -> AppData
    to :: forall x. Rep AppData x -> AppData
    Generic)

    instance ToJSON AppData