module Language.Haskell.Liquid.Constraint.Qualifier (
specificationQualifiers
) where
import TyCon
import Prelude hiding (error)
import Language.Haskell.Liquid.Bare
import Language.Haskell.Liquid.Types.RefType
import Language.Haskell.Liquid.GHC.Misc (getSourcePos)
import Language.Haskell.Liquid.Types.PredType
import Language.Haskell.Liquid.Types
import Language.Fixpoint.Types
import Data.List (delete, nub)
import Data.Maybe (catMaybes, fromMaybe)
import qualified Data.HashSet as S
import Debug.Trace
specificationQualifiers :: Int -> GhcInfo -> SEnv Sort -> [Qualifier]
specificationQualifiers k info lEnv
= [ q | (x, t) <- (tySigs $ spec info) ++ (asmSigs $ spec info) ++ (inSigs $ spec info) ++ (ctors $ spec info)
, x `S.member` (S.fromList $ defVars info ++
if info `hasOpt` scrapeUsedImports
then useVars info
else if info `hasOpt` scrapeImports
then impVars info
else [])
, q <- refTypeQuals lEnv (getSourcePos x) (tcEmbeds $ spec info) (val t)
, length (q_params q) <= k + 1
]
refTypeQuals :: SEnv Sort -> SourcePos -> TCEmb TyCon -> SpecType -> [Qualifier]
refTypeQuals lEnv l tce t0 = go emptySEnv t0
where
scrape = refTopQuals lEnv l tce t0
add x t γ = insertSEnv x (rTypeSort tce t) γ
goBind x t γ t' = go (add x t γ) t'
go γ t@(RVar _ _) = scrape γ t
go γ (RAllT _ t) = go γ t
go γ (RAllP p t) = go (insertSEnv (pname p) (rTypeSort tce $ (pvarRType p :: RSort)) γ) t
go γ t@(RAppTy t1 t2 _) = go γ t1 ++ go γ t2 ++ scrape γ t
go γ (RFun x t t' _) = go γ t ++ goBind x t γ t'
go γ t@(RApp c ts rs _) = scrape γ t ++ concatMap (go γ') ts ++ goRefs c γ' rs
where γ' = add (rTypeValueVar t) t γ
go γ (RAllE x t t') = go γ t ++ goBind x t γ t'
go γ (REx x t t') = go γ t ++ goBind x t γ t'
go _ _ = []
goRefs c g rs = concat $ zipWith (goRef g) rs (rTyConPVs c)
goRef _ (RProp _ (RHole _)) _ = []
goRef g (RProp s t) _ = go (insertsSEnv g s) t
insertsSEnv = foldr (\(x, t) γ -> insertSEnv x (rTypeSort tce t) γ)
refTopQuals lEnv l tce t0 γ t
= [ mkQ v so pa | let (RR so (Reft (v, ra))) = rTypeSortedReft tce t
, pa <- conjuncts ra
, not $ isHole pa
]
++
[ mkP s e | let (MkUReft _ (Pr ps) _) = fromMaybe (msg t) $ stripRTypeBase t
, p <- findPVar (ty_preds $ toRTypeRep t0) <$> ps
, (s, _, e) <- pargs p
]
where
mkQ = mkQual lEnv l t0 γ
mkP = mkPQual lEnv l tce t0 γ
msg t = panic Nothing $ "Qualifier.refTopQuals: no typebase" ++ showpp t
mkPQual lEnv l tce t0 γ t e = mkQual lEnv l t0 γ' v so pa
where
v = "vv"
so = rTypeSort tce t
γ' = insertSEnv v so γ
pa = PAtom Eq (EVar v) e
mkQual = mkQualNEW
mkQualNEW lEnv l _ γ v so p = Q "Auto" ((v, so) : xts) p l
where
xs = delete v $ nub $ syms p
xts = catMaybes $ zipWith (envSort l lEnv γ) xs [0..]
envSort :: SourcePos -> SEnv Sort -> SEnv Sort -> Symbol -> Integer -> Maybe (Symbol, Sort)
envSort l lEnv tEnv x i
| Just t <- lookupSEnv x tEnv = Just (x, t)
| Just _ <- lookupSEnv x lEnv = Nothing
| otherwise = Just (x, ai)
where
ai = trace msg $ fObj $ Loc l l $ tempSymbol "LHTV" i
msg = "unknown symbol in qualifier: " ++ show x