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 Control.Monad.Error()
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)

Plain-text version of OrigTiMonad.hs | Valid HTML?