DrIFT.hs revision edf0b87513720db0373e96424c4ad7b50e54299c
076b559b2ea7b2f1d303df992ae71cd6c6fe563cChristian Maeder-- Based on DrIFT 1.0 by Noel Winstanley
076b559b2ea7b2f1d303df992ae71cd6c6fe563cChristian Maeder-- hacked for Haskell 98 by Malcolm Wallace, University of York, Feb 1999.
81d182b21020b815887e9057959228546cf61b6bChristian Maeder-- modified by various people, now maintained by John Meacham
076b559b2ea7b2f1d303df992ae71cd6c6fe563cChristian Maedermodule Main(process,main,envGlobalRules,env,addGlobals) where
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescuimport ChaseImports
076b559b2ea7b2f1d303df992ae71cd6c6fe563cChristian Maederimport UserRules
3f69b6948966979163bdfe8331c38833d5d90ecdChristian Maederimport StandardRules
076b559b2ea7b2f1d303df992ae71cd6c6fe563cChristian Maederimport RuleUtils (commentLine,texts)
076b559b2ea7b2f1d303df992ae71cd6c6fe563cChristian Maederimport PreludData(preludeData)
568a1ce407fd05a2007c5db3c5c57098bf13997fChristian Maederimport List (partition,isSuffixOf,sort)
568a1ce407fd05a2007c5db3c5c57098bf13997fChristian Maederimport qualified System
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maederimport IO hiding(try)
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maederimport Monad(unless)
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maederimport RuleUtils(Rule,Tag)
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maederimport Version
076b559b2ea7b2f1d303df992ae71cd6c6fe563cChristian Maederdata Op = OpList | OpDerive | OpVersion
35db0960aa2e2a13652381c756fae5fb2b27213bChristian Maederdata Env = Env {
568a1ce407fd05a2007c5db3c5c57098bf13997fChristian Maeder envVerbose :: Bool,
ac510075311023bf24175f7a76b89ec2bbda0626Christian Maeder envOutput :: (Maybe String),
ac510075311023bf24175f7a76b89ec2bbda0626Christian Maeder envOperation :: Op,
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian Maeder envNoline :: Bool,
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian Maeder envArgs :: [(String,String)],
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian Maeder envResultsOnly :: Bool,
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian Maeder envGlobalRules :: [Tag]
6e5180855658f12f9059d9041f447bf0935de344Christian Maeder envVerbose = False,
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian Maeder envOutput = Nothing,
8a1f427564a5ae2db32332512237ef645289c34dChristian Maeder envOperation = OpDerive,
76647324ed70f33b95a881b536d883daccf9568dChristian Maeder envNoline = False,
76647324ed70f33b95a881b536d883daccf9568dChristian Maeder envArgs = [],
76647324ed70f33b95a881b536d883daccf9568dChristian Maeder envResultsOnly = False,
4e013227ed41ccd2e3d09dd44bedd651e1901f38Christian Maeder envGlobalRules = []
76fa667489c5e0868ac68de9f0253ac10f73d0b5Christian MaederputErrDie s = hPutStr stderr s >> System.exitFailure
76647324ed70f33b95a881b536d883daccf9568dChristian MaederexitSuccess = System.exitWith System.ExitSuccess
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian MaedergetOutput e = maybe (return stdout) (\fn -> openFile fn WriteMode) (envOutput e)
76647324ed70f33b95a881b536d883daccf9568dChristian Maederoptions :: [OptDescr (Env -> Env)]
529f678f015ae5276f87da63114cdce750b366aeChristian Maeder [ Option ['v'] ["verbose"] (NoArg (\e->e{envVerbose = True})) "chatty output on stderr"
529f678f015ae5276f87da63114cdce750b366aeChristian Maeder , Option ['V'] ["version"] (NoArg (\e->e{envOperation = OpVersion})) "show version number"
529f678f015ae5276f87da63114cdce750b366aeChristian Maeder , Option ['l'] ["list"] (NoArg (\e->e{envOperation = OpList})) "list available derivations"
529f678f015ae5276f87da63114cdce750b366aeChristian Maeder , Option ['L'] ["noline"] (NoArg (\e->e{envNoline = True})) "omit line pragmas from output"
529f678f015ae5276f87da63114cdce750b366aeChristian Maeder , Option ['o'] ["output"] (ReqArg (\x e->e{envOutput = (Just x)}) "FILE") "output FILE"
529f678f015ae5276f87da63114cdce750b366aeChristian Maeder , Option ['s'] ["set"] (ReqArg setArg "name:value") "set argument to value"
529f678f015ae5276f87da63114cdce750b366aeChristian Maeder , Option ['r'] ["resultsonly"] (NoArg (\e->e{envResultsOnly = True})) "output only results, do not include source file"
529f678f015ae5276f87da63114cdce750b366aeChristian Maeder , Option ['g'] ["global"] (ReqArg addGlobalRule "rule") "addition rules to apply globally"
8a1f427564a5ae2db32332512237ef645289c34dChristian MaedersetArg x e = e {envArgs = (n, tail rest):(envArgs e)} where
529f678f015ae5276f87da63114cdce750b366aeChristian Maeder (n,rest) = span (/= ':') x
b475a916d62584a2af5f51749240db7a5f0c8b82Christian MaederaddGlobalRule x e = e {envGlobalRules = x:(envGlobalRules e)}
568a1ce407fd05a2007c5db3c5c57098bf13997fChristian Maederheader = "Usage: DrIFT [OPTION...] file"
fd5d3885a092ac0727fa2436cdfc3b248318ebd8Christian Maeder (env,n) <- case (getOpt Permute options argv) of
fd5d3885a092ac0727fa2436cdfc3b248318ebd8Christian Maeder (as,n,[]) -> return (foldr ($) env as ,n)
ac9e33c3c35b2663e5cb76483228910f142d9576Christian Maeder (_,_,errs) -> putErrDie (concat errs ++ usageInfo header options)
ac9e33c3c35b2663e5cb76483228910f142d9576Christian Maeder Env { envOperation = OpList } -> mapM_ putStrLn (sort $ map fst rules)
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian Maeder Env { envOperation = OpVersion} -> putStr ("Version " ++ fullName ++ "\n")
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian Maeder _ -> case n of
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian Maeder [n] -> derive env n
ac9e33c3c35b2663e5cb76483228910f142d9576Christian Maeder _ -> putErrDie ("single input file must be specified.\n" ++ usageInfo header options)
ac9e33c3c35b2663e5cb76483228910f142d9576Christian Maederderive env fname = do
ac9e33c3c35b2663e5cb76483228910f142d9576Christian Maeder file <- readFile fname
ac9e33c3c35b2663e5cb76483228910f142d9576Christian Maeder handle <- getOutput env
ac9e33c3c35b2663e5cb76483228910f142d9576Christian Maeder hPutStr handle $ "{- Generated by " ++ package ++ " (Automatic class derivations for Haskell) -}\n"
ac9e33c3c35b2663e5cb76483228910f142d9576Christian Maeder unless (envNoline env) $ hPutStr handle $ "{-# LINE 1 \"" ++ fname ++ "\" #-}\n"
ac510075311023bf24175f7a76b89ec2bbda0626Christian Maeder (body,_) = userCode file
7de39d39bc1700cc8a9bb9df90b920aad9e18d4aChristian Maeder b = ".lhs" `isSuffixOf` fname --isLiterate body
ac9e33c3c35b2663e5cb76483228910f142d9576Christian Maeder (docs,dats,todo) = process . (addGlobals (envGlobalRules env)) . parser . fromLit b $ body
ac510075311023bf24175f7a76b89ec2bbda0626Christian Maeder moreDocs <- fmap ((\(x,_,_) -> x) . process) (chaseImports body todo)
ac510075311023bf24175f7a76b89ec2bbda0626Christian Maeder result = toLit b . (\r -> codeSeperator ++ '\n':r) .
b7941d1840cb336e11e7a7c0916f7b763c0366f0Christian Maeder render . vsep $ (docs ++ sepDoc:moreDocs)
568a1ce407fd05a2007c5db3c5c57098bf13997fChristian Maeder unless (envResultsOnly env) $ hPutStr handle body
ac510075311023bf24175f7a76b89ec2bbda0626Christian Maeder hPutStr handle result
81700fac589336e88451a2a8474a893a28506438Christian MaederaddGlobals :: [Tag] -> ToDo -> ToDo
76647324ed70f33b95a881b536d883daccf9568dChristian MaederaddGlobals tags tds = (tags,Directive):tds
7c57322afb6342e5cc8b1fdc96050b707407fc61Christian Maederrules = userRules ++ standardRules
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian Maeder-- codeRender doc = fullRender PageMode 80 1 doc "" -- now obsolete
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian Maedervsep = vcat . map ($$ (text ""))
5b1f1d57c75562a7af79e8256f4afa07febe921bChristian MaedersepDoc = commentLine . text $ " Imported from other files :-"