[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / ghc / compiler / uniType / UniType.lhs
diff --git a/ghc/compiler/uniType/UniType.lhs b/ghc/compiler/uniType/UniType.lhs
new file mode 100644 (file)
index 0000000..7cbbe44
--- /dev/null
@@ -0,0 +1,370 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+%
+\section[UniType]{The UniType data type}
+
+The module @AbsUniType@ is the normal interface to this datatype.
+This interface is for ``Friends Only.''
+
+\begin{code}
+#include "HsVersions.h"
+
+module UniType (
+       UniType(..),    -- not abstract; usually grabbed through AbsUniType
+
+       -- USEFUL SYNONYMS
+       SigmaType(..), RhoType(..), TauType(..),
+       ThetaType(..),                  -- synonym for [(Class,UniType)]
+       InstTyEnv(..),
+
+       -- CONSTRUCTION
+       mkTyVarTy, mkTyVarTemplateTy, mkDictTy,
+       -- use applyTyCon to make UniDatas, UniSyns
+       mkRhoTy, mkForallTy, mkSigmaTy, -- ToDo: perhaps nuke one?
+
+       -- QUANTIFICATION & INSTANTIATION
+       quantifyTy,
+       instantiateTy,  instantiateTauTy,  instantiateThetaTy,
+
+       -- COMPARISON
+       cmpUniType,
+
+       -- PRE-BUILT TYPES (for Prelude)
+       alpha, beta, gamma, delta, epsilon,                     -- these have templates in them
+       alpha_ty, beta_ty, gamma_ty, delta_ty, epsilon_ty,      -- these have tyvars in them
+
+       -- to make the interface self-sufficient...
+       Class, TyCon, TyVar, TyVarTemplate, Maybe
+   ) where
+
+IMPORT_Trace           -- ToDo:rm (debugging only)
+
+#if USE_ATTACK_PRAGMAS
+import Class           ( cmpClass, getClassSig, Class(..), ClassOp(..) )
+#else
+import Class           ( cmpClass, getClassSig, Class, ClassOp )
+#endif
+import Maybes          ( assocMaybe, Maybe(..) )
+import Outputable      -- the output class, etc.
+import Pretty
+import TyCon           ( cmpTyCon, TyCon, Arity(..) )
+import TyVar           -- various things
+import UniTyFuns       ( pprUniType, unDictifyTy
+                         IF_ATTACK_PRAGMAS(COMMA pprTyCon)
+                       )
+import Util
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[UniType-basics]{Basics of the @UniType@ datatype}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+data UniType
+  = 
+    -- The free variables of a UniType are always TyVars.
+    UniTyVar   TyVar
+
+  | UniFun     UniType -- Function type
+               UniType
+
+  | UniData            -- Application of a non SynonymTyCon
+               TyCon           -- Must NOT be a SynonymTyCon
+               [UniType]       -- Arguments to the type constructor
+
+  | UniSyn             -- Application of a SynonymTyCon
+               TyCon           -- Must be a SynonymTyCon
+               [UniType]       -- Arguments to the type constructor
+               UniType         -- Expanded version (merely cached here)
+
+  | UniDict    Class
+               UniType
+
+  -- The next two are to do with universal quantification
+
+  -- TyVarTemplates only need be unique within a single UniType;
+  -- because they are always bound by an enclosing UniForall.
+  | UniTyVarTemplate           
+               TyVarTemplate
+
+  | UniForall  TyVarTemplate
+               UniType
+\end{code}
+
+Universal quantification is over @TyVarTemplate@s.  A type containing
+a @UniTyVarTemplate@ always has either an enclosing @UniForall@ which
+binds it, or a ``nearby'' binding @TyVarTemplate@.  The only example
+of the latter is that a @ClassOp@ will have a free occurrence of the
+@TyVarTemplate@ which is held in the @Class@ object.
+
+@UniTyVarTemplate@s are never encountered during unification.
+
+The reasons for this huff and puff over template variables are:
+\begin{enumerate}
+\item
+It's nice to be able to identify them in the code.
+\item
+It saves worry about accidental capture when instantiating types,
+because the types with which the template variables are being
+instantiated never themselves contain @UniTyVarTemplates@.
+\end{enumerate}
+
+Note: if not @do_properly@, then we treat @UniTyVarTemplates@ as
+``wildcards;'' we use this {\em only} when comparing types in STG
+land.  It is the responsibility of the caller to strip the
+@UniForalls@ off the front.
+
+\begin{code}
+cmpUniType do_properly ty1 ty2
+  = cmp_ty [] ty1 ty2
+  where
+    cmp_ty equivs (UniTyVar tv1) (UniTyVar  tv2) = tv1 `cmpTyVar` tv2
+
+    cmp_ty equivs (UniFun a1 b1) (UniFun a2 b2)
+      = case cmp_ty equivs a1 a2 of { EQ_ -> cmp_ty equivs b1 b2; other -> other }
+
+    cmp_ty equivs (UniData tc1 tys1) (UniData tc2 tys2)
+      = case cmpTyCon tc1 tc2 of { EQ_ -> cmp_ty_lists equivs tys1 tys2; other -> other }
+
+    cmp_ty equivs (UniForall tv1 ty1) (UniForall tv2 ty2)
+      = cmp_ty ((tv1,tv2) : equivs) ty1 ty2
+\end{code}
+
+Now we deal with the Dict/Dict case.  If the two classes are the same
+then all is straightforward.  If not, the two dicts will usually
+differ, but (rarely) we could still be looking at two equal
+dictionaries!  For example,
+
+     class Foo a => Baz a where
+
+That is, Foo is the only superclass of Baz, and Baz has no methods.
+Then a Baz dictionary will be represented simply by a Foo dictionary!
+
+We could sort this out by unDictifying, but that seems like a
+sledgehammer to crack a (rather rare) nut.  Instead we ``de-synonym''
+each class, by looking to see if it is one of these odd guys which has
+no ops and just one superclass (if so, do the same to this
+superclass), and then compare the results.
+
+\begin{code}
+    cmp_ty equivs (UniDict c1 ty1) (UniDict c2 ty2)
+      = case cmpClass c1 c2 of  
+         EQ_   -> cmp_ty equivs ty1 ty2
+         other -> case cmpClass (super_ify c1) (super_ify c2) of
+                       EQ_   -> cmp_ty equivs ty1 ty2
+                       other -> other
+      where
+       super_ify :: Class -> Class     -- Iff the arg is a class with just one
+                                       -- superclass and no operations, then
+                                       -- return super_ify of the superclass,
+                                       -- otherwise just return the original
+       super_ify clas
+         = case getClassSig clas of
+             (_, [super_clas], [{-no ops-}]) -> super_ify super_clas
+             other                           -> clas
+\end{code}
+               
+Back to more straightforward things.
+
+\begin{code}
+    cmp_ty equivs (UniTyVarTemplate tv1) (UniTyVarTemplate tv2)
+      | not do_properly -- STG case: tyvar templates are ``wildcards''
+      = EQ_
+
+      | otherwise -- compare properly
+      = case (tv1 `cmp_tv_tmpl` tv2) of
+         EQ_ -> EQ_
+         _   -> -- tv1 should Jolly Well be in the equivalents list
+                case assocMaybe equivs tv1 of
+                  Just xx -> xx `cmp_tv_tmpl` tv2
+                  Nothing ->
+#if defined(DEBUG)
+                             case (pprPanic "cmpUniType:failed assoc:" (ppCat [ppr PprDebug tv1, ppr PprDebug tv2, ppr PprDebug ty1, ppr PprDebug ty2, ppr PprDebug equivs])) of
+#else
+                             case (panic "cmpUniType:failed assoc") of
+#endif
+                               s -> -- never get here (BUG)
+                                    cmp_ty equivs s s
+
+    cmp_ty equivs a@(UniDict _ _) b  = cmp_ty equivs (unDictifyTy a) b
+    cmp_ty equivs a b@(UniDict _ _)  = cmp_ty equivs a (unDictifyTy b)
+
+    cmp_ty equivs (UniSyn _ _ expand) b = cmp_ty equivs expand b
+    cmp_ty equivs a (UniSyn _ _ expand) = cmp_ty equivs a expand
+
+    -- more special cases for STG case
+    cmp_ty equivs (UniTyVarTemplate _) b | not do_properly = EQ_
+    cmp_ty equivs a (UniTyVarTemplate _) | not do_properly = EQ_
+
+    cmp_ty equivs other_1 other_2
+      = let tag1 = tag other_1
+           tag2 = tag other_2
+       in
+       if tag1 _LT_ tag2 then LT_ else GT_
+      where
+       tag (UniTyVar _)         = (ILIT(1) :: FAST_INT)
+       tag (UniFun _ _)         = ILIT(2)
+       tag (UniData _ _)        = ILIT(3)
+       tag (UniDict _ _)        = ILIT(4)
+       tag (UniForall _ _)      = ILIT(5)
+       tag (UniTyVarTemplate _) = ILIT(6)
+       tag (UniSyn _ _ _)       = ILIT(7)
+
+    cmp_tv_tmpl :: TyVarTemplate -> TyVarTemplate -> TAG_
+    cmp_tv_tmpl tv1 tv2
+      = if tv1 == tv2 then EQ_ else if tv1 < tv2 then LT_ else GT_
+
+    cmp_ty_lists equivs []     []     = EQ_
+    cmp_ty_lists equivs (x:xs) []     = GT_
+    cmp_ty_lists equivs []     (y:ys) = LT_
+    cmp_ty_lists equivs (x:xs) (y:ys)
+      = case cmp_ty equivs x y of { EQ_ -> cmp_ty_lists equivs xs ys; other -> other }
+\end{code}
+
+\begin{code}
+instance Eq  UniType where
+    a == b = case cmpUniType True{-properly-} a b of { EQ_ -> True;   _ -> False }
+    a /= b = case cmpUniType True{-properly-} a b of { EQ_ -> False;  _ -> True  }
+\end{code}
+
+Useful synonyms:
+
+\begin{code}
+type SigmaType  = UniType
+type RhoType    = UniType              -- No UniForall, UniTyVarTemplate 
+type TauType    = UniType              -- No UniDict constructors either
+type ThetaType  = [(Class, TauType)]   -- No UniForalls in the UniTypes
+
+type InstTyEnv = [(TyVarTemplate, TauType)]    -- Used for instantiating types
+\end{code}
+
+Using @UniType@, a @SigmaType@ such as (Eq a) => a -> [a]
+is written as
+\begin{verbatim}
+UniForall TyVarTemplate
+      (UniFun (UniDict Class (UniTyVarTemplate TyVarTemplate))
+              (UniFun (UniTyVarTemplate TyVarTemplate)
+                      (UniData TyCon [(UniTyVar TyVarTemplate)])))
+\end{verbatim}
+
+NB: @mkFunTy@ comes from the prelude.
+
+\begin{code}
+mkTyVarTy         = UniTyVar
+mkTyVarTemplateTy = UniTyVarTemplate
+mkDictTy          = UniDict
+-- use applyTyCon to make UniDatas and UniSyns
+
+alpha = UniTyVarTemplate alpha_tv
+beta  = UniTyVarTemplate beta_tv
+gamma = UniTyVarTemplate gamma_tv
+delta = UniTyVarTemplate delta_tv
+epsilon = UniTyVarTemplate epsilon_tv
+
+alpha_ty = UniTyVar alpha_tyvar
+beta_ty  = UniTyVar beta_tyvar
+gamma_ty = UniTyVar gamma_tyvar
+delta_ty = UniTyVar delta_tyvar
+epsilon_ty = UniTyVar epsilon_tyvar
+
+mkRhoTy :: ThetaType -> TauType -> RhoType
+mkRhoTy theta tau
+  = foldr mk_dict tau theta
+  where
+    mk_dict (clas,ty) ty_body = UniFun (UniDict clas ty) ty_body
+
+mkForallTy [] ty = ty
+mkForallTy tyvars ty = foldr UniForall ty tyvars
+
+mkSigmaTy :: [TyVarTemplate] -> ThetaType -> TauType -> SigmaType
+mkSigmaTy tyvars theta tau = foldr UniForall (mkRhoTy theta tau) tyvars
+\end{code}
+
+@quantifyTy@ takes @TyVars@ (not templates) and a  @SigmaType@, and quantifies
+over them.  It makes new template type variables, and substitutes for the
+original variables in the body.
+
+\begin{code}
+quantifyTy :: [TyVar] -> SigmaType -> ([TyVarTemplate], SigmaType)
+
+quantifyTy [] ty = ([], ty)    -- Simple, common case
+
+quantifyTy tyvars ty
+ = (templates, foldr UniForall (quant ty) templates)
+ where
+   templates = mkTemplateTyVars tyvars
+   env       = tyvars `zip` (map UniTyVarTemplate templates)
+
+   quant :: SigmaType -> SigmaType     -- Rename the quantified type variables
+                                       -- to their template equivalents
+
+   quant old_ty@(UniTyVar v)  = case (assocMaybe env v) of
+                                 Nothing -> old_ty     -- We may not be quantifying
+                                                       -- over all the type vars!
+                                 Just ty -> ty
+
+   quant ty@(UniTyVarTemplate v) = ty
+   quant ty@(UniData con [])  = ty
+   quant (UniData con tys)    = UniData con (map quant tys)
+   quant (UniSyn con tys ty)  = UniSyn con (map quant tys) (quant ty)
+   quant (UniFun ty1 ty2)     = UniFun (quant ty1) (quant ty2)
+   quant (UniDict clas ty)    = UniDict clas (quant ty)
+
+   quant (UniForall tv ty)    =
+#ifdef DEBUG
+                               -- Paranoia check here; shouldn't happen
+                               if tv `elem` templates then
+                                       panic "quantifyTy"
+                               else
+#endif
+                                       UniForall tv (quant ty)
+\end{code}
+
+@instantiateTy@ is the inverse.  It instantiates the free @TyVarTemplates@ 
+of a type.  We assume that no inner Foralls bind one of the variables
+being instantiated.
+
+\begin{code}
+instantiateTy    :: InstTyEnv -> UniType -> UniType
+
+instantiateTy [] ty = ty       -- Simple, common case
+
+instantiateTy env ty 
+  = inst ty
+  where
+    inst ty@(UniTyVar v)      = ty
+    inst ty@(UniData con [])  = ty
+    inst (UniData con tys)    = UniData con (map inst tys)
+    inst (UniFun ty1 ty2)     = UniFun (inst ty1) (inst ty2)
+    inst (UniSyn con tys ty)  = UniSyn  con (map inst tys) (inst ty)
+    inst (UniDict clas ty)    = UniDict clas (inst ty)
+    inst (UniForall v ty)     = UniForall v (inst ty)
+
+    inst old_ty@(UniTyVarTemplate v) = case (assocMaybe env v) of
+                                        Nothing -> old_ty  -- May partially instantiate
+                                        Just ty -> ty
+\end{code}
+The case mentioned in the comment (ie when the template isn't in the envt)
+occurs when we instantiate a class op type before instantiating with the class
+variable itself.
+\begin{code}
+instantiateTauTy :: InstTyEnv -> TauType -> TauType
+instantiateTauTy tenv ty = instantiateTy tenv ty
+
+instantiateThetaTy :: InstTyEnv -> ThetaType -> ThetaType
+instantiateThetaTy tenv theta
+ = [(clas,instantiateTauTy tenv ty) | (clas,ty) <- theta]
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[UniType-instances]{Instance declarations for @UniType@}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+instance Outputable UniType where
+    ppr = pprUniType
+\end{code}