hat-2.9.1: trans/Flags.hs
{- ---------------------------------------------------------------------------
Flags are all the choices and information given to the compiler in the
argument list. Here a data type Flags is defined for holding this information,
a function processArgs to obtain a value of type Flags from the argument list,
and a simple function pF for printing information demanded by a flag.
-}
module Flags
(Flags,processArgs
,sSourceFile
,sParse
,sPrelude
,sPreludes
,sIncludes
,sDbgTrusted
,sWrap
,sIBound
,sShowWidth
,sHatAuxFile
,sHatTransFile
,sSrcDir
,sFixities
) where
import System.Console.GetOpt(getOpt,usageInfo,ArgOrder(..),OptDescr(..),ArgDescr(..))
import System.FilePath(FilePath(..),splitFileName,replaceExtension,takeExtension,(</>))
import Data.Char(isDigit)
data Flags = FF
{sSourceFile :: String
,sHatAuxFile :: String
,sHatTransFile :: String
,sIncludes :: [String]
,sPreludes :: [String]
,sSrcDir :: String
--v Flags to control compilation
,sPrelude :: Bool -- keep prelude defns in interface file
--v Flags to control compilation for tracing
,sDbgTrusted :: Bool -- trust this module
,sWrap :: Bool -- wrap original defns rather than transforming
--v debugging flags - show program / import tables (after each compiler phase)
,sParse :: Bool -- ast after parsing
,sIBound :: Bool -- environment
,sFixities :: Bool -- fixity declarations in top-level scope
--v pretty-printing flags
,sShowWidth :: Int -- width for showing intermediate program
}
deriving Show
options :: [OptDescr (Flags -> Flags)]
options =
[Option ['i','I'] []
(ReqArg (\p flags -> flags{sIncludes = sIncludes flags ++ [p]}) "DIR")
"Search path for included (imported) modules."
,Option ['P'] []
(ReqArg (\p flags -> flags{sPreludes = sPreludes flags ++ [p]}) "DIR")
"Search path for prelude."
,Option [] ["prelude"]
(NoArg (\flags -> flags{sPrelude = True}))
"Input module is part of the prelude." -- Needs some special handling of imports.
,Option [] ["hierarchical"]
(NoArg (\flags -> let (rootdir,filename) = splitFileName (sSourceFile flags)
in flags{sSrcDir = "Hat" </> rootdir
,sHatTransFile = "Hat" </> rootdir </> replaceExtension filename "hs"}))
"Module belongs in hierarchical library." -- So output in directory Hat/hierachy...
,Option [] ["trusted"]
(NoArg (\flags -> flags{sDbgTrusted = True}))
"Input module shall be trusted, not traced."
,Option [] ["wrap"]
(NoArg (\flags -> flags{sWrap = True}))
"Wrap definitions of input module instead of transforming."
,Option [] ["parse"]
(NoArg (\flags -> flags{sParse = True}))
"Show syntax tree after parsing."
,Option [] ["env"]
(NoArg (\flags -> flags{sIBound = True}))
"Show environment that is written to .aux file."
,Option [] ["fixities"]
(NoArg (\flags -> flags{sFixities = True}))
"Show all fixity declarations in scope."
,Option [] ["width"]
(ReqArg (\w flags -> flags{sShowWidth = if all isDigit w then read w else 80}) "NAT")
"Width for showing intermediate programs (syntax trees)."
]
{-
The main function for processing the argument list.
Aborts with error, if the required filenames are not in argument list.
(But no further error checking)
-}
processArgs :: [String] -> Flags
processArgs argv =
flags {sIncludes = sIncludes flags ++ [fst (splitFileName (sSourceFile flags))]}
-- add rootdir at end
where
flags = case getOpt Permute options argv of
(o,[f],[]) | takeExtension f `elem` [".hs",".lhs"] -> foldl (flip id) (defaultFlags f) o
(_,_,errs) -> error (concat errs ++ usageInfo header options)
header = "Usage: hat-trans [OPTION...] file.[l]hs\n"
defaultFlags :: String -> Flags
defaultFlags sourcefile = flags
where
(rootdir,filename) = splitFileName sourcefile
flags = FF
{sSourceFile = sourcefile -- original name
,sHatAuxFile = rootdir </> replaceExtension filename "hx"
,sHatTransFile = rootdir </> "Hat" </> replaceExtension filename "hs"
,sIncludes = []
,sPreludes = []
,sSrcDir = rootdir </> "Hat" -- directory for transformed sources
,sPrelude = False
,sDbgTrusted = False
,sWrap = False
,sParse = False
,sIBound = False
,sFixities = False
,sShowWidth = 80
}