PageRenderTime 97ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/Data/SBV/SMT/SMTLib2.hs

http://github.com/LeventErkok/sbv
Haskell | 1344 lines | 989 code | 202 blank | 153 comment | 76 complexity | 147fcba7d4dd5ed48a1a7d09661a2a35 MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. -----------------------------------------------------------------------------
  2. -- |
  3. -- Module : Data.SBV.SMT.SMTLib2
  4. -- Copyright : (c) Levent Erkok
  5. -- License : BSD3
  6. -- Maintainer: erkokl@gmail.com
  7. -- Stability : experimental
  8. --
  9. -- Conversion of symbolic programs to SMTLib format, Using v2 of the standard
  10. -----------------------------------------------------------------------------
  11. {-# LANGUAGE PatternGuards #-}
  12. {-# LANGUAGE ScopedTypeVariables #-}
  13. {-# LANGUAGE ViewPatterns #-}
  14. {-# OPTIONS_GHC -Wall -Werror #-}
  15. module Data.SBV.SMT.SMTLib2(cvt, cvtInc) where
  16. import Data.Bits (bit)
  17. import Data.List (intercalate, partition, nub, sort)
  18. import Data.Maybe (listToMaybe, fromMaybe, catMaybes)
  19. import qualified Data.Foldable as F (toList)
  20. import qualified Data.Map.Strict as M
  21. import qualified Data.IntMap.Strict as IM
  22. import Data.Set (Set)
  23. import qualified Data.Set as Set
  24. import Data.SBV.Core.Data
  25. import Data.SBV.Core.Symbolic (QueryContext(..), SetOp(..), OvOp(..), CnstMap, getUserName', getSV, regExpToSMTString)
  26. import Data.SBV.Core.Kind (smtType, needsFlattening)
  27. import Data.SBV.SMT.Utils
  28. import Data.SBV.Control.Types
  29. import Data.SBV.Utils.PrettyNum (smtRoundingMode, cvToSMTLib)
  30. import qualified Data.Generics.Uniplate.Data as G
  31. tbd :: String -> a
  32. tbd e = error $ "SBV.SMTLib2: Not-yet-supported: " ++ e
  33. -- | Translate a problem into an SMTLib2 script
  34. cvt :: SMTLibConverter [String]
  35. cvt ctx kindInfo isSat comments (inputs, trackerVars) skolemInps (allConsts, consts) tbls arrs uis axs (SBVPgm asgnsSeq) cstrs out cfg = pgm
  36. where hasInteger = KUnbounded `Set.member` kindInfo
  37. hasReal = KReal `Set.member` kindInfo
  38. hasFP = not (null [() | KFP{} <- Set.toList kindInfo])
  39. || KFloat `Set.member` kindInfo
  40. || KDouble `Set.member` kindInfo
  41. hasString = KString `Set.member` kindInfo
  42. hasChar = KChar `Set.member` kindInfo
  43. hasRounding = not $ null [s | (s, _) <- usorts, s == "RoundingMode"]
  44. hasBVs = not (null [() | KBounded{} <- Set.toList kindInfo])
  45. usorts = [(s, dt) | KUserSort s dt <- Set.toList kindInfo]
  46. trueUSorts = [s | (s, _) <- usorts, s /= "RoundingMode"]
  47. tupleArities = findTupleArities kindInfo
  48. hasNonBVArrays = (not . null) [() | (_, (_, (k1, k2), _)) <- arrs, not (isBounded k1 && isBounded k2)]
  49. hasArrayInits = (not . null) [() | (_, (_, _, ArrayFree (Just _))) <- arrs]
  50. hasOverflows = (not . null) [() | (_ :: OvOp) <- G.universeBi asgnsSeq]
  51. hasList = any isList kindInfo
  52. hasSets = any isSet kindInfo
  53. hasTuples = not . null $ tupleArities
  54. hasEither = any isEither kindInfo
  55. hasMaybe = any isMaybe kindInfo
  56. hasRational = any isRational kindInfo
  57. rm = roundingMode cfg
  58. solverCaps = capabilities (solver cfg)
  59. -- Is there a reason why we can't handle this problem?
  60. -- NB. There's probably a lot more checking we can do here, but this is a start:
  61. doesntHandle = listToMaybe [nope w | (w, have, need) <- checks, need && not have]
  62. where checks = [ ("data types", supportsDataTypes solverCaps, hasTuples || hasEither || hasMaybe)
  63. , ("set operations", supportsSets solverCaps, hasSets)
  64. , ("bit vectors", supportsBitVectors solverCaps, hasBVs)
  65. ]
  66. nope w = [ "*** Given problem requires support for " ++ w
  67. , "*** But the chosen solver (" ++ show (name (solver cfg)) ++ ") doesn't support this feature."
  68. ]
  69. setAll reason = ["(set-logic ALL) ; " ++ reason ++ ", using catch-all."]
  70. -- Determining the logic is surprisingly tricky!
  71. logic
  72. -- user told us what to do: so just take it:
  73. | Just l <- case [l | SetLogic l <- solverSetOptions cfg] of
  74. [] -> Nothing
  75. [l] -> Just l
  76. ls -> error $ unlines [ ""
  77. , "*** Only one setOption call to 'setLogic' is allowed, found: " ++ show (length ls)
  78. , "*** " ++ unwords (map show ls)
  79. ]
  80. = case l of
  81. Logic_NONE -> ["; NB. Not setting the logic per user request of Logic_NONE"]
  82. _ -> ["(set-logic " ++ show l ++ ") ; NB. User specified."]
  83. -- There's a reason why we can't handle this problem:
  84. | Just cantDo <- doesntHandle
  85. = error $ unlines $ [ ""
  86. , "*** SBV is unable to choose a proper solver configuration:"
  87. , "***"
  88. ]
  89. ++ cantDo
  90. ++ [ "***"
  91. , "*** Please report this as a feature request, either for SBV or the backend solver."
  92. ]
  93. -- Otherwise, we try to determine the most suitable logic.
  94. -- NB. This isn't really fool proof!
  95. -- we never set QF_S (ALL seems to work better in all cases)
  96. -- Things that require ALL
  97. | hasInteger = setAll "has unbounded values"
  98. | hasRational = setAll "has rational values"
  99. | hasReal = setAll "has algebraic reals"
  100. | not (null trueUSorts) = setAll "has user-defined sorts"
  101. | hasNonBVArrays = setAll "has non-bitvector arrays"
  102. | hasTuples = setAll "has tuples"
  103. | hasEither = setAll "has either type"
  104. | hasMaybe = setAll "has maybe type"
  105. | hasSets = setAll "has sets"
  106. | hasList = setAll "has lists"
  107. | hasChar = setAll "has chars"
  108. | hasString = setAll "has strings"
  109. | hasArrayInits = setAll "has array initializers"
  110. | hasOverflows = setAll "has overflow checks"
  111. | hasFP || hasRounding
  112. = if not (null foralls)
  113. then ["(set-logic ALL)"]
  114. else if hasBVs
  115. then ["(set-logic QF_FPBV)"]
  116. else ["(set-logic QF_FP)"]
  117. -- If we're in a user query context, we'll pick ALL, otherwise
  118. -- we'll stick to some bit-vector logic based on what we see in the problem.
  119. -- This is controversial, but seems to work well in practice.
  120. | True
  121. = case ctx of
  122. QueryExternal -> ["(set-logic ALL) ; external query, using all logics."]
  123. QueryInternal -> if supportsBitVectors solverCaps
  124. then ["(set-logic " ++ qs ++ as ++ ufs ++ "BV)"]
  125. else ["(set-logic ALL)"] -- fall-thru
  126. where qs | null foralls && null axs = "QF_" -- axioms are likely to contain quantifiers
  127. | True = ""
  128. as | null arrs = ""
  129. | True = "A"
  130. ufs | null uis && null tbls = "" -- we represent tables as UFs
  131. | True = "UF"
  132. -- SBV always requires the production of models!
  133. getModels = "(set-option :produce-models true)"
  134. : concat [flattenConfig | any needsFlattening kindInfo, Just flattenConfig <- [supportsFlattenedModels solverCaps]]
  135. -- process all other settings we're given. If an option cannot be repeated, we only take the last one.
  136. userSettings = map setSMTOption $ filter (not . isLogic) $ foldr comb [] $ solverSetOptions cfg
  137. where -- Logic is already processed, so drop it:
  138. isLogic SetLogic{} = True
  139. isLogic _ = False
  140. -- SBV sets diagnostic-output channel on some solvers. If the user also gives it, let's just
  141. -- take it by only taking the last one
  142. isDiagOutput DiagnosticOutputChannel{} = True
  143. isDiagOutput _ = False
  144. comb o rest
  145. | isDiagOutput o && any isDiagOutput rest = rest
  146. | True = o : rest
  147. settings = userSettings -- NB. Make sure this comes first!
  148. ++ getModels
  149. ++ logic
  150. pgm = map ("; " ++) comments
  151. ++ settings
  152. ++ [ "; --- uninterpreted sorts ---" ]
  153. ++ concatMap declSort usorts
  154. ++ [ "; --- tuples ---" ]
  155. ++ concatMap declTuple tupleArities
  156. ++ [ "; --- sums ---" ]
  157. ++ (if containsSum kindInfo then declSum else [])
  158. ++ (if containsMaybe kindInfo then declMaybe else [])
  159. ++ (if containsRationals kindInfo then declRationals else [])
  160. ++ [ "; --- literal constants ---" ]
  161. ++ concatMap (declConst cfg) consts
  162. ++ [ "; --- skolem constants ---" ]
  163. ++ concat [declareFun s (SBVType (map kindOf (ss ++ [s]))) (userName s) | Right (s, ss) <- skolemInps]
  164. ++ [ "; --- optimization tracker variables ---" | not (null trackerVars) ]
  165. ++ concat [declareFun s (SBVType [kindOf s]) (Just ("tracks " <> nm)) | var <- trackerVars, let s = getSV var, let nm = getUserName' var]
  166. ++ [ "; --- constant tables ---" ]
  167. ++ concatMap (uncurry (:) . constTable) constTables
  168. ++ [ "; --- skolemized tables ---" ]
  169. ++ map (skolemTable (unwords (map svType foralls))) skolemTables
  170. ++ [ "; --- arrays ---" ]
  171. ++ concat arrayConstants
  172. ++ [ "; --- uninterpreted constants ---" ]
  173. ++ concatMap declUI uis
  174. ++ [ "; --- user given axioms ---" ]
  175. ++ map declAx axs
  176. ++ [ "; --- preQuantifier assignments ---" ]
  177. ++ concatMap (declDef cfg skolemMap tableMap) preQuantifierAssigns
  178. ++ [ "; --- arrayDelayeds ---" ]
  179. ++ concat arrayDelayeds
  180. ++ [ "; --- arraySetups ---" ]
  181. ++ concat arraySetups
  182. ++ [ "; --- formula ---" ]
  183. ++ ["(assert (forall (" ++ intercalate "\n "
  184. ["(" ++ show s ++ " " ++ svType s ++ ")" | s <- foralls] ++ ")"
  185. | not (null foralls)
  186. ]
  187. ++ [ "; --- postQuantifier assignments ---" ]
  188. ++ concatMap mkAssign postQuantifierAssigns
  189. ++ [ "; --- delayedEqualities ---" ]
  190. ++ delayedAsserts delayedEqualities
  191. ++ [ "; -- finalAssert ---" ]
  192. ++ finalAssert
  193. -- identify the assignments that can come before the first quantifier
  194. (preQuantifierAssigns, postQuantifierAssigns)
  195. | null foralls
  196. = (asgns, [])
  197. | True
  198. = span pre asgns
  199. where first = nodeId (minimum foralls)
  200. pre (s, _) = nodeId s < first
  201. nodeId (SV _ n) = n
  202. noOfCloseParens
  203. | null foralls = 0
  204. | True = length postQuantifierAssigns + 2 + (if null delayedEqualities then 0 else 1)
  205. foralls = [s | Left s <- skolemInps]
  206. forallArgs = concatMap ((" " ++) . show) foralls
  207. (constTables, skolemTables) = ([(t, d) | (t, Left d) <- allTables], [(t, d) | (t, Right d) <- allTables])
  208. allTables = [(t, genTableData rm skolemMap (not (null foralls), forallArgs) (map fst consts) t) | t <- tbls]
  209. (arrayConstants, arrayDelayeds, arraySetups) = unzip3 $ map (declArray cfg (not (null foralls)) allConsts skolemMap) arrs
  210. delayedEqualities = concatMap snd skolemTables
  211. delayedAsserts [] = []
  212. delayedAsserts ds@(deH : deTs)
  213. | null foralls = map (\s -> "(assert " ++ s ++ ")") ds
  214. | True = map letShift (("(and " ++ deH) : map (align 5) deTs)
  215. letShift = align 12
  216. finalAssert
  217. | null foralls && noConstraints
  218. = []
  219. | null foralls
  220. = map (\(attr, v) -> "(assert " ++ addAnnotations attr (mkLiteral v) ++ ")") hardAsserts
  221. ++ map (\(attr, v) -> "(assert-soft " ++ addAnnotations attr (mkLiteral v) ++ ")") softAsserts
  222. | not (null namedAsserts)
  223. = error $ intercalate "\n" [ "SBV: Constraints with attributes and quantifiers cannot be mixed!"
  224. , " Quantified variables: " ++ unwords (map show foralls)
  225. , " Named constraints : " ++ intercalate ", " (map show namedAsserts)
  226. ]
  227. | not (null softAsserts)
  228. = error $ intercalate "\n" [ "SBV: Soft constraints and quantifiers cannot be mixed!"
  229. , " Quantified variables: " ++ unwords (map show foralls)
  230. , " Soft constraints : " ++ intercalate ", " (map show softAsserts)
  231. ]
  232. | True
  233. = [impAlign (letShift combined) ++ replicate noOfCloseParens ')']
  234. where mkLiteral (Left v) = cvtSV skolemMap v
  235. mkLiteral (Right v) = "(not " ++ cvtSV skolemMap v ++ ")"
  236. (noConstraints, assertions) = finalAssertions
  237. namedAsserts = [findName attrs | (_, attrs, _) <- assertions, not (null attrs)]
  238. where findName attrs = fromMaybe "<anonymous>" (listToMaybe [nm | (":named", nm) <- attrs])
  239. hardAsserts, softAsserts :: [([(String, String)], Either SV SV)]
  240. hardAsserts = [(attr, v) | (False, attr, v) <- assertions]
  241. softAsserts = [(attr, v) | (True, attr, v) <- assertions]
  242. combined = case lits of
  243. [] -> "true"
  244. [x] -> mkLiteral x
  245. xs | any bad xs -> "false"
  246. | True -> "(and " ++ unwords (map mkLiteral xs) ++ ")"
  247. where lits = filter (not . redundant) $ nub (sort (map snd hardAsserts))
  248. redundant (Left v) = v == trueSV
  249. redundant (Right v) = v == falseSV
  250. bad (Left v) = v == falseSV
  251. bad (Right v) = v == trueSV
  252. impAlign s
  253. | null delayedEqualities = s
  254. | True = " " ++ s
  255. align n s = replicate n ' ' ++ s
  256. finalAssertions :: (Bool, [(Bool, [(String, String)], Either SV SV)]) -- If Left: positive, Right: negative
  257. finalAssertions
  258. | null finals = (True, [(False, [], Left trueSV)])
  259. | True = (False, finals)
  260. where finals = cstrs' ++ maybe [] (\r -> [(False, [], r)]) mbO
  261. cstrs' = [(isSoft, attrs, c') | (isSoft, attrs, c) <- F.toList cstrs, Just c' <- [pos c]]
  262. mbO | isSat = pos out
  263. | True = neg out
  264. neg s
  265. | s == falseSV = Nothing
  266. | s == trueSV = Just $ Left falseSV
  267. | True = Just $ Right s
  268. pos s
  269. | s == trueSV = Nothing
  270. | s == falseSV = Just $ Left falseSV
  271. | True = Just $ Left s
  272. skolemMap = M.fromList [(s, ss) | Right (s, ss) <- skolemInps, not (null ss)]
  273. tableMap = IM.fromList $ map mkConstTable constTables ++ map mkSkTable skolemTables
  274. where mkConstTable (((t, _, _), _), _) = (t, "table" ++ show t)
  275. mkSkTable (((t, _, _), _), _) = (t, "table" ++ show t ++ forallArgs)
  276. asgns = F.toList asgnsSeq
  277. mkAssign a
  278. | null foralls = declDef cfg skolemMap tableMap a
  279. | True = [letShift (mkLet a)]
  280. mkLet (s, SBVApp (Label m) [e]) = "(let ((" ++ show s ++ " " ++ cvtSV skolemMap e ++ ")) ; " ++ m
  281. mkLet (s, e) = "(let ((" ++ show s ++ " " ++ cvtExp solverCaps rm skolemMap tableMap e ++ "))"
  282. userNameMap = M.fromList $ map ((\nSymVar -> (getSV nSymVar, getUserName' nSymVar)) . snd) inputs
  283. userName s = case M.lookup s userNameMap of
  284. Just u | show s /= u -> Just $ "tracks user variable " ++ show u
  285. _ -> Nothing
  286. -- | Declare new sorts
  287. declSort :: (String, Maybe [String]) -> [String]
  288. declSort (s, _)
  289. | s == "RoundingMode" -- built-in-sort; so don't declare.
  290. = []
  291. declSort (s, Nothing) = ["(declare-sort " ++ s ++ " 0) ; N.B. Uninterpreted sort." ]
  292. declSort (s, Just fs) = [ "(declare-datatypes ((" ++ s ++ " 0)) ((" ++ unwords (map (\c -> "(" ++ c ++ ")") fs) ++ ")))"
  293. , "(define-fun " ++ s ++ "_constrIndex ((x " ++ s ++ ")) Int"
  294. ] ++ [" " ++ body fs (0::Int)] ++ [")"]
  295. where body [] _ = ""
  296. body [_] i = show i
  297. body (c:cs) i = "(ite (= x " ++ c ++ ") " ++ show i ++ " " ++ body cs (i+1) ++ ")"
  298. -- | Declare tuple datatypes
  299. --
  300. -- eg:
  301. --
  302. -- @
  303. -- (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
  304. -- ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
  305. -- (proj_2_SBVTuple2 T2))))))
  306. -- @
  307. declTuple :: Int -> [String]
  308. declTuple arity
  309. | arity == 0 = ["(declare-datatypes ((SBVTuple0 0)) (((mkSBVTuple0))))"]
  310. | arity == 1 = error "Data.SBV.declTuple: Unexpected one-tuple"
  311. | True = (l1 ++ "(par (" ++ unwords [param i | i <- [1..arity]] ++ ")")
  312. : [pre i ++ proj i ++ post i | i <- [1..arity]]
  313. where l1 = "(declare-datatypes ((SBVTuple" ++ show arity ++ " " ++ show arity ++ ")) ("
  314. l2 = replicate (length l1) ' ' ++ "((mkSBVTuple" ++ show arity ++ " "
  315. tab = replicate (length l2) ' '
  316. pre 1 = l2
  317. pre _ = tab
  318. proj i = "(proj_" ++ show i ++ "_SBVTuple" ++ show arity ++ " " ++ param i ++ ")"
  319. post i = if i == arity then ")))))" else ""
  320. param i = "T" ++ show i
  321. -- | Find the set of tuple sizes to declare, eg (2-tuple, 5-tuple).
  322. -- NB. We do *not* need to recursively go into list/tuple kinds here,
  323. -- because register-kind function automatically registers all subcomponent
  324. -- kinds, thus everything we need is available at the top-level.
  325. findTupleArities :: Set Kind -> [Int]
  326. findTupleArities ks = Set.toAscList
  327. $ Set.map length
  328. $ Set.fromList [ tupKs | KTuple tupKs <- Set.toList ks ]
  329. -- | Is @Either@ being used?
  330. containsSum :: Set Kind -> Bool
  331. containsSum = not . Set.null . Set.filter isEither
  332. -- | Is @Maybe@ being used?
  333. containsMaybe :: Set Kind -> Bool
  334. containsMaybe = not . Set.null . Set.filter isMaybe
  335. -- | Is @Rational@ being used?
  336. containsRationals :: Set Kind -> Bool
  337. containsRationals = not . Set.null . Set.filter isRational
  338. declSum :: [String]
  339. declSum = [ "(declare-datatypes ((SBVEither 2)) ((par (T1 T2)"
  340. , " ((left_SBVEither (get_left_SBVEither T1))"
  341. , " (right_SBVEither (get_right_SBVEither T2))))))"
  342. ]
  343. declMaybe :: [String]
  344. declMaybe = [ "(declare-datatypes ((SBVMaybe 1)) ((par (T)"
  345. , " ((nothing_SBVMaybe)"
  346. , " (just_SBVMaybe (get_just_SBVMaybe T))))))"
  347. ]
  348. -- Internally, we do *not* keep the rationals in reduced form! So, the boolean operators explicitly do the math
  349. -- to make sure equivalent values are treated correctly.
  350. declRationals :: [String]
  351. declRationals = [ "(declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))"
  352. , ""
  353. , "(define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool"
  354. , " (= (* (sbv.rat.numerator x) (sbv.rat.denominator y))"
  355. , " (* (sbv.rat.denominator x) (sbv.rat.numerator y)))"
  356. , ")"
  357. , ""
  358. , "(define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool"
  359. , " (not (sbv.rat.eq x y))"
  360. , ")"
  361. , ""
  362. , "(define-fun sbv.rat.lt ((x SBVRational) (y SBVRational)) Bool"
  363. , " (< (* (sbv.rat.numerator x) (sbv.rat.denominator y))"
  364. , " (* (sbv.rat.denominator x) (sbv.rat.numerator y)))"
  365. , ")"
  366. , ""
  367. , "(define-fun sbv.rat.leq ((x SBVRational) (y SBVRational)) Bool"
  368. , " (<= (* (sbv.rat.numerator x) (sbv.rat.denominator y))"
  369. , " (* (sbv.rat.denominator x) (sbv.rat.numerator y)))"
  370. , ")"
  371. , ""
  372. , "(define-fun sbv.rat.plus ((x SBVRational) (y SBVRational)) SBVRational"
  373. , " (SBV.Rational (+ (* (sbv.rat.numerator x) (sbv.rat.denominator y))"
  374. , " (* (sbv.rat.denominator x) (sbv.rat.numerator y)))"
  375. , " (* (sbv.rat.denominator x) (sbv.rat.denominator y)))"
  376. , ")"
  377. , ""
  378. , "(define-fun sbv.rat.minus ((x SBVRational) (y SBVRational)) SBVRational"
  379. , " (SBV.Rational (- (* (sbv.rat.numerator x) (sbv.rat.denominator y))"
  380. , " (* (sbv.rat.denominator x) (sbv.rat.numerator y)))"
  381. , " (* (sbv.rat.denominator x) (sbv.rat.denominator y)))"
  382. , ")"
  383. , ""
  384. , "(define-fun sbv.rat.times ((x SBVRational) (y SBVRational)) SBVRational"
  385. , " (SBV.Rational (* (sbv.rat.numerator x) (sbv.rat.numerator y))"
  386. , " (* (sbv.rat.denominator x) (sbv.rat.denominator y)))"
  387. , ")"
  388. , ""
  389. , "(define-fun sbv.rat.uneg ((x SBVRational)) SBVRational"
  390. , " (SBV.Rational (* (- 1) (sbv.rat.numerator x)) (sbv.rat.denominator x))"
  391. , ")"
  392. , ""
  393. , "(define-fun sbv.rat.abs ((x SBVRational)) SBVRational"
  394. , " (SBV.Rational (abs (sbv.rat.numerator x)) (sbv.rat.denominator x))"
  395. , ")"
  396. ]
  397. -- | Convert in a query context.
  398. -- NB. We do not store everything in @newKs@ below, but only what we need
  399. -- to do as an extra in the incremental context. See `Data.SBV.Core.Symbolic.registerKind`
  400. -- for a list of what we include, in case something doesn't show up
  401. -- and you need it!
  402. cvtInc :: SMTLibIncConverter [String]
  403. cvtInc inps newKs (allConsts, consts) arrs tbls uis (SBVPgm asgnsSeq) cstrs cfg =
  404. -- any new settings?
  405. settings
  406. -- sorts
  407. ++ concatMap declSort [(s, dt) | KUserSort s dt <- newKinds]
  408. -- tuples. NB. Only declare the new sizes, old sizes persist.
  409. ++ concatMap declTuple (findTupleArities newKs)
  410. -- sums
  411. ++ (if containsSum newKs then declSum else [])
  412. ++ (if containsMaybe newKs then declMaybe else [])
  413. -- constants
  414. ++ concatMap (declConst cfg) consts
  415. -- inputs
  416. ++ concatMap declInp inps
  417. -- arrays
  418. ++ concat arrayConstants
  419. -- uninterpreteds
  420. ++ concatMap declUI uis
  421. -- table declarations
  422. ++ tableDecls
  423. -- expressions
  424. ++ concatMap (declDef cfg skolemMap tableMap) (F.toList asgnsSeq)
  425. -- delayed equalities
  426. ++ concat arrayDelayeds
  427. -- table setups
  428. ++ concat tableAssigns
  429. -- array setups
  430. ++ concat arraySetups
  431. -- extra constraints
  432. ++ map (\(isSoft, attr, v) -> "(assert" ++ (if isSoft then "-soft " else " ") ++ addAnnotations attr (cvtSV skolemMap v) ++ ")") (F.toList cstrs)
  433. where -- NB. The below setting of skolemMap to empty is OK, since we do
  434. -- not support queries in the context of skolemized variables
  435. skolemMap = M.empty
  436. rm = roundingMode cfg
  437. newKinds = Set.toList newKs
  438. declInp (getSV -> s) = declareFun s (SBVType [kindOf s]) Nothing
  439. (arrayConstants, arrayDelayeds, arraySetups) = unzip3 $ map (declArray cfg False allConsts skolemMap) arrs
  440. allTables = [(t, either id id (genTableData rm skolemMap (False, []) (map fst consts) t)) | t <- tbls]
  441. (tableDecls, tableAssigns) = unzip $ map constTable allTables
  442. tableMap = IM.fromList $ map mkTable allTables
  443. where mkTable (((t, _, _), _), _) = (t, "table" ++ show t)
  444. -- If we need flattening in models, do emit the required lines if preset
  445. settings
  446. | any needsFlattening newKinds
  447. = concat (catMaybes [supportsFlattenedModels solverCaps])
  448. | True
  449. = []
  450. where solverCaps = capabilities (solver cfg)
  451. declDef :: SMTConfig -> SkolemMap -> TableMap -> (SV, SBVExpr) -> [String]
  452. declDef cfg skolemMap tableMap (s, expr) =
  453. case expr of
  454. SBVApp (Label m) [e] -> defineFun cfg (s, cvtSV skolemMap e) (Just m)
  455. e -> defineFun cfg (s, cvtExp caps rm skolemMap tableMap e) Nothing
  456. where caps = capabilities (solver cfg)
  457. rm = roundingMode cfg
  458. defineFun :: SMTConfig -> (SV, String) -> Maybe String -> [String]
  459. defineFun cfg (s, def) mbComment
  460. | hasDefFun = ["(define-fun " ++ varT ++ " " ++ def ++ ")" ++ cmnt]
  461. | True = [ "(declare-fun " ++ varT ++ ")" ++ cmnt
  462. , "(assert (= " ++ var ++ " " ++ def ++ "))"
  463. ]
  464. where var = show s
  465. varT = var ++ " " ++ svFunType [] s
  466. cmnt = maybe "" (" ; " ++) mbComment
  467. hasDefFun = supportsDefineFun $ capabilities (solver cfg)
  468. -- Declare constants. NB. We don't declare true/false; but just inline those as necessary
  469. declConst :: SMTConfig -> (SV, CV) -> [String]
  470. declConst cfg (s, c)
  471. | s == falseSV || s == trueSV
  472. = []
  473. | True
  474. = defineFun cfg (s, cvtCV (roundingMode cfg) c) Nothing
  475. declUI :: (String, SBVType) -> [String]
  476. declUI (i, t) = declareName i t Nothing
  477. -- NB. We perform no check to as to whether the axiom is meaningful in any way.
  478. declAx :: (String, [String]) -> String
  479. declAx (nm, ls) = (";; -- user given axiom: " ++ nm ++ "\n") ++ intercalate "\n" ls
  480. constTable :: (((Int, Kind, Kind), [SV]), [String]) -> (String, [String])
  481. constTable (((i, ak, rk), _elts), is) = (decl, zipWith wrap [(0::Int)..] is ++ setup)
  482. where t = "table" ++ show i
  483. decl = "(declare-fun " ++ t ++ " (" ++ smtType ak ++ ") " ++ smtType rk ++ ")"
  484. -- Arrange for initializers
  485. mkInit idx = "table" ++ show i ++ "_initializer_" ++ show (idx :: Int)
  486. initializer = "table" ++ show i ++ "_initializer"
  487. wrap index s = "(define-fun " ++ mkInit index ++ " () Bool " ++ s ++ ")"
  488. lis = length is
  489. setup
  490. | lis == 0 = [ "(define-fun " ++ initializer ++ " () Bool true) ; no initialization needed"
  491. ]
  492. | lis == 1 = [ "(define-fun " ++ initializer ++ " () Bool " ++ mkInit 0 ++ ")"
  493. , "(assert " ++ initializer ++ ")"
  494. ]
  495. | True = [ "(define-fun " ++ initializer ++ " () Bool (and " ++ unwords (map mkInit [0..lis - 1]) ++ "))"
  496. , "(assert " ++ initializer ++ ")"
  497. ]
  498. skolemTable :: String -> (((Int, Kind, Kind), [SV]), [String]) -> String
  499. skolemTable qsIn (((i, ak, rk), _elts), _) = decl
  500. where qs = if null qsIn then "" else qsIn ++ " "
  501. t = "table" ++ show i
  502. decl = "(declare-fun " ++ t ++ " (" ++ qs ++ smtType ak ++ ") " ++ smtType rk ++ ")"
  503. -- Left if all constants, Right if otherwise
  504. genTableData :: RoundingMode -> SkolemMap -> (Bool, String) -> [SV] -> ((Int, Kind, Kind), [SV]) -> Either [String] [String]
  505. genTableData rm skolemMap (_quantified, args) consts ((i, aknd, _), elts)
  506. | null post = Left (map (topLevel . snd) pre)
  507. | True = Right (map (nested . snd) (pre ++ post))
  508. where ssv = cvtSV skolemMap
  509. (pre, post) = partition fst (zipWith mkElt elts [(0::Int)..])
  510. t = "table" ++ show i
  511. mkElt x k = (isReady, (idx, ssv x))
  512. where idx = cvtCV rm (mkConstCV aknd k)
  513. isReady = x `Set.member` constsSet
  514. topLevel (idx, v) = "(= (" ++ t ++ " " ++ idx ++ ") " ++ v ++ ")"
  515. nested (idx, v) = "(= (" ++ t ++ args ++ " " ++ idx ++ ") " ++ v ++ ")"
  516. constsSet = Set.fromList consts
  517. -- TODO: We currently do not support non-constant arrays when quantifiers are present, as
  518. -- we might have to skolemize those. Implement this properly.
  519. -- The difficulty is with the Mutate/Merge: We have to postpone an init if
  520. -- the components are themselves postponed, so this cannot be implemented as a simple map.
  521. declArray :: SMTConfig -> Bool -> CnstMap -> SkolemMap -> (Int, ArrayInfo) -> ([String], [String], [String])
  522. declArray cfg quantified consts skolemMap (i, (_, (aKnd, bKnd), ctx)) = (adecl : zipWith wrap [(0::Int)..] (map snd pre), zipWith wrap [lpre..] (map snd post), setup)
  523. where constMapping = M.fromList [(s, c) | (c, s) <- M.assocs consts]
  524. constNames = M.keys constMapping
  525. topLevel = not quantified || case ctx of
  526. ArrayFree mbi -> maybe True (`elem` constNames) mbi
  527. ArrayMutate _ a b -> all (`elem` constNames) [a, b]
  528. ArrayMerge c _ _ -> c `elem` constNames
  529. (pre, post) = partition fst ctxInfo
  530. nm = "array_" ++ show i
  531. ssv sv
  532. | topLevel || sv `elem` constNames
  533. = cvtSV skolemMap sv
  534. | True
  535. = tbd "Non-constant array initializer in a quantified context"
  536. atyp = "(Array " ++ smtType aKnd ++ " " ++ smtType bKnd ++ ")"
  537. adecl = case ctx of
  538. ArrayFree (Just v) -> "(define-fun " ++ nm ++ " () " ++ atyp ++ " ((as const " ++ atyp ++ ") " ++ constInit v ++ "))"
  539. ArrayFree Nothing
  540. | bKnd == KChar -> -- Can't support yet, because we need to make sure all the elements are length-1 strings. So, punt for now.
  541. tbd "Free array declarations containing SChars"
  542. _ -> "(declare-fun " ++ nm ++ " () " ++ atyp ++ ")"
  543. -- CVC4 chokes if the initializer is not a constant. (Z3 is ok with it.) So, print it as
  544. -- a constant if we have it in the constants; otherwise, we merely print it and hope for the best.
  545. constInit v = case v `M.lookup` constMapping of
  546. Nothing -> ssv v -- Z3 will work, CVC4 will choke. Others don't even support this.
  547. Just c -> cvtCV (roundingMode cfg) c -- Z3 and CVC4 will work. Other's don't support this.
  548. ctxInfo = case ctx of
  549. ArrayFree _ -> []
  550. ArrayMutate j a b -> [(all (`elem` constNames) [a, b], "(= " ++ nm ++ " (store array_" ++ show j ++ " " ++ ssv a ++ " " ++ ssv b ++ "))")]
  551. ArrayMerge t j k -> [(t `elem` constNames, "(= " ++ nm ++ " (ite " ++ ssv t ++ " array_" ++ show j ++ " array_" ++ show k ++ "))")]
  552. -- Arrange for initializers
  553. mkInit idx = "array_" ++ show i ++ "_initializer_" ++ show (idx :: Int)
  554. initializer = "array_" ++ show i ++ "_initializer"
  555. wrap index s = "(define-fun " ++ mkInit index ++ " () Bool " ++ s ++ ")"
  556. lpre = length pre
  557. lAll = lpre + length post
  558. setup
  559. | lAll == 0 = [ "(define-fun " ++ initializer ++ " () Bool true) ; no initialization needed" | not quantified]
  560. | lAll == 1 = [ "(define-fun " ++ initializer ++ " () Bool " ++ mkInit 0 ++ ")"
  561. , "(assert " ++ initializer ++ ")"
  562. ]
  563. | True = [ "(define-fun " ++ initializer ++ " () Bool (and " ++ unwords (map mkInit [0..lAll - 1]) ++ "))"
  564. , "(assert " ++ initializer ++ ")"
  565. ]
  566. svType :: SV -> String
  567. svType s = smtType (kindOf s)
  568. svFunType :: [SV] -> SV -> String
  569. svFunType ss s = "(" ++ unwords (map svType ss) ++ ") " ++ svType s
  570. cvtType :: SBVType -> String
  571. cvtType (SBVType []) = error "SBV.SMT.SMTLib2.cvtType: internal: received an empty type!"
  572. cvtType (SBVType xs) = "(" ++ unwords (map smtType body) ++ ") " ++ smtType ret
  573. where (body, ret) = (init xs, last xs)
  574. type SkolemMap = M.Map SV [SV]
  575. type TableMap = IM.IntMap String
  576. -- Present an SV; inline true/false as needed
  577. cvtSV :: SkolemMap -> SV -> String
  578. cvtSV skolemMap s@(SV _ (NodeId n))
  579. | Just ss <- s `M.lookup` skolemMap
  580. = "(" ++ show s ++ concatMap ((" " ++) . show) ss ++ ")"
  581. | s == trueSV
  582. = "true"
  583. | s == falseSV
  584. = "false"
  585. | True
  586. = 's' : show n
  587. cvtCV :: RoundingMode -> CV -> String
  588. cvtCV = cvToSMTLib
  589. getTable :: TableMap -> Int -> String
  590. getTable m i
  591. | Just tn <- i `IM.lookup` m = tn
  592. | True = "table" ++ show i -- constant tables are always named this way
  593. cvtExp :: SolverCapabilities -> RoundingMode -> SkolemMap -> TableMap -> SBVExpr -> String
  594. cvtExp caps rm skolemMap tableMap expr@(SBVApp _ arguments) = sh expr
  595. where ssv = cvtSV skolemMap
  596. hasPB = supportsPseudoBooleans caps
  597. hasInt2bv = supportsInt2bv caps
  598. hasDistinct = supportsDistinct caps
  599. bvOp = all isBounded arguments
  600. intOp = any isUnbounded arguments
  601. ratOp = any isRational arguments
  602. realOp = any isReal arguments
  603. fpOp = any (\a -> isDouble a || isFloat a || isFP a) arguments
  604. boolOp = all isBoolean arguments
  605. charOp = any isChar arguments
  606. stringOp = any isString arguments
  607. listOp = any isList arguments
  608. bad | intOp = error $ "SBV.SMTLib2: Unsupported operation on unbounded integers: " ++ show expr
  609. | True = error $ "SBV.SMTLib2: Unsupported operation on real values: " ++ show expr
  610. ensureBVOrBool = bvOp || boolOp || bad
  611. ensureBV = bvOp || bad
  612. addRM s = s ++ " " ++ smtRoundingMode rm
  613. -- lift a binary op
  614. lift2 o _ [x, y] = "(" ++ o ++ " " ++ x ++ " " ++ y ++ ")"
  615. lift2 o _ sbvs = error $ "SBV.SMTLib2.sh.lift2: Unexpected arguments: " ++ show (o, sbvs)
  616. -- lift an arbitrary arity operator
  617. liftN o _ xs = "(" ++ o ++ " " ++ unwords xs ++ ")"
  618. -- lift a binary operation with rounding-mode added; used for floating-point arithmetic
  619. lift2WM o fo | fpOp = lift2 (addRM fo)
  620. | True = lift2 o
  621. lift1FP o fo | fpOp = lift1 fo
  622. | True = lift1 o
  623. liftAbs sgned args | fpOp = lift1 "fp.abs" sgned args
  624. | intOp = lift1 "abs" sgned args
  625. | bvOp, sgned = mkAbs (head args) "bvslt" "bvneg"
  626. | bvOp = head args
  627. | True = mkAbs (head args) "<" "-"
  628. where mkAbs x cmp neg = "(ite " ++ ltz ++ " " ++ nx ++ " " ++ x ++ ")"
  629. where ltz = "(" ++ cmp ++ " " ++ x ++ " " ++ z ++ ")"
  630. nx = "(" ++ neg ++ " " ++ x ++ ")"
  631. z = cvtCV rm (mkConstCV (kindOf (head arguments)) (0::Integer))
  632. lift2B bOp vOp
  633. | boolOp = lift2 bOp
  634. | True = lift2 vOp
  635. lift1B bOp vOp
  636. | boolOp = lift1 bOp
  637. | True = lift1 vOp
  638. eqBV = lift2 "="
  639. neqBV = liftN "distinct"
  640. equal sgn sbvs
  641. | fpOp = lift2 "fp.eq" sgn sbvs
  642. | True = lift2 "=" sgn sbvs
  643. -- Do not use distinct on floats; because +0/-0, and NaNs mess
  644. -- up the meaning. Just go with reqular equals.
  645. notEqual sgn sbvs
  646. | fpOp || not hasDistinct = liftP sbvs
  647. | True = liftN "distinct" sgn sbvs
  648. where liftP xs@[_, _] = "(not " ++ equal sgn xs ++ ")"
  649. liftP args = "(and " ++ unwords (walk args) ++ ")"
  650. walk [] = []
  651. walk (e:es) = map (\e' -> liftP [e, e']) es ++ walk es
  652. lift2S oU oS sgn = lift2 (if sgn then oS else oU) sgn
  653. liftNS oU oS sgn = liftN (if sgn then oS else oU) sgn
  654. lift2Cmp o fo | fpOp = lift2 fo
  655. | True = lift2 o
  656. unintComp o [a, b]
  657. | KUserSort s (Just _) <- kindOf (head arguments)
  658. = let idx v = "(" ++ s ++ "_constrIndex " ++ v ++ ")" in "(" ++ o ++ " " ++ idx a ++ " " ++ idx b ++ ")"
  659. unintComp o sbvs = error $ "SBV.SMT.SMTLib2.sh.unintComp: Unexpected arguments: " ++ show (o, sbvs, map kindOf arguments)
  660. stringOrChar KString = True
  661. stringOrChar KChar = True
  662. stringOrChar _ = False
  663. stringCmp swap o [a, b]
  664. | stringOrChar (kindOf (head arguments))
  665. = let [a1, a2] | swap = [b, a]
  666. | True = [a, b]
  667. in "(" ++ o ++ " " ++ a1 ++ " " ++ a2 ++ ")"
  668. stringCmp _ o sbvs = error $ "SBV.SMT.SMTLib2.sh.stringCmp: Unexpected arguments: " ++ show (o, sbvs)
  669. -- NB. Likewise for sequences
  670. seqCmp swap o [a, b]
  671. | KList{} <- kindOf (head arguments)
  672. = let [a1, a2] | swap = [b, a]
  673. | True = [a, b]
  674. in "(" ++ o ++ " " ++ a1 ++ " " ++ a2 ++ ")"
  675. seqCmp _ o sbvs = error $ "SBV.SMT.SMTLib2.sh.seqCmp: Unexpected arguments: " ++ show (o, sbvs)
  676. lift1 o _ [x] = "(" ++ o ++ " " ++ x ++ ")"
  677. lift1 o _ sbvs = error $ "SBV.SMT.SMTLib2.sh.lift1: Unexpected arguments: " ++ show (o, sbvs)
  678. -- We fully qualify the constructor with their types to work around type checking issues
  679. -- Note that this is rather bizarre, as we're tagging the constructor with its *result* type,
  680. -- not its full function type as one would expect. But this is per the spec: Pg. 27 of SMTLib 2.6 spec
  681. -- says:
  682. --
  683. -- To simplify sort checking, a function symbol in a term can be annotated with one of its result sorts sigma.
  684. --
  685. -- I wish it was the full type here not just the result, but we go with the spec. Also see: <http://github.com/Z3Prover/z3/issues/2135>
  686. -- and in particular <http://github.com/Z3Prover/z3/issues/2135#issuecomment-477636435>
  687. dtConstructor fld args res = "((as " ++ fld ++ " " ++ smtType res ++ ") " ++ unwords (map ssv args) ++ ")"
  688. -- Similarly, we fully qualify the accessors with their types to work around type checking issues
  689. -- Unfortunately, z3 and CVC4 are behaving differently, so we tie this ascription to a solver capability.
  690. dtAccessor fld params res
  691. | supportsDirectAccessors caps = dResult
  692. | True = aResult
  693. where dResult = "(_ is " ++ fld ++ ")"
  694. ps = " (" ++ unwords (map smtType params) ++ ") "
  695. aResult = "(_ is (" ++ fld ++ ps ++ smtType res ++ "))"
  696. sh (SBVApp Ite [a, b, c]) = "(ite " ++ ssv a ++ " " ++ ssv b ++ " " ++ ssv c ++ ")"
  697. sh (SBVApp (LkUp (t, aKnd, _, l) i e) [])
  698. | needsCheck = "(ite " ++ cond ++ ssv e ++ " " ++ lkUp ++ ")"
  699. | True = lkUp
  700. where needsCheck = case aKnd of
  701. KBool -> (2::Integer) > fromIntegral l
  702. KBounded _ n -> (2::Integer)^n > fromIntegral l
  703. KUnbounded -> True
  704. KReal -> error "SBV.SMT.SMTLib2.cvtExp: unexpected real valued index"
  705. KFloat -> error "SBV.SMT.SMTLib2.cvtExp: unexpected float valued index"
  706. KDouble -> error "SBV.SMT.SMTLib2.cvtExp: unexpected double valued index"
  707. KFP{} -> error "SBV.SMT.SMTLib2.cvtExp: unexpected arbitrary float valued index"
  708. KRational{} -> error "SBV.SMT.SMTLib2.cvtExp: unexpected rational valued index"
  709. KChar -> error "SBV.SMT.SMTLib2.cvtExp: unexpected char valued index"
  710. KString -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
  711. KList k -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected list valued: " ++ show k
  712. KSet k -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected set valued: " ++ show k
  713. KTuple k -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected tuple valued: " ++ show k
  714. KMaybe k -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected maybe valued: " ++ show k
  715. KEither k1 k2 -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected sum valued: " ++ show (k1, k2)
  716. KUserSort s _ -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected uninterpreted valued index: " ++ s
  717. lkUp = "(" ++ getTable tableMap t ++ " " ++ ssv i ++ ")"
  718. cond
  719. | hasSign i = "(or " ++ le0 ++ " " ++ gtl ++ ") "
  720. | True = gtl ++ " "
  721. (less, leq) = case aKnd of
  722. KBool -> error "SBV.SMT.SMTLib2.cvtExp: unexpected boolean valued index"
  723. KBounded{} -> if hasSign i then ("bvslt", "bvsle") else ("bvult", "bvule")
  724. KUnbounded -> ("<", "<=")
  725. KReal -> ("<", "<=")
  726. KFloat -> ("fp.lt", "fp.leq")
  727. KDouble -> ("fp.lt", "fp.leq")
  728. KRational -> ("sbv.rat.lt", "sbv.rat.leq")
  729. KFP{} -> ("fp.lt", "fp.leq")
  730. KChar -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
  731. KString -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
  732. KList k -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected sequence valued index: " ++ show k
  733. KSet k -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected set valued index: " ++ show k
  734. KTuple k -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected tuple valued index: " ++ show k
  735. KMaybe k -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected maybe valued index: " ++ show k
  736. KEither k1 k2 -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected sum valued index: " ++ show (k1, k2)
  737. KUserSort s _ -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected uninterpreted valued index: " ++ s
  738. mkCnst = cvtCV rm . mkConstCV (kindOf i)
  739. le0 = "(" ++ less ++ " " ++ ssv i ++ " " ++ mkCnst 0 ++ ")"
  740. gtl = "(" ++ leq ++ " " ++ mkCnst l ++ " " ++ ssv i ++ ")"
  741. sh (SBVApp (KindCast f t) [a]) = handleKindCast hasInt2bv f t (ssv a)
  742. sh (SBVApp (ArrEq i j) []) = "(= array_" ++ show i ++ " array_" ++ show j ++")"
  743. sh (SBVApp (ArrRead i) [a]) = "(select array_" ++ show i ++ " " ++ ssv a ++ ")"
  744. sh (SBVApp (Uninterpreted nm) []) = nm
  745. sh (SBVApp (Uninterpreted nm) args) = "(" ++ nm ++ " " ++ unwords (map ssv args) ++ ")"
  746. sh (SBVApp (Extract i j) [a]) | ensureBV = "((_ extract " ++ show i ++ " " ++ show j ++ ") " ++ ssv a ++ ")"
  747. sh (SBVApp (Rol i) [a])
  748. | bvOp = rot ssv "rotate_left" i a
  749. | True = bad
  750. sh (SBVApp (Ror i) [a])
  751. | bvOp = rot ssv "rotate_right" i a
  752. | True = bad
  753. sh (SBVApp Shl [a, i])
  754. | bvOp = shft ssv "bvshl" "bvshl" a i
  755. | True = bad
  756. sh (SBVApp Shr [a, i])
  757. | bvOp = shft ssv "bvlshr" "bvashr" a i
  758. | True = bad
  759. sh (SBVApp op args)
  760. | Just f <- lookup op smtBVOpTable, ensureBVOrBool
  761. = f (any hasSign args) (map ssv args)
  762. where -- The first 4 operators below do make sense for Integer's in Haskell, but there's
  763. -- no obvious counterpart for them in the SMTLib translation.
  764. -- TODO: provide support for these.
  765. smtBVOpTable = [ (And, lift2B "and" "bvand")
  766. , (Or, lift2B "or" "bvor")
  767. , (XOr, lift2B "xor" "bvxor")
  768. , (Not, lift1B "not" "bvnot")
  769. , (Join, lift2 "concat")
  770. ]
  771. sh (SBVApp (Label _) [a]) = cvtSV skolemMap a -- This won't be reached; but just in case!
  772. sh (SBVApp (IEEEFP (FP_Cast kFrom kTo m)) args) = handleFPCast kFrom kTo (ssv m) (unwords (map ssv args))
  773. sh (SBVApp (IEEEFP w ) args) = "(" ++ show w ++ " " ++ unwords (map ssv args) ++ ")"
  774. sh (SBVApp (NonLinear w) args) = "(" ++ show w ++ " " ++ unwords (map ssv args) ++ ")"
  775. sh (SBVApp (PseudoBoolean pb) args)
  776. | hasPB = handlePB pb args'
  777. | True = reducePB pb args'
  778. where args' = map ssv args
  779. -- NB: Z3 semantics have the predicates reversed: i.e., it returns true if overflow isn't possible. Hence the not.
  780. sh (SBVApp (OverflowOp op) args) = "(not (" ++ show op ++ " " ++ unwords (map ssv args) ++ "))"
  781. -- Note the unfortunate reversal in StrInRe..
  782. sh (SBVApp (StrOp (StrInRe r)) args) = "(str.in.re " ++ unwords (map ssv args) ++ " " ++ regExpToSMTString r ++ ")"
  783. -- StrUnit is no-op, since a character in SMTLib is the same as a string
  784. sh (SBVApp (StrOp StrUnit) [a]) = ssv a
  785. sh (SBVApp (StrOp op) args) = "(" ++ show op ++ " " ++ unwords (map ssv args) ++ ")"
  786. sh (SBVApp (SeqOp op) args) = "(" ++ show op ++ " " ++ unwords (map ssv args) ++ ")"
  787. sh (SBVApp (SetOp SetEqual) args) = "(= " ++ unwords (map ssv args) ++ ")"
  788. sh (SBVApp (SetOp SetMember) [e, s]) = "(select " ++ ssv s ++ " " ++ ssv e ++ ")"
  789. sh (SBVApp (SetOp SetInsert) [e, s]) = "(store " ++ ssv s ++ " " ++ ssv e ++ " true)"
  790. sh (SBVApp (SetOp SetDelete) [e, s]) = "(store " ++ ssv s ++ " " ++ ssv e ++ " false)"
  791. sh (SBVApp (SetOp SetIntersect) args) = "(intersection " ++ unwords (map ssv args) ++ ")"
  792. sh (SBVApp (SetOp SetUnion) args) = "(union " ++ unwords (map ssv args) ++ ")"
  793. sh (SBVApp (SetOp SetSubset) args) = "(subset " ++ unwords (map ssv args) ++ ")"
  794. sh (SBVApp (SetOp SetDifference) args) = "(setminus " ++ unwords (map ssv args) ++ ")"
  795. sh (SBVApp (SetOp SetComplement) args) = "(complement " ++ unwords (map ssv args) ++ ")"
  796. sh (SBVApp (SetOp SetHasSize) args) = "(set-has-size " ++ unwords (map ssv args) ++ ")"
  797. sh (SBVApp (TupleConstructor 0) []) = "mkSBVTuple0"
  798. sh (SBVApp (TupleConstructor n) args) = "((as mkSBVTuple" ++ show n ++ " " ++ smtType (KTuple (map kindOf args)) ++ ") " ++ unwords (map ssv args) ++ ")"
  799. sh (SBVApp (TupleAccess i n) [tup]) = "(proj_" ++ show i ++ "_SBVTuple" ++ show n ++ " " ++ ssv tup ++ ")"
  800. sh (SBVApp (EitherConstructor k1 k2 False) [arg]) = dtConstructor "left_SBVEither" [arg] (KEither k1 k2)
  801. sh (SBVApp (EitherConstructor k1 k2 True ) [arg]) = dtConstructor "right_SBVEither" [arg] (KEither k1 k2)
  802. sh (SBVApp (EitherIs k1 k2 False) [arg]) = '(' : dtAccessor "left_SBVEither" [k1] (KEither k1 k2) ++ " " ++ ssv arg ++ ")"
  803. sh (SBVApp (EitherIs k1 k2 True ) [arg]) = '(' : dtAccessor "right_SBVEither" [k2] (KEither k1 k2) ++ " " ++ ssv arg ++ ")"
  804. sh (SBVApp (EitherAccess False) [arg]) = "(get_left_SBVEither " ++ ssv arg ++ ")"
  805. sh (SBVApp (EitherAccess True ) [arg]) = "(get_right_SBVEither " ++ ssv arg ++ ")"
  806. sh (SBVApp RationalConstructor [t, b]) = "(SBV.Rational " ++ ssv t ++ " " ++ ssv b ++ ")"
  807. sh (SBVApp (MaybeConstructor k False) []) = dtConstructor "nothing_SBVMaybe" [] (KMaybe k)
  808. sh (SBVApp (MaybeConstructor k True) [arg]) = dtConstructor "just_SBVMaybe" [arg] (KMaybe k)
  809. sh (SBVApp (MaybeIs k False) [arg]) = '(' : dtAccessor "nothing_SBVMaybe" [] (KMaybe k) ++ " " ++ ssv arg ++ ")"
  810. sh (SBVApp (MaybeIs k True ) [arg]) = '(' : dtAccessor "just_SBVMaybe" [k] (KMaybe k) ++ " " ++ ssv arg ++ ")"
  811. sh (SBVApp MaybeAccess [arg]) = "(get_just_SBVMaybe " ++ ssv arg ++ ")"
  812. sh inp@(SBVApp op args)
  813. | intOp,

Large files files are truncated, but you can click here to view the full file