packages feed

HaRe-0.6: tools/base/TI/OrigTiMonad.hs

module OrigTiMonad(
   IM,run,--TI,KI,
   KEnv,
   getEnv,getTEnv,getKEnv,getIEnv,getModule,getDefaults,getStdNames,
   extendts,extend,extend1,extendkts,extendEnv,extendIEnv,
   inModule,inEnv,withStdNames,
   env,kenv,sch,kindOf,stdName,stdSch,constrain,getConstraints,monomorphism,
   monomorphismRestriction,
   errorContext,errorContext',posContext,posContext',declContext,moduleContext,
   (>:),freshInt
  ) where
import Prelude hiding (lookup) -- for Hugs
import Monad(MonadPlus(..))
import HsIdent(HsIdentI)
import HsName(ModuleName,Id,noModule)
import TiTypes
import TiKEnv(KEnv,lookup,extenv1,extenv)
import qualified TiKEnv(empty)
import TiTEnv(TEnv)
import qualified TiTEnv(lookup,extenv1,extenv,empty)
import TiInstanceDB(IDB,emptyIdb,extendIdb)
import TiConstraints(Constraints,empty,single,merge)
import DefinedNamesBase(NameSpace)
import TiError
import MUtils
import ExceptM()
import Lift
import PrettyPrint(Printable,pp,(<+>),(<>),ppi,vcat)

--type TEnv i = TiEnv.Env (HsIdentI i) (Scheme i) -- type of value identifiers
--type KEnv i = TiEnv.Env (HsIdentI i) (Kind,TypeInfo i) -- kind of type identifiers

data TiEnv i  = Env { inMod::FilePath->ModuleName,
		      stdNames::NameSpace->(ModuleName,Id)->Either String (HsIdentI i),
		      monomorphism::Bool, -- use the monomorpism restriction?
		      defaults::[[Type i]], -- from all default(t1,...,t2)
		      kenv::KEnv i,
		      tenv::TEnv i,
		      idb::IDB i }

emptyEnv = Env (const noModule) noStdNames
	       True [] TiKEnv.empty TiTEnv.empty emptyIdb
  where
    noStdNames ns (m,n) =
      fail $ pp $
        "Bug: no standard entities provided to the type checker:"<+>m<>"."<>n

newtype IM i c ans = IM { unIM::TiEnv i->Unique->Err i (Out c ans) }
--type TI i = IM i (TypeConstraint i)
--type KI i = IM i KindConstraint

type Err i ans = Either (Error (HsIdentI i)) ans

data Out c ans = Out ans (Unique,Constraints c)
type Unique = [Int]

instance Functor (Out i) where
  fmap f (Out ans out) = Out (f ans) out

instance Functor (IM i c) where
  fmap f (IM m) = IM $ \ env ids -> fmap (fmap f) (m env ids)

instance Monad (IM i c) where
  return ans = IM $ \ env ids -> Right (Out ans (ids,empty))
 
  IM m1 >>= xm2 =
     IM $ \ env ids0 ->
     case m1 env ids0 of
       Left err -> Left err
       Right (Out x (ids1,out1)) ->
         case unIM (xm2 x) env ids1 of
	   Left err -> Left err
	   Right (Out y (ids2,out2)) -> Right (Out y (ids2,merge out1 out2))

  fail = typeError . Other . vcat . lines

instance MonadPlus (IM i c) where
  mzero = fail "No error message provided (PFE programmer used mzero or msum)"
  IM m1 `mplus` IM m2 =
     IM $ \ env ids0 ->
     case m1 env ids0 of
       Left _ -> m2 env ids0
       r -> r

errmap f (IM m) =
  IM $ \ env ids ->
  case m env ids of
    Left err -> Left (f err)
    Right y -> Right y

inContext       ctx = errmap (InContext ctx)
errorContext'   txt locs = inContext (OtherCtx (ppi txt) locs)
errorContext    txt = errorContext' txt []
posContext  loc     = inContext (AtPos loc Nothing)
posContext' loc txt = inContext (AtPos loc (Just (ppi txt)))
moduleContext   ms  = inContext (ModuleCtx ms)
declContext     is  = inContext (DeclCtx is)

run (IM m) =
  case m emptyEnv [1..] of
    Left err -> Left err
    Right (Out ans (_,cs)) -> Right ans

instance (Printable i,Monad m) => Lift (IM i c) m where
  lift = lift . run

getConstraints (IM m) =
 IM $ \ env ids ->
 case m env ids of
   Left err -> Left err
   Right (Out ans (ids,cs)) -> Right (Out (ans,cs) (ids,empty))

typeError err = IM $ \ env ids -> Left err

constrain c = IM $ \ env vs -> Right (Out () (vs,single c))

modEnv f (IM m) = IM $ m . f
modTEnv f = modEnv (\env@Env{tenv=e}->env{tenv=f e})
modKEnv f = modEnv (\env@Env{kenv=e}->env{kenv=f e})
modIEnv f = modEnv (\env@Env{idb=e}->env{idb=f e})
monomorphismRestriction on = modEnv (\env->env{monomorphism=on})

getEnv = IM $ \ env ids -> Right (Out env (ids,empty))
getTEnv = tenv # getEnv
getKEnv = kenv # getEnv
getIEnv = idb # getEnv
getModule = inMod # getEnv
getStdNames = stdNames # getEnv
getDefaults = defaults # getEnv

extend1 x t = modTEnv (TiTEnv.extenv1 x t)
extend bs = modTEnv (TiTEnv.extenv bs)
extendts ts = extend [(x,t)|x:>:t<-ts]

extendk1 x t = modKEnv (extenv1 x t)
extendk bs = modKEnv (extenv bs)
extendkts ts = extendk [(x,t)|x:>:t<-ts]

extendEnv (ks, ts) = extendkts ks . extendts ts
--extendEnv' (ks, ts) = extendk ks . extend ts

extendIEnv env = modIEnv . extendIdb $ env

--inEnv env = modEnv (const env)
inEnv env (IM m) = IM $ \ _ -> m env

inModule m d = modEnv (\env->env{inMod=m,defaults=d})
withStdNames stdNames = modEnv (\env->env{stdNames=stdNames})

env' lookup x =
  do env <- getEnv
     case lookup env x of
       Nothing -> fail ("Not in scope: "++pp x{-++" in "++show (proj env)-})
       Just sch -> return sch

env proj = env' (TiKEnv.lookup . proj)

stdName ns o = do f <- getStdNames
	          lift (f ns o)

stdSch ns = sch @@ stdName ns

sch x = env' (TiTEnv.lookup . tenv) x
kindOf x = fst # env kenv x

freshInt = IM $ \ env (id:ids) -> Right (Out id (ids,empty))

infix 4 >:
(>:) :: e -> t -> IM i c (Typing e t)
e >: t = return (e :>: t)