module Environment
       (Env, emptyEnv, extendLocal, extendGlobal,
        makeEnv, unmakeEnv, lookupEnv, domEnv, freeTVarEnv)
       where

import Shows
import Parse
import Term           (VarId, readsId)
import Type           (TVarId, TConId, MonoType, PolyType (All), freeTVarPoly)
import FiniteMap      (FM, emptyFM, lookupFM, extendFM, makeFM, unmakeFM,
                       mapFM, domFM, ranFM)
data  Env             =   MkEnv (FM VarId PolyType)
rep                   ::  Env -> FM VarId PolyType
rep (MkEnv f)         =   f
emptyEnv              ::  Env
emptyEnv              =   MkEnv emptyFM
extendLocal           ::  Env -> VarId -> MonoType -> Env
extendLocal env x t   =   MkEnv (extendFM (rep env) x (All [] t))
extendGlobal          ::  Env -> VarId -> PolyType -> Env
extendGlobal env x t  =   MkEnv (extendFM (rep env) x t)
makeEnv               ::  [(VarId, PolyType)] -> Env
makeEnv               =   MkEnv . makeFM
unmakeEnv             ::  Env -> [(VarId, PolyType)]
unmakeEnv             =   unmakeFM . rep
lookupEnv             ::  Env -> VarId -> PolyType
lookupEnv env x       =   lookupFM (rep env) x
domEnv                ::  Env -> [VarId]
domEnv env            =   domFM (rep env)
freeTVarEnv           ::  Env -> [TVarId]
freeTVarEnv env       =   concat (map freeTVarPoly (ranFM (rep env)))
instance  Read Env  where
      readsPrec d  =  readsEnv
instance  Show Env  where
      showsPrec d  =  showsEnv
readsEnv              :: Parses Env
readsEnv              =  listP readsPair `eachP` makeEnv
readsPair             :: Parses (VarId, PolyType)
readsPair             =       readsId         `thenP` (\x ->
                              lexP ":"        `thenP` (\_ ->
                              reads           `thenP` (\t ->
                                              returnP (x,t))))
showsEnv              :: Shows Env
showsEnv              =  showsSurround "[" (showsStarSep ",\n " showsPair) "]"
                      .  unmakeEnv
showsPair             :: Shows (VarId, PolyType)
showsPair (x,t)       =  showsString x . showsString " : " . shows t

module Environment
       (Env, emptyEnv, extendLocal, extendGlobal,
        makeEnv, unmakeEnv, lookupEnv, domEnv, freeTVarEnv)
       where

import Shows
import Parse
import Term           (VarId, readsId)
import Type           (TVarId, TConId, MonoType, PolyType (All), freeTVarPoly)
import FiniteMap      (FM, emptyFM, lookupFM, extendFM, makeFM, unmakeFM,
                       mapFM, domFM, ranFM)
data  Env             =   MkEnv (FM VarId PolyType)
rep                   ::  Env -> FM VarId PolyType
rep (MkEnv f)         =   f
emptyEnv              ::  Env
emptyEnv              =   MkEnv emptyFM
extendLocal           ::  Env -> VarId -> MonoType -> Env
extendLocal env x t   =   MkEnv (extendFM (rep env) x (All [] t))
extendGlobal          ::  Env -> VarId -> PolyType -> Env
extendGlobal env x t  =   MkEnv (extendFM (rep env) x t)
makeEnv               ::  [(VarId, PolyType)] -> Env
makeEnv               =   MkEnv . makeFM
unmakeEnv             ::  Env -> [(VarId, PolyType)]
unmakeEnv             =   unmakeFM . rep
lookupEnv             ::  Env -> VarId -> PolyType
lookupEnv env x       =   lookupFM (rep env) x
domEnv                ::  Env -> [VarId]
domEnv env            =   domFM (rep env)
freeTVarEnv           ::  Env -> [TVarId]
freeTVarEnv env       =   concat (map freeTVarPoly (ranFM (rep env)))
instance  Read Env  where
      readsPrec d  =  readsEnv
instance  Show Env  where
      showsPrec d  =  showsEnv
readsEnv              :: Parses Env
readsEnv              =  listP readsPair `eachP` makeEnv
readsPair             :: Parses (VarId, PolyType)
readsPair             =       readsId         `thenP` (\x ->
                              lexP ":"        `thenP` (\_ ->
                              reads           `thenP` (\t ->
                                              returnP (x,t))))
showsEnv              :: Shows Env
showsEnv              =  showsSurround "[" (showsStarSep ",\n " showsPair) "]"
                      .  unmakeEnv
showsPair             :: Shows (VarId, PolyType)
showsPair (x,t)       =  showsString x . showsString " : " . shows t
