module Language.SMTLib2.Internals.Expression where
import Language.SMTLib2.Internals.Type hiding (Field)
import qualified Language.SMTLib2.Internals.Type as Type
import Language.SMTLib2.Internals.Type.Nat
import Language.SMTLib2.Internals.Type.List (List(..))
import qualified Language.SMTLib2.Internals.Type.List as List
import Data.Typeable
import Text.Show
import Data.GADT.Compare
import Data.GADT.Show
import Data.Functor.Identity
import Data.Ratio
import qualified GHC.TypeLits as TL
type family AllEq (tp :: Type) (n :: Nat) :: [Type] where
AllEq tp Z = '[]
AllEq tp (S n) = tp ': (AllEq tp n)
allEqToList :: Natural n -> List a (AllEq tp n) -> [a tp]
allEqToList Zero Nil = []
allEqToList (Succ n) (x ::: xs) = x:allEqToList n xs
allEqFromList :: [a tp] -> (forall n. Natural n -> List a (AllEq tp n) -> r) -> r
allEqFromList [] f = f Zero Nil
allEqFromList (x:xs) f = allEqFromList xs (\n arg -> f (Succ n) (x ::: arg))
allEqOf :: Repr tp -> Natural n -> List Repr (AllEq tp n)
allEqOf tp Zero = Nil
allEqOf tp (Succ n) = tp ::: allEqOf tp n
mapAllEq :: Monad m => (e1 tp -> m (e2 tp))
-> Natural n
-> List e1 (AllEq tp n)
-> m (List e2 (AllEq tp n))
mapAllEq f Zero Nil = return Nil
mapAllEq f (Succ n) (x ::: xs) = do
x' <- f x
xs' <- mapAllEq f n xs
return (x' ::: xs')
data Function (fun :: ([Type],Type) -> *) (sig :: ([Type],Type)) where
Fun :: fun '(arg,res) -> Function fun '(arg,res)
Eq :: Repr tp -> Natural n -> Function fun '(AllEq tp n,BoolType)
Distinct :: Repr tp -> Natural n -> Function fun '(AllEq tp n,BoolType)
Map :: List Repr idx -> Function fun '(arg,res)
-> Function fun '(Lifted arg idx,ArrayType idx res)
Ord :: NumRepr tp -> OrdOp -> Function fun '([tp,tp],BoolType)
Arith :: NumRepr tp -> ArithOp -> Natural n
-> Function fun '(AllEq tp n,tp)
ArithIntBin :: ArithOpInt -> Function fun '([IntType,IntType],IntType)
Divide :: Function fun '([RealType,RealType],RealType)
Abs :: NumRepr tp -> Function fun '( '[tp],tp)
Not :: Function fun '( '[BoolType],BoolType)
Logic :: LogicOp -> Natural n -> Function fun '(AllEq BoolType n,BoolType)
ToReal :: Function fun '( '[IntType],RealType)
ToInt :: Function fun '( '[RealType],IntType)
ITE :: Repr a -> Function fun '([BoolType,a,a],a)
BVComp :: BVCompOp -> BitWidth a -> Function fun '([BitVecType a,BitVecType a],BoolType)
BVBin :: BVBinOp -> BitWidth a -> Function fun '([BitVecType a,BitVecType a],BitVecType a)
BVUn :: BVUnOp -> BitWidth a -> Function fun '( '[BitVecType a],BitVecType a)
Select :: List Repr idx -> Repr val -> Function fun '(ArrayType idx val ': idx,val)
Store :: List Repr idx -> Repr val -> Function fun '(ArrayType idx val ': val ': idx,ArrayType idx val)
ConstArray :: List Repr idx -> Repr val -> Function fun '( '[val],ArrayType idx val)
Concat :: BitWidth n1 -> BitWidth n2 -> Function fun '([BitVecType n1,BitVecType n2],BitVecType (n1 TL.+ n2))
Extract :: BitWidth bw -> BitWidth start -> BitWidth len -> Function fun '( '[BitVecType bw],BitVecType len)
Constructor :: (IsDatatype dt,List.Length par ~ Parameters dt)
=> Datatype dt
-> List Repr par
-> Constr dt sig
-> Function fun '(Instantiated sig par,DataType dt par)
Test :: (IsDatatype dt,List.Length par ~ Parameters dt)
=> Datatype dt
-> List Repr par
-> Constr dt sig
-> Function fun '( '[DataType dt par],BoolType)
Field :: (IsDatatype dt,List.Length par ~ Parameters dt)
=> Datatype dt
-> List Repr par
-> Type.Field dt t
-> Function fun '( '[DataType dt par],CType t par)
Divisible :: Integer -> Function fun '( '[IntType],BoolType)
data AnyFunction (fun :: ([Type],Type) -> *) where
AnyFunction :: Function fun '(arg,t) -> AnyFunction fun
data OrdOp = Ge | Gt | Le | Lt deriving (Eq,Ord,Show)
data ArithOp = Plus | Mult | Minus deriving (Eq,Ord,Show)
data ArithOpInt = Div | Mod | Rem deriving (Eq,Ord,Show)
data LogicOp = And | Or | XOr | Implies deriving (Eq,Ord,Show)
data BVCompOp = BVULE
| BVULT
| BVUGE
| BVUGT
| BVSLE
| BVSLT
| BVSGE
| BVSGT
deriving (Eq,Ord,Show)
data BVBinOp = BVAdd
| BVSub
| BVMul
| BVURem
| BVSRem
| BVUDiv
| BVSDiv
| BVSHL
| BVLSHR
| BVASHR
| BVXor
| BVAnd
| BVOr
deriving (Eq,Ord,Show)
data BVUnOp = BVNot | BVNeg deriving (Eq,Ord,Show)
data LetBinding (v :: Type -> *) (e :: Type -> *) (t :: Type)
= LetBinding { letVar :: v t
, letExpr :: e t }
data Quantifier = Forall | Exists deriving (Typeable,Eq,Ord,Show)
data Expression (v :: Type -> *) (qv :: Type -> *) (fun :: ([Type],Type) -> *) (fv :: Type -> *) (lv :: Type -> *) (e :: Type -> *) (res :: Type) where
#if __GLASGOW_HASKELL__>=712
#endif
Var :: v res -> Expression v qv fun fv lv e res
#if __GLASGOW_HASKELL__>=712
#endif
QVar :: qv res -> Expression v qv fun fv lv e res
#if __GLASGOW_HASKELL__>=712
#endif
FVar :: fv res -> Expression v qv fun fv lv e res
#if __GLASGOW_HASKELL__>=712
#endif
LVar :: lv res -> Expression v qv fun fv lv e res
#if __GLASGOW_HASKELL__>=712
#endif
App :: Function fun '(arg,res)
-> List e arg
-> Expression v qv fun fv lv e res
#if __GLASGOW_HASKELL__>=712
#endif
Const :: Value a -> Expression v qv fun fv lv e a
#if __GLASGOW_HASKELL__>=712
#endif
AsArray :: Function fun '(arg,res)
-> Expression v qv fun fv lv e (ArrayType arg res)
#if __GLASGOW_HASKELL__>=712
#endif
Quantification :: Quantifier -> List qv arg -> e BoolType
-> Expression v qv fun fv lv e BoolType
#if __GLASGOW_HASKELL__>=712
#endif
Let :: List (LetBinding lv e) arg
-> e res
-> Expression v qv fun fv lv e res
instance GEq fun => Eq (Function fun sig) where
(==) = defaultEq
class SMTOrd (t :: Type) where
lt :: Function fun '( '[t,t],BoolType)
le :: Function fun '( '[t,t],BoolType)
gt :: Function fun '( '[t,t],BoolType)
ge :: Function fun '( '[t,t],BoolType)
instance SMTOrd IntType where
lt = Ord NumInt Lt
le = Ord NumInt Le
gt = Ord NumInt Gt
ge = Ord NumInt Ge
instance SMTOrd RealType where
lt = Ord NumReal Lt
le = Ord NumReal Le
gt = Ord NumReal Gt
ge = Ord NumReal Ge
class SMTArith t where
arithFromInteger :: Integer -> Value t
arith :: ArithOp -> Natural n -> Function fun '(AllEq t n,t)
plus :: Natural n -> Function fun '(AllEq t n,t)
minus :: Natural n -> Function fun '(AllEq t n,t)
mult :: Natural n -> Function fun '(AllEq t n,t)
abs' :: Function fun '( '[t],t)
instance SMTArith IntType where
arithFromInteger n = IntValue n
arith = Arith NumInt
plus = Arith NumInt Plus
minus = Arith NumInt Minus
mult = Arith NumInt Mult
abs' = Abs NumInt
instance SMTArith RealType where
arithFromInteger n = RealValue (fromInteger n)
arith = Arith NumReal
plus = Arith NumReal Plus
minus = Arith NumReal Minus
mult = Arith NumReal Mult
abs' = Abs NumReal
functionType :: Monad m
=> (forall arg t. fun '(arg,t) -> m (List Repr arg,Repr t))
-> Function fun '(arg,res)
-> m (List Repr arg,Repr res)
functionType f (Fun fun) = f fun
functionType _ (Eq tp n) = return (allEqOf tp n,BoolRepr)
functionType _ (Distinct tp n) = return (allEqOf tp n,BoolRepr)
functionType f (Map idx fun) = do
(arg,res) <- functionType f fun
return (liftType arg idx,ArrayRepr idx res)
functionType _ (Ord tp _) = return (numRepr tp ::: numRepr tp ::: Nil,BoolRepr)
functionType _ (Arith tp _ n) = return (allEqOf (numRepr tp) n,numRepr tp)
functionType _ (ArithIntBin _) = return (IntRepr ::: IntRepr ::: Nil,IntRepr)
functionType _ Divide = return (RealRepr ::: RealRepr ::: Nil,RealRepr)
functionType _ (Abs tp) = return (numRepr tp ::: Nil,numRepr tp)
functionType _ Not = return (BoolRepr ::: Nil,BoolRepr)
functionType _ (Logic op n) = return (allEqOf BoolRepr n,BoolRepr)
functionType _ ToReal = return (IntRepr ::: Nil,RealRepr)
functionType _ ToInt = return (RealRepr ::: Nil,IntRepr)
functionType _ (ITE tp) = return (BoolRepr ::: tp ::: tp ::: Nil,tp)
functionType _ (BVComp _ n) = return (BitVecRepr n ::: BitVecRepr n ::: Nil,BoolRepr)
functionType _ (BVBin _ n) = return (BitVecRepr n ::: BitVecRepr n ::: Nil,BitVecRepr n)
functionType _ (BVUn _ n) = return (BitVecRepr n ::: Nil,BitVecRepr n)
functionType _ (Select idx el) = return (ArrayRepr idx el ::: idx,el)
functionType _ (Store idx el) = return (ArrayRepr idx el ::: el ::: idx,ArrayRepr idx el)
functionType _ (ConstArray idx el) = return (el ::: Nil,ArrayRepr idx el)
functionType _ (Concat bw1 bw2) = return (BitVecRepr bw1 ::: BitVecRepr bw2 ::: Nil,
BitVecRepr (bwAdd bw1 bw2))
functionType _ (Extract bw start len) = return (BitVecRepr bw ::: Nil,BitVecRepr len)
functionType _ (Constructor dt par con) = case instantiate (constrSig con) par of
(res,Refl) -> return (res,DataRepr dt par)
functionType _ (Test dt par con) = return (DataRepr dt par ::: Nil,BoolRepr)
functionType _ (Field dt par field)
= return (DataRepr dt par ::: Nil,ctype (fieldType field) par)
functionType _ (Divisible _) = return (IntRepr ::: Nil,BoolRepr)
expressionType :: (Monad m,Functor m)
=> (forall t. v t -> m (Repr t))
-> (forall t. qv t -> m (Repr t))
-> (forall arg t. fun '(arg,t) -> m (List Repr arg,Repr t))
-> (forall t. fv t -> m (Repr t))
-> (forall t. lv t -> m (Repr t))
-> (forall t. e t -> m (Repr t))
-> Expression v qv fun fv lv e res
-> m (Repr res)
expressionType f _ _ _ _ _ (Var v) = f v
expressionType _ f _ _ _ _ (QVar v) = f v
expressionType _ _ _ f _ _ (FVar v) = f v
expressionType _ _ _ _ f _ (LVar v) = f v
expressionType _ _ f _ _ _ (App fun arg) = fmap snd $ functionType f fun
expressionType _ _ _ _ _ _ (Const v) = return $ valueType v
expressionType _ _ f _ _ _ (AsArray fun) = do
(arg,res) <- functionType f fun
return $ ArrayRepr arg res
expressionType _ _ _ _ _ _ (Quantification _ _ _) = return BoolRepr
expressionType _ _ _ _ _ f (Let _ body) = f body
mapExpr :: (Functor m,Monad m)
=> (forall t. v1 t -> m (v2 t))
-> (forall t. qv1 t -> m (qv2 t))
-> (forall arg t. fun1 '(arg,t) -> m (fun2 '(arg,t)))
-> (forall t. fv1 t -> m (fv2 t))
-> (forall t. lv1 t -> m (lv2 t))
-> (forall t. e1 t -> m (e2 t))
-> Expression v1 qv1 fun1 fv1 lv1 e1 r
-> m (Expression v2 qv2 fun2 fv2 lv2 e2 r)
mapExpr f _ _ _ _ _ (Var v) = fmap Var (f v)
mapExpr _ f _ _ _ _ (QVar v) = fmap QVar (f v)
mapExpr _ _ _ f _ _ (FVar v) = fmap FVar (f v)
mapExpr _ _ _ _ f _ (LVar v) = fmap LVar (f v)
mapExpr _ _ f _ _ i (App fun args) = do
fun' <- mapFunction f fun
args' <- List.mapM i args
return (App fun' args')
mapExpr _ _ _ _ _ _ (Const val) = return (Const val)
mapExpr _ _ f _ _ _ (AsArray fun) = fmap AsArray (mapFunction f fun)
mapExpr _ f _ _ _ g (Quantification q args body) = do
args' <- List.mapM f args
body' <- g body
return (Quantification q args' body')
mapExpr _ _ _ _ f g (Let args body) = do
args' <- List.mapM (\bind -> do
nv <- f (letVar bind)
nexpr <- g (letExpr bind)
return $ LetBinding nv nexpr
) args
body' <- g body
return (Let args' body')
mapFunction :: (Functor m,Monad m)
=> (forall arg t. fun1 '(arg,t) -> m (fun2 '(arg,t)))
-> Function fun1 '(arg,res)
-> m (Function fun2 '(arg,res))
mapFunction f (Fun x) = fmap Fun (f x)
mapFunction _ (Eq tp n) = return (Eq tp n)
mapFunction _ (Distinct tp n) = return (Distinct tp n)
mapFunction f (Map idx x) = do
x' <- mapFunction f x
return (Map idx x')
mapFunction _ (Ord tp op) = return (Ord tp op)
mapFunction _ (Arith tp op n) = return (Arith tp op n)
mapFunction _ (ArithIntBin op) = return (ArithIntBin op)
mapFunction _ Divide = return Divide
mapFunction _ (Abs tp) = return (Abs tp)
mapFunction _ Not = return Not
mapFunction _ (Logic op n) = return (Logic op n)
mapFunction _ ToReal = return ToReal
mapFunction _ ToInt = return ToInt
mapFunction _ (ITE tp) = return (ITE tp)
mapFunction _ (BVComp op bw) = return (BVComp op bw)
mapFunction _ (BVBin op bw) = return (BVBin op bw)
mapFunction _ (BVUn op bw) = return (BVUn op bw)
mapFunction _ (Select idx el) = return (Select idx el)
mapFunction _ (Store idx el) = return (Store idx el)
mapFunction _ (ConstArray idx el) = return (ConstArray idx el)
mapFunction _ (Concat bw1 bw2) = return (Concat bw1 bw2)
mapFunction _ (Extract bw start len) = return (Extract bw start len)
mapFunction _ (Constructor dt par con) = return (Constructor dt par con)
mapFunction _ (Test dt par con) = return (Test dt par con)
mapFunction _ (Field dt par x) = return (Field dt par x)
mapFunction _ (Divisible x) = return (Divisible x)
instance (GShow v,GShow qv,GShow fun,GShow fv,GShow lv,GShow e)
=> Show (Expression v qv fun fv lv e r) where
showsPrec p (Var v) = showParen (p>10) $
showString "Var " .
gshowsPrec 11 v
showsPrec p (QVar v) = showParen (p>10) $
showString "QVar " .
gshowsPrec 11 v
showsPrec p (FVar v) = showParen (p>10) $
showString "FVar " .
gshowsPrec 11 v
showsPrec p (LVar v) = showParen (p>10) $
showString "LVar " .
gshowsPrec 11 v
showsPrec p (App fun args)
= showParen (p>10) $
showString "App " .
showsPrec 11 fun .
showChar ' ' .
showsPrec 11 args
showsPrec p (Const val) = showsPrec p val
showsPrec p (AsArray fun)
= showParen (p>10) $
showString "AsArray " .
showsPrec 11 fun
showsPrec p (Quantification q args body)
= showParen (p>10) $
showsPrec 11 q .
showChar ' ' .
showsPrec 11 args .
showChar ' ' .
gshowsPrec 11 body
showsPrec p (Let args body)
= showParen (p>10) $
showString "Let " .
showListWith id (runIdentity $ List.toList
(\(LetBinding v e)
-> return $ (gshowsPrec 10 v) . showChar '=' . (gshowsPrec 10 e)
) args) .
showChar ' ' .
gshowsPrec 10 body
instance (GShow v,GShow qv,GShow fun,GShow fv,GShow lv,GShow e)
=> GShow (Expression v qv fun fv lv e) where
gshowsPrec = showsPrec
instance (GShow fun)
=> Show (Function fun sig) where
showsPrec p (Fun x) = gshowsPrec p x
showsPrec _ (Eq _ _) = showString "Eq"
showsPrec _ (Distinct _ _) = showString "Distinct"
showsPrec p (Map _ x) = showParen (p>10) $
showString "Map " .
showsPrec 11 x
showsPrec p (Ord tp op) = showParen (p>10) $
showString "Ord " .
showsPrec 11 tp .
showChar ' ' .
showsPrec 11 op
showsPrec p (Arith tp op _) = showParen (p>10) $
showString "Arith " .
showsPrec 11 tp .
showChar ' ' .
showsPrec 11 op
showsPrec p (ArithIntBin op) = showParen (p>10) $
showString "ArithIntBin " .
showsPrec 11 op
showsPrec p Divide = showString "Divide"
showsPrec p (Abs tp) = showParen (p>10) $
showString "Abs " .
showsPrec 11 tp
showsPrec _ Not = showString "Not"
showsPrec p (Logic op _) = showParen (p>10) $
showString "Logic " .
showsPrec 11 op
showsPrec _ ToReal = showString "ToReal"
showsPrec _ ToInt = showString "ToInt"
showsPrec _ (ITE _) = showString "ITE"
showsPrec p (BVComp op _) = showParen (p>10) $
showString "BVComp " .
showsPrec 11 op
showsPrec p (BVBin op _) = showParen (p>10) $
showString "BVBin " .
showsPrec 11 op
showsPrec p (BVUn op _) = showParen (p>10) $
showString "BVUn " .
showsPrec 11 op
showsPrec _ (Select _ _) = showString "Select"
showsPrec _ (Store _ _) = showString "Store"
showsPrec _ (ConstArray _ _) = showString "ConstArray"
showsPrec _ (Concat _ _) = showString "Concat"
showsPrec p (Extract bw start len)
= showParen (p>10) $
showString "Extract " .
showsPrec 11 bw .
showChar ' ' .
showsPrec 11 start .
showChar ' ' .
showsPrec 11 len
showsPrec p (Constructor _ _ con) = showParen (p>10) $
showString "Constructor " .
showString (constrName con)
showsPrec p (Test _ _ con) = showParen (p>10) $
showString "Test " .
showString (constrName con)
showsPrec p (Field _ _ x) = showParen (p>10) $
showString "Field " .
showString (fieldName x)
showsPrec p (Divisible x) = showParen (p>10) $
showString "Divisible " .
showsPrec 11 x
data RenderMode = SMTRendering deriving (Eq,Ord,Show)
renderExprDefault :: (GetType qv,GShow v,GShow qv,GShow fun,GShow fv,GShow lv,GShow e)
=> RenderMode
-> Expression v qv fun fv lv e tp
-> ShowS
renderExprDefault m
= renderExpr m (gshowsPrec 11) (gshowsPrec 11) (gshowsPrec 11)
(gshowsPrec 11) (gshowsPrec 11) (gshowsPrec 11)
renderExpr :: (GetType qv) => RenderMode
-> (forall tp. v tp -> ShowS)
-> (forall tp. qv tp -> ShowS)
-> (forall arg res. fun '(arg,res) -> ShowS)
-> (forall tp. fv tp -> ShowS)
-> (forall tp. lv tp -> ShowS)
-> (forall tp. e tp -> ShowS)
-> Expression v qv fun fv lv e tp
-> ShowS
renderExpr _ f _ _ _ _ _ (Var x) = f x
renderExpr _ _ f _ _ _ _ (QVar x) = f x
renderExpr _ _ _ _ f _ _ (FVar x) = f x
renderExpr _ _ _ _ _ f _ (LVar x) = f x
renderExpr SMTRendering _ _ f _ _ i (App fun args)
= showChar '(' .
renderFunction SMTRendering f fun .
renderArgs i args .
showChar ')'
where
renderArgs :: (forall tp. e tp -> ShowS) -> List e tps -> ShowS
renderArgs f Nil = id
renderArgs f (x ::: xs) = showChar ' ' . f x . renderArgs f xs
renderExpr m _ _ _ _ _ _ (Const val) = renderValue m val
renderExpr SMTRendering _ _ f _ _ _ (AsArray fun)
= showString "(_ as-array " .
renderFunction SMTRendering f fun .
showChar ')'
renderExpr SMTRendering _ f _ _ _ g (Quantification q args body)
= showChar '(' .
showString (case q of
Forall -> "forall"
Exists -> "exists") .
showString " (" . renderArgs f args . showString ") " . g body . showChar ')'
where
renderArgs :: GetType qv => (forall tp. qv tp -> ShowS)
-> List qv tps -> ShowS
renderArgs _ Nil = id
renderArgs f (x ::: xs) = showChar '(' .
f x . showChar ' ' .
renderType SMTRendering (getType x) .
showChar ')' .
(case xs of
Nil -> id
_ -> showChar ' ' . renderArgs f xs)
renderExpr SMTRendering _ _ _ _ f g (Let args body)
= showString "(let (" . renderArgs f g args . showString ") " . g body . showChar ')'
where
renderArgs :: (forall tp. lv tp -> ShowS) -> (forall tp. e tp -> ShowS)
-> List (LetBinding lv e) args
-> ShowS
renderArgs _ _ Nil = id
renderArgs f g (x ::: xs)
= showChar '(' .
f (letVar x) . showChar ' ' .
g (letExpr x) . showChar ')' .
(case xs of
Nil -> id
_ -> showChar ' ' . renderArgs f g xs)
renderValue :: RenderMode -> Value tp -> ShowS
renderValue SMTRendering (BoolValue v) = if v then showString "true" else showString "false"
renderValue SMTRendering (IntValue v)
= if v>=0 then showsPrec 0 v
else showString "(- " .
showsPrec 0 (negate v) .
showChar ')'
renderValue SMTRendering (RealValue v)
= showString "(/ " . n . showChar ' ' . d . showChar ')'
where
n = if numerator v >= 0
then showsPrec 0 (numerator v)
else showString "(- " . showsPrec 0 (negate $ numerator v) . showChar ')'
d = showsPrec 0 (denominator v)
renderValue SMTRendering (BitVecValue n bw)
= showString "(_ bv" .
showsPrec 0 n .
showChar ' ' .
showsPrec 0 (bwSize bw) .
showChar ')'
renderValue SMTRendering (ConstrValue par con Nil) = showString (constrName con)
renderValue SMTRendering (ConstrValue par con xs)
= showChar '(' . showString (constrName con) . renderValues xs . showChar ')'
where
renderValues :: List Value arg -> ShowS
renderValues Nil = id
renderValues (x ::: xs) = showChar ' ' . renderValue SMTRendering x . renderValues xs
renderFunction :: RenderMode
-> (forall arg res. fun '(arg,res) -> ShowS)
-> Function fun '(arg,res)
-> ShowS
renderFunction _ f (Fun x) = f x
renderFunction SMTRendering _ (Eq _ _) = showChar '='
renderFunction SMTRendering _ (Distinct _ _) = showString "distinct"
renderFunction SMTRendering f (Map _ fun)
= showString "(map " .
renderFunction SMTRendering f fun .
showChar ')'
renderFunction SMTRendering _ (Ord _ Ge) = showString ">="
renderFunction SMTRendering _ (Ord _ Gt) = showChar '>'
renderFunction SMTRendering _ (Ord _ Le) = showString "<="
renderFunction SMTRendering _ (Ord _ Lt) = showString "<"
renderFunction SMTRendering _ (Arith _ Plus _) = showChar '+'
renderFunction SMTRendering _ (Arith _ Mult _) = showChar '*'
renderFunction SMTRendering _ (Arith _ Minus _) = showChar '-'
renderFunction SMTRendering _ (ArithIntBin Div) = showString "div"
renderFunction SMTRendering _ (ArithIntBin Mod) = showString "mod"
renderFunction SMTRendering _ (ArithIntBin Rem) = showString "rem"
renderFunction SMTRendering _ Divide = showChar '/'
renderFunction SMTRendering _ (Abs _) = showString "abs"
renderFunction SMTRendering _ Not = showString "not"
renderFunction SMTRendering _ (Logic And _) = showString "and"
renderFunction SMTRendering _ (Logic Or _) = showString "or"
renderFunction SMTRendering _ (Logic XOr _) = showString "xor"
renderFunction SMTRendering _ (Logic Implies _) = showString "=>"
renderFunction SMTRendering _ ToReal = showString "to_real"
renderFunction SMTRendering _ ToInt = showString "to_int"
renderFunction SMTRendering _ (ITE _) = showString "ite"
renderFunction SMTRendering _ (BVComp op _) = showString $ case op of
BVULE -> "bvule"
BVULT -> "bvult"
BVUGE -> "bvuge"
BVUGT -> "bvugt"
BVSLE -> "bvsle"
BVSLT -> "bvslt"
BVSGE -> "bvsge"
BVSGT -> "bvsgt"
renderFunction SMTRendering _ (BVBin op _) = showString $ case op of
BVAdd -> "bvadd"
BVSub -> "bvsub"
BVMul -> "bvmul"
BVURem -> "bvurem"
BVSRem -> "bvsrem"
BVUDiv -> "bvudiv"
BVSDiv -> "bvsdiv"
BVSHL -> "bvshl"
BVLSHR -> "bvshr"
BVASHR -> "bvashr"
BVXor -> "bvxor"
BVAnd -> "bvand"
BVOr -> "bvor"
renderFunction SMTRendering _ (BVUn op _) = showString $ case op of
BVNot -> "bvnot"
BVNeg -> "bvneg"
renderFunction SMTRendering _ (Select _ _) = showString "select"
renderFunction SMTRendering _ (Store _ _) = showString "store"
renderFunction SMTRendering _ (ConstArray idx el)
= showString "(as const " .
renderType SMTRendering (ArrayRepr idx el) .
showChar ')'
renderFunction SMTRendering _ (Concat _ _) = showString "concat"
renderFunction SMTRendering _ (Extract _ start len)
= showString "(_ extract " .
showString (show $ start'+len'1) .
showChar ' ' .
showString (show start') .
showChar ')'
where
start' = bwSize start
len' = bwSize len
renderFunction SMTRendering _ (Constructor dt par con)
| determines dt con = showString (constrName con)
| otherwise = showString "(as " .
showString (constrName con) .
renderType SMTRendering (DataRepr dt par) .
showChar ')'
renderFunction SMTRendering _ (Test _ _ con)
= showString "is-" . showString (constrName con)
renderFunction SMTRendering _ (Field _ _ field) = showString (fieldName field)
renderFunction SMTRendering _ (Divisible n) = showString "(_ divisible " .
showsPrec 10 n .
showChar ')'
renderType :: RenderMode -> Repr tp -> ShowS
renderType SMTRendering BoolRepr = showString "Bool"
renderType SMTRendering IntRepr = showString "Int"
renderType SMTRendering RealRepr = showString "Real"
renderType SMTRendering (BitVecRepr bw) = showString "(BitVec " .
showString (show $ bwSize bw) .
showChar ')'
renderType SMTRendering (ArrayRepr idx el) = showString "(Array (" .
renderTypes idx .
showString ") " .
renderType SMTRendering el .
showChar ')'
renderType _ (DataRepr dt Nil) = showString (datatypeName dt)
renderType SMTRendering (DataRepr dt par)
= showChar '(' .
showString (datatypeName dt) .
showChar ' ' .
renderTypes par .
showChar ')'
renderTypes :: List Repr tps -> ShowS
renderTypes Nil = id
renderTypes (tp ::: Nil) = renderType SMTRendering tp
renderTypes (tp ::: tps) = renderType SMTRendering tp .
showChar ' ' .
renderTypes tps
instance GShow fun => GShow (Function fun) where
gshowsPrec = showsPrec
instance (GEq v,GEq e) => GEq (LetBinding v e) where
geq (LetBinding v1 e1) (LetBinding v2 e2) = do
Refl <- geq v1 v2
geq e1 e2
instance (GCompare v,GCompare e) => GCompare (LetBinding v e) where
gcompare (LetBinding v1 e1) (LetBinding v2 e2) = case gcompare v1 v2 of
GEQ -> gcompare e1 e2
r -> r
instance (GEq v,GEq qv,GEq fun,GEq fv,GEq lv,GEq e)
=> GEq (Expression v qv fun fv lv e) where
geq (Var v1) (Var v2) = geq v1 v2
geq (QVar v1) (QVar v2) = geq v1 v2
geq (FVar v1) (FVar v2) = geq v1 v2
geq (LVar v1) (LVar v2) = geq v1 v2
geq (App f1 arg1) (App f2 arg2) = do
Refl <- geq f1 f2
Refl <- geq arg1 arg2
return Refl
geq (Const x) (Const y) = geq x y
geq (AsArray f1) (AsArray f2) = do
Refl <- geq f1 f2
return Refl
geq (Quantification q1 arg1 body1) (Quantification q2 arg2 body2)
| q1==q2 = do
Refl <- geq arg1 arg2
geq body1 body2
| otherwise = Nothing
geq (Let bnd1 body1) (Let bnd2 body2) = do
Refl <- geq bnd1 bnd2
geq body1 body2
geq _ _ = Nothing
instance (GEq v,GEq qv,GEq fun,GEq fv,GEq lv,GEq e)
=> Eq (Expression v qv fun fv lv e t) where
(==) = defaultEq
instance (GCompare v,GCompare qv,GCompare fun,GCompare fv,GCompare lv,GCompare e)
=> GCompare (Expression v qv fun fv lv e) where
gcompare (Var v1) (Var v2) = gcompare v1 v2
gcompare (Var _) _ = GLT
gcompare _ (Var _) = GGT
gcompare (QVar v1) (QVar v2) = gcompare v1 v2
gcompare (QVar _) _ = GLT
gcompare _ (QVar _) = GGT
gcompare (FVar v1) (FVar v2) = gcompare v1 v2
gcompare (FVar _) _ = GLT
gcompare _ (FVar _) = GGT
gcompare (LVar v1) (LVar v2) = gcompare v1 v2
gcompare (LVar _) _ = GLT
gcompare _ (LVar _) = GGT
gcompare (App f1 arg1) (App f2 arg2) = case gcompare f1 f2 of
GEQ -> case gcompare arg1 arg2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (App _ _) _ = GLT
gcompare _ (App _ _) = GGT
gcompare (Const v1) (Const v2) = gcompare v1 v2
gcompare (Const _) _ = GLT
gcompare _ (Const _) = GGT
gcompare (AsArray f1) (AsArray f2) = case gcompare f1 f2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
gcompare (AsArray _) _ = GLT
gcompare _ (AsArray _) = GGT
gcompare (Quantification q1 arg1 body1) (Quantification q2 arg2 body2) = case compare q1 q2 of
LT -> GLT
GT -> GGT
EQ -> case gcompare arg1 arg2 of
GEQ -> gcompare body1 body2
GLT -> GLT
GGT -> GGT
gcompare (Quantification _ _ _) _ = GLT
gcompare _ (Quantification _ _ _) = GGT
gcompare (Let bnd1 body1) (Let bnd2 body2) = case gcompare bnd1 bnd2 of
GEQ -> gcompare body1 body2
GLT -> GLT
GGT -> GGT
instance (GCompare v,GCompare qv,GCompare fun,GCompare fv,GCompare lv,GCompare e)
=> Ord (Expression v qv fun fv lv e t) where
compare = defaultCompare
instance GEq fun => GEq (Function fun) where
geq (Fun f1) (Fun f2) = geq f1 f2
geq (Eq tp1 n1) (Eq tp2 n2) = do
Refl <- geq tp1 tp2
Refl <- geq n1 n2
return Refl
geq (Distinct tp1 n1) (Distinct tp2 n2) = do
Refl <- geq tp1 tp2
Refl <- geq n1 n2
return Refl
geq (Map i1 f1) (Map i2 f2) = do
Refl <- geq f1 f2
Refl <- geq i1 i2
return Refl
geq (Ord tp1 o1) (Ord tp2 o2) = do
Refl <- geq tp1 tp2
if o1==o2 then return Refl else Nothing
geq (Arith tp1 o1 n1) (Arith tp2 o2 n2) = do
Refl <- geq tp1 tp2
if o1==o2
then do
Refl <- geq n1 n2
return Refl
else Nothing
geq (ArithIntBin o1) (ArithIntBin o2) = if o1==o2 then Just Refl else Nothing
geq Divide Divide = Just Refl
geq (Abs tp1) (Abs tp2) = do
Refl <- geq tp1 tp2
return Refl
geq Not Not = Just Refl
geq (Logic o1 n1) (Logic o2 n2)
= if o1==o2
then do
Refl <- geq n1 n2
return Refl
else Nothing
geq ToReal ToReal = Just Refl
geq ToInt ToInt = Just Refl
geq (ITE t1) (ITE t2) = do
Refl <- geq t1 t2
return Refl
geq (BVComp o1 bw1) (BVComp o2 bw2)
= if o1==o2
then do
Refl <- geq bw1 bw2
return Refl
else Nothing
geq (BVBin o1 bw1) (BVBin o2 bw2)
= if o1==o2
then do
Refl <- geq bw1 bw2
return Refl
else Nothing
geq (BVUn o1 bw1) (BVUn o2 bw2)
= if o1==o2
then do
Refl <- geq bw1 bw2
return Refl
else Nothing
geq (Select i1 e1) (Select i2 e2) = do
Refl <- geq i1 i2
Refl <- geq e1 e2
return Refl
geq (Store i1 e1) (Store i2 e2) = do
Refl <- geq i1 i2
Refl <- geq e1 e2
return Refl
geq (ConstArray i1 e1) (ConstArray i2 e2) = do
Refl <- geq i1 i2
Refl <- geq e1 e2
return Refl
geq (Concat a1 b1) (Concat a2 b2) = do
Refl <- geq a1 a2
Refl <- geq b1 b2
return Refl
geq (Extract bw1 start1 len1) (Extract bw2 start2 len2) = do
Refl <- geq bw1 bw2
Refl <- geq start1 start2
Refl <- geq len1 len2
return Refl
geq (Constructor d1 par1 (c1 :: Constr dt1 sig1)) (Constructor d2 par2 (c2 :: Constr dt2 sig2)) = do
Refl <- datatypeEq d1 d2
Refl <- geq par1 par2
Refl <- geq c1 c2
return Refl
geq (Test d1 par1 (c1 :: Constr dt1 sig1)) (Test d2 par2 (c2 :: Constr dt2 sig2)) = do
Refl <- datatypeEq d1 d2
Refl <- geq par1 par2
Refl <- geq c1 c2
return Refl
geq (Field d1 par1 (f1 :: Type.Field dt1 tp1))
(Field d2 par2 (f2 :: Type.Field dt2 tp2)) = do
Refl <- datatypeEq d1 d2
Refl <- geq par1 par2
Refl <- geq f1 f2
return Refl
geq (Divisible n1) (Divisible n2) = if n1==n2 then Just Refl else Nothing
geq _ _ = Nothing
instance GCompare fun => GCompare (Function fun) where
gcompare (Fun x) (Fun y) = gcompare x y
gcompare (Fun _) _ = GLT
gcompare _ (Fun _) = GGT
gcompare (Eq t1 n1) (Eq t2 n2) = case gcompare t1 t2 of
GEQ -> case gcompare n1 n2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Eq _ _) _ = GLT
gcompare _ (Eq _ _) = GGT
gcompare (Distinct t1 n1) (Distinct t2 n2) = case gcompare t1 t2 of
GEQ -> case gcompare n1 n2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Distinct _ _) _ = GLT
gcompare _ (Distinct _ _) = GGT
gcompare (Map i1 f1) (Map i2 f2) = case gcompare f1 f2 of
GEQ -> case gcompare i1 i2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Map _ _) _ = GLT
gcompare _ (Map _ _) = GGT
gcompare (Ord tp1 o1) (Ord tp2 o2) = case gcompare tp1 tp2 of
GEQ -> case compare o1 o2 of
EQ -> GEQ
LT -> GLT
GT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Ord _ _) _ = GLT
gcompare _ (Ord _ _) = GGT
gcompare (Arith tp1 o1 n1) (Arith tp2 o2 n2) = case gcompare tp1 tp2 of
GEQ -> case compare o1 o2 of
EQ -> case gcompare n1 n2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
LT -> GLT
GT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Arith _ _ _) _ = GLT
gcompare _ (Arith _ _ _) = GGT
gcompare (ArithIntBin o1) (ArithIntBin o2) = case compare o1 o2 of
EQ -> GEQ
LT -> GLT
GT -> GGT
gcompare (ArithIntBin _) _ = GLT
gcompare _ (ArithIntBin _) = GGT
gcompare Divide Divide = GEQ
gcompare Divide _ = GLT
gcompare _ Divide = GGT
gcompare (Abs tp1) (Abs tp2) = case gcompare tp1 tp2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
gcompare (Abs _) _ = GLT
gcompare _ (Abs _) = GGT
gcompare Not Not = GEQ
gcompare Not _ = GLT
gcompare _ Not = GGT
gcompare (Logic o1 n1) (Logic o2 n2) = case compare o1 o2 of
EQ -> case gcompare n1 n2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
LT -> GLT
GT -> GGT
gcompare (Logic _ _) _ = GLT
gcompare _ (Logic _ _) = GGT
gcompare ToReal ToReal = GEQ
gcompare ToReal _ = GLT
gcompare _ ToReal = GGT
gcompare ToInt ToInt = GEQ
gcompare ToInt _ = GLT
gcompare _ ToInt = GGT
gcompare (ITE t1) (ITE t2) = case gcompare t1 t2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
gcompare (ITE _) _ = GLT
gcompare _ (ITE _) = GGT
gcompare (BVComp o1 bw1) (BVComp o2 bw2) = case compare o1 o2 of
EQ -> case gcompare bw1 bw2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
LT -> GLT
GT -> GGT
gcompare (BVComp _ _) _ = GLT
gcompare _ (BVComp _ _) = GGT
gcompare (BVBin o1 bw1) (BVBin o2 bw2) = case compare o1 o2 of
EQ -> case gcompare bw1 bw2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
LT -> GLT
GT -> GGT
gcompare (BVBin _ _) _ = GLT
gcompare _ (BVBin _ _) = GGT
gcompare (BVUn o1 bw1) (BVUn o2 bw2) = case compare o1 o2 of
EQ -> case gcompare bw1 bw2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
LT -> GLT
GT -> GGT
gcompare (BVUn _ _) _ = GLT
gcompare _ (BVUn _ _) = GGT
gcompare (Select i1 e1) (Select i2 e2) = case gcompare i1 i2 of
GEQ -> case gcompare e1 e2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Select _ _) _ = GLT
gcompare _ (Select _ _) = GGT
gcompare (Store i1 e1) (Store i2 e2) = case gcompare i1 i2 of
GEQ -> case gcompare e1 e2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Store _ _) _ = GLT
gcompare _ (Store _ _) = GGT
gcompare (ConstArray i1 e1) (ConstArray i2 e2) = case gcompare i1 i2 of
GEQ -> case gcompare e1 e2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (ConstArray _ _) _ = GLT
gcompare _ (ConstArray _ _) = GGT
gcompare (Concat a1 b1) (Concat a2 b2) = case gcompare a1 a2 of
GEQ -> case gcompare b1 b2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Concat _ _) _ = GLT
gcompare _ (Concat _ _) = GGT
gcompare (Extract bw1 start1 len1) (Extract bw2 start2 len2)
= case gcompare bw1 bw2 of
GEQ -> case gcompare start1 start2 of
GEQ -> case gcompare len1 len2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Extract _ _ _) _ = GLT
gcompare _ (Extract _ _ _) = GGT
gcompare (Constructor d1 par1 c1) (Constructor d2 par2 c2)
= case datatypeCompare d1 d2 of
GEQ -> case gcompare par1 par2 of
GEQ -> case gcompare c1 c2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Constructor _ _ _) _ = GLT
gcompare _ (Constructor _ _ _) = GGT
gcompare (Test d1 par1 c1) (Test d2 par2 c2)
= case datatypeCompare d1 d2 of
GEQ -> case gcompare par1 par2 of
GEQ -> case gcompare c1 c2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Test _ _ _) _ = GLT
gcompare _ (Test _ _ _) = GGT
gcompare (Field d1 par1 f1) (Field d2 par2 f2)
= case datatypeCompare d1 d2 of
GEQ -> case gcompare par1 par2 of
GEQ -> case gcompare f1 f2 of
GEQ -> GEQ
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
GLT -> GLT
GGT -> GGT
gcompare (Field _ _ _) _ = GLT
gcompare _ (Field _ _ _) = GGT
gcompare (Divisible n1) (Divisible n2) = case compare n1 n2 of
EQ -> GEQ
LT -> GLT
GT -> GGT
data NoVar (t::Type) = NoVar'
data NoFun (sig::([Type],Type)) = NoFun'
data NoCon (sig::([Type],*)) = NoCon'
data NoField (sig::(*,Type)) = NoField'
instance GEq NoVar where
geq _ _ = error "geq for NoVar"
instance GEq NoFun where
geq _ _ = error "geq for NoFun"
instance GEq NoCon where
geq _ _ = error "geq for NoCon"
instance GEq NoField where
geq _ _ = error "geq for NoField"
instance GCompare NoVar where
gcompare _ _ = error "gcompare for NoVar"
instance GCompare NoFun where
gcompare _ _ = error "gcompare for NoFun"
instance GCompare NoCon where
gcompare _ _ = error "gcompare for NoCon"
instance GCompare NoField where
gcompare _ _ = error "gcompare for NoField"
instance Eq (NoVar t) where
(==) _ _ = error "== for NoVar"
instance Eq (NoFun t) where
(==) _ _ = error "== for NoFun"
instance Eq (NoCon t) where
(==) _ _ = error "== for NoCon"
instance Eq (NoField t) where
(==) _ _ = error "== for NoField"
instance Ord (NoVar t) where
compare _ _ = error "compare for NoVar"
instance Ord (NoFun t) where
compare _ _ = error "compare for NoFun"
instance Ord (NoCon t) where
compare _ _ = error "compare for NoCon"
instance Ord (NoField t) where
compare _ _ = error "compare for NoField"
instance Show (NoVar t) where
showsPrec _ _ = showString "NoVar"
instance GShow NoVar where
gshowsPrec = showsPrec
instance Show (NoFun t) where
showsPrec _ _ = showString "NoFun"
instance GShow NoFun where
gshowsPrec = showsPrec
instance Show (NoCon t) where
showsPrec _ _ = showString "NoCon"
instance GShow NoCon where
gshowsPrec = showsPrec
instance Show (NoField t) where
showsPrec _ _ = showString "NoVar"
instance GShow NoField where
gshowsPrec = showsPrec
instance GetType NoVar where
getType _ = error "getType called on NoVar."
instance GetFunType NoFun where
getFunType _ = error "getFunType called on NoFun."
instance (GetType v,GetType qv,GetFunType fun,GetType fv,GetType lv,GetType e)
=> GetType (Expression v qv fun fv lv e) where
getType = runIdentity . expressionType
(return.getType) (return.getType) (return.getFunType)
(return.getType) (return.getType) (return.getType)
instance (GetFunType fun)
=> GetFunType (Function fun) where
getFunType = runIdentity . functionType (return.getFunType)