    -- Copyright © 2011 National Institute of Aerospace / Galois, Inc.

    -- | Primitives to build streams connected to external variables.

    {-# LANGUAGE Safe #-}

    module Copilot.Language.Operators.Extern
      ( extern
      , externB
      , externW8
      , externW16
      , externW32
      , externW64
      , externI8
      , externI16
      , externI32
      , externI64
      , externF
      , externD
      ) where

    import Copilot.Core (Typed)
    import Copilot.Language.Stream
    import Data.Word
    import Data.Int

    -- | Create a stream populated by an external global variable.
    --
    -- The Copilot compiler does not check that the type is correct. If the list
    -- given as second argument does not constrain the type of the values carried
    -- by the stream, this primitive stream building function will match any stream
    -- of any type, which is potentially dangerous if the global variable mentioned
    -- has a different type. We rely on the compiler used with the generated code
    -- to detect type errors of this kind.
    extern :: Typed a
           => String    -- ^ Name of the global variable to make accessible.
           -> Maybe [a] -- ^ Values to be used exclusively for testing/simulation.
           -> Stream a
    extern :: forall a. Typed a => String -> Maybe [a] -> Stream a
    extern = String -> Maybe [a] -> Stream a
    forall a. Typed a => String -> Maybe [a] -> Stream a
    Extern

    -- | Create a stream carrying values of type Bool, populated by an external
    -- global variable.
    externB :: String       -- ^ Name of the global variable to make accessible.
            -> Maybe [Bool] -- ^ Values to be used exclusively for
                            -- testing/simulation.
            -> Stream Bool
    externB :: String -> Maybe [Bool] -> Stream Bool
    externB = String -> Maybe [Bool] -> Stream Bool
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern

    -- | Create a stream carrying values of type Word8, populated by an external
    -- global variable.
    externW8 :: String         -- ^ Name of the global variable to make accessible.
             -> Maybe [Word8]  -- ^ Values to be used exclusively for
                               --   testing/simulation.
             -> Stream Word8
    externW8 :: String -> Maybe [Word8] -> Stream Word8
    externW8 = String -> Maybe [Word8] -> Stream Word8
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern

    -- | Create a stream carrying values of type Word16, populated by an external
    -- global variable.
    externW16 :: String          -- ^ Name of the global variable to make accessible.
              -> Maybe [Word16]  -- ^ Values to be used exclusively for
                                 -- testing/simulation.
              -> Stream Word16
    externW16 :: String -> Maybe [Word16] -> Stream Word16
    externW16 = String -> Maybe [Word16] -> Stream Word16
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern

    -- | Create a stream carrying values of type Word32, populated by an external
    -- global variable.
    externW32 :: String          -- ^ Name of the global variable to make accessible.
              -> Maybe [Word32]  -- ^ Values to be used exclusively for
                                 -- testing/simulation.
              -> Stream Word32
    externW32 :: String -> Maybe [Word32] -> Stream Word32
    externW32 = String -> Maybe [Word32] -> Stream Word32
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern

    -- | Create a stream carrying values of type Word64, populated by an external
    -- global variable.
    externW64 :: String          -- ^ Name of the global variable to make accessible.
              -> Maybe [Word64]  -- ^ Values to be used exclusively for
                                 -- testing/simulation.
              -> Stream Word64
    externW64 :: String -> Maybe [Word64] -> Stream Word64
    externW64 = String -> Maybe [Word64] -> Stream Word64
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern

    -- | Create a stream carrying values of type Int8, populated by an external
    -- global variable.
    externI8 :: String    -- ^ Name of the global variable to make accessible.
             -> Maybe [Int8] -- ^ Values to be used exclusively for testing/simulation.
             -> Stream Int8
    externI8 :: String -> Maybe [Int8] -> Stream Int8
    externI8 = String -> Maybe [Int8] -> Stream Int8
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern

    -- | Create a stream carrying values of type Int16, populated by an external
    -- global variable.
    externI16 :: String    -- ^ Name of the global variable to make accessible.
              -> Maybe [Int16] -- ^ Values to be used exclusively for testing/simulation.
              -> Stream Int16
    externI16 :: String -> Maybe [Int16] -> Stream Int16
    externI16 = String -> Maybe [Int16] -> Stream Int16
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern

    -- | Create a stream carrying values of type Int32, populated by an external
    -- global variable.
    externI32 :: String    -- ^ Name of the global variable to make accessible.
              -> Maybe [Int32] -- ^ Values to be used exclusively for testing/simulation.
              -> Stream Int32
    externI32 :: String -> Maybe [Int32] -> Stream Int32
    externI32 = String -> Maybe [Int32] -> Stream Int32
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern

    -- | Create a stream carrying values of type Int64, populated by an external
    -- global variable.
    externI64 :: String    -- ^ Name of the global variable to make accessible.
              -> Maybe [Int64] -- ^ Values to be used exclusively for testing/simulation.
              -> Stream Int64
    externI64 :: String -> Maybe [Int64] -> Stream Int64
    externI64 = String -> Maybe [Int64] -> Stream Int64
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern

    -- | Create a stream carrying values of type Float, populated by an external
    -- global variable.
    externF :: String        -- ^ Name of the global variable to make accessible.
            -> Maybe [Float] -- ^ Values to be used exclusively for testing/simulation.
            -> Stream Float
    externF :: String -> Maybe [Float] -> Stream Float
    externF = String -> Maybe [Float] -> Stream Float
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern

    -- | Create a stream carrying values of type Double, populated by an external
    -- global variable.
    externD :: String    -- ^ Name of the global variable to make accessible.
            -> Maybe [Double] -- ^ Values to be used exclusively for testing/simulation.
            -> Stream Double
    externD :: String -> Maybe [Double] -> Stream Double
    externD = String -> Maybe [Double] -> Stream Double
    forall a. Typed a => String -> Maybe [a] -> Stream a
    extern