{-# LANGUAGE FlexibleContexts #-}
module Language.Haskell.Liquid.Bare.Misc
( joinVar
, mkVarExpr
, vmap
, runMapTyVars
, matchKindArgs
, symbolRTyVar
, simpleSymbolVar
, hasBoolResult
, isKind
) where
import Prelude hiding (error)
import Liquid.GHC.API as Ghc hiding (Located, get, showPpr)
import Control.Monad (zipWithM_)
import Control.Monad.Except (MonadError, throwError)
import Control.Monad.State
import qualified Data.Maybe as Mb
import qualified Text.PrettyPrint.HughesPJ as PJ
import qualified Data.List as L
import qualified Language.Fixpoint.Types as F
import Language.Haskell.Liquid.GHC.Misc
import Language.Haskell.Liquid.Types.RefType
import Language.Haskell.Liquid.Types.RType
import Language.Haskell.Liquid.Types.Types
runMapTyVars :: Bool -> Type -> SpecType -> (PJ.Doc -> PJ.Doc -> Error) -> Either Error MapTyVarST
runMapTyVars :: Bool
-> Type
-> SpecType
-> (Doc -> Doc -> Error)
-> Either Error MapTyVarST
runMapTyVars Bool
allowTC Type
τ SpecType
t Doc -> Doc -> Error
err = StateT MapTyVarST (Either Error) ()
-> MapTyVarST -> Either Error MapTyVarST
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m s
execStateT (Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ SpecType
t) ([(Var, RTyVar)] -> (Doc -> Doc -> Error) -> MapTyVarST
MTVST [] Doc -> Doc -> Error
err)
data MapTyVarST = MTVST
{ MapTyVarST -> [(Var, RTyVar)]
vmap :: [(Var, RTyVar)]
, MapTyVarST -> Doc -> Doc -> Error
errmsg :: PJ.Doc -> PJ.Doc -> Error
}
mapTyVars :: Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars :: Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC (FunTy { ft_arg :: Type -> Type
ft_arg = Type
τ, ft_res :: Type -> Type
ft_res = Type
τ'}) SpecType
t
| Type -> Bool
isErasable Type
τ
= Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ' SpecType
t
where isErasable :: Type -> Bool
isErasable = if Bool
allowTC then Type -> Bool
isEmbeddedDictType else Type -> Bool
isClassPred
mapTyVars Bool
allowTC (FunTy { ft_arg :: Type -> Type
ft_arg = Type
τ, ft_res :: Type -> Type
ft_res = Type
τ'}) (RFun Symbol
_ RFInfo
_ SpecType
t SpecType
t' UReftV Symbol (ReftV Symbol)
_)
= Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ SpecType
t StateT MapTyVarST (Either Error) ()
-> StateT MapTyVarST (Either Error) ()
-> StateT MapTyVarST (Either Error) ()
forall a b.
StateT MapTyVarST (Either Error) a
-> StateT MapTyVarST (Either Error) b
-> StateT MapTyVarST (Either Error) b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ' SpecType
t'
mapTyVars Bool
allowTC Type
τ (RAllT RTVUV Symbol RTyCon RTyVar
_ SpecType
t UReftV Symbol (ReftV Symbol)
_)
= Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ SpecType
t
mapTyVars Bool
allowTC (TyConApp TyCon
_ [Type]
τs) (RApp RTyCon
_ [SpecType]
ts [RTProp RTyCon RTyVar (UReftV Symbol (ReftV Symbol))]
_ UReftV Symbol (ReftV Symbol)
_)
= (Type -> SpecType -> StateT MapTyVarST (Either Error) ())
-> [Type] -> [SpecType] -> StateT MapTyVarST (Either Error) ()
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ (Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC) [Type]
τs ([Type] -> [SpecType] -> [SpecType]
matchKindArgs' [Type]
τs [SpecType]
ts)
mapTyVars Bool
_ (TyVarTy Var
α) (RVar RTyVar
a UReftV Symbol (ReftV Symbol)
_)
= do s <- StateT MapTyVarST (Either Error) MapTyVarST
forall s (m :: * -> *). MonadState s m => m s
get
s' <- mapTyRVar α a s
put s'
mapTyVars Bool
allowTC Type
τ (RAllP PVUV Symbol RTyCon RTyVar
_ SpecType
t)
= Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ SpecType
t
mapTyVars Bool
allowTC Type
τ (RAllE Symbol
_ SpecType
_ SpecType
t)
= Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ SpecType
t
mapTyVars Bool
allowTC Type
τ (RRTy [(Symbol, SpecType)]
_ UReftV Symbol (ReftV Symbol)
_ Oblig
_ SpecType
t)
= Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ SpecType
t
mapTyVars Bool
allowTC Type
τ (REx Symbol
_ SpecType
_ SpecType
t)
= Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ SpecType
t
mapTyVars Bool
_ Type
_ (RExprArg Located (ExprV Symbol)
_)
= () -> StateT MapTyVarST (Either Error) ()
forall a. a -> StateT MapTyVarST (Either Error) a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
mapTyVars Bool
allowTC (AppTy Type
τ Type
τ') (RAppTy SpecType
t SpecType
t' UReftV Symbol (ReftV Symbol)
_)
= do Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ SpecType
t
Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ' SpecType
t'
mapTyVars Bool
_ Type
_ (RHole UReftV Symbol (ReftV Symbol)
_)
= () -> StateT MapTyVarST (Either Error) ()
forall a. a -> StateT MapTyVarST (Either Error) a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
mapTyVars Bool
_ Type
k SpecType
_ | Type -> Bool
isKind Type
k
= () -> StateT MapTyVarST (Either Error) ()
forall a. a -> StateT MapTyVarST (Either Error) a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
mapTyVars Bool
allowTC (ForAllTy ForAllTyBinder
_ Type
τ) SpecType
t
= Bool -> Type -> SpecType -> StateT MapTyVarST (Either Error) ()
mapTyVars Bool
allowTC Type
τ SpecType
t
mapTyVars Bool
_ Type
hsT SpecType
lqT
= do err <- (MapTyVarST -> Doc -> Doc -> Error)
-> StateT MapTyVarST (Either Error) (Doc -> Doc -> Error)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets MapTyVarST -> Doc -> Doc -> Error
errmsg
throwError (err (F.pprint hsT) (F.pprint lqT))
isKind :: Kind -> Bool
isKind :: Type -> Bool
isKind = Type -> Bool
isTYPEorCONSTRAINT
mapTyRVar :: MonadError Error m
=> Var -> RTyVar -> MapTyVarST -> m MapTyVarST
mapTyRVar :: forall (m :: * -> *).
MonadError Error m =>
Var -> RTyVar -> MapTyVarST -> m MapTyVarST
mapTyRVar Var
α RTyVar
a s :: MapTyVarST
s@(MTVST [(Var, RTyVar)]
αas Doc -> Doc -> Error
err)
= case Var -> [(Var, RTyVar)] -> Maybe RTyVar
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Var
α [(Var, RTyVar)]
αas of
Just RTyVar
a' | RTyVar
a RTyVar -> RTyVar -> Bool
forall a. Eq a => a -> a -> Bool
== RTyVar
a' -> MapTyVarST -> m MapTyVarST
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return MapTyVarST
s
| Bool
otherwise -> Error -> m MapTyVarST
forall a. Error -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (Doc -> Doc -> Error
err (RTyVar -> Doc
forall a. PPrint a => a -> Doc
F.pprint RTyVar
a) (RTyVar -> Doc
forall a. PPrint a => a -> Doc
F.pprint RTyVar
a'))
Maybe RTyVar
Nothing -> MapTyVarST -> m MapTyVarST
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (MapTyVarST -> m MapTyVarST) -> MapTyVarST -> m MapTyVarST
forall a b. (a -> b) -> a -> b
$ [(Var, RTyVar)] -> (Doc -> Doc -> Error) -> MapTyVarST
MTVST ((Var
α,RTyVar
a)(Var, RTyVar) -> [(Var, RTyVar)] -> [(Var, RTyVar)]
forall a. a -> [a] -> [a]
:[(Var, RTyVar)]
αas) Doc -> Doc -> Error
err
matchKindArgs' :: [Type] -> [SpecType] -> [SpecType]
matchKindArgs' :: [Type] -> [SpecType] -> [SpecType]
matchKindArgs' [Type]
ts1' = [SpecType] -> [SpecType]
forall a. [a] -> [a]
reverse ([SpecType] -> [SpecType])
-> ([SpecType] -> [SpecType]) -> [SpecType] -> [SpecType]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Type] -> [SpecType] -> [SpecType]
go ([Type] -> [Type]
forall a. [a] -> [a]
reverse [Type]
ts1') ([SpecType] -> [SpecType])
-> ([SpecType] -> [SpecType]) -> [SpecType] -> [SpecType]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [SpecType] -> [SpecType]
forall a. [a] -> [a]
reverse
where
go :: [Type] -> [SpecType] -> [SpecType]
go (Type
_:[Type]
ts1) (SpecType
t2:[SpecType]
ts2) = SpecType
t2SpecType -> [SpecType] -> [SpecType]
forall a. a -> [a] -> [a]
:[Type] -> [SpecType] -> [SpecType]
go [Type]
ts1 [SpecType]
ts2
go [Type]
ts [] | (Type -> Bool) -> [Type] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Type -> Bool
isKind [Type]
ts
= (Type -> SpecType
forall r. Monoid r => Type -> RRType r
ofType (Type -> SpecType) -> [Type] -> [SpecType]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Type]
ts) :: [SpecType]
go [Type]
_ [SpecType]
ts = [SpecType]
ts
matchKindArgs :: [SpecType] -> [SpecType] -> [SpecType]
matchKindArgs :: [SpecType] -> [SpecType] -> [SpecType]
matchKindArgs [SpecType]
ts1' = [SpecType] -> [SpecType]
forall a. [a] -> [a]
reverse ([SpecType] -> [SpecType])
-> ([SpecType] -> [SpecType]) -> [SpecType] -> [SpecType]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [SpecType] -> [SpecType] -> [SpecType]
forall {a}. [a] -> [a] -> [a]
go ([SpecType] -> [SpecType]
forall a. [a] -> [a]
reverse [SpecType]
ts1') ([SpecType] -> [SpecType])
-> ([SpecType] -> [SpecType]) -> [SpecType] -> [SpecType]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [SpecType] -> [SpecType]
forall a. [a] -> [a]
reverse
where
go :: [a] -> [a] -> [a]
go (a
_:[a]
ts1) (a
t2:[a]
ts2) = a
t2a -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a] -> [a] -> [a]
go [a]
ts1 [a]
ts2
go [a]
ts [] = [a]
ts
go [a]
_ [a]
ts = [a]
ts
mkVarExpr :: Id -> F.Expr
mkVarExpr :: Var -> ExprV Symbol
mkVarExpr Var
v
| Var -> Bool
isFunVar Var
v = LocSymbol -> [ExprV Symbol] -> ExprV Symbol
F.mkEApp (Var -> LocSymbol
varFunSymbol Var
v) []
| Bool
otherwise = Var -> ExprV Symbol
forall a. Symbolic a => a -> ExprV Symbol
F.eVar Var
v
varFunSymbol :: Id -> Located F.Symbol
varFunSymbol :: Var -> LocSymbol
varFunSymbol = Symbol -> LocSymbol
forall a. a -> Located a
dummyLoc (Symbol -> LocSymbol) -> (Var -> Symbol) -> Var -> LocSymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DataCon -> Symbol
forall a. Symbolic a => a -> Symbol
F.symbol (DataCon -> Symbol) -> (Var -> DataCon) -> Var -> Symbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Var -> DataCon
idDataCon
isFunVar :: Id -> Bool
isFunVar :: Var -> Bool
isFunVar Var
v = Var -> Bool
isDataConId Var
v Bool -> Bool -> Bool
&& Bool -> Bool
not ([Var] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Var]
αs) Bool -> Bool -> Bool
&& Maybe (FunTyFlag, Type, Type, Type) -> Bool
forall a. Maybe a -> Bool
Mb.isNothing Maybe (FunTyFlag, Type, Type, Type)
tf
where
([Var]
αs, Type
t) = Type -> ([Var], Type)
splitForAllTyCoVars (Type -> ([Var], Type)) -> Type -> ([Var], Type)
forall a b. (a -> b) -> a -> b
$ Var -> Type
varType Var
v
tf :: Maybe (FunTyFlag, Type, Type, Type)
tf = Type -> Maybe (FunTyFlag, Type, Type, Type)
splitFunTy_maybe Type
t
joinVar :: [Var] -> (Var, s, t) -> (Var, s, t)
joinVar :: forall s t. [Var] -> (Var, s, t) -> (Var, s, t)
joinVar [Var]
vs (Var
v,s
s,t
t) = case (Var -> Bool) -> [Var] -> Maybe Var
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
L.find ((String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== Var -> String
forall a. Outputable a => a -> String
showPpr Var
v) (String -> Bool) -> (Var -> String) -> Var -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Var -> String
forall a. Outputable a => a -> String
showPpr) [Var]
vs of
Just Var
v' -> (Var
v',s
s,t
t)
Maybe Var
Nothing -> (Var
v,s
s,t
t)
simpleSymbolVar :: Var -> F.Symbol
simpleSymbolVar :: Var -> Symbol
simpleSymbolVar = Symbol -> Symbol
dropModuleNames (Symbol -> Symbol) -> (Var -> Symbol) -> Var -> Symbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Symbol
forall a. Symbolic a => a -> Symbol
F.symbol (String -> Symbol) -> (Var -> String) -> Var -> Symbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> String
forall a. Outputable a => a -> String
showPpr (Name -> String) -> (Var -> Name) -> Var -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Var -> Name
forall a. NamedThing a => a -> Name
getName
hasBoolResult :: Type -> Bool
hasBoolResult :: Type -> Bool
hasBoolResult (ForAllTy ForAllTyBinder
_ Type
t) = Type -> Bool
hasBoolResult Type
t
hasBoolResult (FunTy { ft_res :: Type -> Type
ft_res = Type
t} ) | Type -> Type -> Bool
eqType Type
boolTy Type
t = Bool
True
hasBoolResult (FunTy { ft_res :: Type -> Type
ft_res = Type
t} ) = Type -> Bool
hasBoolResult Type
t
hasBoolResult Type
_ = Bool
False