-- | Monad for running Feldspar programs

module Feldspar.Run.Frontend
  ( Run
  , MonadRun (..)
  , module Feldspar.Run.Frontend
  , module Language.Embedded.Imperative.Frontend.General
  ) where



import Language.Syntactic

import qualified Control.Monad.Operational.Higher as Oper

import Language.Embedded.Imperative.Frontend.General hiding (Ref, Arr, IArr)
import qualified Language.Embedded.Imperative as Imp
import qualified Language.Embedded.Imperative.CMD as Imp

import Data.TypedStruct
import Feldspar.Primitive.Representation
import Feldspar.Primitive.Backend.C ()
import Feldspar.Representation
import Feldspar.Run.Representation



--------------------------------------------------------------------------------
-- * Pointer operations
--------------------------------------------------------------------------------

-- | Swap two pointers
--
-- This is generally an unsafe operation. E.g. it can be used to make a
-- reference to a data structure escape the scope of the data.
unsafeSwap :: Ptr a -> Ptr a -> Run ()
unsafeSwap :: Ptr a -> Ptr a -> Run ()
unsafeSwap Ptr a
a Ptr a
b = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
-> Run ()
forall a b. (a -> b) -> a -> b
$ Ptr a
-> Ptr a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall k1 (instr :: (* -> *, (k1, (* -> Constraint, *))) -> * -> *)
       a (exp :: k1) (pred :: * -> Constraint) (m :: * -> *).
(PtrCMD :<: instr) =>
Ptr a -> Ptr a -> ProgramT instr (Param2 exp pred) m ()
Imp.unsafeSwap Ptr a
a Ptr a
b

-- | Like 'unsafeSwap' but for arrays. The why we cannot use 'unsafeSwap'
-- directly is that 'Arr' cannot be made an instance of 'IsPointer'.
unsafeSwapArr :: Arr a -> Arr a -> Run ()
unsafeSwapArr :: Arr a -> Arr a -> Run ()
unsafeSwapArr Arr a
arr1 Arr a
arr2 = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
-> Run ()
forall a b. (a -> b) -> a -> b
$ [ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()]
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ ([ProgramT
    RunCMD
    (Param2 Data PrimType')
    (Program CompCMD (Param2 Data PrimType'))
    ()]
 -> ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      ())
-> [ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      ()]
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall a b. (a -> b) -> a -> b
$
    (forall a.
 PrimType' a =>
 Arr Index a
 -> Arr Index a
 -> ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      ())
-> Struct PrimType' (Arr Index) (Internal a)
-> Struct PrimType' (Arr Index) (Internal a)
-> [ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      ()]
forall (pred :: * -> Constraint) (c1 :: * -> *) (c2 :: * -> *) b r.
(forall a. pred a => c1 a -> c2 a -> r)
-> Struct pred c1 b -> Struct pred c2 b -> [r]
zipListStruct forall a.
PrimType' a =>
Arr Index a
-> Arr Index a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall k1 i a (pred :: * -> Constraint)
       (instr :: (* -> *, (k1, (* -> Constraint, *))) -> * -> *)
       (exp :: k1) (m :: * -> *).
(Typeable i, Typeable a, pred i, pred a, PtrCMD :<: instr) =>
Arr i a -> Arr i a -> ProgramT instr (Param2 exp pred) m ()
Imp.unsafeSwapArr (Arr a -> Struct PrimType' (Arr Index) (Internal a)
forall a. Arr a -> Struct PrimType' (Arr Index) (Internal a)
unArr Arr a
arr1) (Arr a -> Struct PrimType' (Arr Index) (Internal a)
forall a. Arr a -> Struct PrimType' (Arr Index) (Internal a)
unArr Arr a
arr2)
  -- An alternative would be to make a new `IsPointer` class for Feldspar



--------------------------------------------------------------------------------
-- * File handling
--------------------------------------------------------------------------------

-- | Open a file
fopen :: FilePath -> IOMode -> Run Handle
fopen :: FilePath -> IOMode -> Run Handle
fopen FilePath
file = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  Handle
-> Run Handle
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   Handle
 -> Run Handle)
-> (IOMode
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         Handle)
-> IOMode
-> Run Handle
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath
-> IOMode
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     Handle
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *).
(FileCMD :<: instr) =>
FilePath -> IOMode -> ProgramT instr (Param2 exp pred) m Handle
Imp.fopen FilePath
file

-- | Close a file
fclose :: Handle -> Run ()
fclose :: Handle -> Run ()
fclose = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> (Handle
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> Handle
-> Run ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *).
(FileCMD :<: instr) =>
Handle -> ProgramT instr (Param2 exp pred) m ()
Imp.fclose

-- | Check for end of file
feof :: Handle -> Run (Data Bool)
feof :: Handle -> Run (Data Bool)
feof = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data Bool)
-> Run (Data Bool)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Data Bool)
 -> Run (Data Bool))
