module Cryptol.TypeCheck.Solver.Improve where
import qualified Data.Set as Set
import Control.Applicative
import Control.Monad
import Cryptol.Utils.Patterns
import Cryptol.TypeCheck.Type
import Cryptol.TypeCheck.SimpType as Mk
import Cryptol.TypeCheck.Solver.Types
import Cryptol.TypeCheck.Solver.Numeric.Interval
import Cryptol.TypeCheck.TypePat
import Cryptol.TypeCheck.Subst
improveProps :: Bool -> Ctxt -> [Prop] -> Match (Subst,[Prop])
improveProps :: Bool -> Ctxt -> [Prop] -> Match (Subst, [Prop])
improveProps Bool
impSkol Ctxt
ctxt [Prop]
ps0 = Subst -> [Prop] -> Match (Subst, [Prop])
forall (m :: * -> *).
MonadPlus m =>
Subst -> [Prop] -> m (Subst, [Prop])
loop Subst
emptySubst [Prop]
ps0
where
loop :: Subst -> [Prop] -> m (Subst, [Prop])
loop Subst
su [Prop]
props = case Subst -> [Prop] -> [Prop] -> (Subst, [Prop])
go Subst
emptySubst [] [Prop]
props of
(Subst
newSu,[Prop]
newProps)
| Subst -> Bool
isEmptySubst Subst
newSu ->
if Subst -> Bool
isEmptySubst Subst
su then m (Subst, [Prop])
forall (m :: * -> *) a. MonadPlus m => m a
mzero else (Subst, [Prop]) -> m (Subst, [Prop])
forall (m :: * -> *) a. Monad m => a -> m a
return (Subst
su,[Prop]
props)
| Bool
otherwise -> Subst -> [Prop] -> m (Subst, [Prop])
loop (Subst
newSu Subst -> Subst -> Subst
@@ Subst
su) [Prop]
newProps
go :: Subst -> [Prop] -> [Prop] -> (Subst, [Prop])
go Subst
su [Prop]
subs [] = (Subst
su,[Prop]
subs)
go Subst
su [Prop]
subs (Prop
p : [Prop]
ps) =
case Match (Subst, [Prop]) -> Maybe (Subst, [Prop])
forall a. Match a -> Maybe a
matchMaybe (Bool -> Ctxt -> Prop -> Match (Subst, [Prop])
improveProp Bool
impSkol Ctxt
ctxt Prop
p) of
Maybe (Subst, [Prop])
Nothing -> Subst -> [Prop] -> [Prop] -> (Subst, [Prop])
go Subst
su (Prop
pProp -> [Prop] -> [Prop]
forall a. a -> [a] -> [a]
:[Prop]
subs) [Prop]
ps
Just (Subst
suNew,[Prop]
psNew) -> Subst -> [Prop] -> [Prop] -> (Subst, [Prop])
go (Subst
suNew Subst -> Subst -> Subst
@@ Subst
su) ([Prop]
psNew [Prop] -> [Prop] -> [Prop]
forall a. [a] -> [a] -> [a]
++ Subst -> [Prop] -> [Prop]
forall t. TVars t => Subst -> t -> t
apSubst Subst
suNew [Prop]
subs)
(Subst -> [Prop] -> [Prop]
forall t. TVars t => Subst -> t -> t
apSubst Subst
su [Prop]
ps)
improveProp :: Bool -> Ctxt -> Prop -> Match (Subst,[Prop])
improveProp :: Bool -> Ctxt -> Prop -> Match (Subst, [Prop])
improveProp Bool
impSkol Ctxt
ctxt Prop
prop =
Bool -> Ctxt -> Prop -> Match (Subst, [Prop])
improveEq Bool
impSkol Ctxt
ctxt Prop
prop Match (Subst, [Prop])
-> Match (Subst, [Prop]) -> Match (Subst, [Prop])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
Bool -> Prop -> Match (Subst, [Prop])
improveLit Bool
impSkol Prop
prop
improveLit :: Bool -> Prop -> Match (Subst, [Prop])
improveLit :: Bool -> Prop -> Match (Subst, [Prop])
improveLit Bool
impSkol Prop
prop =
do (Prop
_,Prop
t) <- Pat Prop (Prop, Prop)
aLiteral Prop
prop
(Prop
_,Prop
b) <- Pat Prop (Prop, Prop)
aSeq Prop
t
TVar
a <- Pat Prop TVar
aTVar Prop
b
Bool -> Match () -> Match ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
impSkol (Match () -> Match ()) -> Match () -> Match ()
forall a b. (a -> b) -> a -> b
$ Bool -> Match ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (TVar -> Bool
isFreeTV TVar
a)
let su :: Subst
su = TVar -> Prop -> Subst
uncheckedSingleSubst TVar
a Prop
tBit
(Subst, [Prop]) -> Match (Subst, [Prop])
forall (m :: * -> *) a. Monad m => a -> m a
return (Subst
su, [])
improveEq :: Bool -> Ctxt -> Prop -> Match (Subst,[Prop])
improveEq :: Bool -> Ctxt -> Prop -> Match (Subst, [Prop])
improveEq Bool
impSkol Ctxt
fins Prop
prop =
do (Prop
lhs,Prop
rhs) <- Pat Prop (Prop, Prop)
(|=|) Prop
prop
Prop -> Prop -> Match (Subst, [Prop])
rewrite Prop
lhs Prop
rhs Match (Subst, [Prop])
-> Match (Subst, [Prop]) -> Match (Subst, [Prop])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Prop -> Prop -> Match (Subst, [Prop])
rewrite Prop
rhs Prop
lhs
where
rewrite :: Prop -> Prop -> Match (Subst, [Prop])
rewrite Prop
this Prop
other =
do TVar
x <- Pat Prop TVar
aTVar Prop
this
Bool -> Match ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (TVar -> Bool
considerVar TVar
x)
case TVar -> Prop -> Either SubstError Subst
singleSubst TVar
x Prop
other of
Left SubstError
_ -> Match (Subst, [Prop])
forall (m :: * -> *) a. MonadPlus m => m a
mzero
Right Subst
su -> (Subst, [Prop]) -> Match (Subst, [Prop])
forall (m :: * -> *) a. Monad m => a -> m a
return (Subst
su, [])
Match (Subst, [Prop])
-> Match (Subst, [Prop]) -> Match (Subst, [Prop])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
do (TVar
v,Prop
s) <- Prop -> Match (TVar, Prop)
isSum Prop
this
case TVar -> Prop -> Either SubstError Subst
singleSubst TVar
v (Prop -> Prop -> Prop
Mk.tSub Prop
other Prop
s) of
Left SubstError
_ -> Match (Subst, [Prop])
forall (m :: * -> *) a. MonadPlus m => m a
mzero
Right Subst
su -> (Subst, [Prop]) -> Match (Subst, [Prop])
forall (m :: * -> *) a. Monad m => a -> m a
return (Subst
su, [ Prop
other Prop -> Prop -> Prop
>== Prop
s ])
isSum :: Prop -> Match (TVar, Prop)
isSum Prop
t = do (TVar
v,Prop
s) <- Prop
-> (Pat Prop (Prop, Prop), Pat Prop TVar, Pat Prop Prop)
-> Match (TVar, Prop)
forall thing pats res.
Matches thing pats res =>
thing -> pats -> Match res
matches Prop
t (Pat Prop (Prop, Prop)
anAdd, Pat Prop TVar
aTVar, Pat Prop Prop
forall a. Pat a a
__)
TVar -> Prop -> Match (TVar, Prop)
forall (m :: * -> *).
(Monad m, Alternative m) =>
TVar -> Prop -> m (TVar, Prop)
valid TVar
v Prop
s
Match (TVar, Prop) -> Match (TVar, Prop) -> Match (TVar, Prop)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> do (Prop
s,TVar
v) <- Prop
-> (Pat Prop (Prop, Prop), Pat Prop Prop, Pat Prop TVar)
-> Match (Prop, TVar)
forall thing pats res.
Matches thing pats res =>
thing -> pats -> Match res
matches Prop
t (Pat Prop (Prop, Prop)
anAdd, Pat Prop Prop
forall a. Pat a a
__, Pat Prop TVar
aTVar)
TVar -> Prop -> Match (TVar, Prop)
forall (m :: * -> *).
(Monad m, Alternative m) =>
TVar -> Prop -> m (TVar, Prop)
valid TVar
v Prop
s
valid :: TVar -> Prop -> m (TVar, Prop)
valid TVar
v Prop
s = do let i :: Interval
i = Map TVar Interval -> Prop -> Interval
typeInterval (Ctxt -> Map TVar Interval
intervals Ctxt
fins) Prop
s
Bool -> m ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (TVar -> Bool
considerVar TVar
v Bool -> Bool -> Bool
&& TVar
v TVar -> Set TVar -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.notMember` Prop -> Set TVar
forall t. FVS t => t -> Set TVar
fvs Prop
s Bool -> Bool -> Bool
&& Interval -> Bool
iIsFin Interval
i)
(TVar, Prop) -> m (TVar, Prop)
forall (m :: * -> *) a. Monad m => a -> m a
return (TVar
v,Prop
s)
considerVar :: TVar -> Bool
considerVar TVar
x = Bool
impSkol Bool -> Bool -> Bool
|| TVar -> Bool
isFreeTV TVar
x