module Language.Haskell.Liquid.Bare.Plugged (
makePluggedSigs
, makePluggedAsmSigs
, makePluggedDataCons
) where
import DataCon
import Module
import Name
import NameSet
import TyCon
import Type (expandTypeSynonyms)
import Var
import Control.Applicative ((<$>), (<*>))
import Control.Monad
import Control.Monad.Error
import Data.Generics.Aliases (mkT)
import Data.Generics.Schemes (everywhere)
import Data.Monoid
import qualified Data.HashMap.Strict as M
import Language.Fixpoint.Names (dummySymbol)
import Language.Fixpoint.Types (mapPredReft, pAnd, conjuncts, Refa (..), TCEmb)
import Language.Haskell.Liquid.GhcMisc (sourcePosSrcSpan)
import Language.Haskell.Liquid.RefType (addTyConInfo, ofType, rVar, rTyVar, subts, toType, uReft)
import Language.Haskell.Liquid.Types
import Language.Haskell.Liquid.Bare.Env
import Language.Haskell.Liquid.Bare.Misc
makePluggedSigs name embs tcEnv exports sigs
= forM sigs $ \(x,t) -> do
let τ = expandTypeSynonyms $ varType x
let r = maybeTrue x name exports
(x,) <$> plugHoles embs tcEnv x r τ t
makePluggedAsmSigs embs tcEnv sigs
= forM sigs $ \(x,t) -> do
let τ = expandTypeSynonyms $ varType x
let r = killHoles
(x,) <$> plugHoles embs tcEnv x r τ t
makePluggedDataCons embs tcEnv dcs
= forM dcs $ \(dc, Loc l l' dcp) -> do
let (das, _, dts, dt) = dataConSig dc
tyArgs <- zipWithM (\t1 (x,t2) ->
(x,) . val <$> plugHoles embs tcEnv (dataConName dc) killHoles t1 (Loc l l' t2))
dts (reverse $ tyArgs dcp)
tyRes <- val <$> plugHoles embs tcEnv (dataConName dc) killHoles dt (Loc l l' (tyRes dcp))
return (dc, Loc l l' dcp { freeTyVars = map rTyVar das
, freePred = map (subts (zip (freeTyVars dcp) (map (rVar :: TyVar -> RSort) das))) (freePred dcp)
, tyArgs = reverse tyArgs
, tyRes = tyRes})
plugHoles tce tyi x f t (Loc l l' st)
= do tyvsmap <- case runMapTyVars (mapTyVars (toType rt') st'') initvmap of
Left e -> throwError e
Right s -> return $ vmap s
let su = [(y, rTyVar x) | (x, y) <- tyvsmap]
st''' = subts su st''
ps' = fmap (subts su') <$> ps
su' = [(y, RVar (rTyVar x) ()) | (x, y) <- tyvsmap] :: [(RTyVar, RSort)]
Loc l l' . mkArrow αs ps' (ls1 ++ ls2) [] . makeCls cs' <$> go rt' st'''
where
(αs, _, ls1, rt) = bkUniv (ofType t :: SpecType)
(cs, rt') = bkClass rt
(_, ps, ls2, st') = bkUniv st
(_, st'') = bkClass st'
cs' = [(dummySymbol, RApp c t [] mempty) | (c,t) <- cs]
initvmap = initMapSt $ ErrMismatch (sourcePosSrcSpan l) (pprint x) t (toType st)
go :: SpecType -> SpecType -> BareM SpecType
go t (RHole r) = return $ (addHoles t') { rt_reft = f r }
where
t' = everywhere (mkT $ addRefs tce tyi) t
addHoles = fmap (const $ f $ uReft ("v", Refa hole))
go (RVar _ _) v@(RVar _ _) = return v
go (RFun _ i o _) (RFun x i' o' r) = RFun x <$> go i i' <*> go o o' <*> return r
go (RAllT _ t) (RAllT a t') = RAllT a <$> go t t'
go (RAllT a t) t' = RAllT a <$> go t t'
go t (RAllP p t') = RAllP p <$> go t t'
go t (RAllS s t') = RAllS s <$> go t t'
go t (RAllE b a t') = RAllE b a <$> go t t'
go t (REx b x t') = REx b x <$> go t t'
go t (RRTy e r o t') = RRTy e r o <$> go t t'
go (RAppTy t1 t2 _) (RAppTy t1' t2' r) = RAppTy <$> go t1 t1' <*> go t2 t2' <*> return r
go (RApp _ t _ _) (RApp c t' p r) = RApp c <$> (zipWithM go t t') <*> return p <*> return r
go _ st = return st
makeCls cs t = foldr (uncurry rFun) t cs
addRefs :: TCEmb TyCon
-> M.HashMap TyCon RTyCon
-> SpecType
-> SpecType
addRefs tce tyi (RApp c ts _ r) = RApp c' ts ps r
where
RApp c' _ ps _ = addTyConInfo tce tyi (RApp c ts [] r)
addRefs _ _ t = t
maybeTrue :: NamedThing a => a -> ModName -> NameSet -> RReft -> RReft
maybeTrue x target exports r
| isInternalName name || inTarget && notExported
= r
| otherwise
= killHoles r
where
inTarget = moduleName (nameModule name) == getModName target
name = getName x
notExported = not $ getName x `elemNameSet` exports
killHoles ur = ur { ur_reft = tx $ ur_reft ur }
where
tx r = mapPredReft dropHoles r
dropHoles = pAnd . filter (not . isHole) . conjuncts