module Language.SMTLib2.Internals.Embed where
import Language.SMTLib2.Internals.Expression
import Language.SMTLib2.Internals.Type hiding (Constr,Field)
import Language.SMTLib2.Internals.Type.List (List(..))
import qualified Language.SMTLib2.Internals.Type.List as List
import Language.SMTLib2.Internals.Monad
import Language.SMTLib2.Internals.Backend
import Language.SMTLib2.Internals.Evaluate
import Data.Functor.Identity
import Control.Monad.State
import Control.Monad.Except
import Data.GADT.Compare
import Data.GADT.Show
import qualified Data.Dependent.Map as DMap
type EmbedExpr m e tp = Expression (EmVar m e) (EmQVar m e) (EmFun m e) (EmFunArg m e) (EmLVar m e) e tp
class (Applicative m,
GCompare (EmVar m e),
GCompare (EmQVar m e),
GCompare (EmFun m e),
GCompare (EmFunArg m e),
GCompare (EmLVar m e)
) => Embed m e where
type EmVar m e :: Type -> *
type EmQVar m e :: Type -> *
type EmFun m e :: ([Type],Type) -> *
type EmFunArg m e :: Type -> *
type EmLVar m e :: Type -> *
embed :: m (EmbedExpr m e tp)
-> m (e tp)
embedQuantifier :: Quantifier
-> List Repr arg
-> (forall m e. (Embed m e,Monad m) => List (EmQVar m e) arg -> m (e BoolType))
-> m (e BoolType)
embedTypeOf :: m (e tp -> Repr tp)
class (GCompare (ExVar i e),
GCompare (ExQVar i e),
GCompare (ExFun i e),
GCompare (ExFunArg i e),
GCompare (ExLVar i e)) => Extract i e where
type ExVar i e :: Type -> *
type ExQVar i e :: Type -> *
type ExFun i e :: ([Type],Type) -> *
type ExFunArg i e :: Type -> *
type ExLVar i e :: Type -> *
extract :: i -> e tp
-> Maybe (Expression (ExVar i e) (ExQVar i e) (ExFun i e) (ExFunArg i e) (ExLVar i e) e tp)
instance (Backend b) => Embed (SMT b) (Expr b) where
type EmVar (SMT b) (Expr b) = Var b
type EmQVar (SMT b) (Expr b) = QVar b
type EmFun (SMT b) (Expr b) = Fun b
type EmFunArg (SMT b) (Expr b) = FunArg b
type EmLVar (SMT b) (Expr b) = LVar b
embed x = do
rx <- x
embedSMT (toBackend rx)
embedQuantifier quant tps f = do
args <- List.mapM (\tp -> embedSMT (createQVar tp Nothing)) tps
body <- f args
embedSMT $ toBackend (Quantification quant args body)
embedTypeOf = pure getType
instance Embed Identity Repr where
type EmVar Identity Repr = Repr
type EmQVar Identity Repr = Repr
type EmFun Identity Repr = FunRepr
type EmFunArg Identity Repr = Repr
type EmLVar Identity Repr = Repr
embed e = pure f <*> e
where
f e = runIdentity $ expressionType return return (\(FunRepr arg tp) -> return (arg,tp)) return return return e
embedQuantifier _ _ _ = pure bool
embedTypeOf = pure id
data UserFun (m :: * -> *) (e :: Type -> *) (sig :: ([Type],Type)) where
UserFun :: List Repr arg
-> Repr res
-> Int
-> (List e arg -> m (e res))
-> UserFun m e '(arg,res)
instance GEq (UserFun m e) where
geq (UserFun arg1 res1 n1 _) (UserFun arg2 res2 n2 _) = do
Refl <- geq arg1 arg2
Refl <- geq res1 res2
if n1==n2
then return Refl
else Nothing
instance GCompare (UserFun m e) where
gcompare (UserFun arg1 res1 n1 _) (UserFun arg2 res2 n2 _) = case gcompare arg1 arg2 of
GLT -> GLT
GGT -> GGT
GEQ -> case gcompare res1 res2 of
GLT -> GLT
GGT -> GGT
GEQ -> case compare n1 n2 of
LT -> GLT
GT -> GGT
EQ -> GEQ
instance GetFunType (UserFun m e) where
getFunType (UserFun arg res _ _) = (arg,res)
instance GShow (UserFun m e) where
gshowsPrec p (UserFun idx res n _)
= showParen (p>10) $ showsPrec 11 n . showString " : " .
showsPrec 11 idx . showString " -> " .
showsPrec 11 res
instance Embed Identity Value where
type EmVar Identity Value = NoVar
type EmQVar Identity Value = NoVar
type EmFun Identity Value = UserFun Identity Value
type EmFunArg Identity Value = NoVar
type EmLVar Identity Value = NoVar
embed e = do
re <- e
res <- evaluateExpr
(error "embed: No variables in embedded values")
(error "embed: No quantified variables in embedded values")
(error "embed: No function variables in embedded values")
(\(UserFun _ _ _ f) lst -> do
lst' <- List.mapM (\res -> case res of
ValueResult v -> return v) lst
fmap ValueResult $ f lst')
(error "embed: No fields in embedded values")
(error "embed: No quantifier in embedded values")
DMap.empty
(\_ val -> return $ ValueResult val) re
case res of
ValueResult v -> return v
embedTypeOf = pure getType
newtype ValueExt m tp = ValueExt { valueExt :: EvalResult (UserFun m (ValueExt m)) tp }
instance GetType (ValueExt m) where
getType (ValueExt e) = getType e
instance GShow (ValueExt m) where
gshowsPrec p (ValueExt e) = gshowsPrec p e
instance GEq (ValueExt m) where
geq (ValueExt e1) (ValueExt e2) = geq e1 e2
instance GCompare (ValueExt m) where
gcompare (ValueExt e1) (ValueExt e2) = gcompare e1 e2
instance Embed Identity (ValueExt Identity) where
type EmVar Identity (ValueExt Identity) = NoVar
type EmQVar Identity (ValueExt Identity) = NoVar
type EmFun Identity (ValueExt Identity) = UserFun Identity (ValueExt Identity)
type EmFunArg Identity (ValueExt Identity) = NoVar
type EmLVar Identity (ValueExt Identity) = NoVar
embed e = do
re <- e
fmap ValueExt $ evaluateExpr
(error "embed: No variables in embedded values")
(error "embed: No quantified variables in embedded values")
(error "embed: No function variables in embedded values")
(\(UserFun _ _ _ f) lst -> do
lst' <- List.mapM (return.ValueExt) lst
fmap valueExt $ f lst')
(error "embed: No fields in embedded values")
(error "embed: No quantifier in embedded values")
DMap.empty
(\_ val -> return $ valueExt val) re
embedTypeOf = pure getType
newtype BackendInfo b = BackendInfo b
instance (Backend b) => Extract (BackendInfo b) (Expr b) where
type ExVar (BackendInfo b) (Expr b) = Var b
type ExQVar (BackendInfo b) (Expr b) = QVar b
type ExFun (BackendInfo b) (Expr b) = Fun b
type ExFunArg (BackendInfo b) (Expr b) = FunArg b
type ExLVar (BackendInfo b) (Expr b) = LVar b
extract (BackendInfo b) e = Just (fromBackend b e)
data SMTExpr var qvar fun farg lvar tp where
SMTExpr :: Expression var qvar fun farg lvar
(SMTExpr var qvar fun farg lvar)
tp -> SMTExpr var qvar fun farg lvar tp
SMTQuant :: Quantifier
-> List Repr args
-> (List qvar args
-> SMTExpr var qvar fun farg lvar BoolType)
-> SMTExpr var qvar fun farg lvar BoolType
instance (GCompare var,GetType var,
GCompare qvar,GetType qvar,
GCompare fun,GetFunType fun,
GCompare farg,GetType farg,
GCompare lvar,GetType lvar
) => Embed Identity (SMTExpr var qvar fun farg lvar) where
type EmVar Identity (SMTExpr var qvar fun farg lvar) = var
type EmQVar Identity (SMTExpr var qvar fun farg lvar) = qvar
type EmFun Identity (SMTExpr var qvar fun farg lvar) = fun
type EmFunArg Identity (SMTExpr var qvar fun farg lvar) = farg
type EmLVar Identity (SMTExpr var qvar fun farg lvar) = lvar
embed e = do
re <- e
return $ SMTExpr re
embedQuantifier quant tps f = return $ SMTQuant quant tps (runIdentity . f)
embedTypeOf = pure getType
instance (GetType var,GetType qvar,GetFunType fun,GetType farg,GetType lvar)
=> GetType (SMTExpr var qvar fun farg lvar) where
getType (SMTExpr e) = getType e
getType (SMTQuant _ _ _) = BoolRepr
instance (GCompare var,
GCompare qvar,
GCompare fun,
GCompare farg,
GCompare lvar) => Extract () (SMTExpr var qvar fun farg lvar) where
type ExVar () (SMTExpr var qvar fun farg lvar) = var
type ExQVar () (SMTExpr var qvar fun farg lvar) = qvar
type ExFun () (SMTExpr var qvar fun farg lvar) = fun
type ExFunArg () (SMTExpr var qvar fun farg lvar) = farg
type ExLVar () (SMTExpr var qvar fun farg lvar) = lvar
extract _ (SMTExpr e) = Just e
extract _ _ = Nothing
encodeExpr :: (Backend b)
=> SMTExpr (Var b) (QVar b) (Fun b) (FunArg b) (LVar b) tp
-> SMT b (Expr b tp)
encodeExpr (SMTExpr e) = do
e' <- mapExpr return return return return return
encodeExpr e
embedSMT $ toBackend e'
encodeExpr (SMTQuant q tps f) = do
args <- List.mapM (\tp -> embedSMT (createQVar tp Nothing)) tps
body <- encodeExpr (f args)
embedSMT $ toBackend (Quantification q args body)
decodeExpr :: (Backend b) => Expr b tp
-> SMT b (SMTExpr (Var b) (QVar b) (Fun b) (FunArg b) (LVar b) tp)
decodeExpr e = do
st <- get
let e' = fromBackend (backend st) e
e'' <- mapExpr return return return return return decodeExpr e'
return (SMTExpr e'')
data AnalyzedExpr i e tp
= AnalyzedExpr (Maybe (Expression
(ExVar i e)
(ExQVar i e)
(ExFun i e)
(ExFunArg i e)
(ExLVar i e)
(AnalyzedExpr i e)
tp)) (e tp)
analyze' :: (Extract i e) => i -> e tp -> AnalyzedExpr i e tp
analyze' i expr
= AnalyzedExpr expr' expr
where
expr' = do
e <- extract i expr
return $ runIdentity (mapExpr return return return return return
(return . analyze' i) e)
analyze :: (Backend b) => Expr b tp -> SMT b (AnalyzedExpr (BackendInfo b) (Expr b) tp)
analyze e = do
st <- get
return (analyze' (BackendInfo (backend st)) e)
instance (Embed m e,Monad m) => Embed (ExceptT err m) e where
type EmVar (ExceptT err m) e = EmVar m e
type EmQVar (ExceptT err m) e = EmQVar m e
type EmFun (ExceptT err m) e = EmFun m e
type EmFunArg (ExceptT err m) e = EmFunArg m e
type EmLVar (ExceptT err m) e = EmLVar m e
embed e = do
re <- e
lift $ embed (pure re)
embedQuantifier q arg body = lift $ embedQuantifier q arg body
embedTypeOf = lift embedTypeOf