SSTG-0.1.1.2: app/Main.hs
module Main where
import SSTG
import qualified Data.Char as C
import qualified Data.List as L
import qualified Data.Map as M
import System.Environment
import Text.Read
trim :: String -> String
trim = L.dropWhileEnd C.isSpace . L.dropWhile C.isSpace
trimSlash :: String -> String
trimSlash str = case trim str of
"" -> ""
trimmed -> case last trimmed of
'/' -> trimSlash (init trimmed)
_ -> trimmed
matchArg :: String -> [String] -> (String -> a) -> a -> a
matchArg tgt args fun def = case L.elemIndex tgt args of
Nothing -> def
Just i -> if i >= length args
then error ("Invalid use of " ++ tgt)
else fun (args !! (i + 1)) -- fun (args !! (i + 1))
parseStepCount :: [String] -> Int
parseStepCount args = matchArg "--n" args read 200
parseStepType :: [String] -> StepType
parseStepType args = case matched of { Just t -> t; Nothing -> BFS }
where matched = matchArg "--method" args (\a -> M.lookup a types) Nothing
types = M.fromList [ ("bfs", BFS)
, ("bfs-log", BFSLogged)
, ("dfs", DFS)
, ("dfs-log", DFSLogged) ]
parseDumpDir :: [String] -> Maybe FilePath
parseDumpDir args = case matchArg "--dump" args (readMaybe . show) Nothing of
Nothing -> Nothing
Just raw -> case trimSlash raw of
"" -> error ("Invalid use of " ++ raw)
ok -> Just ok
parseFlags :: [String] -> RunFlags
parseFlags args = RunFlags { flag_step_count = parseStepCount args
, flag_step_type = parseStepType args
, flag_dump_dir = parseDumpDir args }
injDumpLocs :: String -> Int -> FilePath -> [FilePath]
injDumpLocs entry n dir = map (\i -> start ++ (show i) ++ ".txt") [1..n]
where start = dir ++ "/" ++ entry
main :: IO ()
main = do
-- Get command line arguments.
(proj:src:tail_args) <- getArgs
-- Make bindings.
binds <- mkTargetBinds proj src
-- Configure entry.
let entry = if length tail_args > 0 then tail_args !! 0 else "main"
-- Get the flags.
let flags = parseFlags tail_args
-- Do the loading.
let load_result = loadStateEntry entry (Program binds)
putStrLn $ "binds: " ++ show (length binds)
-- Get the state from the loader.
state <- case load_result of
LoadError str -> error str
LoadOkay state -> return state
LoadGuess state cands -> do
putStrLn "Other possible candidates:"
putStrLn $ show cands
return state
putStrLn $ show flags
-- Execution!
let ldss = execute flags state
case flag_dump_dir flags of
-- Dump to terminal.
Nothing -> mapM_ (putStrLn . pprLivesDeadsStr) ldss
-- Dump to file.
Just dir -> do
let locs = injDumpLocs entry (length ldss) dir
putStrLn $ show (length ldss)
mapM_ (\(fp, lds) -> writePrettyState fp lds) (zip locs ldss)