[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / ghc / compiler / uniType / Class.lhs
diff --git a/ghc/compiler/uniType/Class.lhs b/ghc/compiler/uniType/Class.lhs
new file mode 100644 (file)
index 0000000..ca6c2ce
--- /dev/null
@@ -0,0 +1,386 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+%
+\section[Class]{The @Class@ datatype}
+
+\begin{code}
+#include "HsVersions.h"
+
+module Class (
+       Class(..),      -- must be *NON*-abstract so UniTyFuns can see it
+
+       mkClass,
+       getClassKey, getClassOps,
+       getSuperDictSelId, getClassOpId, getDefaultMethodId,
+       getConstMethodId,
+       getClassSig, getClassBigSig, getClassInstEnv,
+--UNUSED: getClassDefaultMethodsInfo,
+       isSuperClassOf,
+       cmpClass,
+
+       derivableClassKeys,
+       isNumericClass, isStandardClass, --UNUSED: isDerivableClass,
+
+       ClassOp(..),    -- must be non-abstract so UniTyFuns can see them
+       mkClassOp,
+       getClassOpTag, getClassOpString,
+--UNUSED: getClassOpSig,
+       getClassOpLocalType,
+
+       -- and to make the interface self-sufficient...
+       Id, InstTemplate, Maybe, Name, FullName, TyVarTemplate,
+       UniType, Unique
+    ) where
+
+import Id              ( getIdSpecialisation, Id )
+import IdInfo
+import InstEnv         ( ClassInstEnv(..), MatchEnv(..) )
+import Maybes          ( assocMaybe, Maybe(..) )
+import Name            ( Name(..), ShortName )
+import NameTypes       ( FullName, SrcLoc )
+import Pretty
+import Outputable      -- class for printing, forcing
+import TyCon           ( TyCon, Arity(..)
+                         IF_ATTACK_PRAGMAS(COMMA cmpTyCon)
+                       )
+import TyVar           ( TyVarTemplate )
+import Unique          -- class key stuff
+import UniType         ( UniType, ThetaType(..), TauType(..)
+                         IF_ATTACK_PRAGMAS(COMMA cmpUniType)
+                       )
+import UniTyFuns       ( splitType, pprClassOp
+                         IF_ATTACK_PRAGMAS(COMMA pprUniType COMMA pprTyCon)
+                       )
+import Util
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[Class-basic]{@Class@: basic definition}
+%*                                                                     *
+%************************************************************************
+
+A @Class@ corresponds to a Greek kappa in the static semantics:
+
+\begin{code}
+data Class
+  = MkClass 
+       Unique{-ClassKey-}-- Key for fast comparison
+       FullName
+
+       TyVarTemplate     -- The class type variable
+
+       [Class] [Id]      -- Immediate superclasses, and the
+                         -- corresponding selector functions to
+                         -- extract them from a dictionary of this
+                         -- class
+
+       [ClassOp]         -- The * class operations
+       [Id]              --     * selector functions
+       [Id]              --     * default methods
+                         -- They are all ordered by tag.  The
+                         -- selector ids are less innocent than they
+                         -- look, because their IdInfos contains
+                         -- suitable specialisation information.  In
+                         -- particular, constant methods are
+                         -- instances of selectors at suitably simple
+                         -- types.
+
+       ClassInstEnv      -- Gives details of all the instances of this class
+
+       [(Class,[Class])] -- Indirect superclasses;
+                         --   (k,[k1,...,kn]) means that
+                         --   k is an immediate superclass of k1
+                         --   k1 is an immediate superclass of k2
+                         --   ... and kn is an immediate superclass
+                         -- of this class.  (This is all redundant
+                         -- information, since it can be derived from
+                         -- the superclass information above.)
+\end{code}
+
+The @mkClass@ function fills in the indirect superclasses.
+
+\begin{code}
+mkClass :: Name -> TyVarTemplate
+       -> [Class] -> [Id]
+       -> [ClassOp] -> [Id] -> [Id]
+       -> ClassInstEnv
+       -> Class
+
+mkClass name tyvar super_classes superdict_sels
+       class_ops dict_sels defms class_insts
+  = MkClass key full_name tyvar
+               super_classes superdict_sels
+               class_ops dict_sels defms
+               class_insts
+               trans_clos
+  where
+    (key,full_name) = case name of
+                       OtherClass  uniq full_name _ -> (uniq, full_name)
+                       PreludeClass key full_name   -> (key,  full_name)
+
+    trans_clos :: [(Class,[Class])]
+    trans_clos = transitiveClosure succ (==) [ (clas, []) | clas <- super_classes ]
+
+    succ (clas@(MkClass _ _ _ super_classes _ _ _ _ _ _), links) 
+      = [(super, (clas:links)) | super <- super_classes]
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[Class-selectors]{@Class@: simple selectors}
+%*                                                                     *
+%************************************************************************
+
+The rest of these functions are just simple selectors.
+
+\begin{code}
+getClassKey (MkClass key _ _ _ _ _ _ _ _ _) = key
+
+getClassOps (MkClass _ _ _ _ _ ops _ _ _ _) = ops
+
+getSuperDictSelId (MkClass _ _ _ scs scsel_ids _ _ _ _ _) super_clas
+  = assoc "getSuperDictSelId" (scs `zip` scsel_ids) super_clas
+
+getClassOpId (MkClass _ _ _ _ _ ops op_ids _ _ _) op
+  = op_ids !! (getClassOpTag op - 1)
+
+getDefaultMethodId (MkClass _ _ _ _ _ ops _ defm_ids _ _) op
+  = defm_ids !! (getClassOpTag op - 1)
+
+getConstMethodId (MkClass _ _ _ _ _ ops op_ids _ _ _) op ty
+  = -- constant-method info is hidden in the IdInfo of
+    -- the class-op id (as mentioned up above).
+    let
+       sel_id = op_ids !! (getClassOpTag op - 1)
+    in
+    case (lookupConstMethodId (getIdSpecialisation sel_id) ty) of
+      Just xx -> xx
+      Nothing -> error (ppShow 80 (ppAboves [
+       ppCat [ppStr "ERROR: getConstMethodId:", ppr PprDebug op, ppr PprDebug ty, ppr PprDebug ops, ppr PprDebug op_ids, ppr PprDebug sel_id],
+       ppStr "(This can arise if an interface pragma refers to an instance",
+       ppStr "but there is no imported interface which *defines* that instance.",
+       ppStr "The info above, however ugly, should indicate what else you need to import."
+       ]))
+
+getClassSig :: Class -> (TyVarTemplate, [Class], [ClassOp])
+
+getClassSig (MkClass _ _ tyvar super_classes _ ops _ _ _ _)
+  = (tyvar, super_classes, ops)
+
+getClassBigSig (MkClass _ _ tyvar super_classes sdsels ops sels defms _ _)
+  = (tyvar, super_classes, sdsels, ops, sels, defms)
+
+getClassInstEnv (MkClass _ _ _ _ _ _ _ _ inst_env _) = inst_env
+
+--UNUSED: getClassDefaultMethodsInfo (MkClass _ _ _ _ _ _ _ defms _ _) = defms
+\end{code}
+
+@a `isSuperClassOf` b@ returns @Nothing@ if @a@ is not a superclass of
+@b@, but if it is, it returns $@Just@~[k_1,\ldots,k_n]$, where the
+$k_1,\ldots,k_n$ are exactly as described in the definition of the
+@MkClass@ constructor above.
+
+\begin{code}
+isSuperClassOf :: Class -> Class -> Maybe [Class]
+
+clas `isSuperClassOf` (MkClass _ _ _ _ _ _ _ _ _ links) = assocMaybe links clas
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[Class-std-groups]{Standard groups of Prelude classes}
+%*                                                                     *
+%************************************************************************
+
+@derivableClassKeys@ is also used in checking \tr{deriving} constructs
+(@TcDeriv@).
+
+NOTE: @Eq@ and @Text@ do need to appear in @standardClasses@
+even though every numeric class has these two as a superclass, 
+because the list of ambiguous dictionaries hasn't been simplified.
+
+\begin{code}
+isNumericClass, isStandardClass {-UNUSED:, isDerivableClass-} :: Class -> Bool
+
+isNumericClass   (MkClass key _ _ _ _ _ _ _ _ _) = key `is_elem` numericClassKeys
+isStandardClass  (MkClass key _ _ _ _ _ _ _ _ _) = key `is_elem` standardClassKeys
+--isDerivableClass (MkClass key _ _ _ _ _ _ _ _ _) = key `is_elem` derivableClassKeys
+
+is_elem = isIn "is_X_Class"
+
+numericClassKeys
+  = [ numClassKey, 
+      realClassKey, 
+      integralClassKey, 
+      fractionalClassKey, 
+      floatingClassKey, 
+      realFracClassKey, 
+      realFloatClassKey ]
+
+derivableClassKeys
+  = [ eqClassKey, 
+      textClassKey, 
+      ordClassKey, 
+      enumClassKey, 
+      ixClassKey ]
+      -- ToDo: add binaryClass
+
+standardClassKeys
+  = derivableClassKeys ++ numericClassKeys
+    ++ [ cCallableClassKey, cReturnableClassKey ]
+    --
+    -- We have to have "_CCallable" and "_CReturnable" in the standard
+    -- classes, so that if you go...
+    --
+    --     _ccall_ foo ... 93{-numeric literal-} ...
+    --
+    -- ... it can do The Right Thing on the 93.
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[Class-instances]{Instance declarations for @Class@}
+%*                                                                     *
+%************************************************************************
+
+We compare @Classes@ by their keys (which include @Uniques@).
+
+\begin{code}
+cmpClass (MkClass k1 _ _ _ _ _ _ _ _ _) (MkClass k2 _ _ _ _ _ _ _ _ _)
+  = cmpUnique k1 k2
+
+instance Eq Class where
+    (MkClass k1 _ _ _ _ _ _ _ _ _) == (MkClass k2 _ _ _ _ _ _ _ _ _) = k1 == k2
+    (MkClass k1 _ _ _ _ _ _ _ _ _) /= (MkClass k2 _ _ _ _ _ _ _ _ _) = k1 /= k2
+
+instance Ord Class where
+    (MkClass k1 _ _ _ _ _ _ _ _ _) <= (MkClass k2 _ _ _ _ _ _ _ _ _) = k1 <= k2
+    (MkClass k1 _ _ _ _ _ _ _ _ _) <  (MkClass k2 _ _ _ _ _ _ _ _ _) = k1 <  k2
+    (MkClass k1 _ _ _ _ _ _ _ _ _) >= (MkClass k2 _ _ _ _ _ _ _ _ _) = k1 >= k2
+    (MkClass k1 _ _ _ _ _ _ _ _ _) >  (MkClass k2 _ _ _ _ _ _ _ _ _) = k1 >  k2
+#ifdef __GLASGOW_HASKELL__
+    _tagCmp a b = case cmpClass a b of { LT_ -> _LT; EQ_ -> _EQ; GT__ -> _GT }
+#endif
+\end{code}
+
+\begin{code}
+instance NamedThing Class where
+    getExportFlag      (MkClass _ n _ _ _ _ _ _ _ _) = getExportFlag n
+    isLocallyDefined   (MkClass _ n _ _ _ _ _ _ _ _) = isLocallyDefined n
+    getOrigName                (MkClass _ n _ _ _ _ _ _ _ _) = getOrigName n
+    getOccurrenceName  (MkClass _ n _ _ _ _ _ _ _ _) = getOccurrenceName n
+    getInformingModules        (MkClass _ n _ _ _ _ _ _ _ _) = getInformingModules n
+    getSrcLoc          (MkClass _ n _ _ _ _ _ _ _ _) = getSrcLoc n
+    fromPreludeCore    (MkClass _ n _ _ _ _ _ _ _ _) = fromPreludeCore n
+
+    getTheUnique = panic "NamedThing.Class.getTheUnique"
+    hasType     = panic "NamedThing.Class.hasType"
+    getType     = panic "NamedThing.Class.getType"
+\end{code}
+
+And the usual output stuff:
+\begin{code}
+instance Outputable Class where
+    -- we use pprIfaceClass for printing in interfaces
+
+{-  ppr sty@PprShowAll (MkClass u n _ _ _ ops _ _ _ _)
+      = ppCat [ppr sty n, pprUnique u, ppr sty ops]
+-}
+    ppr sty (MkClass u n _ _ _ _ _ _ _ _) = ppr sty n
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[ClassOp-basic]{@ClassOp@: type and basic functions}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+data ClassOp
+  = MkClassOp  FAST_STRING -- The operation name
+
+               Int     -- Unique within a class; starts at 1
+
+               UniType -- Type; the class tyvar is free (you can find
+                       -- it from the class). This means that a
+                       -- ClassOp doesn't make much sense outside the
+                       -- context of its parent class.
+\end{code}
+
+A @ClassOp@ represents a a class operation.  From it and its parent
+class we can construct the dictionary-selector @Id@ for the
+operation/superclass dictionary, and the @Id@ for its default method.
+It appears in a list inside the @Class@ object.
+
+The type of a method in a @ClassOp@ object is its local type; that is,
+without the overloading of the class itself.  For example, in the
+declaration
+\begin{pseudocode}
+       class Foo a where
+               op :: Ord b => a -> b -> a
+\end{pseudocode}
+the type recorded for @op@ in the @ClassOp@ list of the @Class@ object is
+just 
+       $\forall \beta.~
+               @Ord@~\beta \Rightarrow 
+               \alpha \rightarrow \beta \rightarrow alpha$ 
+
+(where $\alpha$ is the class type variable recorded in the @Class@
+object).  Of course, the type of @op@ recorded in the GVE will be its
+``full'' type
+
+       $\forall \alpha \forall \beta.~ 
+               @Foo@~\alpha \Rightarrow
+               ~@Ord@~\beta \Rightarrow \alpha
+               \rightarrow \beta \rightarrow alpha$
+
+******************************************************************
+**** That is, the type variables of a class op selector
+***  are all at the outer level.
+******************************************************************
+
+\begin{code}
+mkClassOp = MkClassOp
+
+getClassOpTag :: ClassOp -> Int
+getClassOpTag    (MkClassOp _ tag _) = tag
+
+getClassOpString :: ClassOp -> FAST_STRING
+getClassOpString (MkClassOp str _ _) = str
+
+{- UNUSED:
+getClassOpSig :: ClassOp -> ([TyVarTemplate], ThetaType, TauType)
+getClassOpSig (MkClassOp _ _ ty) = splitType ty
+-}
+
+getClassOpLocalType :: ClassOp -> UniType {-SigmaType-}
+getClassOpLocalType (MkClassOp _ _ ty) = ty
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[ClassOp-instances]{Instance declarations for @ClassOp@}
+%*                                                                     *
+%************************************************************************
+
+@ClassOps@ are compared by their tags.
+
+\begin{code}
+instance Eq ClassOp where
+    (MkClassOp _ i1 _) == (MkClassOp _ i2 _) = i1 == i2
+    (MkClassOp _ i1 _) /= (MkClassOp _ i2 _) = i1 == i2
+
+instance Ord ClassOp where
+    (MkClassOp _ i1 _) <= (MkClassOp _ i2 _) = i1 <= i2
+    (MkClassOp _ i1 _) <  (MkClassOp _ i2 _) = i1 <  i2
+    (MkClassOp _ i1 _) >= (MkClassOp _ i2 _) = i1 >= i2
+    (MkClassOp _ i1 _) >  (MkClassOp _ i2 _) = i1 >  i2
+    -- ToDo: something for _tagCmp? (WDP 94/10)
+\end{code}
+
+And the usual output stuff:
+\begin{code}
+instance Outputable ClassOp where
+    ppr = pprClassOp
+\end{code}