~jojo/Carth

ref: db87ea9bdce9470b546bb3098f5d79a9b1023af1 Carth/app/Config.hs -rw-r--r-- 2.4 KiB
db87ea9bJoJo Disclaim WIP status in readme 1 year, 10 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
{-# LANGUAGE TupleSections #-}

-- | Read all the different kinds of configurtion options for Carth. Command
--    line options, config files, environment variables, etc.
module Config (getConfig, ModeConfig) where

import Compile
import System.Console.GetOpt
import System.Environment
import System.Exit
import Data.List
import Data.Function
import Control.Monad

type ModeConfig = (FilePath, CompileConfig)

getConfig :: IO ModeConfig
getConfig = do
    as <- getArgs
    case as of
        a : as' | a == "c" || a == "compile" -> compileCfg as'
        a : _ | a == "-h" || a == "--help" -> do
            putStrLn usageSubs
            exitFailure
        "help" : [] -> do
            putStrLn usageSubs
            exitFailure
        "help" : a : _ | a == "c" || a == "compile" -> usageCompile
        a : _ -> do
            putStrLn ("Error: `" ++ a ++ "` is not a valid subcommand\n")
            putStrLn usageSubs
            exitFailure
        [] -> do
            putStrLn "Error: No subcommand given\n"
            putStrLn usageSubs
            exitFailure

usageSubs :: String
usageSubs = unlines
    [ "Usage: carth SUBCOMMAND ..."
    , ""
    , "Available subcommands are:"
    , "  c, compile       Compile a source file"
    , ""
    , "See `carth help SUBCOMMAND` for help on a specific subcommand"
    ]

compileCfg :: [String] -> IO ModeConfig
compileCfg args = do
    let (fs, extras, errs) = getOpt Permute compileOpts args
    when (not (null errs)) $ putStrLn (concat errs) *> usageCompile
    let cfg = foldl (&) defaultCompileConfig fs
    case extras of
        infile : [] -> pure (infile, cfg)
        _ : es -> do
            putStrLn ("Unexpected extra arguments: " ++ intercalate ", " es)
            exitFailure
        [] -> putStrLn "Missing input source file" *> usageCompile

usageCompile :: IO a
usageCompile = do
    putStrLn $ unlines
        [ "Carth compiler"
        , "Compile a Carth program to an executable"
        , ""
        , usageInfo "Usage: carth c [OPTIONS] SOURCE-FILE" compileOpts
        ]
    exitFailure

compileOpts :: [OptDescr (CompileConfig -> CompileConfig)]
compileOpts =
    [ Option
        []
        ["cc"]
        (ReqArg (\cc' cfg -> cfg { cc = cc' }) "PROGRAM")
        "C compiler to use for linking and compiling C files"
    , Option
        ['o']
        ["outfile"]
        (ReqArg (\f cfg -> cfg { outfile = Just f }) "FILE")
        "Output filepath"
    ]