+ | nullary_con = -- skip the showParen junk...
+ ASSERT(null bs_needed)
+ ([nlWildPat, con_pat], mk_showString_app con_str)
+ | otherwise =
+ ([a_Pat, con_pat],
+ showParen_Expr (nlHsPar (genOpApp a_Expr ge_RDR (nlHsLit (HsInt con_prec_plus_one))))
+ (nlHsPar (nested_compose_Expr show_thingies)))
+ where
+ data_con_RDR = getRdrName data_con
+ con_arity = dataConSourceArity data_con
+ bs_needed = take con_arity bs_RDRs
+ arg_tys = dataConOrigArgTys data_con -- Correspond 1-1 with bs_needed
+ con_pat = nlConVarPat data_con_RDR bs_needed
+ nullary_con = con_arity == 0
+ labels = dataConFieldLabels data_con
+ lab_fields = length labels
+ record_syntax = lab_fields > 0
+
+ dc_nm = getName data_con
+ dc_occ_nm = getOccName data_con
+ con_str = occNameUserString dc_occ_nm
+
+ show_thingies
+ | is_infix = [show_arg1, mk_showString_app (" " ++ con_str ++ " "), show_arg2]
+ | record_syntax = mk_showString_app (con_str ++ " {") :
+ show_record_args ++ [mk_showString_app "}"]
+ | otherwise = mk_showString_app (con_str ++ " ") : show_prefix_args
+
+ show_label l = mk_showString_app (the_name ++ " = ")
+ -- Note the spaces around the "=" sign. If we don't have them
+ -- then we get Foo { x=-1 } and the "=-" parses as a single
+ -- lexeme. Only the space after the '=' is necessary, but
+ -- it seems tidier to have them both sides.
+ where
+ occ_nm = getOccName (fieldLabelName l)
+ nm = occNameUserString occ_nm
+ is_op = isSymOcc occ_nm -- Legal, but rare.
+ the_name | is_op = '(':nm ++ ")"
+ | otherwise = nm
+
+ show_args = zipWith show_arg bs_needed arg_tys
+ (show_arg1:show_arg2:_) = show_args
+ show_prefix_args = intersperse (nlHsVar showSpace_RDR) show_args
+
+ -- Assumption for record syntax: no of fields == no of labelled fields
+ -- (and in same order)
+ show_record_args = concat $
+ intersperse [mk_showString_app ", "] $
+ [ [show_label lbl, arg]
+ | (lbl,arg) <- zipEqual "gen_Show_binds"
+ labels show_args ]
+
+ -- Generates (showsPrec p x) for argument x, but it also boxes
+ -- the argument first if necessary. Note that this prints unboxed
+ -- things without any '#' decorations; could change that if need be
+ show_arg b arg_ty = nlHsApps showsPrec_RDR [nlHsLit (HsInt arg_prec),
+ box_if_necy "Show" tycon (nlHsVar b) arg_ty]
+
+ -- Fixity stuff
+ is_infix = isDataSymOcc dc_occ_nm
+ con_prec_plus_one = 1 + getPrec is_infix get_fixity dc_nm
+ arg_prec | record_syntax = 0 -- Record fields don't need parens
+ | otherwise = con_prec_plus_one
+
+mk_showString_app str = nlHsApp (nlHsVar showString_RDR) (nlHsLit (mkHsString str))
+\end{code}
+
+\begin{code}
+getPrec :: Bool -> FixityEnv -> Name -> Integer
+getPrec is_infix get_fixity nm
+ | not is_infix = appPrecedence
+ | otherwise = getPrecedence get_fixity nm
+
+appPrecedence :: Integer
+appPrecedence = fromIntegral maxPrecedence + 1
+ -- One more than the precedence of the most
+ -- tightly-binding operator
+
+getPrecedence :: FixityEnv -> Name -> Integer
+getPrecedence get_fixity nm
+ = case lookupFixity get_fixity nm of
+ Fixity x _ -> fromIntegral x
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Typeable}
+%* *
+%************************************************************************
+
+From the data type
+
+ data T a b = ....
+
+we generate
+
+ instance Typeable2 T where
+ typeOf2 _ = mkTyConApp (mkTyConRep "T") []
+
+We are passed the Typeable2 class as well as T
+
+\begin{code}
+gen_Typeable_binds :: TyCon -> LHsBinds RdrName
+gen_Typeable_binds tycon
+ = unitBag $
+ mk_easy_FunBind tycon_loc
+ (mk_typeOf_RDR tycon) -- Name of appropriate type0f function
+ [nlWildPat] emptyBag
+ (nlHsApps mkTypeRep_RDR [tycon_rep, nlList []])
+ where
+ tycon_loc = getSrcSpan tycon
+ tycon_rep = nlHsVar mkTyConRep_RDR `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon)))
+
+mk_typeOf_RDR :: TyCon -> RdrName
+-- Use the arity of the TyCon to make the right typeOfn function
+mk_typeOf_RDR tycon = varQual_RDR tYPEABLE_Name (mkFastString ("typeOf" ++ suffix))
+ where
+ arity = tyConArity tycon
+ suffix | arity == 0 = ""
+ | otherwise = show arity
+\end{code}
+
+
+
+%************************************************************************
+%* *
+\subsection{Data}
+%* *
+%************************************************************************
+
+From the data type
+
+ data T a b = T1 a b | T2
+
+we generate
+
+ $cT1 = mkDataCon $dT "T1" Prefix
+ $cT2 = mkDataCon $dT "T2" Prefix
+ $dT = mkDataType "Module.T" [] [$con_T1, $con_T2]
+ -- the [] is for field labels.
+
+ instance (Data a, Data b) => Data (T a b) where
+ gfoldl k z (T1 a b) = z T `k` a `k` b
+ gfoldl k z T2 = z T2
+ -- ToDo: add gmapT,Q,M, gfoldr
+
+ gunfold k z c = case conIndex c of
+ I# 1# -> k (k (z T1))
+ I# 2# -> z T2
+
+ toConstr (T1 _ _) = $cT1
+ toConstr T2 = $cT2
+
+ dataTypeOf _ = $dT
+
+\begin{code}
+gen_Data_binds :: FixityEnv
+ -> TyCon
+ -> (LHsBinds RdrName, -- The method bindings
+ LHsBinds RdrName) -- Auxiliary bindings
+gen_Data_binds fix_env tycon
+ = (listToBag [gfoldl_bind, gunfold_bind, toCon_bind, dataTypeOf_bind],
+ -- Auxiliary definitions: the data type and constructors
+ datatype_bind `consBag` listToBag (map mk_con_bind data_cons))
+ where
+ tycon_loc = getSrcSpan tycon
+ tycon_name = tyConName tycon
+ data_cons = tyConDataCons tycon
+ n_cons = length data_cons
+
+ ------------ gfoldl
+ gfoldl_bind = mk_FunBind tycon_loc gfoldl_RDR (map gfoldl_eqn data_cons)
+ gfoldl_eqn con = ([nlVarPat k_RDR, nlVarPat z_RDR, nlConVarPat con_name as_needed],
+ foldl mk_k_app (nlHsVar z_RDR `nlHsApp` nlHsVar con_name) as_needed)
+ where
+ con_name :: RdrName
+ con_name = getRdrName con
+ as_needed = take (dataConSourceArity con) as_RDRs
+ mk_k_app e v = nlHsPar (nlHsOpApp e k_RDR (nlHsVar v))
+
+ ------------ gunfold
+ gunfold_bind = mk_FunBind tycon_loc
+ gunfold_RDR
+ [([k_Pat,z_Pat,c_Pat], gunfold_rhs)]
+
+ gunfold_rhs = nlHsCase (nlHsVar conIndex_RDR `nlHsApp` c_Expr)
+ (map gunfold_alt data_cons)
+
+ gunfold_alt dc
+ = mkSimpleHsAlt (mk_tag_pat dc)
+ (foldr nlHsApp
+ (nlHsVar z_RDR `nlHsApp` nlHsVar (getRdrName dc))
+ (replicate (dataConSourceArity dc) (nlHsVar k_RDR)))
+ mk_tag_pat dc -- Last one is a wild-pat, to avoid
+ -- redundant test, and annoying warning
+ | tag-fIRST_TAG == n_cons-1 = nlWildPat -- Last constructor
+ | otherwise = nlConPat intDataCon_RDR [nlLitPat (HsIntPrim (toInteger tag))]
+ where
+ tag = dataConTag dc
+
+ ------------ toConstr
+ toCon_bind = mk_FunBind tycon_loc toConstr_RDR (map to_con_eqn data_cons)
+ to_con_eqn dc = ([nlWildConPat dc], nlHsVar (mk_constr_name dc))
+
+ ------------ dataTypeOf
+ dataTypeOf_bind = mk_easy_FunBind
+ tycon_loc
+ dataTypeOf_RDR
+ [nlWildPat]
+ emptyBag
+ (nlHsVar data_type_name)
+
+ ------------ $dT
+
+ data_type_name = mkDerivedRdrName tycon_name mkDataTOcc
+ datatype_bind = mkVarBind
+ tycon_loc
+ data_type_name
+ ( nlHsVar mkDataType_RDR
+ `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon)))
+ `nlHsApp` nlList constrs
+ )
+ constrs = [nlHsVar (mk_constr_name con) | con <- data_cons]
+
+
+ ------------ $cT1 etc
+ mk_constr_name con = mkDerivedRdrName (dataConName con) mkDataCOcc
+ mk_con_bind dc = mkVarBind
+ tycon_loc
+ (mk_constr_name dc)
+ (nlHsApps mkConstr_RDR (constr_args dc))
+ constr_args dc =
+ [ -- nlHsIntLit (toInteger (dataConTag dc)), -- Tag
+ nlHsVar data_type_name, -- DataType
+ nlHsLit (mkHsString (occNameUserString dc_occ)), -- String name
+ nlList labels, -- Field labels
+ nlHsVar fixity] -- Fixity
+ where
+ labels = map (nlHsLit . mkHsString . getOccString . fieldLabelName)
+ (dataConFieldLabels dc)
+ dc_occ = getOccName dc
+ is_infix = isDataSymOcc dc_occ
+ fixity | is_infix = infix_RDR
+ | otherwise = prefix_RDR
+
+gfoldl_RDR = varQual_RDR gENERICS_Name FSLIT("gfoldl")
+gunfold_RDR = varQual_RDR gENERICS_Name FSLIT("gunfold")
+toConstr_RDR = varQual_RDR gENERICS_Name FSLIT("toConstr")
+dataTypeOf_RDR = varQual_RDR gENERICS_Name FSLIT("dataTypeOf")
+mkConstr_RDR = varQual_RDR gENERICS_Name FSLIT("mkConstr")
+mkDataType_RDR = varQual_RDR gENERICS_Name FSLIT("mkDataType")
+conIndex_RDR = varQual_RDR gENERICS_Name FSLIT("constrIndex")
+prefix_RDR = dataQual_RDR gENERICS_Name FSLIT("Prefix")
+infix_RDR = dataQual_RDR gENERICS_Name FSLIT("Infix")