{- |
Module : ./CSL/EvalSpec.hs
Description : EvalSpec program
Copyright : (c) Ewaryst Schulz, DFKI Bremen 2010
License : similar to LGPL, see HetCATS/LICENSE.txt or LIZENZ.txt
Maintainer : ewaryst.schulz@dfki.de
Stability : experimental
Portability : non-portable (via imports)
Program for evaluating EnCL specifications
-}
module Main (main, runMain) where
import System.Environment
import System.Console.GetOpt
import qualified Interfaces.Process as PC
import CSL.AnEvenTool (evalWithVerification, CAS (..), CASState (..), runTool)
import Common.Utils
import Data.Bits
import Data.Maybe
import Data.List
import Control.Monad
main :: IO ()
main = getArgs >>= runMain True >> putStr ""
-- main = runTool >> return ()
runMain :: Bool -> [String] -> IO (Maybe CASState)
runMain cl args =
case processArgs args of
Left msg -> do
putStrLn $ "Evaluation: " ++ msg ++ "\n\n" ++ esUsage
return Nothing
Right st -> liftM Just $ runProg cl st
runProg :: Bool -> ProgSettings -> IO CASState
runProg cl st =
evalWithVerification cl
(cas st)
(logFile st)
(connectionName st)
(symbolicmode st)
(debugmode st)
(timeout st)
(verbosity st)
(lib st)
(spec st)
-- ----------------------- Input Arguments -------------------------
processArgs :: [String] -> Either String ProgSettings
processArgs args =
let (flags, noopts, unrecopts, errs) =
getOpt' (ReturnInOrder PFLib) options args
msgl = checkFlags flags
f str (l, s) = if null l then str else str ++ "\n" ++ s ++ unlines l
msg = foldl f ""
[ (noopts, "non-handled extra arguments encountered ")
, (unrecopts, "unrecognized flags encountered ")
, (errs, "")
, (msgl, "")
]
in if null msg then Right $ getSettings flags else Left msg
esHeader :: String
esHeader = unlines
[ "Usage: evalspec [OPTION...] [file]"
, ""
, "evalspec /tmp/f.het -sFlangeComplete"
, ""
]
esUsage :: String
esUsage = usageInfo esHeader options
{- | 'options' describes all available options and is used to generate usage
information -}
options :: [OptDescr ProgFlag]
-- Option [Char] [String] (ArgDescr a) String
options = map f
[ ( "lib", "Path to the hets file", ReqArg PFLib "FILE")
, ( "spec"
, "Name of specification importing both, " ++
"the pattern and the design specification"
, ReqArg PFSpec "SPECNAME")
, ( "CAS"
, "Name of the computer algebra system to " ++
"carry out the computations"
, ReqArg (PFCAS . fromMaybe (error "Unknown CAS") . readMaybe)
"Mathematica or Maple")
, ( "Logfile"
, "Path to a logfile which will contain low " ++
"level CAS connection information"
, ReqArg PFLogFile "FILE")
, ( "connection"
, "A connection name as given e.g. to the MathLink server"
, ReqArg PFConnection "String")
, ( "timeout"
, "Timeout for communication with external CAS " ++
"system in deziseconds (tenth of a second)"
, ReqArg (PFTimeout . fromRational
. fromMaybe (error "Could not parse timeout")
. (readMaybe :: String -> Maybe Rational)
. (++ "%10")) "1-1000")
, ( "verbosity"
, "A value from 0=quiet to 4=print out all " ++
"information during processing"
, ReqArg (PFVerbosity . read) "0-4")
, ( "quiet", "Equal to -v0", NoArg PFQuiet)
, ( "Symbolic", "Enables symbolic evaluation mode",
NoArg (PFSymbolic True))
, ( "debug", "Enables debug mode", NoArg (PFDebug True))
] where
f (fs, descr, arg) = Option [head fs] [fs] arg descr
checkFlags :: [ProgFlag] -> [String]
checkFlags = g . mapAccumL f (0 :: Int) where
f i (PFLib _) = (setBit i 0, ())
f i (PFSpec _) = (setBit i 1, ())
f i _ = (i, ())
g (i, _) = mapMaybe (h i) [ (0, "lib")
, (1, "spec") ]
h i (j, s)
| testBit i j = Nothing
| otherwise = Just $ s ++ " argument is missing"
data ProgSettings =
ProgSettings
{ lib :: String
, spec :: String
, cas :: CAS
, logFile :: Maybe FilePath
, connectionName :: Maybe String
, timeout :: PC.DTime
, verbosity :: Int
, debugmode :: Bool
, symbolicmode :: Bool
}
defaultSettings :: ProgSettings
defaultSettings = ProgSettings
{ lib = error "uninitialized settings"
, spec = error "uninitialized settings"
, cas = Maple
, timeout = 1
, verbosity = 4
, debugmode = False
, symbolicmode = False
, logFile = Nothing
, connectionName = Nothing
}
data ProgFlag =
PFLib String
| PFSpec String
| PFTimeout PC.DTime
| PFVerbosity Int
| PFLogFile FilePath
| PFConnection String
| PFCAS CAS
| PFQuiet
| PFDebug Bool
| PFSymbolic Bool
makeSettings :: ProgSettings -> ProgFlag -> ProgSettings
makeSettings settings flg =
case flg of
PFLib s -> settings { lib = s }
PFSpec s -> settings { spec = s }
PFVerbosity i -> settings { verbosity = i }
PFQuiet -> settings { verbosity = 0 }
PFTimeout t -> settings { timeout = t }
PFDebug b -> settings { debugmode = b }
PFSymbolic b -> settings { symbolicmode = b }
PFLogFile fp -> settings { logFile = Just fp }
PFConnection n -> settings { connectionName = Just n }
PFCAS c -> settings { cas = c }
getSettings :: [ProgFlag] -> ProgSettings
getSettings = foldl makeSettings defaultSettings