1module Main where23import Data.Map.Strict qualified as Map4import Control.Monad (forM_)5import Control.Monad.State.Strict (State, modify, runState)6import SimpleSMT qualified as SMT7import System.IO (stdin, hGetContents)89type Stats = Map.Map String Int1011mkStats :: Stats12mkStats = Map.empty1314toCSV :: Stats -> String15toCSV e =16 unlines $ header : map go (Map.toList e)17 where18 seperator :: String19 seperator = ";"2021 header :: String22 header = "name" ++ seperator ++ "occurrence"2324 go :: (String, Int) -> String25 go (n, c) = "\"" ++ n ++ "\"" ++ seperator ++ show c2627------------------------------------------------------------------------2829collectName :: String -> State Stats ()30collectName name =31 modify $ Map.insertWith (+) name 13233collectBinary :: String -> SMT.SExpr -> SMT.SExpr -> State Stats ()34collectBinary name lhs rhs = do35 collectName name36 collectExpr lhs >> collectExpr rhs3738collectExpr :: SMT.SExpr -> State Stats ()39collectExpr (SMT.List (SMT.Atom "=" : values))40 = forM_ values collectExpr41collectExpr (SMT.List [SMT.Atom "or", lhs, rhs]) = collectBinary "or" lhs rhs42collectExpr (SMT.List [SMT.Atom "not", p]) = collectName "not" >> collectExpr p43collectExpr (SMT.List [SMT.Atom "bvneg", p]) = collectName "bvneg" >> collectExpr p44collectExpr (SMT.List [SMT.List [SMT.Atom "_", SMT.Atom "extract", _, _], expr])45 = collectName "extract" >> collectExpr expr46collectExpr (SMT.List [SMT.List [SMT.Atom "_", SMT.Atom "zero_extend", _], expr])47 = collectName "zero_extend" >> collectExpr expr48collectExpr (SMT.List [SMT.List [SMT.Atom "_", SMT.Atom "sign_extend", _], expr])49 = collectName "sign_extend" >> collectExpr expr50collectExpr (SMT.List [SMT.Atom "ite", cond, ifT, ifF]) = do51 collectName "ite"52 collectExpr cond >> collectExpr ifT >> collectExpr ifF53collectExpr (SMT.List [SMT.Atom "select", lhs, rhs]) = collectBinary "select" lhs rhs54collectExpr (SMT.List [SMT.Atom "and", lhs, rhs]) = collectBinary "and" lhs rhs55collectExpr (SMT.List [SMT.Atom "concat", lhs, rhs]) = collectBinary "concat" lhs rhs56collectExpr (SMT.List [SMT.Atom "bvadd", lhs, rhs]) = collectBinary "bvadd" lhs rhs57collectExpr (SMT.List [SMT.Atom "bvsub", lhs, rhs]) = collectBinary "bvsub" lhs rhs58collectExpr (SMT.List [SMT.Atom "bvmul", lhs, rhs]) = collectBinary "bvmul" lhs rhs59collectExpr (SMT.List [SMT.Atom "bvsdiv", lhs, rhs]) = collectBinary "bvsdiv" lhs rhs60collectExpr (SMT.List [SMT.Atom "bvudiv", lhs, rhs]) = collectBinary "bvudiv" lhs rhs61collectExpr (SMT.List [SMT.Atom "bvxor", lhs, rhs]) = collectBinary "bvxor" lhs rhs62collectExpr (SMT.List [SMT.Atom "bvand", lhs, rhs]) = collectBinary "bvand" lhs rhs63collectExpr (SMT.List [SMT.Atom "bvor", lhs, rhs]) = collectBinary "bvor" lhs rhs64collectExpr (SMT.List [SMT.Atom "bvurem", lhs, rhs]) = collectBinary "bvurem" lhs rhs65collectExpr (SMT.List [SMT.Atom "bvsrem", lhs, rhs]) = collectBinary "bvsrem" lhs rhs66collectExpr (SMT.List [SMT.Atom "bvashr", lhs, rhs]) = collectBinary "bvashr" lhs rhs67collectExpr (SMT.List [SMT.Atom "bvlshr", lhs, rhs]) = collectBinary "bvlshr" lhs rhs68collectExpr (SMT.List [SMT.Atom "bvshl", lhs, rhs]) = collectBinary "bvshl" lhs rhs69collectExpr (SMT.List [SMT.Atom "bvsle", lhs, rhs]) = collectBinary "bvsle" lhs rhs70collectExpr (SMT.List [SMT.Atom "bvslt", lhs, rhs]) = collectBinary "bvslt" lhs rhs71collectExpr (SMT.List [SMT.Atom "bvsge", lhs, rhs]) = collectBinary "bvsge" lhs rhs72collectExpr (SMT.List [SMT.Atom "bvsgt", lhs, rhs]) = collectBinary "bvsgt" lhs rhs73collectExpr (SMT.List [SMT.Atom "bvule", lhs, rhs]) = collectBinary "bvule" lhs rhs74collectExpr (SMT.List [SMT.Atom "bvult", lhs, rhs]) = collectBinary "bvult" lhs rhs75collectExpr (SMT.List [SMT.Atom "bvuge", lhs, rhs]) = collectBinary "bvuge" lhs rhs76collectExpr (SMT.List [SMT.Atom "bvugt", lhs, rhs]) = collectBinary "bvugt" lhs rhs77collectExpr (SMT.Atom _) = pure ()78collectExpr (SMT.List [SMT.Atom "_", SMT.Atom _, SMT.Atom _]) = pure ()79collectExpr e = error $ "collectExpr: Unknown expression '" ++ show e ++ "'"8081collectCmd :: SMT.SExpr -> State Stats ()82collectCmd (SMT.List [SMT.Atom "check-sat-assuming", SMT.List assumptions])83 = collectName "check-sat-assuming" >> forM_ assumptions collectExpr84collectCmd (SMT.List ((SMT.Atom "set-logic") : _)) = pure ()85collectCmd (SMT.List ((SMT.Atom "declare-fun") : _)) = pure ()86collectCmd (SMT.List (SMT.Atom "check-sat":_)) = collectName "check-sat" >> pure ()87collectCmd (SMT.List (SMT.Atom "pop":_)) = pure ()88collectCmd (SMT.List (SMT.Atom "push":_)) = pure ()89collectCmd (SMT.List [SMT.Atom "assert", expr]) = collectExpr expr90collectCmd cmd = error $ "collectCmd: Unknown command '" ++ show cmd ++ "'"9192collect :: [SMT.SExpr] -> State Stats ()93collect sexprs = forM_ sexprs collectCmd9495------------------------------------------------------------------------9697readSExprs :: String -> [SMT.SExpr]98readSExprs str = go (SMT.readSExpr str)99 where100 go :: Maybe (SMT.SExpr, String) -> [SMT.SExpr]101 go Nothing = []102 go (Just (acc, rest)) = acc : go (SMT.readSExpr rest)103104getStats :: [SMT.SExpr] -> Stats105getStats exprs = snd $ collectStats exprs106 where107 collectStats e = runState (collect e) mkStats108109------------------------------------------------------------------------110111main :: IO ()112main = do113 exprs <- readSExprs <$> hGetContents stdin114 putStr (toCSV $! getStats exprs)