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)