module Assembler (
  createExecutable,
) where

-- Roda comandos de terminal

import System.Directory.OsPath (createDirectoryIfMissing)
import System.OsPath (encodeFS)
import System.Process (callCommand)

-- Função principal
-- IO () significa que o programa vai realizar ações em arquivos externos (escrever em arquivos e chamar programas)
-- IO () não retorna valor
createExecutable :: String -> FilePath -> IO ()
createExecutable :: String -> String -> IO ()
createExecutable String
assemblyCode String
outputFilename = do
  let buildDir :: String
buildDir = String
"build/"
  let asmFile :: String
asmFile = String
buildDir String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"temp.s"
  let objFile :: String
objFile = String
buildDir String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"temp.o"

  -- Cria diretório para os artefatos de build, caso não exista
  OsPath
buildPath <- String -> IO OsPath
encodeFS String
buildDir
  ()
_ <- Bool -> OsPath -> IO ()
createDirectoryIfMissing Bool
True OsPath
buildPath

  -- Aqui o 'do' se mostra útil, deixando o código mais limpo em comandos sequenciais
  String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Escrevendo codigo Assembly para " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
asmFile String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"..."
  String -> String -> IO ()
writeFile String
asmFile String
assemblyCode

  String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Montando com NASM " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
asmFile String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" -> " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
objFile String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"..."
  String -> IO ()
callCommand (String
"nasm -felf64 " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
asmFile String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" -o " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
objFile) -- felf64 está indicando que é para o formato x86_64 do Linux
  String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Linkando com GCC: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
objFile String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" -> " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
outputFilename String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"..."
  String -> IO ()
callCommand (String
"gcc -no-pie " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
objFile String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" -o " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
outputFilename)

  String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Executavel '" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
outputFilename String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"' criado com sucesso!"