    -- | C code generator.  This module can convert a correct ImpCode
    -- program to an equivalent C program.  This C program is expected to
    -- be converted to WebAssembly, so we also produce the intended
    -- JavaScript wrapper.
    module Futhark.CodeGen.Backends.SequentialWASM
      ( compileProg,
        runServer,
        libraryExports,
        GC.CParts (..),
        GC.asLibrary,
        GC.asExecutable,
        GC.asServer,
      )
    where

    import Data.Maybe
    import Data.Text qualified as T
    import Futhark.CodeGen.Backends.GenericC qualified as GC
    import Futhark.CodeGen.Backends.GenericWASM
    import Futhark.CodeGen.Backends.SequentialC.Boilerplate
    import Futhark.CodeGen.ImpCode.Sequential qualified as Imp
    import Futhark.CodeGen.ImpGen.Sequential qualified as ImpGen
    import Futhark.IR.SeqMem
    import Futhark.MonadFreshNames

    -- | Compile Futhark program to wasm program (some assembly
    -- required).
    --
    -- The triple that is returned consists of
    --
    -- * Generated C code (to be passed to Emscripten).
    --
    -- * JavaScript wrapper code that presents a nicer interface to the
    --   Emscripten-produced code (this should be put in a @.class.js@
    --   file by itself).
    --
    -- * Options that should be passed to @emcc@.
    compileProg :: (MonadFreshNames m) => T.Text -> Prog SeqMem -> m (ImpGen.Warnings, (GC.CParts, T.Text, [String]))
    compileProg :: forall (m :: * -> *).
    MonadFreshNames m =>
    Text -> Prog SeqMem -> m (Warnings, (CParts, Text, [String]))
    compileProg Text
    version Prog SeqMem
    prog = do
      (ws, prog') <- Prog SeqMem -> m (Warnings, Program)
    forall (m :: * -> *).
    MonadFreshNames m =>
    Prog SeqMem -> m (Warnings, Program)
    ImpGen.compileProg Prog SeqMem
    prog

      prog'' <-
        GC.compileProg
          "wasm"
          version
          mempty
          operations
          generateBoilerplate
          ""
          (DefaultSpace, [DefaultSpace])
          []
          prog'
      pure (ws, (prog'', javascriptWrapper (fRepMyRep prog'), emccExportNames (fRepMyRep prog')))
      where
        operations :: GC.Operations Imp.Sequential ()
        operations :: Operations Sequential ()
    operations =
          Operations Sequential ()
    forall op s. Operations op s
    GC.defaultOperations
            { GC.opsCompiler = const $ pure ()
            }

    fRepMyRep :: Imp.Program -> [JSEntryPoint]
    fRepMyRep :: Program -> [JSEntryPoint]
    fRepMyRep Program
    prog =
      let Imp.Functions [(Name, Function Sequential)]
    fs = Program -> Functions Sequential
    forall a. Definitions a -> Functions a
    Imp.defFuns Program
    prog
          function :: FunctionT a -> Maybe JSEntryPoint
    function (Imp.Function Maybe EntryPoint
    entry [Param]
    _ [Param]
    _ Code a
    _) = do
            Imp.EntryPoint n res args <- Maybe EntryPoint
    entry
            Just $
              JSEntryPoint
                { name = nameToString n,
                  parameters = map (extToString . snd) args,
                  ret = map (extToString . snd) res
                }
       in ((Name, Function Sequential) -> Maybe JSEntryPoint)
    -> [(Name, Function Sequential)] -> [JSEntryPoint]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe (Function Sequential -> Maybe JSEntryPoint
    forall {a}. FunctionT a -> Maybe JSEntryPoint
    function (Function Sequential -> Maybe JSEntryPoint)
    -> ((Name, Function Sequential) -> Function Sequential)
    -> (Name, Function Sequential)
    -> Maybe JSEntryPoint
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Name, Function Sequential) -> Function Sequential
    forall a b. (a, b) -> b
    snd) [(Name, Function Sequential)]
    fs