summaryrefslogtreecommitdiff
path: root/compiler/iface/BuildTyCl.lhs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/iface/BuildTyCl.lhs')
-rw-r--r--compiler/iface/BuildTyCl.lhs256
1 files changed, 256 insertions, 0 deletions
diff --git a/compiler/iface/BuildTyCl.lhs b/compiler/iface/BuildTyCl.lhs
new file mode 100644
index 0000000000..f81f2e7d07
--- /dev/null
+++ b/compiler/iface/BuildTyCl.lhs
@@ -0,0 +1,256 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+
+\begin{code}
+module BuildTyCl (
+ buildSynTyCon, buildAlgTyCon, buildDataCon,
+ buildClass,
+ mkAbstractTyConRhs, mkNewTyConRhs, mkDataTyConRhs
+ ) where
+
+#include "HsVersions.h"
+
+import IfaceEnv ( newImplicitBinder )
+import TcRnMonad
+
+import DataCon ( DataCon, isNullarySrcDataCon, dataConTyVars,
+ mkDataCon, dataConFieldLabels, dataConOrigArgTys )
+import Var ( tyVarKind, TyVar, Id )
+import VarSet ( isEmptyVarSet, intersectVarSet, elemVarSet )
+import TysWiredIn ( unitTy )
+import BasicTypes ( RecFlag, StrictnessMark(..) )
+import Name ( Name )
+import OccName ( mkDataConWrapperOcc, mkDataConWorkerOcc, mkClassTyConOcc,
+ mkClassDataConOcc, mkSuperDictSelOcc )
+import MkId ( mkDataConIds, mkRecordSelId, mkDictSelId )
+import Class ( mkClass, Class( classTyCon), FunDep, DefMeth(..) )
+import TyCon ( mkSynTyCon, mkAlgTyCon, visibleDataCons, tyConStupidTheta,
+ tyConDataCons, isNewTyCon, mkClassTyCon, TyCon( tyConTyVars ),
+ isRecursiveTyCon,
+ ArgVrcs, AlgTyConRhs(..), newTyConRhs )
+import Type ( mkArrowKinds, liftedTypeKind, typeKind,
+ tyVarsOfType, tyVarsOfTypes, tyVarsOfPred,
+ splitTyConApp_maybe, splitAppTy_maybe, getTyVar_maybe,
+ mkPredTys, mkTyVarTys, ThetaType, Type,
+ substTyWith, zipTopTvSubst, substTheta )
+import Outputable
+import List ( nub )
+
+\end{code}
+
+
+\begin{code}
+------------------------------------------------------
+buildSynTyCon name tvs rhs_ty arg_vrcs
+ = mkSynTyCon name kind tvs rhs_ty arg_vrcs
+ where
+ kind = mkArrowKinds (map tyVarKind tvs) (typeKind rhs_ty)
+
+
+------------------------------------------------------
+buildAlgTyCon :: Name -> [TyVar]
+ -> ThetaType -- Stupid theta
+ -> AlgTyConRhs
+ -> ArgVrcs -> RecFlag
+ -> Bool -- True <=> want generics functions
+ -> TcRnIf m n TyCon
+
+buildAlgTyCon tc_name tvs stupid_theta rhs arg_vrcs is_rec want_generics
+ = do { let { tycon = mkAlgTyCon tc_name kind tvs arg_vrcs stupid_theta
+ rhs fields is_rec want_generics
+ ; kind = mkArrowKinds (map tyVarKind tvs) liftedTypeKind
+ ; fields = mkTyConSelIds tycon rhs
+ }
+ ; return tycon }
+
+------------------------------------------------------
+mkAbstractTyConRhs :: AlgTyConRhs
+mkAbstractTyConRhs = AbstractTyCon
+
+mkDataTyConRhs :: [DataCon] -> AlgTyConRhs
+mkDataTyConRhs cons
+ = DataTyCon { data_cons = cons, is_enum = all isNullarySrcDataCon cons }
+
+mkNewTyConRhs :: TyCon -> DataCon -> AlgTyConRhs
+mkNewTyConRhs tycon con
+ = NewTyCon { data_con = con,
+ nt_rhs = rhs_ty,
+ nt_etad_rhs = eta_reduce tvs rhs_ty,
+ nt_rep = mkNewTyConRep tycon rhs_ty }
+ where
+ tvs = dataConTyVars con
+ rhs_ty = head (dataConOrigArgTys con)
+ -- Newtypes are guaranteed vanilla, so OrigArgTys will do
+
+ eta_reduce [] ty = ([], ty)
+ eta_reduce (a:as) ty | null as',
+ Just (fun, arg) <- splitAppTy_maybe ty',
+ Just tv <- getTyVar_maybe arg,
+ tv == a,
+ not (a `elemVarSet` tyVarsOfType fun)
+ = ([], fun) -- Successful eta reduction
+ | otherwise
+ = (a:as', ty')
+ where
+ (as', ty') = eta_reduce as ty
+
+mkNewTyConRep :: TyCon -- The original type constructor
+ -> Type -- The arg type of its constructor
+ -> Type -- Chosen representation type
+-- The "representation type" is guaranteed not to be another newtype
+-- at the outermost level; but it might have newtypes in type arguments
+
+-- Find the representation type for this newtype TyCon
+-- Remember that the representation type is the *ultimate* representation
+-- type, looking through other newtypes.
+--
+-- The non-recursive newtypes are easy, because they look transparent
+-- to splitTyConApp_maybe, but recursive ones really are represented as
+-- TyConApps (see TypeRep).
+--
+-- The trick is to to deal correctly with recursive newtypes
+-- such as newtype T = MkT T
+
+mkNewTyConRep tc rhs_ty
+ | null (tyConDataCons tc) = unitTy
+ -- External Core programs can have newtypes with no data constructors
+ | otherwise = go [tc] rhs_ty
+ where
+ -- Invariant: tcs have been seen before
+ go tcs rep_ty
+ = case splitTyConApp_maybe rep_ty of
+ Just (tc, tys)
+ | tc `elem` tcs -> unitTy -- Recursive loop
+ | isNewTyCon tc -> ASSERT( isRecursiveTyCon tc )
+ -- Non-recursive ones have been
+ -- dealt with by splitTyConApp_maybe
+ go (tc:tcs) (substTyWith tvs tys rhs_ty)
+ where
+ (tvs, rhs_ty) = newTyConRhs tc
+
+ other -> rep_ty
+
+------------------------------------------------------
+buildDataCon :: Name -> Bool -> Bool
+ -> [StrictnessMark]
+ -> [Name] -- Field labels
+ -> [TyVar]
+ -> ThetaType -- Does not include the "stupid theta"
+ -> [Type] -> TyCon -> [Type]
+ -> TcRnIf m n DataCon
+-- A wrapper for DataCon.mkDataCon that
+-- a) makes the worker Id
+-- b) makes the wrapper Id if necessary, including
+-- allocating its unique (hence monadic)
+buildDataCon src_name declared_infix vanilla arg_stricts field_lbls
+ tyvars ctxt arg_tys tycon res_tys
+ = do { wrap_name <- newImplicitBinder src_name mkDataConWrapperOcc
+ ; work_name <- newImplicitBinder src_name mkDataConWorkerOcc
+ -- This last one takes the name of the data constructor in the source
+ -- code, which (for Haskell source anyway) will be in the DataName name
+ -- space, and puts it into the VarName name space
+
+ ; let
+ stupid_ctxt = mkDataConStupidTheta tycon arg_tys res_tys
+ data_con = mkDataCon src_name declared_infix vanilla
+ arg_stricts field_lbls
+ tyvars stupid_ctxt ctxt
+ arg_tys tycon res_tys dc_ids
+ dc_ids = mkDataConIds wrap_name work_name data_con
+
+ ; returnM data_con }
+
+
+-- The stupid context for a data constructor should be limited to
+-- the type variables mentioned in the arg_tys
+mkDataConStupidTheta tycon arg_tys res_tys
+ | null stupid_theta = [] -- The common case
+ | otherwise = filter in_arg_tys stupid_theta
+ where
+ tc_subst = zipTopTvSubst (tyConTyVars tycon) res_tys
+ stupid_theta = substTheta tc_subst (tyConStupidTheta tycon)
+ -- Start by instantiating the master copy of the
+ -- stupid theta, taken from the TyCon
+
+ arg_tyvars = tyVarsOfTypes arg_tys
+ in_arg_tys pred = not $ isEmptyVarSet $
+ tyVarsOfPred pred `intersectVarSet` arg_tyvars
+
+------------------------------------------------------
+mkTyConSelIds :: TyCon -> AlgTyConRhs -> [Id]
+mkTyConSelIds tycon rhs
+ = [ mkRecordSelId tycon fld
+ | fld <- nub (concatMap dataConFieldLabels (visibleDataCons rhs)) ]
+ -- We'll check later that fields with the same name
+ -- from different constructors have the same type.
+\end{code}
+
+
+------------------------------------------------------
+\begin{code}
+buildClass :: Name -> [TyVar] -> ThetaType
+ -> [FunDep TyVar] -- Functional dependencies
+ -> [(Name, DefMeth, Type)] -- Method info
+ -> RecFlag -> ArgVrcs -- Info for type constructor
+ -> TcRnIf m n Class
+
+buildClass class_name tvs sc_theta fds sig_stuff tc_isrec tc_vrcs
+ = do { tycon_name <- newImplicitBinder class_name mkClassTyConOcc
+ ; datacon_name <- newImplicitBinder class_name mkClassDataConOcc
+ -- The class name is the 'parent' for this datacon, not its tycon,
+ -- because one should import the class to get the binding for
+ -- the datacon
+ ; sc_sel_names <- mapM (newImplicitBinder class_name . mkSuperDictSelOcc)
+ [1..length sc_theta]
+ -- We number off the superclass selectors, 1, 2, 3 etc so that we
+ -- can construct names for the selectors. Thus
+ -- class (C a, C b) => D a b where ...
+ -- gives superclass selectors
+ -- D_sc1, D_sc2
+ -- (We used to call them D_C, but now we can have two different
+ -- superclasses both called C!)
+
+ ; fixM (\ clas -> do { -- Only name generation inside loop
+
+ let { op_tys = [ty | (_,_,ty) <- sig_stuff]
+ ; sc_tys = mkPredTys sc_theta
+ ; dict_component_tys = sc_tys ++ op_tys
+ ; sc_sel_ids = [mkDictSelId sc_name clas | sc_name <- sc_sel_names]
+ ; op_items = [ (mkDictSelId op_name clas, dm_info)
+ | (op_name, dm_info, _) <- sig_stuff ] }
+ -- Build the selector id and default method id
+
+ ; dict_con <- buildDataCon datacon_name
+ False -- Not declared infix
+ True -- Is vanilla; tyvars same as tycon
+ (map (const NotMarkedStrict) dict_component_tys)
+ [{- No labelled fields -}]
+ tvs [{-No context-}] dict_component_tys
+ (classTyCon clas) (mkTyVarTys tvs)
+
+ ; let { clas = mkClass class_name tvs fds
+ sc_theta sc_sel_ids op_items
+ tycon
+
+ ; tycon = mkClassTyCon tycon_name clas_kind tvs
+ tc_vrcs rhs clas tc_isrec
+ -- A class can be recursive, and in the case of newtypes
+ -- this matters. For example
+ -- class C a where { op :: C b => a -> b -> Int }
+ -- Because C has only one operation, it is represented by
+ -- a newtype, and it should be a *recursive* newtype.
+ -- [If we don't make it a recursive newtype, we'll expand the
+ -- newtype like a synonym, but that will lead to an infinite type]
+
+ ; clas_kind = mkArrowKinds (map tyVarKind tvs) liftedTypeKind
+
+ ; rhs = case dict_component_tys of
+ [rep_ty] -> mkNewTyConRhs tycon dict_con
+ other -> mkDataTyConRhs [dict_con]
+ }
+ ; return clas
+ })}
+\end{code}
+
+