liquidhaskell-0.4.0.0: src/Language/Haskell/Liquid/Bare/Plugged.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TupleSections #-}
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.Fixpoint.Types (traceFix, showFix)
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
-- If we reach the default case, there's probably an error, but we defer
-- throwing it as checkGhcSpec does a much better job of reporting the
-- problem to the user.
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 r@(U (Reft (v, rs)) _ _) = r { ur_reft = Reft (v, filter (not . isHole) rs) }
killHoles ur = ur { ur_reft = tx $ ur_reft ur }
where
tx r = {- traceFix ("killholes: r = " ++ showFix r) $ -} mapPredReft dropHoles r
dropHoles = pAnd . filter (not . isHole) . conjuncts