module Kempe.Proc.Nasm ( writeO
                       ) where

import           Data.Functor              (void)
import           Prettyprinter             (Doc, defaultLayoutOptions, layoutPretty)
import           Prettyprinter.Render.Text (renderIO)
import           System.IO                 (hFlush)
import           System.IO.Temp            (withSystemTempFile)
import           System.Process            (CreateProcess (..), StdStream (Inherit), proc, readCreateProcess)

-- | Assemble using @nasm@, output in some file.
writeO :: Doc ann
       -> FilePath
       -> Bool -- ^ Debug symbols?
       -> IO ()
writeO :: Doc ann -> FilePath -> Bool -> IO ()
writeO Doc ann
p FilePath
fpO Bool
dbg = FilePath -> (FilePath -> Handle -> IO ()) -> IO ()
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
FilePath -> (FilePath -> Handle -> m a) -> m a
withSystemTempFile FilePath
"kmp.S" ((FilePath -> Handle -> IO ()) -> IO ())
-> (FilePath -> Handle -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \FilePath
fp Handle
h -> do
    Handle -> SimpleDocStream ann -> IO ()
forall ann. Handle -> SimpleDocStream ann -> IO ()
renderIO Handle
h (LayoutOptions -> Doc ann -> SimpleDocStream ann
forall ann. LayoutOptions -> Doc ann -> SimpleDocStream ann
layoutPretty LayoutOptions
defaultLayoutOptions Doc ann
p)
    Handle -> IO ()
hFlush Handle
h
    let debugFlag :: [FilePath] -> [FilePath]
debugFlag = if Bool
dbg then (FilePath
"-g"FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
:) else [FilePath] -> [FilePath]
forall a. a -> a
id
    -- -O1 is signed byte optimization but no multi-passes
    IO FilePath -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO FilePath -> IO ()) -> IO FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess ((FilePath -> [FilePath] -> CreateProcess
proc FilePath
"nasm" ([FilePath] -> [FilePath]
debugFlag [FilePath
fp, FilePath
"-f", FilePath
"elf64", FilePath
"-O1", FilePath
"-o", FilePath
fpO])) { std_err :: StdStream
std_err = StdStream
Inherit }) FilePath
""