content: -- | 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 version prog = do
    (ws, prog') <- ImpGen.compileProg 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 =
        GC.defaultOperations
          { GC.opsCompiler = const $ pure ()
          }
  
  fRepMyRep :: Imp.Program -> [JSEntryPoint]
  fRepMyRep prog =
    let Imp.Functions fs = Imp.defFuns prog
        function (Imp.Function entry _ _ _) = do
          Imp.EntryPoint n res args <- entry
          Just $
            JSEntryPoint
              { name = nameToString n,
                parameters = map (extToString . snd) args,
                ret = map (extToString . snd) res
              }
     in mapMaybe (function . snd) fs
  