1module Main where23import Conduit4import Data.Functor (($>))5import Data.List (uncons)6import Data.Text (Text, unpack)7import SimpleSMT qualified as SMT8import System.Environment (getArgs)9import System.Exit (exitFailure)10import System.IO (hPutStrLn, stderr)1112z3Solver :: IO SMT.Solver13z3Solver = do14 -- l <- SMT.newLogger 015 s <- SMT.newSolver "z3" ["-smt2", "-in"] Nothing16 return s1718simplify :: SMT.Solver -> SMT.SExpr -> IO SMT.SExpr19simplify s e = SMT.command s $ SMT.List [SMT.Atom "simplify", e]2021------------------------------------------------------------------------2223fwdCmd :: SMT.Solver -> SMT.SExpr -> IO SMT.SExpr24fwdCmd solver expr = SMT.command solver expr $> expr2526transSExpr :: String -> SMT.Solver -> SMT.SExpr -> IO SMT.SExpr27transSExpr _ s e@(SMT.List ((SMT.Atom "set-logic") : _)) = fwdCmd s e28transSExpr _ s e@(SMT.List ((SMT.Atom "declare-fun") : _)) = fwdCmd s e29transSExpr a s e@(SMT.List xs) =30 let recur = SMT.List <$> mapM (transSExpr a s) xs31 in case uncons xs of32 Just (SMT.Atom name, _) ->33 if name == a34 then simplify s e35 else recur36 _ -> recur37transSExpr _ _ e = pure e3839yieldSExpr :: ConduitM Text SMT.SExpr IO ()40yieldSExpr = loop ""41 where42 loop rest = await >>= maybe (return ()) (go . (rest ++) . unpack)43 go x =44 case SMT.readSExpr x of45 Just (expr, rest) -> yield expr >> go rest46 Nothing -> loop x4748------------------------------------------------------------------------4950transformStdin :: String -> SMT.Solver -> IO ()51transformStdin atomName solver =52 runConduit $53 stdinC54 .| decodeUtf8C55 .| yieldSExpr56 .| mapMC (transSExpr atomName solver)57 .| mapM_C printSExpr58 where59 printSExpr :: SMT.SExpr -> IO ()60 printSExpr e = putStrLn $ SMT.showsSExpr e ""6162main :: IO ()63main = do64 args <- getArgs65 case args of66 [exprName] -> z3Solver >>= transformStdin exprName67 _ -> do68 hPutStrLn stderr "Expected single name of expression to simplify"69 exitFailure