packages feed

kempe-0.1.0.2: run/Main.hs

module Main (main) where

import           Control.Exception         (throwIO)
import           Control.Monad             ((<=<))
import qualified Data.Version              as V
import           Kempe.AST
import           Kempe.File
import           Options.Applicative
import qualified Paths_kempe               as P
import           Prettyprinter             (LayoutOptions (LayoutOptions), PageWidth (AvailablePerLine), hardline, layoutSmart)
import           Prettyprinter.Render.Text (renderIO)
import           System.Exit               (ExitCode (ExitFailure), exitWith)
import           System.IO                 (stdout)

data Command = TypeCheck !FilePath
             | Compile !FilePath !(Maybe FilePath) !Bool !Bool !Bool -- TODO: take arch on cli
             | Format !FilePath

fmt :: FilePath -> IO ()
fmt = renderIO stdout <=< fmap (render . (<> hardline) . prettyModule . snd) . parsedFp
    where render = layoutSmart settings
          settings = LayoutOptions $ AvailablePerLine 80 0.5

run :: Command -> IO ()
run (TypeCheck fp)                        = either throwIO pure =<< tcFile fp
run (Compile _ Nothing _ False False)     = putStrLn "No output file specified!"
run (Compile fp (Just o) dbg False False) = compile fp o dbg
run (Compile fp Nothing False True False) = irFile fp
run (Compile fp Nothing False False True) = x86File fp
run (Format fp)                           = fmt fp
run _                                     = putStrLn "Invalid combination of CLI options. Try kc --help" *> exitWith (ExitFailure 1)

kmpFile :: Parser FilePath
kmpFile = argument str
    (metavar "FILE"
    <> help "Source file"
    <> kmpCompletions)

fmtP :: Parser Command
fmtP = Format <$> kmpFile

debugSwitch :: Parser Bool
debugSwitch = switch
    (long "debug"
    <> short 'g'
    <> help "Include debug symbols")

irSwitch :: Parser Bool
irSwitch = switch
    (long "dump-ir"
    <> help "Write intermediate representation to stdout")

asmSwitch :: Parser Bool
asmSwitch = switch
    (long "dump-asm"
    <> help "Write assembly (intel syntax) to stdout")

exeFile :: Parser (Maybe FilePath)
exeFile = optional $ argument str
    (metavar "OUTPUT"
    <> help "File output")

kmpCompletions :: HasCompleter f => Mod f a
kmpCompletions = completer . bashCompleter $ "file -X '!*.kmp' -o plusdirs"

commandP :: Parser Command
commandP = hsubparser
    (command "typecheck" (info tcP (progDesc "Type-check module contents")))
    <|> hsubparser (command "fmt" (info fmtP (progDesc "Pretty-print a Kempe file")) <> internal)
    <|> compileP
    where
        tcP = TypeCheck <$> kmpFile
        compileP = Compile <$> kmpFile <*> exeFile <*> debugSwitch <*> irSwitch <*> asmSwitch

wrapper :: ParserInfo Command
wrapper = info (helper <*> versionMod <*> commandP)
    (fullDesc
    <> progDesc "Kempe language compiler, x86_64 backend"
    <> header "Kempe - a stack-based language")

versionMod :: Parser (a -> a)
versionMod = infoOption (V.showVersion P.version) (short 'V' <> long "version" <> help "Show version")

main :: IO ()
main = run =<< execParser wrapper