summaryrefslogtreecommitdiff
path: root/ghc/compiler/envs/E.lhs
diff options
context:
space:
mode:
Diffstat (limited to 'ghc/compiler/envs/E.lhs')
-rw-r--r--ghc/compiler/envs/E.lhs268
1 files changed, 268 insertions, 0 deletions
diff --git a/ghc/compiler/envs/E.lhs b/ghc/compiler/envs/E.lhs
new file mode 100644
index 0000000000..c0c8b0f764
--- /dev/null
+++ b/ghc/compiler/envs/E.lhs
@@ -0,0 +1,268 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+%
+\section[E]{Main typechecker environment}
+
+\begin{code}
+#include "HsVersions.h"
+
+module E (
+ E,
+ mkE, nullE,
+ getE_GlobalVals, getE_TCE, getE_CE,
+ plusE_TCE, plusE_CE,
+
+ growE_LVE, plusE_GVE, tvOfE,
+
+ lookupE_Value, lookupE_ValueQuietly,
+ lookupE_ClassOpByKey, lookupE_Binder,
+
+ GVE(..), LVE(..),
+ plusLVE, nullLVE,
+ plusGVE, nullGVE, unitGVE, -- UNUSED: rngGVE,
+
+ -- and to make the interface self-sufficient...
+ CE(..), Id, Name, TCE(..), TyVar, Maybe, UniqFM
+ ) where
+
+import CE
+import TCE
+import UniqFM -- basic env handling code
+
+import AbsPrel ( PrimOp
+ IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
+ IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
+ )
+import AbsUniType ( getClassOps, extractTyVarsFromTy,
+ getClassBigSig, getClassOpString, TyVar,
+ TyVarTemplate, ClassOp, Class, Arity(..),
+ TauType(..)
+ IF_ATTACK_PRAGMAS(COMMA cmpTyVar COMMA cmpClass)
+ )
+import Id ( getIdUniType, Id, IdInfo )
+import Maybes ( MaybeErr(..), Maybe(..) )
+import Name -- Name(..), etc.
+import Outputable -- def of ppr, etc.
+import Pretty -- to pretty-print error messages
+import UniqSet -- this use of Sets is a HACK (WDP 94/05)
+import Unique -- *Key stuff
+import Util
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Type declarations}
+%* *
+%************************************************************************
+
+
+\begin{code}
+data E
+ = MkE TCE -- type environment
+ GVB -- "global" value bindings; no free type vars
+ LVB -- "local" value bindings; may have free type vars
+ CE -- class environment
+
+mkE :: TCE -> CE -> E
+mkE tce ce = MkE tce nullGVB nullLVB ce
+
+nullE :: E
+nullE = MkE nullTCE nullGVB nullLVB nullCE
+\end{code}
+
+The ``local'' and ``global'' bindings, @LVB@ and @GVB@, are
+non-exported synonyms. The important thing is that @GVB@ doesn't
+contain any free type variables. This is used (only) in @tvOfE@,
+which extracts free type variables from the environment. It's quite a
+help to have this separation because there may be quite a large bunch
+of imported things in the @GVB@, all of which are guaranteed
+polymorphic.
+
+\begin{code}
+type LVB = UniqFM Id -- Locals just have a Unique
+type GVB = UniqFM Id -- Globals might be a prelude thing; hence IdKey
+
+nullLVB = (emptyUFM :: LVB)
+nullGVB = (emptyUFM :: GVB)
+\end{code}
+
+The ``local'' and ``global'' value environments are not part of @E@ at
+all, but is used to provide increments to the value bindings. GVE are
+carries the implication that there are no free type variables.
+
+\begin{code}
+type LVE = [(Name, Id)] -- Maps Names to Ids
+type GVE = [(Name, Id)] -- Maps Names to Ids
+
+nullLVE = ([] :: LVE)
+plusLVE a b = a ++ b
+nullGVE = ([] :: GVE)
+unitGVE n i = ( [(n, i)] :: GVE )
+-- UNUSED: rngGVE gve = map snd gve
+plusGVE a b = a ++ b
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Value environment stuff}
+%* *
+%************************************************************************
+
+Looking up things should mostly succeed, because the renamer should
+have spotted all out-of-scope names. The exception is instances.
+
+The ``Quietly'' version is for pragmas, where lookups very well may
+fail. @lookup_val@ is the internal function that does the work.
+
+\begin{code}
+lookupE_Value :: E -> Name -> Id
+lookupE_ValueQuietly :: E -> Name -> Maybe Id
+
+lookupE_Value e nm
+ = case lookup_val e nm of
+ Succeeded id -> id
+ Failed (should_panic, msg)
+ -> if should_panic then panic msg else error msg
+
+lookupE_ValueQuietly e nm
+ = case lookup_val e nm of
+ Succeeded id -> Just id
+ Failed _ -> Nothing
+\end{code}
+
+\begin{code}
+lookup_val (MkE _ gvb lvb ce) name
+ = case name of
+
+ WiredInVal id -> Succeeded id
+ PreludeVal key _ -> case (lookupDirectlyUFM gvb key) of
+ Just id -> Succeeded id
+ Nothing -> Failed (False, prelude_err_msg)
+
+ ClassOpName uniq clas_name _ tag -> id_from_env uniq
+
+ -- You might think that top-level ids are guaranteed to have no
+ -- free tyvars, so look only in gvb; but you'd be wrong! When
+ -- type-checking the RHS of recursive top-level defns, the name
+ -- of the thing is bound to a *monomorphic* type, which is later
+ -- generalised. So we have to look in the LVE too.
+
+ OtherTopId uniq _ -> id_from_env uniq
+
+ -- Short names could be in either GVB or LVB
+ Short uniq _ -> id_from_env uniq
+
+ funny_name -> pprPanic "lookup_val: funny Name" (ppr PprDebug funny_name)
+ where
+ prelude_err_msg = "ERROR: in looking up a built-in Prelude value!\n(This can happen if you use `-fno-implicit-prelude'\nor you hide the system's Prelude.hi in some way.)"
+
+ id_from_env uniq
+ = case (lookupDirectlyUFM lvb uniq) of
+ Just id -> Succeeded id
+ Nothing ->
+ case (lookupDirectlyUFM gvb uniq) of
+ Just id -> Succeeded id
+ Nothing -> Failed (True, -- should panic
+ ("lookupE_Value: unbound name: "++(ppShow 80 (ppr PprShowAll name))))
+\end{code}
+
+For Prelude things that we reach out and grab, we have only an @Unique@.
+\begin{code}
+lookupE_ClassOpByKey :: E -> Unique{-ClassKey-} -> FAST_STRING -> Id
+
+lookupE_ClassOpByKey (MkE _ gvb lvb ce) clas_key op_str
+ = let
+ clas = lookupCE ce (PreludeClass clas_key bottom)
+ bottom = pprPanic ("lookupE_ClassOpByKey: "++(_UNPK_ op_str))
+ (ppAbove (pprUnique clas_key) (ppr PprShowAll (rngCE ce)))
+
+ (clas_tyvar_tmpl, scs, sc_sel_ids, ops, op_sel_ids, defm_ids)
+ = getClassBigSig clas
+ in
+ case [ op_sel_id | (op, op_sel_id) <- ops `zip` op_sel_ids,
+ op_str == getClassOpString op ] of
+ [op] -> op
+ -- Seems a rather horrible way to do it (ToDo)
+\end{code}
+
+@lookupE_Binder@ is like @lookupE_Value@, but it is used for {\em
+binding} occurrences of a variable, rather than {\em uses}. The
+difference is that there should always be an entry in the LVE for
+binding occurrences. Just a sanity check now, really.
+
+\begin{code}
+lookupE_Binder :: E -> Name -> Id
+lookupE_Binder (MkE _ _ lvb _) name
+ = case (lookupDirectlyUFM lvb (name2uniq name)) of
+ Just id -> id
+ Nothing -> pprPanic "lookupE_Binder: unbound name: " (ppr PprShowAll name)
+\end{code}
+
+\begin{code}
+getE_GlobalVals :: E -> [Id]
+getE_GlobalVals (MkE tce gvb lvb ce)
+ = let
+ result = eltsUFM gvb ++ eltsUFM lvb
+ in
+ -- pprTrace "Global Ids:" (ppr PprShowAll result)
+ result
+
+plusE_GVE :: E -> GVE -> E
+plusE_GVE (MkE tce gvb lvb ce) gve
+ = let
+ new_stuff = listToUFM_Directly [(name2idkey n, i) | (n,i) <- gve ]
+ in
+ MkE tce (plusUFM gvb new_stuff) lvb ce
+ where
+ name2idkey (PreludeVal k _) = k
+ name2idkey (OtherTopId u _) = u
+ name2idkey (ClassOpName u _ _ _) = u
+
+growE_LVE :: E -> LVE -> E
+growE_LVE (MkE tce gvb lvb ce) lve
+ = let
+ new_stuff = listToUFM_Directly [(name2uniq n, i) | (n,i) <- lve ]
+ in
+ MkE tce gvb (plusUFM lvb new_stuff) ce
+
+-- ToDo: move this elsewhere??
+name2uniq (Short u _) = u
+name2uniq (OtherTopId u _) = u
+name2uniq (ClassOpName u _ _ _) = panic "growE_LVE:name2uniq"
+\end{code}
+
+Return the free type variables of an LVE; there are no duplicates in
+the result---hence all the @Set@ bozo-ery. The free tyvars can only
+occur in the LVB part.
+
+\begin{code}
+tvOfE :: E -> [TyVar]
+tvOfE (MkE tce gvb lvb ce)
+ = uniqSetToList (mkUniqSet (
+ foldr ((++) . extractTyVarsFromTy . getIdUniType) [] (eltsUFM lvb)
+ ))
+\end{code}
+
+%************************************************************************
+%* *
+%*
+\subsection{Type and class environments}
+%* *
+%************************************************************************
+
+\begin{code}
+getE_TCE :: E -> TCE
+getE_TCE (MkE tce gvb lvb ce) = tce
+
+getE_CE :: E -> CE
+getE_CE (MkE tce gvb lvb ce) = ce
+
+plusE_TCE :: E -> TCE -> E
+plusE_TCE (MkE tce gvb lvb ce) tce'
+ = MkE (plusTCE tce' tce) gvb lvb ce
+
+plusE_CE :: E -> CE -> E
+plusE_CE (MkE tce gvb lvb ce) ce'
+ = MkE tce gvb lvb (plusCE ce ce')
+\end{code}