module Cryptol.ModuleSystem.NamingEnv where
import Cryptol.ModuleSystem.Interface
import Cryptol.Parser.AST
import Cryptol.Parser.Names (namesP)
import Cryptol.Parser.Position
import qualified Cryptol.TypeCheck.AST as T
import Cryptol.Utils.PP
import Cryptol.Utils.Panic (panic)
import qualified Data.Map as Map
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative (Applicative, (<$>), (<*>))
import Data.Monoid (Monoid(..))
import Data.Foldable (foldMap)
import Data.Traversable (traverse)
#endif
data NameOrigin = Local (Located QName)
| Imported QName
deriving (Show)
instance PP NameOrigin where
ppPrec _ o = case o of
Local lqn -> pp lqn
Imported (QName m n) -> pp n <+> trailer
where
trailer = case m of
Just mn -> text "from module" <+> pp mn
_ -> empty
data EName = EFromBind (Located QName)
| EFromNewtype (Located QName)
| EFromMod QName
deriving (Show)
data TName = TFromParam QName
| TFromSyn (Located QName)
| TFromNewtype (Located QName)
| TFromMod QName
deriving (Show)
class HasQName a where
qname :: a -> QName
origin :: a -> NameOrigin
instance HasQName TName where
qname tn = case tn of
TFromParam qn -> qn
TFromSyn lqn -> thing lqn
TFromNewtype lqn -> thing lqn
TFromMod qn -> qn
origin tn = case tn of
TFromParam qn -> Local Located { srcRange = emptyRange, thing = qn }
TFromSyn lqn -> Local lqn
TFromNewtype lqn -> Local lqn
TFromMod qn -> Imported qn
instance HasQName EName where
qname en = case en of
EFromBind lqn -> thing lqn
EFromNewtype lqn -> thing lqn
EFromMod qn -> qn
origin en = case en of
EFromBind lqn -> Local lqn
EFromNewtype lqn -> Local lqn
EFromMod qn -> Imported qn
data NamingEnv = NamingEnv { neExprs :: Map.Map QName [EName]
, neTypes :: Map.Map QName [TName]
} deriving (Show)
instance Monoid NamingEnv where
mempty =
NamingEnv { neExprs = Map.empty
, neTypes = Map.empty }
mappend l r =
NamingEnv { neExprs = Map.unionWith (++) (neExprs l) (neExprs r)
, neTypes = Map.unionWith (++) (neTypes l) (neTypes r) }
mconcat envs =
NamingEnv { neExprs = Map.unionsWith (++) (map neExprs envs)
, neTypes = Map.unionsWith (++) (map neTypes envs) }
singletonT :: QName -> TName -> NamingEnv
singletonT qn tn = mempty { neTypes = Map.singleton qn [tn] }
singletonE :: QName -> EName -> NamingEnv
singletonE qn en = mempty { neExprs = Map.singleton qn [en] }
shadowing :: NamingEnv -> NamingEnv -> NamingEnv
shadowing l r = NamingEnv
{ neExprs = Map.union (neExprs l) (neExprs r)
, neTypes = Map.union (neTypes l) (neTypes r) }
travNamingEnv :: Applicative f => (QName -> f QName) -> NamingEnv -> f NamingEnv
travNamingEnv f ne = NamingEnv <$> neExprs' <*> neTypes'
where
neExprs' = traverse (traverse travE) (neExprs ne)
neTypes' = traverse (traverse travT) (neTypes ne)
travE en = case en of
EFromBind lqn -> EFromBind <$> travLoc lqn
EFromNewtype lqn -> EFromNewtype <$> travLoc lqn
EFromMod qn -> EFromMod <$> f qn
travT tn = case tn of
TFromParam qn -> TFromParam <$> f qn
TFromSyn lqn -> TFromSyn <$> travLoc lqn
TFromNewtype lqn -> TFromNewtype <$> travLoc lqn
TFromMod qn -> TFromMod <$> f qn
travLoc loc = Located (srcRange loc) <$> f (thing loc)
class BindsNames a where
namingEnv :: a -> NamingEnv
instance BindsNames NamingEnv where
namingEnv = id
instance BindsNames a => BindsNames (Maybe a) where
namingEnv = foldMap namingEnv
instance BindsNames a => BindsNames [a] where
namingEnv = foldMap namingEnv
instance BindsNames Schema where
namingEnv (Forall ps _ _ _) = foldMap namingEnv ps
instance BindsNames Iface where
namingEnv = namingEnv . ifPublic
instance BindsNames IfaceDecls where
namingEnv binds = mconcat [ types, newtypes, vars ]
where
types = mempty
{ neTypes = Map.map (map (TFromMod . ifTySynName)) (ifTySyns binds)
}
newtypes = mempty
{ neTypes = Map.map (map (TFromMod . T.ntName)) (ifNewtypes binds)
, neExprs = Map.map (map (EFromMod . T.ntName)) (ifNewtypes binds)
}
vars = mempty
{ neExprs = Map.map (map (EFromMod . ifDeclName)) (ifDecls binds)
}
instance BindsNames Match where
namingEnv m = case m of
Match p _ -> namingEnv p
MatchLet b -> namingEnv b
instance BindsNames Bind where
namingEnv b = singletonE (thing qn) (EFromBind qn)
where
qn = bName b
instance BindsNames TParam where
namingEnv p = singletonT qn (TFromParam qn)
where
qn = mkUnqual (tpName p)
instance BindsNames Pattern where
namingEnv p = foldMap unqualBind (namesP p)
where
unqualBind qn = singletonE (thing qn) (EFromBind qn)
instance BindsNames Module where
namingEnv m = foldMap topDeclEnv (mDecls m)
where
topDeclEnv td = case td of
Decl d -> declEnv (tlValue d)
TDNewtype n -> newtypeEnv (tlValue n)
Include _ -> mempty
qual = fmap (\qn -> mkQual (thing (mName m)) (unqual qn))
qualBind ln = singletonE (thing ln) (EFromBind (qual ln))
qualType ln = singletonT (thing ln) (TFromSyn (qual ln))
declEnv d = case d of
DSignature ns _sig -> foldMap qualBind ns
DPragma ns _p -> foldMap qualBind ns
DBind b -> qualBind (bName b)
DPatBind _pat _e -> panic "ModuleSystem" ["Unexpected pattern binding"]
DType (TySyn lqn _ _) -> qualType lqn
DLocated d' _ -> declEnv d'
newtypeEnv n = singletonT (thing qn) (TFromNewtype (qual qn))
`mappend` singletonE (thing qn) (EFromNewtype (qual qn))
where
qn = nName n
instance BindsNames Decl where
namingEnv d = case d of
DSignature ns _sig -> foldMap qualBind ns
DPragma ns _p -> foldMap qualBind ns
DBind b -> qualBind (bName b)
DPatBind _pat _e -> panic "ModuleSystem" ["Unexpected pattern binding"]
DType (TySyn lqn _ _) -> qualType lqn
DLocated d' _ -> namingEnv d'
where
qualBind ln = singletonE (thing ln) (EFromBind ln)
qualType ln = singletonT (thing ln) (TFromSyn ln)