--- ----------------------------------------------------------------------------
--- This module provides some goodies and utility functions for SMT-LIB.
---
--- @author Jan Tikovsky
--- @version January 2018
--- ----------------------------------------------------------------------------
module Language.SMTLIB.Goodies where
import Language.SMTLIB.Types
infixl 7 *%
infixl 6 +%, -%
infix 4 =%, /=%, <%, >%, <=%, >=%
--- Declare a list of variables
declVars :: [(Symbol, Sort)] -> [Command]
declVars = map (uncurry DeclareConst)
--------------------------------------------------------------------------------
-- Smart constructors for SMT terms
--------------------------------------------------------------------------------
--- Construct SMT-LIB term from given integer
tint :: Int -> Term
tint = TConst . Num
--- Construct SMT-LIB term from given float
tfloat :: Float -> Term
tfloat = TConst . Dec
--- Construct SMT-LIB term from given character
tchar :: Char -> Term
tchar = TConst . Str . (: [])
--- Construct SMT-LIB term from given variable index
tvar :: Int -> Term
tvar vi = tcomb (var2SMT vi) []
--- Construct SMT-LIB term from a string
var :: String -> Term
var str = tcomb str []
--- Construct SMT-LIB constructor term
tcomb :: Ident -> [Term] -> Term
tcomb i ts = TComb (Id i) ts
--- Construct qualified SMT-LIB constructor term
qtcomb :: QIdent -> [Term] -> Term
qtcomb qi ts = TComb qi ts
--- Construct universally quantified SMT-LIB term
forAll :: [Int] -> [Sort] -> Term -> Term
forAll vs ss t = case vs of
[] -> t
_ -> Forall (zipWith SV (map var2SMT vs) ss) t
--- Negate given numeral SMT-LIB term
tneg :: Term -> Term
tneg t = tcomb "-" [t]
--- Absolute value of an SMT-LIB term
tabs :: Term -> Term
tabs t = tcomb "abs" [t]
--- Add two SMT-LIB terms
(+%) :: Term -> Term -> Term
t1 +% t2 = tcomb "+" [t1, t2]
--- Subtract an SMT-LIB term from another one
(-%) :: Term -> Term -> Term
t1 -% t2 = tcomb "-" [t1, t2]
--- Multiply two SMT-LIB terms
(*%) :: Term -> Term -> Term
t1 *% t2 = tcomb "*" [t1, t2]
--- Divide an SMT-LIB term by another one
(/%) :: Term -> Term -> Term
t1 /% t2 = tcomb "/" [t1, t2]
--- SMT-LIB term `true`
true :: Term
true = qtcomb (As "true" boolSort) []
--- SMT-LIB term `false`
false :: Term
false = qtcomb (As "false" boolSort) []
--- Constrain two SMT-LIB terms to be equal
(=%) :: Term -> Term -> Term
t1 =% t2 = tcomb "=" [t1, t2]
--- Constrain two SMT-LIB terms to be different
(/=%) :: Term -> Term -> Term
t1 /=% t2 = tcomb "not" [tcomb "=" [t1, t2]]
--- Constrain two SMT-LIB terms with a less-than-relation
(<%) :: Term -> Term -> Term
t1 <% t2 = tcomb "<" [t1, t2]
--- Constrain two SMT-LIB terms with a less-than-or-equal-relation
(<=%) :: Term -> Term -> Term
t1 <=% t2 = tcomb "<=" [t1, t2]
--- Constrain two SMT-LIB terms with a greater-than-relation
(>%) :: Term -> Term -> Term
t1 >% t2 = tcomb ">" [t1, t2]
--- Constrain two SMT-LIB terms with a greater-than-or-equal-relation
(>=%) :: Term -> Term -> Term
t1 >=% t2 = tcomb ">=" [t1, t2]
--- Combine a list of SMT-LIB terms using a conjunction
tand :: [Term] -> Term
tand = tcomb "and"
--- Combine a list of SMT-LIB terms using a disjunction
tor :: [Term] -> Term
tor = tcomb "or"
--- Logical implication
(==>) :: Term -> Term -> Term
t1 ==> t2 = tcomb "=>" [t1, t2]
--- Logical negation of an SMT-LIB term
tnot :: Term -> Term
tnot t = tcomb "not" [t]
instance Num Term where
t1 + t2 = t1 +% t2
t1 - t2 = t1 -% t2
t1 * t2 = t1 *% t2
negate = tneg
abs = tabs
fromInt = tint
instance Fractional Term where
t1 / t2 = t1 /% t2
fromFloat = tfloat
--------------------------------------------------------------------------------
-- Smart constructors for SMT sorts
--------------------------------------------------------------------------------
--- Construct an SMT-LIB sort
scomb :: Ident -> [Sort] -> Sort
scomb i ss = SComb i ss
--- Representation of 'Ordering' type as SMT-LIB sort
orderingSort :: Sort
orderingSort = scomb "Ordering" []
--- Representation of 'Bool' type as SMT-LIB sort
boolSort :: Sort
boolSort = scomb "Bool" []
--- Representation of 'Int' type as SMT-LIB sort
intSort :: Sort
intSort = scomb "Int" []
--- Representation of 'Float' type as SMT-LIB sort
floatSort :: Sort
floatSort = scomb "Real" []
--- Representation of '->' type constructor as SMT-LIB sort constructor
funSC :: [Sort] -> Sort
funSC = scomb "Fun"
--- Generate a `nop` SMT-LIB command
nop :: Command
nop = echo ""
--- Generate an `assert` SMT-LIB command
assert :: [Term] -> Command
assert ts = case ts of
[] -> nop
[t] -> Assert t
_ -> Assert $ tand ts
--- Get the unqualified identifier of a qualified SMT-LIB identifier
unqual :: QIdent -> Ident
unqual (Id i) = i
unqual (As i _) = i
--- Is given SMT-LIB command a declaration of an algebraic data type
isDeclData :: Command -> Bool
isDeclData cmd = case cmd of
DeclareDatatype _ _ -> True
DeclareDatatypes _ -> True
_ -> False
--- Is given SMT-LIB command an 'Echo'
isEcho :: Command -> Bool
isEcho cmd = case cmd of
Echo _ -> True
_ -> False
--- Smart constructor for the 'Echo' SMT-LIB command
--- marking every 'Echo' command with an initial '@' character
--- which is necessary to recognize 'Echo's during parsing
echo :: String -> Command
echo str = Echo ('@' : str)
--- Smart constructor to generate a comment in an SMT-LIB script
comment :: String -> Command
comment = Comment
--- Transform a FlatCurry variable index into an SMT-LIB symbol
var2SMT :: Int -> Symbol
var2SMT vi = 'x' : show (abs vi)