-- | C code generator.  This module can convert a correct ImpCode
-- program to an equivalent C program. The C code is strictly
-- sequential, but can handle the full Futhark language.
module Futhark.CodeGen.Backends.SequentialC
  ( compileProg,
    GC.CParts (..),
    GC.asLibrary,
    GC.asExecutable,
    GC.asServer,
  )
where

import Control.Monad
import qualified Futhark.CodeGen.Backends.GenericC as GC
import Futhark.CodeGen.Backends.SequentialC.Boilerplate
import qualified Futhark.CodeGen.ImpCode.Sequential as Imp
import qualified Futhark.CodeGen.ImpGen.Sequential as ImpGen
import Futhark.IR.SeqMem
import Futhark.MonadFreshNames

-- | Compile the program to sequential C.
compileProg :: MonadFreshNames m => Prog SeqMem -> m (ImpGen.Warnings, GC.CParts)
compileProg :: Prog SeqMem -> m (Warnings, CParts)
compileProg =
  (Definitions Sequential -> m CParts)
-> (Warnings, Definitions Sequential) -> m (Warnings, CParts)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse
    (String
-> Operations Sequential ()
-> CompilerM Sequential () ()
-> String
-> [Space]
-> [Option]
-> Definitions Sequential
-> m CParts
forall (m :: * -> *) op.
MonadFreshNames m =>
String
-> Operations op ()
-> CompilerM op () ()
-> String
-> [Space]
-> [Option]
-> Definitions op
-> m CParts
GC.compileProg String
"c" Operations Sequential ()
operations CompilerM Sequential () ()
forall op s. CompilerM op s ()
generateBoilerplate String
"" [Space
DefaultSpace] [])
    ((Warnings, Definitions Sequential) -> m (Warnings, CParts))
-> (Prog SeqMem -> m (Warnings, Definitions Sequential))
-> Prog SeqMem
-> m (Warnings, CParts)
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< Prog SeqMem -> m (Warnings, Definitions Sequential)
forall (m :: * -> *).
MonadFreshNames m =>
Prog SeqMem -> m (Warnings, Definitions Sequential)
ImpGen.compileProg
  where
    operations :: GC.Operations Imp.Sequential ()
    operations :: Operations Sequential ()
operations =
      Operations Sequential ()
forall op s. Operations op s
GC.defaultOperations
        { opsCompiler :: OpCompiler Sequential ()
GC.opsCompiler = CompilerM Sequential () () -> OpCompiler Sequential ()
forall a b. a -> b -> a
const (CompilerM Sequential () () -> OpCompiler Sequential ())
-> CompilerM Sequential () () -> OpCompiler Sequential ()
forall a b. (a -> b) -> a -> b
$ () -> CompilerM Sequential () ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        }