-> (Handle
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         (Data Bool))
-> Handle
-> Run (Data Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data Bool)
forall (exp :: * -> *)
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (m :: * -> *) (pred :: * -> Constraint).
(FreeExp exp, FreePred exp Bool, FileCMD :<: instr, Monad m) =>
Handle -> ProgramT instr (Param2 exp pred) m (exp Bool)
Imp.feof

class PrintfType r
  where
    fprf :: Handle -> String -> [Imp.PrintfArg Data PrimType'] -> r

instance (a ~ ()) => PrintfType (Run a)
  where
    fprf :: Handle -> FilePath -> [PrintfArg Data PrimType'] -> Run a
fprf Handle
h FilePath
form = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> ([PrintfArg Data PrimType']
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> [PrintfArg Data PrimType']
-> Run ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileCMD
  '(ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType')),
    Param2 Data PrimType')
  ()
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall k (i :: (* -> *, k) -> * -> *)
       (instr :: (* -> *, k) -> * -> *) (fs :: k) (m :: * -> *) a.
(i :<: instr) =>
i '(ProgramT instr fs m, fs) a -> ProgramT instr fs m a
Oper.singleInj (FileCMD
   '(ProgramT
       RunCMD
       (Param2 Data PrimType')
       (Program CompCMD (Param2 Data PrimType')),
     Param2 Data PrimType')
   ()
 -> ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      ())
-> ([PrintfArg Data PrimType']
    -> FileCMD
         '(ProgramT
             RunCMD
             (Param2 Data PrimType')
             (Program CompCMD (Param2 Data PrimType')),
           Param2 Data PrimType')
         ())
-> [PrintfArg Data PrimType']
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle
-> FilePath
-> [PrintfArg Data PrimType']
-> FileCMD
     '(ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType')),
       Param2 Data PrimType')
     ()
forall k (exp :: * -> *) (pred :: * -> Constraint) (prog :: k).
Handle
-> FilePath
-> [PrintfArg exp pred]
-> FileCMD '(prog, Param2 exp pred) ()
Imp.FPrintf Handle
h FilePath
form ([PrintfArg Data PrimType']
 -> FileCMD
      '(ProgramT
          RunCMD
          (Param2 Data PrimType')
          (Program CompCMD (Param2 Data PrimType')),
        Param2 Data PrimType')
      ())
-> ([PrintfArg Data PrimType'] -> [PrintfArg Data PrimType'])
-> [PrintfArg Data PrimType']
-> FileCMD
     '(ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType')),
       Param2 Data PrimType')
     ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [PrintfArg Data PrimType'] -> [PrintfArg Data PrimType']
forall a. [a] -> [a]
reverse

instance (Formattable a, PrimType a, PrintfType r) => PrintfType (Data a -> r)
  where
    fprf :: Handle -> FilePath -> [PrintfArg Data PrimType'] -> Data a -> r
fprf Handle
h FilePath
form [PrintfArg Data PrimType']
as = \Data a
a -> Handle -> FilePath -> [PrintfArg Data PrimType'] -> r
forall r.
PrintfType r =>
Handle -> FilePath -> [PrintfArg Data PrimType'] -> r
fprf Handle
h FilePath
form (Data a -> PrintfArg Data PrimType'
forall a (pred :: * -> Constraint) (exp :: * -> *).
(PrintfArg a, pred a) =>
exp a -> PrintfArg exp pred
Imp.PrintfArg Data a
a PrintfArg Data PrimType'
-> [PrintfArg Data PrimType'] -> [PrintfArg Data PrimType']
forall a. a -> [a] -> [a]
: [PrintfArg Data PrimType']
as)

-- | Print to a handle. Accepts a variable number of arguments.
fprintf :: PrintfType r => Handle -> String -> r
fprintf :: Handle -> FilePath -> r
fprintf Handle
h FilePath
format = Handle -> FilePath -> [PrintfArg Data PrimType'] -> r
forall r.
PrintfType r =>
Handle -> FilePath -> [PrintfArg Data PrimType'] -> r
fprf Handle
h FilePath
format []

-- | Put a primitive value to a handle
fput :: (Formattable a, PrimType a)
    => Handle
    -> String  -- Prefix
    -> Data a  -- Expression to print
    -> String  -- Suffix
    -> Run ()
fput :: Handle -> FilePath -> Data a -> FilePath -> Run ()
fput Handle
h FilePath
pre Data a
e FilePath
post = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
-> Run ()
forall a b. (a -> b) -> a -> b
$ Handle
-> FilePath
-> Data a
-> FilePath
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) a (m :: * -> *).
(Formattable a, FreePred exp a, FileCMD :<: instr, pred a) =>
Handle
-> FilePath
-> exp a
-> FilePath
-> ProgramT instr (Param2 exp pred) m ()
Imp.fput Handle
h FilePath
pre Data a
e FilePath
post

-- | Get a primitive value from a handle
fget :: (Formattable a, PrimType a) => Handle -> Run (Data a)
fget :: Handle -> Run (Data a)
fget = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data a)
-> Run (Data a)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Data a)
 -> Run (Data a))
-> (Handle
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         (Data a))
-> Handle
-> Run (Data a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data a)
forall a (pred :: * -> Constraint) (exp :: * -> *)
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (m :: * -> *).
(Formattable a, pred a, FreeExp exp, FreePred exp a,
 FileCMD :<: instr, Monad m) =>
Handle -> ProgramT instr (Param2 exp pred) m (exp a)
Imp.fget

-- | Print to @stdout@. Accepts a variable number of arguments.
printf :: PrintfType r => String -> r
printf :: FilePath -> r
printf = Handle -> FilePath -> r
forall r. PrintfType r => Handle -> FilePath -> r
fprintf Handle
Imp.stdout



--------------------------------------------------------------------------------
-- * C-specific commands
--------------------------------------------------------------------------------

-- | Create a null pointer
newPtr :: PrimType a => Run (Ptr a)
newPtr :: Run (Ptr a)
newPtr = FilePath -> Run (Ptr a)
forall a. PrimType a => FilePath -> Run (Ptr a)
newNamedPtr FilePath
"p"

-- | Create a named null pointer
--
-- The provided base name may be appended with a unique identifier to avoid name
-- collisions.
newNamedPtr :: PrimType a
    => String  -- ^ Base name
    -> Run (Ptr a)
newNamedPtr :: FilePath -> Run (Ptr a)
newNamedPtr = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Ptr a)
-> Run (Ptr a)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Ptr a)
 -> Run (Ptr a))
-> (FilePath
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         (Ptr a))
-> FilePath
-> Run (Ptr a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Ptr a)
forall (pred :: * -> Constraint) a
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (exp :: * -> *) (m :: * -> *).
(pred a, C_CMD :<: instr) =>
FilePath -> ProgramT instr (Param2 exp pred) m (Ptr a)
Imp.newNamedPtr

-- | Cast a pointer to an array
ptrToArr :: PrimType a => Ptr a -> Data Length -> Run (DArr a)
ptrToArr :: Ptr a -> Data Index -> Run (DArr a)
ptrToArr Ptr a
ptr Data Index
len = (Arr Index a -> DArr a) -> Run (Arr Index a) -> Run (DArr a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Data Index
-> Data Index
-> Struct PrimType' (Arr Index) (Internal (Data a))
-> DArr a
forall a.
Data Index
-> Data Index -> Struct PrimType' (Arr Index) (Internal a) -> Arr a
Arr Data Index
0 Data Index
len (Struct PrimType' (Arr Index) a -> DArr a)
-> (Arr Index a -> Struct PrimType' (Arr Index) a)
-> Arr Index a
-> DArr a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arr Index a -> Struct PrimType' (Arr Index) a
forall (pred :: * -> Constraint) a (con :: * -> *).
pred a =>
con a -> Struct pred con a
Single) (Run (Arr Index a) -> Run (DArr a))
-> Run (Arr Index a) -> Run (DArr a)
forall a b. (a -> b) -> a -> b
$ ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Arr Index a)
-> Run (Arr Index a)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Arr Index a)
 -> Run (Arr Index a))
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Arr Index a)
-> Run (Arr Index a)
forall a b. (a -> b) -> a -> b
$ Ptr a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Arr Index a)
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       a (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *) i.
(C_CMD :<: instr) =>
Ptr a -> ProgramT instr (Param2 exp pred) m (Arr i a)
Imp.ptrToArr Ptr a
ptr

-- | Create a pointer to an abstract object. The only thing one can do with such
-- objects is to pass them to 'callFun' or 'callProc'.
newObject
    :: String  -- ^ Object type
    -> Bool    -- ^ Pointed?
    -> Run Object
newObject :: FilePath -> Bool -> Run Object
newObject = FilePath -> FilePath -> Bool -> Run Object
newNamedObject FilePath
"obj"

-- | Create a pointer to an abstract object. The only thing one can do with such
-- objects is to pass them to 'callFun' or 'callProc'.
--
-- The provided base name may be appended with a unique identifier to avoid name
-- collisions.
newNamedObject
    :: String  -- ^ Base name
    -> String  -- ^ Object type
    -> Bool    -- ^ Pointed?
    -> Run Object
newNamedObject :: FilePath -> FilePath -> Bool -> Run Object
newNamedObject FilePath
base FilePath
t Bool
p = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  Object
-> Run Object
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   Object
 -> Run Object)
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     Object
-> Run Object
forall a b. (a -> b) -> a -> b
$ FilePath
-> FilePath
-> Bool
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     Object
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *).
(C_CMD :<: instr) =>
FilePath
-> FilePath -> Bool -> ProgramT instr (Param2 exp pred) m Object
Imp.newNamedObject FilePath
base FilePath
t Bool
p

-- | Add an @#include@ statement to the generated code
addInclude :: String -> Run ()
addInclude :: FilePath -> Run ()
addInclude = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> (FilePath
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> FilePath
-> Run ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *).
(C_CMD :<: instr) =>
FilePath -> ProgramT instr (Param2 exp pred) m ()
Imp.addInclude

-- | Add a global definition to the generated code
--
-- Can be used conveniently as follows:
--
-- > {-# LANGUAGE QuasiQuotes #-}
-- >
-- > import Feldspar.IO
-- >
-- > prog = do
-- >     ...
-- >     addDefinition myCFunction
-- >     ...
-- >   where
-- >     myCFunction = [cedecl|
-- >       void my_C_function( ... )
-- >       {
-- >           // C code
-- >           // goes here
-- >       }
-- >       |]
addDefinition :: Imp.Definition -> Run ()
addDefinition :: Definition -> Run ()
addDefinition = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> (Definition
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> Definition
-> Run ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Definition
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *).
(C_CMD :<: instr) =>
Definition -> ProgramT instr (Param2 exp pred) m ()
Imp.addDefinition

-- | Declare an external function
addExternFun :: PrimType res
    => String                   -- ^ Function name
    -> proxy res                -- ^ Proxy for expression and result type
    -> [FunArg Data PrimType']  -- ^ Arguments (only used to determine types)
    -> Run ()
addExternFun :: FilePath -> proxy res -> [FunArg Data PrimType'] -> Run ()
addExternFun FilePath
fun proxy res
res [FunArg Data PrimType']
args = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
-> Run ()
forall a b. (a -> b) -> a -> b
$ FilePath
-> proxy res
-> [FunArg Data PrimType']
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall (pred :: * -> Constraint) res
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (proxy :: * -> *) (exp :: * -> *) (m :: * -> *).
(pred res, C_CMD :<: instr) =>
FilePath
-> proxy res
-> [FunArg exp pred]
-> ProgramT instr (Param2 exp pred) m ()
Imp.addExternFun FilePath
fun proxy res
res [FunArg Data PrimType']
args

-- | Declare an external procedure
addExternProc
    :: String                   -- ^ Procedure name
    -> [FunArg Data PrimType']  -- ^ Arguments (only used to determine types)
    -> Run ()
addExternProc :: FilePath -> [FunArg Data PrimType'] -> Run ()
addExternProc FilePath
proc [FunArg Data PrimType']
args = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
-> Run ()
forall a b. (a -> b) -> a -> b
$ FilePath
-> [FunArg Data PrimType']
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *).
(C_CMD :<: instr) =>
FilePath
-> [FunArg exp pred] -> ProgramT instr (Param2 exp pred) m ()
Imp.addExternProc FilePath
proc [FunArg Data PrimType']
args

-- | Call a function
callFun :: PrimType a
    => String                   -- ^ Function name
    -> [FunArg Data PrimType']  -- ^ Arguments
    -> Run (Data a)
callFun :: FilePath -> [FunArg Data PrimType'] -> Run (Data a)
callFun FilePath
fun [FunArg Data PrimType']
as = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data a)
-> Run (Data a)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Data a)
 -> Run (Data a))
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data a)
-> Run (Data a)
forall a b. (a -> b) -> a -> b
$ FilePath
-> [FunArg Data PrimType']
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data a)
forall (pred :: * -> Constraint) a (exp :: * -> *)
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (m :: * -> *).
(pred a, FreeExp exp, FreePred exp a, C_CMD :<: instr, Monad m) =>
FilePath
-> [FunArg exp pred] -> ProgramT instr (Param2 exp pred) m (exp a)
Imp.callFun FilePath
fun [FunArg Data PrimType']
as

-- | Call a procedure
callProc
    :: String                   -- ^ Function name
    -> [FunArg Data PrimType']  -- ^ Arguments
    -> Run ()
callProc :: FilePath -> [FunArg Data PrimType'] -> Run ()
callProc FilePath
fun [FunArg Data PrimType']
as = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
-> Run ()
forall a b. (a -> b) -> a -> b
$ FilePath
-> [FunArg Data PrimType']
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *).
(C_CMD :<: instr) =>
FilePath
-> [FunArg exp pred] -> ProgramT instr (Param2 exp pred) m ()
Imp.callProc FilePath
fun [FunArg Data PrimType']
as

-- | Call a procedure and assign its result
callProcAssign :: Assignable obj
    => obj                      -- ^ Object to which the result should be assigned
    -> String                   -- ^ Procedure name
    -> [FunArg Data PrimType']  -- ^ Arguments
    -> Run ()
callProcAssign :: obj -> FilePath -> [FunArg Data PrimType'] -> Run ()
callProcAssign obj
obj FilePath
fun [FunArg Data PrimType']
as = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
-> Run ()
forall a b. (a -> b) -> a -> b
$ obj
-> FilePath
-> [FunArg Data PrimType']
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall obj
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *).
(Assignable obj, C_CMD :<: instr) =>
obj
-> FilePath
-> [FunArg exp pred]
-> ProgramT instr (Param2 exp pred) m ()
Imp.callProcAssign obj
obj FilePath
fun [FunArg Data PrimType']
as

-- | Declare and call an external function
externFun :: PrimType res
    => String                   -- ^ Procedure name
    -> [FunArg Data PrimType']  -- ^ Arguments
    -> Run (Data res)
externFun :: FilePath -> [FunArg Data PrimType'] -> Run (Data res)
externFun FilePath
fun [FunArg Data PrimType']
args = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data res)
-> Run (Data res)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   (Data res)
 -> Run (Data res))
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data res)
-> Run (Data res)
forall a b. (a -> b) -> a -> b
$ FilePath
-> [FunArg Data PrimType']
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     (Data res)
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (m :: * -> *) (exp :: * -> *) (pred :: * -> Constraint) res.
(pred res, FreeExp exp, FreePred exp res, C_CMD :<: instr,
 Monad m) =>
FilePath
-> [FunArg exp pred]
-> ProgramT instr (Param2 exp pred) m (exp res)
Imp.externFun FilePath
fun [FunArg Data PrimType']
args

-- | Declare and call an external procedure
externProc
    :: String                   -- ^ Procedure name
    -> [FunArg Data PrimType']  -- ^ Arguments
    -> Run ()
externProc :: FilePath -> [FunArg Data PrimType'] -> Run ()
externProc FilePath
proc [FunArg Data PrimType']
args = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
-> Run ()
forall a b. (a -> b) -> a -> b
$ FilePath
-> [FunArg Data PrimType']
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (m :: * -> *) (exp :: * -> *) (pred :: * -> Constraint).
(C_CMD :<: instr, Monad m) =>
FilePath
-> [FunArg exp pred] -> ProgramT instr (Param2 exp pred) m ()
Imp.externProc FilePath
proc [FunArg Data PrimType']
args

-- | Generate code into another translation unit
inModule :: String -> Run () -> Run ()
inModule :: FilePath -> Run () -> Run ()
inModule FilePath
mod = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  ()
-> Run ()
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> Run ())
-> (Run ()
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> Run ()
-> Run ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall (instr :: (* -> *, (* -> *, (* -> Constraint, *)))
                 -> * -> *)
       (exp :: * -> *) (pred :: * -> Constraint) (m :: * -> *).
(C_CMD :<: instr) =>
FilePath
-> ProgramT instr (Param2 exp pred) m ()
-> ProgramT instr (Param2 exp pred) m ()
Imp.inModule FilePath
mod (ProgramT
   RunCMD
   (Param2 Data PrimType')
   (Program CompCMD (Param2 Data PrimType'))
   ()
 -> ProgramT
      RunCMD
      (Param2 Data PrimType')
      (Program CompCMD (Param2 Data PrimType'))
      ())
-> (Run ()
    -> ProgramT
         RunCMD
         (Param2 Data PrimType')
         (Program CompCMD (Param2 Data PrimType'))
         ())
-> Run ()
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Run ()
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     ()
forall a.
Run a
-> ProgramT
     RunCMD
     (Param2 Data PrimType')
     (Program CompCMD (Param2 Data PrimType'))
     a
unRun

-- | Get current time as number of seconds passed today
getTime :: Run (Data Double)
getTime :: Run (Data Double)
getTime = ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data Double)
-> Run (Data Double)
forall a.
ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  a
-> Run a
Run ProgramT
  RunCMD
  (Param2 Data PrimType')
  (Program CompCMD (Param2 Data PrimType'))
  (Data Double)
forall (pred :: * -> Constraint) (exp :: * -> *)
       (instr :: (* -> *, (* -> *, (* -> Constraint, *))) -> * -> *)
       (m :: * -> *).
(pred Double, FreeExp exp, FreePred exp Double, C_CMD :<: instr,
 Monad m) =>
ProgramT instr (Param2 exp pred) m (exp Double)
Imp.getTime

-- | Constant string argument
strArg :: String -> FunArg Data PrimType'
strArg :: FilePath -> FunArg Data PrimType'
strArg = FilePath -> FunArg Data PrimType'
forall k (exp :: k -> *) (pred :: k -> Constraint).
FilePath -> FunArg exp pred
Imp.strArg

-- | Value argument
valArg :: PrimType' a => Data a -> FunArg Data PrimType'
valArg :: Data a -> FunArg Data PrimType'
valArg = Data a -> FunArg Data PrimType'
forall k (pred :: k -> Constraint) (a :: k) (exp :: k -> *).
pred a =>
exp a -> FunArg exp pred
Imp.valArg

-- | Reference argument
refArg :: PrimType' (Internal a) => Ref a -> FunArg Data PrimType'
refArg :: Ref a -> FunArg Data PrimType'
refArg (Ref Struct PrimType' Ref (Internal a)
r) = Ref (Internal a) -> FunArg Data PrimType'
forall (pred :: * -> Constraint) a (exp :: * -> *).
(pred a, Arg RefArg pred) =>
Ref a -> FunArg exp pred
Imp.refArg (Struct PrimType' Ref (Internal a) -> Ref (Internal a)
forall (pred :: * -> Constraint) a (c :: * -> *).
pred a =>
Struct pred c a -> c a
extractSingle Struct PrimType' Ref (Internal a)
r)

-- | Mutable array argument
arrArg :: PrimType' (Internal a) => Arr a -> FunArg Data PrimType'
arrArg :: Arr a -> FunArg Data PrimType'
arrArg (Arr Data Index
o Data Index
_ Struct PrimType' (Arr Index) (Internal a)
a) = FunArg Data PrimType' -> Data Index -> FunArg Data PrimType'
forall i (exp :: * -> *) (pred :: * -> Constraint).
Integral i =>
FunArg exp pred -> exp i -> FunArg exp pred
Imp.offset (Arr Index (Internal a) -> FunArg Data PrimType'
forall (pred :: * -> Constraint) a i (exp :: * -> *).
(pred a, Arg ArrArg pred) =>
Arr i a -> FunArg exp pred
Imp.arrArg (Struct PrimType' (Arr Index) (Internal a) -> Arr Index (Internal a)
forall (pred :: * -> Constraint) a (c :: * -> *).
pred a =>
Struct pred c a -> c a
extractSingle Struct PrimType' (Arr Index) (Internal a)
a)) Data Index
o

-- | Immutable array argument
iarrArg :: PrimType' (Internal a) => IArr a -> FunArg Data PrimType'
iarrArg :: IArr a -> FunArg Data PrimType'
iarrArg (IArr Data Index
o Data Index
_ Struct PrimType' (IArr Index) (Internal a)
a) = FunArg Data PrimType' -> Data Index -> FunArg Data PrimType'
forall i (exp :: * -> *) (pred :: * -> Constraint).
Integral i =>
FunArg exp pred -> exp i -> FunArg exp pred
Imp.offset (IArr Index (Internal a) -> FunArg Data PrimType'
forall (pred :: * -> Constraint) a i (exp :: * -> *).
(pred a, Arg IArrArg pred) =>
IArr i a -> FunArg exp pred
Imp.iarrArg (Struct PrimType' (IArr Index) (Internal a)
-> IArr Index (Internal a)
forall (pred :: * -> Constraint) a (c :: * -> *).
pred a =>
Struct pred c a -> c a
extractSingle Struct PrimType' (IArr Index) (Internal a)
a)) Data Index
o

-- | Abstract object argument
objArg :: Object -> FunArg Data PrimType'
objArg :: Object -> FunArg Data PrimType'
objArg = Object -> FunArg Data PrimType'
forall k (exp :: k -> *) (pred :: k -> Constraint).
Object -> FunArg exp pred
Imp.objArg

-- | Named constant argument
constArg
    :: String  -- ^ Type
    -> String  -- ^ Named constant
    -> FunArg Data PrimType'
constArg :: FilePath -> FilePath -> FunArg Data PrimType'
constArg = FilePath -> FilePath -> FunArg Data PrimType'
forall k (exp :: k -> *) (pred :: k -> Constraint).
FilePath -> FilePath -> FunArg exp pred
Imp.constArg

-- | Modifier that takes the address of another argument
addr :: FunArg Data PrimType' -> FunArg Data PrimType'
addr :: FunArg Data PrimType' -> FunArg Data PrimType'
addr = FunArg Data PrimType' -> FunArg Data PrimType'
forall k (exp :: k -> *) (pred :: k -> Constraint).
FunArg exp pred -> FunArg exp pred
Imp.addr

-- | Modifier that dereferences another argument
deref :: FunArg Data PrimType' -> FunArg Data PrimType'
deref :: FunArg Data PrimType' -> FunArg Data PrimType'
deref = FunArg Data PrimType' -> FunArg Data PrimType'
forall k (exp :: k -> *) (pred :: k -> Constraint).
FunArg exp pred -> FunArg exp pred
Imp.deref