• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

msakai / toysolver / 513

24 Nov 2024 08:49AM UTC coverage: 68.675% (-1.0%) from 69.681%
513

push

github

web-flow
Merge 496ed4263 into 46e1509c4

5 of 121 new or added lines in 7 files covered. (4.13%)

105 existing lines in 14 files now uncovered.

9745 of 14190 relevant lines covered (68.68%)

0.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.25
/src/ToySolver/SMT.hs
1
{-# OPTIONS_HADDOCK show-extensions #-}
2
{-# LANGUAGE DeriveDataTypeable #-}
3
{-# LANGUAGE FlexibleInstances #-}
4
{-# LANGUAGE MultiParamTypeClasses #-}
5
{-# LANGUAGE OverloadedStrings #-}
6
{-# LANGUAGE ScopedTypeVariables #-}
7
-----------------------------------------------------------------------------
8
-- |
9
-- Module      :  ToySolver.SMT
10
-- Copyright   :  (c) Masahiro Sakai 2015
11
-- License     :  BSD-style
12
--
13
-- Maintainer  :  masahiro.sakai@gmail.com
14
-- Stability   :  unstable
15
-- Portability :  non-portable
16
--
17
-----------------------------------------------------------------------------
18
module ToySolver.SMT
19
  (
20
  -- * The Solver type
21
    Solver
22
  , newSolver
23
  , Exception (..)
24

25
  -- * Problem Specification
26
  , SSym (..)
27
  , ssymArity
28
  , Sort (..)
29
  , sBool
30
  , sReal
31
  , sBitVec
32
  , FunType
33
  , Expr (..)
34
  , exprSort
35
  , Index (..)
36
  , FSym (..)
37
  , declareSSym
38
  , declareSort
39
  , VASortFun
40
  , declareFSym
41
  , declareFun
42
  , declareConst
43
  , VAFun
44
  , assert
45
  , assertNamed
46
  , getGlobalDeclarations
47
  , setGlobalDeclarations
48

49
  -- * Solving
50
  , checkSAT
51
  , checkSATAssuming
52
  , push
53
  , pop
54

55
  -- * Inspecting models
56
  , Model
57
  , Value (..)
58
  , getModel
59
  , eval
60
  , valSort
61
  , FunDef (..)
62
  , evalFSym
63
  , modelGetAssertions
64

65
  -- * Inspecting proofs
66
  , getUnsatAssumptions
67
  , getUnsatCore
68
  ) where
69

70
import Control.Applicative
71
import qualified Control.Exception as E
72
import Control.Monad
73
import Control.Monad.Trans
74
import Control.Monad.Trans.Except
75
import Data.Bits
76
import Data.Either
77
import Data.Interned (intern, unintern)
78
import Data.Interned.Text
79
import Data.IntMap (IntMap)
80
import qualified Data.IntMap as IntMap
81
import Data.IntSet (IntSet)
82
import qualified Data.IntSet as IntSet
83
import Data.IORef
84
import Data.List
85
import Data.Map (Map)
86
import qualified Data.Map as Map
87
import Data.Maybe (catMaybes)
88
import Data.Monoid
89
import Data.Set (Set)
90
import qualified Data.Set as Set
91
import Data.String
92
import qualified Data.Text as T
93
import Data.Typeable
94
import Data.VectorSpace
95

96
import ToySolver.Data.Delta
97
import ToySolver.Data.Boolean
98
import ToySolver.Data.OrdRel
99
import qualified ToySolver.Data.LA as LA
100
import qualified ToySolver.Internal.Data.Vec as Vec
101
import qualified ToySolver.SAT as SAT
102
import ToySolver.SAT.TheorySolver
103
import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin
104
import ToySolver.SAT.Encoder.Tseitin (Formula (..))
105
import qualified ToySolver.Arith.Simplex as Simplex
106
import qualified ToySolver.BitVector as BV
107
import qualified ToySolver.EUF.EUFSolver as EUF
108

109
data Index
110
  = IndexNumeral !Integer
111
  | IndexSymbol !InternedText
112
  deriving (Show,Eq, Ord)
×
113

114
data FSym
115
  = FSym !InternedText [Index]
116
  deriving (Show,Eq,Ord)
×
117

118
instance IsString FSym where
119
  fromString s = FSym (fromString s) []
1✔
120

121
-- | Sort symbols
122
data SSym
123
  = SSymBool
124
  | SSymReal
125
  | SSymBitVec !Int
126
  | SSymUninterpreted !InternedText !Int
127
  deriving (Show, Eq, Ord)
×
128

129
ssymArity :: SSym -> Int
130
ssymArity SSymBool = 0
1✔
131
ssymArity SSymReal = 0
1✔
132
ssymArity (SSymBitVec _) = 0
×
133
ssymArity (SSymUninterpreted _ ar) = ar
1✔
134

135
data Sort = Sort SSym [Sort]
136
  deriving (Show, Eq, Ord)
×
137

138
sBool :: Sort
139
sBool = Sort SSymBool []
1✔
140

141
sReal :: Sort
142
sReal = Sort SSymReal []
1✔
143

144
sBitVec :: Int -> Sort
145
sBitVec n = Sort (SSymBitVec n) []
1✔
146

147
type FunType = ([Sort],Sort)
148

149
data Expr
150
  = EAp FSym [Expr]
151
  | EValue !Value
152
  deriving (Show, Eq, Ord)
×
153

154
instance MonotoneBoolean Expr where
×
155
  true  = EAp "true" []
1✔
156
  false = EAp "false" []
×
157
  andB = EAp "and"
×
158
  orB  = EAp "or"
1✔
159

160
instance Complement Expr where
161
  notB x = EAp "not" [x]
1✔
162

163
instance IfThenElse Expr Expr where
164
  ite x y z = EAp "ite" [x,y,z]
1✔
165

166
instance Boolean Expr where
167
  x .=>. y  = EAp "=>" [x,y]
1✔
168
  x .<=>. y = EAp "=" [x,y]
1✔
169

170
instance Num Expr where
171
  x + y = EAp "+" [x,y]
1✔
172
  x - y = EAp "-" [x,y]
×
173
  x * y = EAp "*" [x,y]
1✔
174
  negate x = EAp "-" [x]
1✔
175
  abs x = error "Num{ToySolver.SMT.Expr}.abs is not implemented"
×
176
  signum x = error "Num{ToySolver.SMT.Expr}.signum is not implemented"
×
177
  fromInteger x = EValue $ ValRational $ fromInteger x
1✔
178

179
instance Fractional Expr where
×
180
  x / y = EAp "/" [x,y]
1✔
181
  fromRational x = EValue $ ValRational x
1✔
182

183
instance IsEqRel Expr Expr where
184
  a .==. b = EAp "=" [a,b]
1✔
185
  a ./=. b = notB (a .==. b)
1✔
186

187
instance IsOrdRel Expr Expr where
×
188
  a .<. b = EAp "<" [a,b]
1✔
189
  a .>. b = EAp ">" [a,b]
1✔
190
  a .<=. b = EAp "<=" [a,b]
1✔
191
  a .>=. b = EAp ">=" [a,b]
1✔
192

193
data FDef
194
  = FBoolVar SAT.Var
195
  | FLRAVar LA.Var
196
  | FBVVar BV.Var
197
  | FEUFFun FunType EUF.FSym
198
  deriving (Show)
×
199

200
data Exception
201
  = Error String
202
  | Unsupported
203
  deriving (Show, Typeable)
×
204

205
instance E.Exception Exception
×
206

207
data Solver
208
  = Solver
209
  { smtSAT :: !SAT.Solver
1✔
210
  , smtEnc :: !(Tseitin.Encoder IO)
1✔
211
  , smtEUF :: !EUF.Solver
1✔
212
  , smtLRA :: !(Simplex.GenericSolver (Delta Rational))
1✔
213
  , smtBV :: !BV.Solver
1✔
214

215
  , smtEUFAtomDefs  :: !(IORef (Map (EUF.Term, EUF.Term) SAT.Var, IntMap (EUF.Term, EUF.Term)))
1✔
216
  , smtLRAAtomDefs  :: !(IORef (Map (LA.Var, Rational) (SAT.Lit, SAT.Lit, SAT.Lit), IntMap (LA.Atom Rational)))
1✔
217
  , smtBVAtomDefs   :: !(IORef (Map BVAtomNormalized SAT.Var, IntMap BVAtomNormalized))
1✔
218
  , smtBoolTermDefs :: !(IORef (Map EUF.Term SAT.Lit, IntMap EUF.Term))
1✔
219
  , smtRealTermDefs :: !(IORef (Map (LA.Expr Rational) EUF.FSym, IntMap (LA.Expr Rational)))
1✔
220
  , smtBVTermDefs :: !(IORef (Map BV.Expr EUF.FSym, IntMap (IntMap BV.Expr)))
1✔
221
  , smtEUFTrue  :: !EUF.Term
1✔
222
  , smtEUFFalse :: !EUF.Term
1✔
223

224
  , smtEUFModel :: !(IORef EUF.Model)
1✔
225
  , smtLRAModel :: !(IORef Simplex.Model)
1✔
226
  , smtBVModel :: !(IORef BV.Model)
1✔
227

228
  , smtGlobalDeclarationsRef :: !(IORef Bool)
1✔
229
  , smtFDefs :: !(IORef (Map FSym FDef))
1✔
230
  , smtNamedAssertions :: !(IORef (Map String SAT.Lit))
1✔
231
  , smtAssertionStack :: !(Vec.Vec AssertionLevel)
1✔
232

233
  , smtUnsatAssumptions :: !(IORef [Expr])
1✔
234
  , smtUnsatCore :: !(IORef [String])
1✔
235
  }
236

237
data AssertionLevel
238
  = AssertionLevel
239
  { alSavedNamedAssertions :: Map String SAT.Lit
1✔
240
  , alSavedFDefs :: Maybe (Map FSym FDef)
1✔
241
  , alSelector :: SAT.Lit
1✔
242
  }
243

244
data TheorySolverID
245
  = TheorySolverEUF
246
  | TheorySolverSimplex
247
  | TheorySolverBV
248
  deriving (Eq, Ord, Enum, Bounded)
×
249

250
newSolver :: IO Solver
251
newSolver = do
1✔
252
  sat <- SAT.newSolver
1✔
253
  enc <- Tseitin.newEncoder sat
1✔
254
  euf <- EUF.newSolver
1✔
255
  lra <- Simplex.newSolver
1✔
256
  bv <- BV.newSolver
1✔
257

258
  litTrue <- Tseitin.encodeConj enc []
1✔
259
  let litFalse = -litTrue
1✔
260

261
  eufTrue  <- EUF.newConst euf
1✔
262
  eufFalse <- EUF.newConst euf
1✔
263
  EUF.assertNotEqual euf eufTrue eufFalse
1✔
264
  divByZero <- EUF.newFSym euf
1✔
265

266
  eufAtomDefs <- newIORef (Map.empty, IntMap.empty)
1✔
267
  lraAtomDefs <- newIORef (Map.empty, IntMap.empty)
1✔
268
  bvAtomDefs <- newIORef (Map.empty, IntMap.empty)
1✔
269
  boolTermDefs <- newIORef $
1✔
270
    ( Map.fromList [(eufTrue, litTrue), (eufFalse, litFalse)]
×
271
    , IntMap.fromList [(litTrue, eufTrue), (litFalse, eufFalse)]
1✔
272
    )
273
  realTermDefs <- newIORef (Map.empty, IntMap.empty)
1✔
274
  bvTermDefs <- newIORef (Map.empty, IntMap.empty)
1✔
275

276
  eufModelRef <- newIORef (undefined :: EUF.Model)
×
277
  lraModelRef <- newIORef (undefined :: Simplex.Model)
×
278
  bvModelRef <- newIORef (undefined :: BV.Model)
×
279

280
  globalDeclarationsRef <- newIORef False
1✔
281
  fdefs <- newIORef $ Map.singleton "_/0" (FEUFFun ([sReal], sReal) divByZero)
×
282

283
  conflictTheory <- newIORef undefined
×
284

285
  let tsolver =
1✔
286
        TheorySolver
1✔
287
        { thAssertLit = \_ l -> liftM (either id id) $ runExceptT $ do
1✔
288
            (_, defsLRA) <- lift $ readIORef lraAtomDefs
1✔
289
            case IntMap.lookup l defsLRA of
1✔
290
              Nothing -> return ()
×
291
              Just atom -> do
1✔
292
                lift $ Simplex.assertAtomEx' lra atom (Just l)
1✔
293
                throwE True
1✔
294

295
            (_, defsEUF) <- lift $ readIORef eufAtomDefs
1✔
296
            case IntMap.lookup (SAT.litVar l) defsEUF of
1✔
297
              Nothing -> return ()
×
298
              Just (t1,t2) -> do
1✔
299
                if SAT.litPolarity l then do
1✔
300
                  lift $ EUF.assertEqual' euf t1 t2 (Just l)
1✔
301
                else do
1✔
302
                  lift $ EUF.assertNotEqual' euf t1 t2 (Just l)
1✔
303
                throwE True
1✔
304

305
            (_, defsBV) <- lift $ readIORef bvAtomDefs
1✔
306
            case IntMap.lookup (SAT.litVar l) defsBV of
1✔
307
              Nothing -> return ()
×
308
              Just atom -> do
1✔
309
                lift $ BV.assertAtom bv (unnormalizeBVAtom (atom, SAT.litPolarity l)) (Just l)
1✔
310
                throwE True
1✔
311

312
            return True
1✔
313

314
        , thCheck = \callback -> liftM isRight $ runExceptT $ do
1✔
315
            do b <- lift $ Simplex.check lra
1✔
316
               unless b $ do
1✔
317
                 lift $ writeIORef conflictTheory TheorySolverSimplex
1✔
318
                 throwE ()
×
319
            do b <- lift $ EUF.check euf
1✔
320
               unless b $ do
1✔
321
                 lift $ writeIORef conflictTheory TheorySolverEUF
1✔
322
                 throwE ()
×
323
               (_, defsEUF) <- lift $ readIORef eufAtomDefs
1✔
324
               forM_ (IntMap.toList defsEUF) $ \(v, (t1, t2)) -> do
1✔
325
                  b2 <- lift $ EUF.areEqual euf t1 t2
1✔
326
                  when b2 $ do
1✔
327
                    b3 <- lift $ callback v
1✔
328
                    unless b3 $ throwE ()
×
329
            do b <- lift $ BV.check bv
1✔
330
               unless b $ do
1✔
331
                 lift $ writeIORef conflictTheory TheorySolverBV
1✔
332
                 throwE ()
×
333

334
        , thExplain = \m -> do
1✔
335
            case m of
1✔
336
              Nothing -> do
1✔
337
                t <- readIORef conflictTheory
1✔
338
                case t of
1✔
339
                  TheorySolverSimplex -> liftM IntSet.toList $ Simplex.explain lra
1✔
340
                  TheorySolverBV -> liftM IntSet.toList $ BV.explain bv
1✔
341
                  TheorySolverEUF -> liftM IntSet.toList $ EUF.explain euf Nothing
1✔
342
              Just v -> do
1✔
343
                (_, defsEUF) <- readIORef eufAtomDefs
1✔
344
                case IntMap.lookup v defsEUF of
1✔
345
                  Nothing -> error "should not happen"
×
346
                  Just (t1,t2) -> liftM IntSet.toList $ EUF.explain euf (Just (t1,t2))
1✔
347

348
        , thPushBacktrackPoint = do
1✔
349
            Simplex.pushBacktrackPoint lra
1✔
350
            EUF.pushBacktrackPoint euf
1✔
351
            BV.pushBacktrackPoint bv
1✔
352
        , thPopBacktrackPoint = do
1✔
353
            Simplex.popBacktrackPoint lra
1✔
354
            EUF.popBacktrackPoint euf
1✔
355
            BV.popBacktrackPoint bv
1✔
356
        , thConstructModel = do
1✔
357
            writeIORef eufModelRef =<< EUF.getModel euf
1✔
358
            -- We need to call Simplex.getModel here.
359
            -- Because backtracking removes constraints that are necessary
360
            -- for computing the value of delta.
361
            writeIORef lraModelRef =<< Simplex.getModel lra
1✔
362
            writeIORef bvModelRef =<< BV.getModel bv
1✔
363
            return ()
×
364
        }
365
  SAT.setTheory sat tsolver
1✔
366

367
  named <- newIORef Map.empty
1✔
368

369
  stack <- Vec.new
1✔
370

371
  unsatAssumptionsRef <- newIORef undefined
×
372
  unsatCoreRef <- newIORef undefined
×
373

374
  return $
1✔
375
    Solver
1✔
376
    { smtSAT = sat
1✔
377
    , smtEnc = enc
1✔
378
    , smtEUF = euf
1✔
379
    , smtLRA = lra
1✔
380
    , smtBV  = bv
1✔
381

382
    , smtEUFAtomDefs = eufAtomDefs
1✔
383
    , smtLRAAtomDefs = lraAtomDefs
1✔
384
    , smtBVAtomDefs = bvAtomDefs
1✔
385
    , smtBoolTermDefs = boolTermDefs
1✔
386
    , smtRealTermDefs = realTermDefs
1✔
387
    , smtBVTermDefs = bvTermDefs
1✔
388
    , smtEUFTrue  = eufTrue
1✔
389
    , smtEUFFalse = eufFalse
1✔
390

391
    , smtEUFModel = eufModelRef
1✔
392
    , smtLRAModel = lraModelRef
1✔
393
    , smtBVModel = bvModelRef
1✔
394

395
    , smtGlobalDeclarationsRef = globalDeclarationsRef
1✔
396
    , smtFDefs = fdefs
1✔
397
    , smtNamedAssertions = named
1✔
398
    , smtAssertionStack = stack
1✔
399

400
    , smtUnsatAssumptions = unsatAssumptionsRef
1✔
401
    , smtUnsatCore = unsatCoreRef
1✔
402
    }
403

404
declareSSym :: Solver -> String -> Int -> IO SSym
405
declareSSym solver name arity = return (SSymUninterpreted (fromString name) arity)
1✔
406

407
declareSort :: VASortFun a => Solver -> String -> Int -> IO a
408
declareSort solver name arity = do
1✔
409
  ssym <- declareSSym solver name arity
×
410
  let f = withSortVArgs (Sort ssym)
1✔
411
  unless (arityVASortFun f == arity) $ do
×
412
    E.throwIO $ Error "ToySolver.SMT.declareSort: argument number error"
×
413
  return f
1✔
414

415
class VASortFun a where
416
  withSortVArgs :: ([Sort] -> Sort) -> a
417
  arityVASortFun :: a -> Int
418

419
instance VASortFun Sort where
420
  withSortVArgs k = k []
1✔
421
  arityVASortFun f = 0
1✔
422

423
instance VASortFun a => VASortFun (Sort -> a) where
424
  withSortVArgs k x = withSortVArgs (\xs -> k (x : xs))
1✔
425
  arityVASortFun f = arityVASortFun (f undefined) + 1
×
426

427
declareFSym :: Solver -> String -> [Sort] -> Sort -> IO FSym
428
declareFSym solver f' xs y = do
1✔
429
  let f = FSym (intern (T.pack f')) []
1✔
430
  fdefs <- readIORef (smtFDefs solver)
1✔
431
  when (f `Map.member` fdefs) $ do
×
432
    E.throwIO $ Error $ "function symbol " ++ f' ++ " is already used"
×
433
  fdef <-
434
    case (xs, y) of
1✔
435
      ([], Sort SSymBool _) -> do
1✔
436
        v <- SAT.newVar (smtSAT solver)
1✔
437
        return (FBoolVar v)
1✔
438
      ([], Sort SSymReal _) -> do
1✔
439
        v <- Simplex.newVar (smtLRA solver)
1✔
440
        return (FLRAVar v)
1✔
441
      ([], Sort (SSymBitVec n) _) -> do
1✔
442
        v <- BV.newVar' (smtBV solver) n
1✔
443
        return (FBVVar v)
1✔
444
      _ -> do
1✔
445
        v <- EUF.newFSym (smtEUF solver)
1✔
446
        return (FEUFFun (xs,y) v)
1✔
447
  writeIORef (smtFDefs solver) $ Map.insert f fdef fdefs
1✔
448
  return f
1✔
449

450
class VAFun a where
451
  withVArgs :: ([Expr] -> Expr) -> a
452
  arityVAFun :: a -> Int
453

454
instance VAFun Expr where
455
  withVArgs k = k []
1✔
456
  arityVAFun _ = 0
1✔
457

458
instance VAFun a => VAFun (Expr -> a) where
459
  withVArgs k x = withVArgs (\xs -> k (x : xs))
1✔
460
  arityVAFun f = arityVAFun (f undefined) + 1
×
461

462
declareFun :: VAFun a => Solver -> String -> [Sort] -> Sort -> IO a
463
declareFun solver name ps r = do
1✔
464
  fsym <- declareFSym solver name ps r
1✔
465
  let f = withVArgs (EAp fsym)
1✔
466
  unless (arityVAFun f == length ps) $ do
×
467
    E.throwIO $ Error "ToySolver.SMT.declareFun: argument number error"
×
468
  return f
1✔
469

470
declareConst :: Solver -> String -> Sort -> IO Expr
471
declareConst solver name s = declareFun solver name [] s
1✔
472

473
assert :: Solver -> Expr -> IO ()
474
assert solver e = do
1✔
475
  formula <- exprToFormula solver e
1✔
476
  n <- Vec.getSize (smtAssertionStack solver)
1✔
477
  if n>0 then do
1✔
478
    assertionLevel <- Vec.peek (smtAssertionStack solver)
1✔
479
    Tseitin.addFormula (smtEnc solver) $ Atom (alSelector assertionLevel) .=>. formula
1✔
480
  else
481
    Tseitin.addFormula (smtEnc solver) formula
1✔
482

483
assertNamed :: Solver -> String -> Expr -> IO ()
484
assertNamed solver name e = do
1✔
485
  lit <- Tseitin.encodeFormula (smtEnc solver) =<< exprToFormula solver e
1✔
486
  modifyIORef (smtNamedAssertions solver) (Map.insert name lit)
1✔
487

488
getGlobalDeclarations :: Solver -> IO Bool
489
getGlobalDeclarations solver = readIORef (smtGlobalDeclarationsRef solver)
×
490

491
setGlobalDeclarations :: Solver -> Bool -> IO ()
492
setGlobalDeclarations solver = writeIORef (smtGlobalDeclarationsRef solver)
1✔
493

494
exprSort :: Solver -> Expr -> IO Sort
495
exprSort solver e = do
1✔
496
  fdefs <- readIORef (smtFDefs solver)
1✔
497
  return $! exprSort' fdefs e
1✔
498

499
exprSort' :: Map FSym FDef -> Expr -> Sort
500
exprSort' _fdefs (EValue v) = valSort v
1✔
501
exprSort' fdefs (EAp f xs)
502
  | f `Set.member` Set.fromList ["true","false","and","or","xor","not","=>","=",">=","<=",">","<"] = sBool
1✔
503
  | f `Set.member` Set.fromList ["bvule", "bvult", "bvuge", "bvugt", "bvsle", "bvslt", "bvsge", "bvsgt"] = sBool
1✔
504
  | f `Set.member` Set.fromList ["+", "-", "*", "/"] = sReal
1✔
505
  | FSym "extract" [IndexNumeral i, IndexNumeral j] <- f = sBitVec (fromIntegral (i - j + 1))
1✔
506
  | f == "concat" =
1✔
507
      case (exprSort' fdefs (xs !! 0), exprSort' fdefs (xs !! 1)) of
×
508
        (Sort (SSymBitVec m) [], Sort (SSymBitVec n) []) -> sBitVec (m+n)
1✔
509
        _ -> undefined
×
510
  | FSym "repeat" [IndexNumeral i] <- f =
1✔
511
      case exprSort' fdefs (xs !! 0) of
×
512
        Sort (SSymBitVec m) [] -> sBitVec (m * fromIntegral i)
×
513
        _ -> undefined
×
514
  | FSym name [IndexNumeral i] <- f, name == "zero_extend" || name == "sign_extend" =
×
515
      case exprSort' fdefs (xs !! 0) of
×
516
        Sort (SSymBitVec m) [] -> sBitVec (m + fromIntegral i)
×
517
        _ -> undefined
×
518
  | FSym name [IndexNumeral i] <- f, name == "rotate_left" || name == "rotate_right" =
×
519
      exprSort' fdefs (xs !! 0)
×
520
  | f == "bvnot" || f == "bvneg" = exprSort' fdefs (xs !! 0)
×
521
  | f == "bvcomp" = sBitVec 1
×
522
  | f `Set.member` Set.fromList [name | (name, _op::BV.BV->BV.BV->BV.BV) <- bvBinOpsSameSize] =
1✔
UNCOV
523
      exprSort' fdefs (xs !! 0)
×
524
  | f == "ite" = exprSort' fdefs (xs !! 1)
1✔
525
  | otherwise =
×
526
      case Map.lookup f fdefs of
1✔
527
        Nothing -> error $ show f ++ " was not found"
×
528
        Just fdef ->
529
          case fdef of
1✔
530
            FBoolVar _ -> sBool
1✔
531
            FLRAVar _ -> sReal
1✔
532
            FBVVar v -> sBitVec (BV.varWidth v)
1✔
533
            FEUFFun (_,s) _ -> s
1✔
534

535
-- -------------------------------------------------------------------
536

537
exprToFormula :: Solver -> Expr -> IO Tseitin.Formula
538
exprToFormula solver (EAp "true" [])  = return true
1✔
539
exprToFormula solver (EAp "false" []) = return false
1✔
540
exprToFormula solver (EAp "and" xs) =
541
  liftM andB $ mapM (exprToFormula solver) xs
1✔
542
exprToFormula solver (EAp "or" xs) =
543
  liftM orB $ mapM (exprToFormula solver) xs
1✔
544
exprToFormula solver (EAp "xor" xs) = do
1✔
545
  ys <- mapM (exprToFormula solver) xs
1✔
546
  return $ foldr (\a b -> notB (a .<=>. b)) false ys
1✔
547
exprToFormula solver (EAp "not" [x]) =
548
  liftM notB $ exprToFormula solver x
1✔
549
exprToFormula solver (EAp "not" _) = undefined
×
550
exprToFormula solver (EAp "=>" [e1,e2]) = do
1✔
551
  b1 <- exprToFormula solver e1
1✔
552
  b2 <- exprToFormula solver e2
1✔
553
  return $ b1 .=>. b2
1✔
554
exprToFormula solver (EAp "ite" [e1,e2,e3]) = do
1✔
555
  b1 <- exprToFormula solver e1
1✔
556
  b2 <- exprToFormula solver e2
1✔
557
  b3 <- exprToFormula solver e3
1✔
558
  return $ ite b1 b2 b3
1✔
559
exprToFormula solver (EAp "=" []) = return true -- ???
×
560
exprToFormula solver (EAp "=" xs) =
561
  chain solver (abstractEq solver) xs
×
562
exprToFormula solver (EAp "distinct" []) = return true -- ???
×
563
exprToFormula solver (EAp "distinct" xs) =
564
  pairwise solver (\e1 e2 -> liftM notB (abstractEq solver e1 e2)) xs
×
565
exprToFormula solver (EAp ">=" xs) = do
1✔
566
  let f e1 e2 = do
1✔
567
        e1' <- exprToLRAExpr solver e1
1✔
568
        e2' <- exprToLRAExpr solver e2
1✔
569
        liftM Atom $ abstractLRAAtom solver (e1' .>=. e2')
1✔
570
  chain solver f xs
×
571
exprToFormula solver (EAp "<=" xs) = do
1✔
572
    let f e1 e2 = do
1✔
573
          e1' <- exprToLRAExpr solver e1
1✔
574
          e2' <- exprToLRAExpr solver e2
1✔
575
          liftM Atom $ abstractLRAAtom solver (e1' .<=. e2')
1✔
576
    chain solver f xs
×
577
exprToFormula solver (EAp ">" xs) = do
1✔
578
  let f e1 e2 = do
1✔
579
        e1' <- exprToLRAExpr solver e1
1✔
580
        e2' <- exprToLRAExpr solver e2
1✔
581
        liftM Atom $ abstractLRAAtom solver (e1' .>. e2')
1✔
582
  chain solver f xs
×
583
exprToFormula solver (EAp "<" xs) = do
1✔
584
  let f e1 e2 = do
1✔
585
        e1' <- exprToLRAExpr solver e1
1✔
586
        e2' <- exprToLRAExpr solver e2
1✔
587
        liftM Atom $ abstractLRAAtom solver (e1' .<. e2')
1✔
588
  chain solver f xs
×
589
exprToFormula solver (EAp f []) = do
1✔
590
  fdefs <- readIORef (smtFDefs solver)
1✔
591
  case Map.lookup f fdefs of
1✔
592
    Just (FBoolVar v) -> return (Atom v)
1✔
593
    Just _ -> E.throwIO $ Error "non Bool constant appears in a boolean context"
×
594
    Nothing -> E.throwIO $ Error $ "unknown function symbol: " ++ show f
×
595
exprToFormula solver (EAp op [e1,e2]) | Just f <- Map.lookup op table = do
1✔
596
  e1' <- exprToBVExpr solver e1
1✔
UNCOV
597
  e2' <- exprToBVExpr solver e2
×
598
  liftM Atom $ abstractBVAtom solver (f e1' e2')
1✔
599
  where
600
    table = Map.fromList
1✔
601
      [ ("bvule", BV.bvule)
1✔
602
      , ("bvult", BV.bvult)
1✔
603
      , ("bvuge", BV.bvuge)
1✔
604
      , ("bvugt", BV.bvugt)
1✔
605
      , ("bvsle", BV.bvsle)
1✔
606
      , ("bvslt", BV.bvslt)
1✔
607
      , ("bvsge", BV.bvsge)
1✔
608
      , ("bvsgt", BV.bvsgt)
1✔
609
      ]
610
exprToFormula solver (EAp f xs) = do
1✔
611
  e' <- exprToEUFTerm solver f xs
1✔
612
  formulaFromEUFTerm solver e'
1✔
613

614
chain :: Solver -> (Expr -> Expr -> IO Tseitin.Formula) -> [Expr] -> IO Tseitin.Formula
615
chain _ _ [] = return true
×
616
chain solver p xs = liftM andB $ mapM (uncurry p) (zip xs (tail xs))
1✔
617

618
pairwise :: Solver -> (Expr -> Expr -> IO Tseitin.Formula) -> [Expr] -> IO Tseitin.Formula
619
pairwise _ _ [] = return true
×
620
pairwise solver p xs = liftM andB $ mapM (uncurry p) (pairs xs)
×
621

622
abstractEq :: Solver -> Expr -> Expr -> IO Tseitin.Formula
623
abstractEq solver e1 e2 = do
1✔
624
  s <- exprSort solver e1
1✔
625
  case s of
1✔
626
    (Sort SSymBool _) -> do
1✔
627
      b1 <- exprToFormula solver e1
1✔
628
      b2 <- exprToFormula solver e2
1✔
629
      return $ b1 .<=>. b2
1✔
630
    (Sort SSymReal _) -> do
1✔
631
      e1' <- exprToLRAExpr solver e1
1✔
632
      e2' <- exprToLRAExpr solver e2
1✔
633
      liftM Atom $ abstractLRAAtom solver (e1' .==. e2')
1✔
634
    (Sort (SSymBitVec _) _) -> do
1✔
UNCOV
635
      e1' <- exprToBVExpr solver e1
×
636
      e2' <- exprToBVExpr solver e2
×
637
      liftM Atom $ abstractBVAtom solver (e1' .==. e2')
1✔
638
    (Sort (SSymUninterpreted _ _) _) -> do
1✔
639
      e1' <- exprToEUFArg solver e1
1✔
640
      e2' <- exprToEUFArg solver e2
1✔
641
      liftM Atom $ abstractEUFAtom solver (e1',e2')
1✔
642

643
-- -------------------------------------------------------------------
644

645
exprToLRAExpr :: Solver -> Expr -> IO (LA.Expr Rational)
646
exprToLRAExpr solver (EValue (ValRational r)) = return (LA.constant r)
1✔
647
exprToLRAExpr solver (EAp "-" []) = E.throwIO $ Error "ToySolver.SMT: nullary '-' function"
×
648
exprToLRAExpr solver (EAp "-" [x]) = liftM negateV $ exprToLRAExpr solver x
1✔
649
exprToLRAExpr solver (EAp "-" (x:xs)) = do
1✔
650
  x' <- exprToLRAExpr solver x
1✔
651
  xs' <- mapM (exprToLRAExpr solver) xs
1✔
652
  return $ foldl' (^-^) x' xs'
1✔
653
exprToLRAExpr solver (EAp "+" xs) = liftM sumV $ mapM (exprToLRAExpr solver) xs
1✔
654
exprToLRAExpr solver (EAp "*" xs) = liftM (foldr mult (LA.constant 1)) $ mapM (exprToLRAExpr solver) xs
1✔
655
  where
656
    mult e1 e2
1✔
657
      | Just c <- LA.asConst e1 = c *^ e2
1✔
658
      | Just c <- LA.asConst e2 = c *^ e1
1✔
659
      | otherwise = E.throw $ Error "non-linear multiplication is not supported"
×
660
exprToLRAExpr solver (EAp "/" [x,y]) = do
1✔
661
  y' <- exprToLRAExpr solver y
×
662
  case LA.asConst y' of
1✔
663
    Nothing -> E.throwIO $ Error "division by non-constant is not supported"
×
664
    Just 0 -> do
1✔
665
      lraExprFromTerm solver =<< exprToEUFTerm solver "_/0" [x]
1✔
666
    Just c -> do
1✔
667
      x' <- exprToLRAExpr solver x
1✔
668
      return $ (1/c) *^ x'
1✔
669
exprToLRAExpr solver (EAp "ite" [c,t,e]) = do
1✔
670
  c' <- exprToFormula solver c
1✔
671
  ret <- liftM LA.var $ Simplex.newVar (smtLRA solver)
1✔
672
  t' <- exprToLRAExpr solver t
1✔
673
  e' <- exprToLRAExpr solver e
1✔
674
  c1 <- abstractLRAAtom solver (ret .==. t')
1✔
675
  c2 <- abstractLRAAtom solver (ret .==. e')
1✔
676
  Tseitin.addFormula (smtEnc solver) $ ite c' (Atom c1) (Atom c2)
1✔
677
  return ret
1✔
678
exprToLRAExpr solver (EAp f xs) =
679
  lraExprFromTerm solver =<< exprToEUFTerm solver f xs
1✔
680

681
abstractLRAAtom :: Solver -> LA.Atom Rational -> IO SAT.Lit
682
abstractLRAAtom solver atom = do
1✔
683
  (v,op,rhs) <- Simplex.simplifyAtom (smtLRA solver) atom
1✔
684
  (tbl,defs) <- readIORef (smtLRAAtomDefs solver)
1✔
685
  (vLt, vEq, vGt) <-
686
    case Map.lookup (v,rhs) tbl of
1✔
687
      Just (vLt, vEq, vGt) -> return (vLt, vEq, vGt)
1✔
688
      Nothing -> do
1✔
689
        vLt <- SAT.newVar (smtSAT solver)
1✔
690
        vEq <- SAT.newVar (smtSAT solver)
1✔
691
        vGt <- SAT.newVar (smtSAT solver)
1✔
692
        SAT.addClause (smtSAT solver) [vLt,vEq,vGt]
1✔
693
        SAT.addClause (smtSAT solver) [-vLt, -vEq]
1✔
694
        SAT.addClause (smtSAT solver) [-vLt, -vGt]
1✔
695
        SAT.addClause (smtSAT solver) [-vEq, -vGt]
1✔
696
        let xs = IntMap.fromList
1✔
697
                 [ (vEq,  LA.var v .==. LA.constant rhs)
1✔
698
                 , (vLt,  LA.var v .<.  LA.constant rhs)
1✔
699
                 , (vGt,  LA.var v .>.  LA.constant rhs)
1✔
700
                 , (-vLt, LA.var v .>=. LA.constant rhs)
1✔
701
                 , (-vGt, LA.var v .<=. LA.constant rhs)
1✔
702
                 ]
703
        writeIORef (smtLRAAtomDefs solver) (Map.insert (v,rhs) (vLt, vEq, vGt) tbl, IntMap.union xs defs)
1✔
704
        return (vLt, vEq, vGt)
1✔
705
  case op of
1✔
706
    Lt  -> return vLt
1✔
707
    Gt  -> return vGt
1✔
708
    Eql -> return vEq
1✔
709
    Le  -> return (-vGt)
1✔
710
    Ge  -> return (-vLt)
1✔
711
    NEq -> return (-vEq)
×
712

713

714
lraExprToEUFTerm :: Solver -> LA.Expr Rational -> IO EUF.Term
715
lraExprToEUFTerm solver e = do
1✔
716
  (realToFSym, fsymToReal) <- readIORef (smtRealTermDefs solver)
1✔
717
  case Map.lookup e realToFSym of
1✔
718
    Just c -> return (EUF.TApp c [])
1✔
719
    Nothing -> do
1✔
720
      c <- EUF.newFSym (smtEUF solver)
1✔
721
      forM_ (IntMap.toList fsymToReal) $ \(d, d_lra) -> do
1✔
722
        -- allocate interface equalities
723
        b1 <- abstractEUFAtom solver (EUF.TApp c [], EUF.TApp d [])
1✔
724
        b2 <- abstractLRAAtom solver (e .==. d_lra)
1✔
725
        Tseitin.addFormula (smtEnc solver) (Atom b1 .<=>. Atom b2)
1✔
726
      writeIORef (smtRealTermDefs solver) $
1✔
727
        ( Map.insert e c realToFSym
1✔
728
        , IntMap.insert c e fsymToReal
1✔
729
        )
730
      return (EUF.TApp c [])
1✔
731

732
lraExprFromTerm :: Solver -> EUF.Term -> IO (LA.Expr Rational)
733
lraExprFromTerm solver t = do
1✔
734
  (realToFSym, fsymToReal) <- readIORef (smtRealTermDefs solver)
1✔
735
  c <- EUF.termToFSym (smtEUF solver) t
1✔
736
  case IntMap.lookup c fsymToReal of
1✔
737
    Just e -> return e
1✔
738
    Nothing -> do
1✔
739
      v <- Simplex.newVar (smtLRA solver)
1✔
740
      let e = LA.var v
1✔
741
      forM_ (IntMap.toList fsymToReal) $ \(d, d_lra) -> do
1✔
742
        -- allocate interface equalities
743
        b1 <- abstractEUFAtom solver (EUF.TApp c [], EUF.TApp d [])
1✔
744
        b2 <- abstractLRAAtom solver (e .==. d_lra)
1✔
745
        Tseitin.addFormula (smtEnc solver) (Atom b1 .<=>. Atom b2)
1✔
746
      writeIORef (smtRealTermDefs solver) $
1✔
747
        ( Map.insert e c realToFSym
1✔
748
        , IntMap.insert c e fsymToReal
1✔
749
        )
750
      return e
1✔
751

752
-- -------------------------------------------------------------------
753

754
bvBinOpsSameSize :: (IsString s, BV.IsBV bv) => [(s, bv -> bv -> bv)]
755
bvBinOpsSameSize =
1✔
756
  [ ("bvand", BV.bvand)
1✔
757
  , ("bvor", BV.bvor)
1✔
758
  , ("bvxor", BV.bvxor)
1✔
759
  , ("bvnand", BV.bvnand)
1✔
760
  , ("bvnor", BV.bvnor)
1✔
761
  , ("bvxnor", BV.bvxnor)
1✔
762
  , ("bvadd", BV.bvadd)
1✔
763
  , ("bvsub", BV.bvsub)
1✔
764
  , ("bvmul", BV.bvmul)
1✔
765
  , ("bvudiv", BV.bvudiv)
1✔
766
  , ("bvurem", BV.bvurem)
1✔
767
  , ("bvsdiv", BV.bvsdiv)
1✔
768
  , ("bvsrem", BV.bvsrem)
1✔
769
  , ("bvsmod", BV.bvsmod)
1✔
770
  , ("bvshl", BV.bvshl)
1✔
771
  , ("bvlshr", BV.bvlshr)
1✔
772
  , ("bvashr", BV.bvashr)
1✔
773
  ]
774

775
exprToBVExpr :: Solver -> Expr -> IO BV.Expr
776
exprToBVExpr solver (EValue (ValBitVec bv)) = return $ BV.fromBV bv
1✔
777
exprToBVExpr solver (EAp "concat" [x,y]) = do
1✔
UNCOV
778
  liftM2 (<>) (exprToBVExpr solver x) (exprToBVExpr solver y)
×
779
exprToBVExpr solver (EAp (FSym "extract" [IndexNumeral i, IndexNumeral j]) [x]) = do
1✔
780
  BV.extract (fromIntegral i) (fromIntegral j) <$> exprToBVExpr solver x
1✔
781
exprToBVExpr solver (EAp (FSym "repeat" [IndexNumeral i]) [x]) = do
×
782
  BV.repeat (fromIntegral i) <$> exprToBVExpr solver x
×
783
exprToBVExpr solver (EAp (FSym "zero_extend" [IndexNumeral i]) [x]) = do
×
784
  BV.zeroExtend (fromIntegral i) <$> exprToBVExpr solver x
×
785
exprToBVExpr solver (EAp (FSym "sign_extend" [IndexNumeral i]) [x]) = do
×
786
  BV.signExtend (fromIntegral i) <$> exprToBVExpr solver x
×
787
exprToBVExpr solver (EAp (FSym "rotate_left" [IndexNumeral i]) [x]) = do
×
788
  rotateL <$> exprToBVExpr solver x <*> pure (fromIntegral i)
×
789
exprToBVExpr solver (EAp (FSym "rotate_right" [IndexNumeral i]) [x]) = do
×
790
  rotateR <$> exprToBVExpr solver x <*> pure (fromIntegral i)
×
791
exprToBVExpr solver (EAp (FSym op1 []) [x])
792
  | Just op1' <- Map.lookup op1 table = op1' <$> exprToBVExpr solver x
1✔
793
  where
794
    table =
1✔
795
      Map.fromList
1✔
796
      [ ("bvnot", BV.bvnot)
1✔
797
      , ("bvneg", BV.bvneg)
1✔
798
      ]
799
exprToBVExpr solver (EAp (FSym op2 []) [x,y])
800
  | Just op2' <- Map.lookup op2 table = liftM2 op2' (exprToBVExpr solver x) (exprToBVExpr solver y)
1✔
801
  where
802
    table = Map.fromList $ [("bvcomp", BV.bvcomp)] ++ bvBinOpsSameSize
1✔
803
exprToBVExpr solver (EAp "ite" [c,t,e]) = do
1✔
804
  c' <- exprToFormula solver c
1✔
805
  t' <- exprToBVExpr solver t
1✔
806
  e' <- exprToBVExpr solver e
×
807
  ret <- BV.newVar (smtBV solver) (BV.width t')
1✔
808
  c1 <- abstractBVAtom solver (ret .==. t')
1✔
809
  c2 <- abstractBVAtom solver (ret .==. e')
1✔
810
  Tseitin.addFormula (smtEnc solver) $ ite c' (Atom c1) (Atom c2)
1✔
811
  return ret
1✔
812
exprToBVExpr solver e@(EAp f xs) = do
1✔
813
  s <- exprSort solver e
1✔
814
  case s of
1✔
815
    Sort (SSymBitVec w) [] -> do
1✔
816
      t <- exprToEUFTerm solver f xs
1✔
817
      bvExprFromTerm solver t w
1✔
818
    _ -> error "should not happen"
×
819

820
data BVAtomNormalized
821
  = BVEql BV.Expr BV.Expr
822
  | BVULt BV.Expr BV.Expr
823
  | BVSLt BV.Expr BV.Expr
824
  deriving (Eq, Ord)
×
825

826
normalizeBVAtom :: BV.Atom -> (BVAtomNormalized, Bool)
827
normalizeBVAtom (BV.Rel (OrdRel lhs op rhs) False) =
1✔
828
  case op of
1✔
829
    Lt  -> (BVULt lhs rhs, True)
1✔
830
    Gt  -> (BVULt rhs lhs, True)
1✔
831
    Eql -> (BVEql lhs rhs, True)
1✔
832
    NEq -> (BVEql lhs rhs, False)
×
833
    Le  -> (BVULt rhs lhs, False)
1✔
834
    Ge  -> (BVULt lhs rhs, False)
1✔
835
normalizeBVAtom (BV.Rel (OrdRel lhs op rhs) True) =
836
  case op of
1✔
837
    Lt  -> (BVSLt lhs rhs, True)
1✔
838
    Gt  -> (BVSLt rhs lhs, True)
1✔
839
    Eql -> (BVEql lhs rhs, True)
×
840
    NEq -> (BVEql lhs rhs, False)
×
841
    Le  -> (BVSLt rhs lhs, False)
1✔
842
    Ge  -> (BVSLt lhs rhs, False)
1✔
843

844
unnormalizeBVAtom :: (BVAtomNormalized, Bool) -> BV.Atom
845
unnormalizeBVAtom (BVEql lhs rhs, p) = (if p then id else notB) $ BV.Rel (OrdRel lhs Eql rhs) False
1✔
846
unnormalizeBVAtom (BVULt lhs rhs, p) = (if p then id else notB) $ BV.Rel (OrdRel lhs Lt rhs) False
1✔
847
unnormalizeBVAtom (BVSLt lhs rhs, p) = (if p then id else notB) $ BV.Rel (OrdRel lhs Lt rhs) True
1✔
848

849
abstractBVAtom :: Solver -> BV.Atom -> IO SAT.Lit
850
abstractBVAtom solver atom = do
1✔
851
  let (atom', s) = normalizeBVAtom atom
1✔
852
  (tbl,defs) <- readIORef (smtBVAtomDefs solver)
1✔
853
  v <- case Map.lookup atom' tbl of
1✔
854
         Just v -> return v
1✔
855
         Nothing -> do
1✔
856
           v <- SAT.newVar (smtSAT solver)
1✔
857
           writeIORef (smtBVAtomDefs solver) (Map.insert atom' v tbl, IntMap.insert v atom' defs)
1✔
858
           return v
1✔
859
  return $ if s then v else -v
1✔
860

861
bvExprToEUFTerm :: Solver -> BV.Expr -> IO EUF.Term
862
bvExprToEUFTerm solver e = do
1✔
863
  (bvToFSym, fsymToBV) <- readIORef (smtBVTermDefs solver)
1✔
864
  case Map.lookup e bvToFSym of
1✔
865
    Just c -> return (EUF.TApp c [])
1✔
866
    Nothing -> do
1✔
867
      c <- EUF.newFSym (smtEUF solver)
1✔
868
      let w = BV.width e
1✔
869
          m = IntMap.findWithDefault IntMap.empty w fsymToBV
1✔
870
      forM_ (IntMap.toList m) $ \(d, d_bv) -> do
1✔
871
        -- allocate interface equalities
872
        b1 <- abstractEUFAtom solver (EUF.TApp c [], EUF.TApp d [])
1✔
873
        b2 <- abstractBVAtom solver (e .==. d_bv)
1✔
874
        Tseitin.addFormula (smtEnc solver) (Atom b1 .<=>. Atom b2)
1✔
875
      writeIORef (smtBVTermDefs solver) $
1✔
876
        ( Map.insert e c bvToFSym
1✔
877
        , IntMap.insert w (IntMap.insert c e m) fsymToBV
1✔
878
        )
879
      return (EUF.TApp c [])
1✔
880

881
bvExprFromTerm :: Solver -> EUF.Term -> Int -> IO BV.Expr
882
bvExprFromTerm solver t w = do
1✔
883
  (bvToFSym, fsymToBV) <- readIORef (smtBVTermDefs solver)
1✔
884
  c <- EUF.termToFSym (smtEUF solver) t
1✔
885
  let m = IntMap.findWithDefault IntMap.empty w fsymToBV
1✔
886
  case IntMap.lookup c m of
1✔
887
    Just e -> return e
1✔
888
    Nothing -> do
1✔
889
      e <- BV.newVar (smtBV solver) w
1✔
890
      forM_ (IntMap.toList m) $ \(d, d_bv) -> do
×
891
        -- allocate interface equalities
892
        b1 <- abstractEUFAtom solver (EUF.TApp c [], EUF.TApp d [])
×
893
        b2 <- abstractBVAtom solver (e .==. d_bv)
×
894
        Tseitin.addFormula (smtEnc solver) (Atom b1 .<=>. Atom b2)
×
895
      writeIORef (smtBVTermDefs solver) $
1✔
896
        ( Map.insert e c bvToFSym
×
UNCOV
897
        , IntMap.insert w (IntMap.insert c e m) fsymToBV
×
898
        )
899
      return e
1✔
900

901
-- -------------------------------------------------------------------
902

903
exprToEUFTerm :: Solver -> FSym -> [Expr] -> IO EUF.Term
904
exprToEUFTerm solver "ite" [c,t,e] = do
1✔
905
  c' <- exprToFormula solver c
1✔
906
  ret <- EUF.newConst (smtEUF solver)
1✔
907
  t' <- exprToEUFArg solver t
1✔
908
  e' <- exprToEUFArg solver e
1✔
909
  c1 <- abstractEUFAtom solver (ret, t')
1✔
910
  c2 <- abstractEUFAtom solver (ret, e')
1✔
911
  Tseitin.addFormula (smtEnc solver) $ ite c' (Atom c1) (Atom c2)
1✔
912
  return ret
1✔
913
exprToEUFTerm solver f xs = do
1✔
914
  fdefs <- readIORef (smtFDefs solver)
1✔
915
  case Map.lookup f fdefs of
1✔
916
    Just (FBoolVar v) -> formulaToEUFTerm solver (Atom v)
×
917
    Just (FLRAVar v) -> lraExprToEUFTerm solver (LA.var v)
1✔
918
    Just (FBVVar v) -> bvExprToEUFTerm solver (BV.EVar v)
1✔
919
    Just (FEUFFun (ps,_) fsym) -> do
1✔
920
      unless (length ps == length xs) $ do
×
921
        E.throwIO $ Error "argument number error"
×
922
      liftM (EUF.TApp fsym) $ mapM (exprToEUFArg solver) xs
1✔
923
    _ -> E.throw $ Error $ "unknown function symbol: " ++ show f
×
924

925
valToEUFArg :: Solver -> Value -> IO EUF.Term
926
valToEUFArg solver (ValBool b) = return $! if b then smtEUFTrue solver else smtEUFFalse solver
×
927
valToEUFArg solver (ValRational r) = lraExprToEUFTerm solver (LA.constant r)
1✔
928
valToEUFArg solver (ValBitVec bv) = bvExprToEUFTerm solver (BV.fromBV bv)
1✔
929

930
exprToEUFArg :: Solver -> Expr -> IO EUF.Term
931
exprToEUFArg solver (EValue v) = valToEUFArg solver v
1✔
932
exprToEUFArg solver e@(EAp f xs) = do
1✔
933
  Sort s _ <- exprSort solver e
1✔
934
  case s of
1✔
935
    SSymBool -> formulaToEUFTerm solver =<< exprToFormula solver e
1✔
936
    SSymReal -> lraExprToEUFTerm solver =<< exprToLRAExpr solver e
1✔
937
    SSymBitVec _ -> bvExprToEUFTerm solver =<< exprToBVExpr solver e
1✔
938
    _ -> exprToEUFTerm solver f xs
1✔
939

940
abstractEUFAtom :: Solver -> (EUF.Term, EUF.Term) -> IO SAT.Lit
941
abstractEUFAtom solver (t1,t2) | t1 > t2 = abstractEUFAtom solver (t2,t1)
1✔
942
abstractEUFAtom solver (t1,t2) = do
1✔
943
  (tbl,defs) <- readIORef (smtEUFAtomDefs solver)
1✔
944
  case Map.lookup (t1,t2) tbl of
1✔
945
    Just v -> return v
1✔
946
    Nothing -> do
1✔
947
      v <- SAT.newVar (smtSAT solver)
1✔
948
      writeIORef (smtEUFAtomDefs solver) (Map.insert (t1,t2) v tbl, IntMap.insert v (t1,t2) defs)
1✔
949
      return v
1✔
950

951
formulaToEUFTerm :: Solver -> Tseitin.Formula -> IO EUF.Term
952
formulaToEUFTerm solver formula = do
1✔
953
  lit <- Tseitin.encodeFormula (smtEnc solver) formula
1✔
954
  (_, boolToTerm) <- readIORef (smtBoolTermDefs solver)
1✔
955
  case IntMap.lookup lit boolToTerm of
1✔
956
    Just t -> return t
1✔
957
    Nothing -> do
1✔
958
      t <- EUF.newConst (smtEUF solver)
1✔
959
      connectBoolTerm solver lit t
1✔
960
      return t
1✔
961

962
formulaFromEUFTerm :: Solver -> EUF.Term -> IO Tseitin.Formula
963
formulaFromEUFTerm solver t = do
1✔
964
  (termToBool, _) <- readIORef (smtBoolTermDefs solver)
1✔
965
  case Map.lookup t termToBool of
1✔
966
    Just lit -> return (Atom lit)
×
967
    Nothing -> do
1✔
968
      lit <- SAT.newVar (smtSAT solver)
1✔
969
      connectBoolTerm solver lit t
1✔
970
      return $ Atom lit
1✔
971

972
connectBoolTerm :: Solver -> SAT.Lit -> EUF.Term -> IO ()
973
connectBoolTerm solver lit t = do
1✔
974
  lit1 <- abstractEUFAtom solver (t, smtEUFTrue solver)
1✔
975
  lit2 <- abstractEUFAtom solver (t, smtEUFFalse solver)
1✔
976
  SAT.addClause (smtSAT solver) [-lit, lit1]  --  lit  ->  lit1
1✔
977
  SAT.addClause (smtSAT solver) [-lit1, lit]  --  lit1 ->  lit
1✔
978
  SAT.addClause (smtSAT solver) [lit, lit2]   -- -lit  ->  lit2
1✔
979
  SAT.addClause (smtSAT solver) [-lit2, -lit] --  lit2 -> -lit
1✔
980
  modifyIORef (smtBoolTermDefs solver) $ \(termToBool, boolToTerm) ->
1✔
981
    ( Map.insert t lit termToBool
×
982
    , IntMap.insert lit t boolToTerm
1✔
983
    )
984

985
-- -------------------------------------------------------------------
986

987
checkSAT :: Solver -> IO Bool
988
checkSAT solver = checkSATAssuming solver []
1✔
989

990
checkSATAssuming :: Solver -> [Expr] -> IO Bool
991
checkSATAssuming solver xs = do
1✔
992
  l <- getContextLit solver
1✔
993
  named <- readIORef (smtNamedAssertions solver)
1✔
994

995
  ref <- newIORef IntMap.empty
1✔
996
  ls <- forM xs $ \x -> do
1✔
997
    b <- Tseitin.encodeFormula (smtEnc solver) =<< exprToFormula solver x
×
998
    modifyIORef ref (IntMap.insert b x)
1✔
999
    return b
1✔
1000

1001
  ret <- SAT.solveWith (smtSAT solver) (l : ls ++ Map.elems named)
1✔
1002
  if ret then do
1✔
1003
    writeIORef (smtUnsatAssumptions solver) undefined
×
1004
    writeIORef (smtUnsatCore solver) undefined
×
1005
  else do
1✔
1006
    m1 <- readIORef ref
1✔
1007
    let m2 = IntMap.fromList [(lit, name) | (name, lit) <- Map.toList named]
1✔
1008
    failed <- SAT.getFailedAssumptions (smtSAT solver)
1✔
1009
    writeIORef (smtUnsatAssumptions solver) $ IntMap.elems $ IntMap.restrictKeys m1 failed
1✔
1010
    writeIORef (smtUnsatCore solver) $ IntMap.elems $ IntMap.restrictKeys m2 failed
1✔
1011
  return ret
1✔
1012

1013
getContextLit :: Solver -> IO SAT.Lit
1014
getContextLit solver = do
1✔
1015
  n <- Vec.getSize (smtAssertionStack solver)
1✔
1016
  if n>0 then do
1✔
1017
    assertionLevel <- Vec.peek (smtAssertionStack solver)
1✔
1018
    return $ alSelector assertionLevel
1✔
1019
  else
1020
    Tseitin.encodeConj (smtEnc solver) [] -- true
1✔
1021

1022
push :: Solver -> IO ()
1023
push solver = do
1✔
1024
  l1 <- getContextLit solver
1✔
1025
  l2 <- SAT.newVar (smtSAT solver)
1✔
1026
  SAT.addClause (smtSAT solver) [-l2, l1] -- l2 → l1
1✔
1027
  globalDeclarations <- readIORef (smtGlobalDeclarationsRef solver)
1✔
1028
  named <- readIORef (smtNamedAssertions solver)
1✔
1029
  fdefs <- readIORef (smtFDefs solver)
1✔
1030
  let newLevel =
1✔
1031
        AssertionLevel
1✔
1032
        { alSavedNamedAssertions = named
1✔
1033
        , alSavedFDefs = if globalDeclarations then Nothing else Just fdefs
1✔
1034
        , alSelector = l2
1✔
1035
        }
1036
  Vec.push (smtAssertionStack solver) newLevel
1✔
1037

1038
pop :: Solver -> IO ()
1039
pop solver = do
1✔
1040
  n <- Vec.getSize (smtAssertionStack solver)
1✔
1041
  if n==0 then
×
1042
    E.throwIO $ Error $ "cannot pop first assertion level"
×
1043
  else do
1✔
1044
    assertionLevel <- Vec.unsafePop (smtAssertionStack solver)
1✔
1045
    SAT.addClause (smtSAT solver) [- alSelector assertionLevel]
1✔
1046
    writeIORef (smtNamedAssertions solver) (alSavedNamedAssertions assertionLevel)
1✔
1047
    case alSavedFDefs assertionLevel of
1✔
1048
      Nothing -> return ()
×
1049
      Just fdefs -> writeIORef (smtFDefs solver) fdefs
1✔
1050
    return ()
×
1051

1052
-- -------------------------------------------------------------------
1053

1054
data Model
1055
  = Model
1056
  { mDefs      :: !(Map FSym FDef)
1✔
1057
  , mBoolModel :: !SAT.Model
1✔
1058
  , mLRAModel  :: !Simplex.Model
1✔
1059
  , mBVModel   :: !BV.Model
1✔
1060
  , mEUFModel  :: !EUF.Model
1✔
1061
  , mEUFTrue   :: !EUF.Entity
1✔
1062
  , mEUFFalse  :: !EUF.Entity
1✔
1063
  , mEntityToRational :: !(IntMap Rational)
1✔
1064
  , mRationalToEntity :: !(Map Rational EUF.Entity)
1✔
1065
  , mEntityToBitVec :: !(IntMap BV.BV)
1✔
1066
  , mBitVecToEntity :: !(Map BV.BV EUF.Entity)
1✔
1067
  }
1068
  deriving (Show)
×
1069

1070
data Value
1071
  = ValRational !Rational
1072
  | ValBitVec !BV.BV
1073
  | ValBool !Bool
1074
  | ValUninterpreted !Int !Sort
1075
  deriving (Eq, Ord, Show)
×
1076

1077
getModel :: Solver -> IO Model
1078
getModel solver = do
1✔
1079
  defs <- readIORef (smtFDefs solver)
1✔
1080
  boolModel <- SAT.getModel (smtSAT solver)
1✔
1081
  lraModel <- readIORef (smtLRAModel solver)
1✔
1082
  bvModel  <- readIORef (smtBVModel solver)
1✔
1083
  eufModel <- readIORef (smtEUFModel solver)
1✔
1084

1085
  (_, fsymToReal) <- readIORef (smtRealTermDefs solver)
1✔
1086
  let xs = [(e, LA.eval lraModel lraExpr) | (fsym, lraExpr) <- IntMap.toList fsymToReal, let e = EUF.evalAp eufModel fsym [], e /= EUF.mUnspecified eufModel]
×
1087

1088
  (_, fsymToBV) <- readIORef (smtBVTermDefs solver)
1✔
1089
  let ys = [(e, BV.evalExpr bvModel bvExpr) | (w,m) <- IntMap.toList fsymToBV, (fsym, bvExpr) <- IntMap.toList m, let e = EUF.evalAp eufModel fsym [], e /= EUF.mUnspecified eufModel]
×
1090

1091
  return $
1✔
1092
    Model
1✔
1093
    { mDefs = defs
1✔
1094
    , mBoolModel = boolModel
1✔
1095
    , mLRAModel = lraModel
1✔
1096
    , mBVModel  = bvModel
1✔
1097
    , mEUFModel = eufModel
1✔
1098
    , mEUFTrue  = EUF.eval eufModel (smtEUFTrue solver)
1✔
1099
    , mEUFFalse = EUF.eval eufModel (smtEUFFalse solver)
1✔
1100
    , mEntityToRational = IntMap.fromList xs
1✔
1101
    , mRationalToEntity = Map.fromList [(r,e) | (e,r) <- xs]
1✔
1102

1103
    , mEntityToBitVec = IntMap.fromList ys
1✔
1104
    , mBitVecToEntity = Map.fromList [(bv,e) | (e,bv) <- ys]
1✔
1105
    }
1106

1107
eval :: Model -> Expr -> Value
1108
eval m (EValue v) = v
1✔
1109
eval m (EAp "true" [])   = ValBool True
1✔
1110
eval m (EAp "false" [])  = ValBool False
1✔
1111
eval m (EAp "ite" [a,b,c]) = if valToBool m (eval m a) then eval m b else eval m c
×
1112
eval m (EAp "and" xs)    = ValBool $ and $ map (valToBool m . eval m) xs
×
1113
eval m (EAp "or" xs)     = ValBool $ or $ map (valToBool m . eval m) xs
×
1114
eval m (EAp "xor" xs)    = ValBool $ foldr xor False $ map (valToBool m . eval m) xs
×
1115
eval m (EAp "not" [x])   = ValBool $ not $ valToBool m $ eval m x
×
1116
eval m (EAp "=>" [x,y])  = ValBool $ valToBool m (eval m x) .=>. valToBool m (eval m y)
×
1117
eval m (EAp "<=" [x,y])  = ValBool $ valToRational m (eval m x) <= valToRational m (eval m y)
×
1118
eval m (EAp ">=" [x,y])  = ValBool $ valToRational m (eval m x) >= valToRational m (eval m y)
×
1119
eval m (EAp ">" [x,y])   = ValBool $ valToRational m (eval m x) >  valToRational m (eval m y)
×
1120
eval m (EAp "<" [x,y])   = ValBool $ valToRational m (eval m x) <  valToRational m (eval m y)
×
1121
eval m (EAp "+" xs)      = ValRational $ sum $ map (valToRational m . eval m) xs
×
1122
eval m (EAp "-" [x])     = ValRational $ negate $ valToRational m (eval m x)
×
1123
eval m (EAp "-" [x,y])   = ValRational $ valToRational m (eval m x) - valToRational m (eval m y)
×
1124
eval m (EAp "*" xs)      = ValRational $ product $ map (valToRational m . eval m) xs
×
1125
eval m (EAp "/" [x,y])
1126
  | y' == 0   = eval m (EAp "_/0" [x])
×
1127
  | otherwise = ValRational $ valToRational m (eval m x) / y'
×
1128
  where
1129
    y' = valToRational m (eval m y)
×
1130

1131
eval m (EAp "bvule" [x,y]) = ValBool $ BV.bvule (valToBitVec m (eval m x)) (valToBitVec m (eval m y))
×
1132
eval m (EAp "bvult" [x,y]) = ValBool $ BV.bvult (valToBitVec m (eval m x)) (valToBitVec m (eval m y))
×
1133
eval m (EAp "bvuge" [x,y]) = ValBool $ BV.bvuge (valToBitVec m (eval m x)) (valToBitVec m (eval m y))
×
1134
eval m (EAp "bvugt" [x,y]) = ValBool $ BV.bvugt (valToBitVec m (eval m x)) (valToBitVec m (eval m y))
×
1135
eval m (EAp "bvsle" [x,y]) = ValBool $ BV.bvsle (valToBitVec m (eval m x)) (valToBitVec m (eval m y))
×
1136
eval m (EAp "bvslt" [x,y]) = ValBool $ BV.bvslt (valToBitVec m (eval m x)) (valToBitVec m (eval m y))
×
1137
eval m (EAp "bvsge" [x,y]) = ValBool $ BV.bvsge (valToBitVec m (eval m x)) (valToBitVec m (eval m y))
×
1138
eval m (EAp "bvsgt" [x,y]) = ValBool $ BV.bvsgt (valToBitVec m (eval m x)) (valToBitVec m (eval m y))
×
1139
eval m (EAp "concat" [x,y]) =
1140
  ValBitVec $ valToBitVec m (eval m x) <> valToBitVec m (eval m y)
×
1141
eval m (EAp (FSym "extract" [IndexNumeral i, IndexNumeral j]) [x]) =
1142
  ValBitVec $ BV.extract (fromIntegral i) (fromIntegral j) (valToBitVec m (eval m x))
×
1143
eval m (EAp (FSym "repeat" [IndexNumeral i]) [x]) =
1144
  ValBitVec $ BV.repeat (fromIntegral i) (valToBitVec m (eval m x))
×
1145
eval m (EAp (FSym "zero_extend" [IndexNumeral i]) [x]) =
1146
  ValBitVec $ BV.zeroExtend (fromIntegral i) (valToBitVec m (eval m x))
×
1147
eval m (EAp (FSym "sign_extend" [IndexNumeral i]) [x]) =
1148
  ValBitVec $ BV.signExtend (fromIntegral i) (valToBitVec m (eval m x))
×
1149
eval m (EAp (FSym "rotate_left" [IndexNumeral i]) [x]) =
1150
  ValBitVec $ rotateL (valToBitVec m (eval m x)) (fromIntegral i)
×
1151
eval m (EAp (FSym "rotate_right" [IndexNumeral i]) [x]) =
1152
  ValBitVec $ rotateR (valToBitVec m (eval m x)) (fromIntegral i)
×
1153
eval m (EAp (FSym op1 []) [x])
1154
  | Just op1' <- Map.lookup op1 table =
1✔
1155
      let x' = BV.EConst $ valToBitVec m (eval m x)
×
1156
      in ValBitVec $ BV.evalExpr (mBVModel m) $ op1' x'
1✔
1157
  where
1158
    table =
1✔
1159
      Map.fromList
1✔
1160
      [ ("bvnot", BV.bvnot)
1✔
1161
      , ("bvneg", BV.bvneg)
1✔
1162
      ]
1163
eval m (EAp (FSym op2 []) [x,y])
1164
  | Just op2' <- Map.lookup op2 table =
1✔
1165
      let x' = BV.EConst $ valToBitVec m (eval m x)
×
1166
          y' = BV.EConst $ valToBitVec m (eval m y)
×
1167
      in ValBitVec $ BV.evalExpr (mBVModel m) $ op2' x' y'
1✔
1168
  where
1169
    table = Map.fromList $ [("bvcomp", BV.bvcomp)] ++ bvBinOpsSameSize
1✔
1170

1171
eval m (EAp "=" [x,y])   = ValBool $
1✔
1172
  case (eval m x, eval m y) of
1✔
1173
    (v1, v2) -> v1 == v2
1✔
1174
eval m expr@(EAp f xs) =
1175
  case Map.lookup f (mDefs m) of
1✔
1176
    Nothing -> E.throw $ Error $ "unknown function symbol: " ++ show f
×
1177
    Just (FBoolVar v) -> ValBool $ SAT.evalLit (mBoolModel m) v
1✔
1178
    Just (FLRAVar v) -> ValRational $ mLRAModel m IntMap.! v
1✔
1179
    Just (FBVVar v) -> ValBitVec $ BV.evalExpr (mBVModel m) (BV.EVar v)
1✔
1180
    Just (FEUFFun (_, Sort s _) sym) ->
1181
      let e = EUF.evalAp (mEUFModel m) sym (map (valToEntity m . eval m) xs)
1✔
1182
      in case s of
1✔
1183
           SSymUninterpreted _ _ -> ValUninterpreted e (exprSort' (mDefs m) expr)
1✔
1184
           SSymBool -> ValBool (e == mEUFTrue m)
1✔
1185
           SSymReal ->
1186
             case IntMap.lookup e (mEntityToRational m) of
1✔
1187
               Just r -> ValRational r
1✔
1188
               Nothing -> ValRational (fromIntegral (1000000 + e))
1✔
1189
           SSymBitVec w ->
1190
             case IntMap.lookup e (mEntityToBitVec m) of
×
1191
               Just bv -> ValBitVec bv
×
1192
               Nothing -> ValBitVec (BV.nat2bv w 0)
×
1193

1194
valToBool :: Model -> Value -> Bool
1195
valToBool _ (ValBool b) = b
1✔
1196
valToBool _ _ = E.throw $ Error "boolean value is expected"
×
1197

1198
valToRational :: Model -> Value -> Rational
1199
valToRational _ (ValRational r) = r
1✔
1200
valToRational _ _ = E.throw $ Error "rational value is expected"
×
1201

1202
valToBitVec :: Model -> Value -> BV.BV
1203
valToBitVec _ (ValBitVec bv) = bv
1✔
1204
valToBitVec _ _ = E.throw $ Error "bitvector value is expected"
×
1205

1206
valToEntity :: Model -> Value -> EUF.Entity
1207
valToEntity _ (ValUninterpreted e _) = e
1✔
1208
valToEntity m (ValBool b)     = if b then mEUFTrue m else mEUFFalse m
1✔
1209
valToEntity m (ValRational r) =
1210
  case Map.lookup r (mRationalToEntity m) of
1✔
1211
    Just e -> e
1✔
1212
    Nothing -> EUF.mUnspecified (mEUFModel m)
×
1213
valToEntity m (ValBitVec bv) =
1214
  case Map.lookup bv (mBitVecToEntity m) of
1✔
1215
    Just e -> e
1✔
1216
    Nothing -> EUF.mUnspecified (mEUFModel m)
×
1217

1218
entityToValue :: Model -> EUF.Entity -> Sort -> Value
1219
entityToValue m e s =
1✔
1220
  case s of
1✔
1221
    Sort SSymBool _ -> ValBool (e == mEUFTrue m)
1✔
1222
    Sort SSymReal _ ->
1223
      case IntMap.lookup e (mEntityToRational m) of
1✔
1224
        Just r -> ValRational r
1✔
1225
        Nothing -> ValRational (fromIntegral (1000000 + e))
1✔
1226
    Sort (SSymBitVec n) _ ->
1227
      case IntMap.lookup e (mEntityToBitVec m) of
1✔
1228
        Just bv -> ValBitVec bv
1✔
1229
        Nothing -> ValBitVec (BV.nat2bv n 0)
1✔
1230
    Sort (SSymUninterpreted _ _) _ -> ValUninterpreted e s
1✔
1231

1232
valSort :: Value -> Sort
1233
valSort (ValUninterpreted _e s) = s
×
1234
valSort (ValBool _b)     = sBool
×
1235
valSort (ValRational _r) = sReal
1✔
1236
valSort (ValBitVec bv) = sBitVec (BV.width bv)
1✔
1237

1238
data FunDef = FunDef [([Value], Value)] Value
1239
  deriving (Eq, Show)
×
1240

1241
evalFSym :: Model -> FSym -> FunDef
1242
evalFSym m f =
1✔
1243
  case Map.lookup f (mDefs m) of
1✔
1244
    Just (FEUFFun (argsSorts@(_:_), resultSort) sym) -> -- proper function symbol
1245
      let tbl = EUF.mFunctions (mEUFModel m) IntMap.! sym
1✔
1246
          defaultVal =
1✔
1247
            case resultSort of
1✔
1248
              Sort SSymReal _ -> ValRational 555555
1✔
1249
              Sort SSymBool _ -> ValBool False
1✔
1250
              Sort (SSymBitVec w) _ -> ValBitVec (BV.nat2bv w 0)
1✔
1251
              Sort (SSymUninterpreted _s _ar) _ -> ValUninterpreted (EUF.mUnspecified (mEUFModel m)) resultSort
1✔
1252
      in FunDef [ (zipWith (entityToValue m) args argsSorts, entityToValue m result resultSort)
1✔
1253
                | (args, result) <- Map.toList tbl ]
1✔
1254
                defaultVal
1✔
1255
    Just _ -> FunDef [] $ eval m (EAp f []) -- constant symbol
1✔
1256
    Nothing -> E.throw $ Error $ "unknown function symbol: " ++ show f
×
1257

1258
-- | Constraints that cannot represented as function definitions.
1259
--
1260
-- For example, zero-division result values cannot be specified by
1261
-- function definition, because division is interpreted function.
1262
modelGetAssertions :: Model -> [Expr]
1263
modelGetAssertions m =
1✔
1264
  [ EAp "="
×
1265
      [ EAp "/"
×
1266
        [ EValue (entityToValue m arg sReal)
×
1267
        , EValue (ValRational 0)
×
1268
        ]
1269
      , EValue (entityToValue m result sReal)
×
1270
      ]
1271
  | let FEUFFun _ sym = mDefs m Map.! "_/0"
1✔
1272
  , ([arg], result) <- Map.toList $ EUF.mFunctions (mEUFModel m) IntMap.! sym
1✔
1273
  ]
1274
  ++
1275
  [ EAp "="
×
1276
      [ EAp "bvudiv"
×
1277
        [ EValue (ValBitVec s)
×
1278
        , EValue (ValBitVec (BV.nat2bv (BV.width s) 0))
×
1279
        ]
1280
      , EValue (ValBitVec t)
×
1281
      ]
1282
  | (s,t) <- Map.toList bvDivTable
1✔
1283
  ]
1284
  ++
1285
  [ EAp "="
×
1286
      [ EAp "bvurem"
×
1287
        [ EValue (ValBitVec s)
×
1288
        , EValue (ValBitVec (BV.nat2bv (BV.width s) 0))
×
1289
        ]
1290
      , EValue (ValBitVec t)
×
1291
      ]
1292
  | (s,t) <- Map.toList bvRemTable
1✔
1293
  ]
1294
  where
1295
    (_, bvDivTable, bvRemTable) = mBVModel m
1✔
1296

1297
-- -------------------------------------------------------------------
1298

1299
getUnsatAssumptions :: Solver -> IO [Expr]
1300
getUnsatAssumptions solver = do
1✔
1301
  readIORef (smtUnsatAssumptions solver)
1✔
1302

1303
getUnsatCore :: Solver -> IO [String]
1304
getUnsatCore solver = do
1✔
1305
  readIORef (smtUnsatCore solver)
1✔
1306

1307
-- -------------------------------------------------------------------
1308

1309
pairs :: [a] -> [(a,a)]
1310
pairs [] = []
×
1311
pairs (x:xs) = [(x,y) | y <- xs] ++ pairs xs
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc