    -- Copyright 2024 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.

    -- | Typechecking of Copilot specs.
    module Copilot.Language.Reify.Extra
        ( reifySpec )
      where

    -- External imports
    import qualified Copilot.Core                 as Core
    import qualified Copilot.Language             as Copilot
    import qualified Copilot.Language.Reify       as Copilot
    import qualified Language.Haskell.Interpreter as HI

    -- | Read a specification from a 'String' and reify it.
    --
    -- This function receives a list of possibly qualified imports.
    reifySpec :: [(String, Maybe String)] -> String -> IO Core.Spec
    reifySpec :: [(String, Maybe String)] -> String -> IO Spec
    reifySpec [(String, Maybe String)]
    imports String
    specText = do
      coreSpecE <- InterpreterT IO Spec -> IO (Either InterpreterError Spec)
    forall (m :: * -> *) a.
    (MonadIO m, MonadMask m) =>
    InterpreterT m a -> m (Either InterpreterError a)
    HI.runInterpreter (InterpreterT IO Spec -> IO (Either InterpreterError Spec))
    -> InterpreterT IO Spec -> IO (Either InterpreterError Spec)
    forall a b. (a -> b) -> a -> b
    $ do
                     [(String, Maybe String)] -> InterpreterT IO ()
    forall (m :: * -> *).
    MonadInterpreter m =>
    [(String, Maybe String)] -> m ()
    HI.setImportsQ [(String, Maybe String)]
    imports
                     copilotSpec <- String -> Spec -> InterpreterT IO Spec
    forall (m :: * -> *) a.
    (MonadInterpreter m, Typeable a) =>
    String -> a -> m a
    HI.interpret String
    specText (Spec
    forall a. Typeable a => a
    HI.as :: Copilot.Spec)
                     HI.liftIO $ Copilot.reify copilotSpec

      case coreSpecE of
        Left InterpreterError
    err -> do String -> IO ()
    putStrLn (String -> IO ()) -> String -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String
    "Error: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ InterpreterError -> String
    forall a. Show a => a -> String
    show InterpreterError
    err
                       String -> IO Spec
    forall a. HasCallStack => String -> a
    error (String -> IO Spec) -> String -> IO Spec
    forall a b. (a -> b) -> a -> b
    $ InterpreterError -> String
    forall a. Show a => a -> String
    show InterpreterError
    err

        Right Spec
    coreSpec -> Spec -> IO Spec
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Spec
    coreSpec