{-# LANGUAGE CPP #-}
module BuildTyCl (
buildDataCon,
buildPatSyn,
TcMethInfo, MethInfo, buildClass,
mkNewTyConRhs,
newImplicitBinder, newTyConRepName
) where
#include "HsVersions.h"
import GhcPrelude
import IfaceEnv
import FamInstEnv( FamInstEnvs, mkNewTypeCoAxiom )
import TysWiredIn( isCTupleTyConName )
import TysPrim ( voidPrimTy )
import DataCon
import PatSyn
import Var
import VarSet
import BasicTypes
import Name
import NameEnv
import MkId
import Class
import TyCon
import Type
import Id
import TcType
import SrcLoc( SrcSpan, noSrcSpan )
import DynFlags
import TcRnMonad
import UniqSupply
import Util
import Outputable
mkNewTyConRhs :: Name -> TyCon -> DataCon -> TcRnIf m n AlgTyConRhs
mkNewTyConRhs tycon_name tycon con
= do { co_tycon_name <- newImplicitBinder tycon_name mkNewTyCoOcc
; let nt_ax = mkNewTypeCoAxiom co_tycon_name tycon etad_tvs etad_roles etad_rhs
; traceIf (text "mkNewTyConRhs" <+> ppr nt_ax)
; return (NewTyCon { data_con = con,
nt_rhs = rhs_ty,
nt_etad_rhs = (etad_tvs, etad_rhs),
nt_co = nt_ax } ) }
where
tvs = tyConTyVars tycon
roles = tyConRoles tycon
con_arg_ty = case dataConRepArgTys con of
[arg_ty] -> arg_ty
tys -> pprPanic "mkNewTyConRhs" (ppr con <+> ppr tys)
rhs_ty = substTyWith (dataConUnivTyVars con)
(mkTyVarTys tvs) con_arg_ty
etad_tvs :: [TyVar]
etad_roles :: [Role]
etad_rhs :: Type
(etad_tvs, etad_roles, etad_rhs) = eta_reduce (reverse tvs) (reverse roles) rhs_ty
eta_reduce :: [TyVar]
-> [Role]
-> Type
-> ([TyVar], [Role], Type)
eta_reduce (a:as) (_:rs) ty | Just (fun, arg) <- splitAppTy_maybe ty,
Just tv <- getTyVar_maybe arg,
tv == a,
not (a `elemVarSet` tyCoVarsOfType fun)
= eta_reduce as rs fun
eta_reduce tvs rs ty = (reverse tvs, reverse rs, ty)
buildDataCon :: FamInstEnvs
-> Name
-> Bool
-> TyConRepName
-> [HsSrcBang]
-> Maybe [HsImplBang]
-> [FieldLabel]
-> [TyVar]
-> [TyCoVar]
-> [TyVarBinder]
-> [EqSpec]
-> KnotTied ThetaType
-> [KnotTied Type]
-> KnotTied Type
-> KnotTied TyCon
-> NameEnv ConTag
-> TcRnIf m n DataCon
buildDataCon fam_envs src_name declared_infix prom_info src_bangs impl_bangs
field_lbls univ_tvs ex_tvs user_tvbs eq_spec ctxt arg_tys res_ty
rep_tycon tag_map
= do { wrap_name <- newImplicitBinder src_name mkDataConWrapperOcc
; work_name <- newImplicitBinder src_name mkDataConWorkerOcc
; traceIf (text "buildDataCon 1" <+> ppr src_name)
; us <- newUniqueSupply
; dflags <- getDynFlags
; let stupid_ctxt = mkDataConStupidTheta rep_tycon arg_tys univ_tvs
tag = lookupNameEnv_NF tag_map src_name
data_con = mkDataCon src_name declared_infix prom_info
src_bangs field_lbls
univ_tvs ex_tvs user_tvbs eq_spec ctxt
arg_tys res_ty NoRRI rep_tycon tag
stupid_ctxt dc_wrk dc_rep
dc_wrk = mkDataConWorkId work_name data_con
dc_rep = initUs_ us (mkDataConRep dflags fam_envs wrap_name
impl_bangs data_con)
; traceIf (text "buildDataCon 2" <+> ppr src_name)
; return data_con }
mkDataConStupidTheta :: TyCon -> [Type] -> [TyVar] -> [PredType]
mkDataConStupidTheta tycon arg_tys univ_tvs
| null stupid_theta = []
| otherwise = filter in_arg_tys stupid_theta
where
tc_subst = zipTvSubst (tyConTyVars tycon)
(mkTyVarTys univ_tvs)
stupid_theta = substTheta tc_subst (tyConStupidTheta tycon)
arg_tyvars = tyCoVarsOfTypes arg_tys
in_arg_tys pred = not $ isEmptyVarSet $
tyCoVarsOfType pred `intersectVarSet` arg_tyvars
buildPatSyn :: Name -> Bool
-> (Id,Bool) -> Maybe (Id, Bool)
-> ([TyVarBinder], ThetaType)
-> ([TyVarBinder], ThetaType)
-> [Type]
-> Type
-> [FieldLabel]
-> PatSyn
buildPatSyn src_name declared_infix matcher@(matcher_id,_) builder
(univ_tvs, req_theta) (ex_tvs, prov_theta) arg_tys
pat_ty field_labels
=
ASSERT2((and [ univ_tvs `equalLength` univ_tvs1
, ex_tvs `equalLength` ex_tvs1
, pat_ty `eqType` substTy subst pat_ty1
, prov_theta `eqTypes` substTys subst prov_theta1
, req_theta `eqTypes` substTys subst req_theta1
, compareArgTys arg_tys (substTys subst arg_tys1)
])
, (vcat [ ppr univ_tvs <+> twiddle <+> ppr univ_tvs1
, ppr ex_tvs <+> twiddle <+> ppr ex_tvs1
, ppr pat_ty <+> twiddle <+> ppr pat_ty1
, ppr prov_theta <+> twiddle <+> ppr prov_theta1
, ppr req_theta <+> twiddle <+> ppr req_theta1
, ppr arg_tys <+> twiddle <+> ppr arg_tys1]))
mkPatSyn src_name declared_infix
(univ_tvs, req_theta) (ex_tvs, prov_theta)
arg_tys pat_ty
matcher builder field_labels
where
((_:_:univ_tvs1), req_theta1, tau) = tcSplitSigmaTy $ idType matcher_id
([pat_ty1, cont_sigma, _], _) = tcSplitFunTys tau
(ex_tvs1, prov_theta1, cont_tau) = tcSplitSigmaTy cont_sigma
(arg_tys1, _) = (tcSplitFunTys cont_tau)
twiddle = char '~'
subst = zipTvSubst (univ_tvs1 ++ ex_tvs1)
(mkTyVarTys (binderVars (univ_tvs ++ ex_tvs)))
compareArgTys :: [Type] -> [Type] -> Bool
compareArgTys [] [x] = x `eqType` voidPrimTy
compareArgTys arg_tys matcher_arg_tys = arg_tys `eqTypes` matcher_arg_tys
type TcMethInfo = MethInfo
type MethInfo
= ( Name
, Type
, Maybe (DefMethSpec (SrcSpan, Type)))
buildClass :: Name
-> [TyConBinder]
-> [Role]
-> [FunDep TyVar]
-> Maybe (KnotTied ThetaType, [ClassATItem], [KnotTied MethInfo], ClassMinimalDef)
-> TcRnIf m n Class
buildClass tycon_name binders roles fds Nothing
= fixM $ \ rec_clas ->
do { traceIf (text "buildClass")
; tc_rep_name <- newTyConRepName tycon_name
; let univ_tvs = binderVars binders
tycon = mkClassTyCon tycon_name binders roles
AbstractTyCon rec_clas tc_rep_name
result = mkAbstractClass tycon_name univ_tvs fds tycon
; traceIf (text "buildClass" <+> ppr tycon)
; return result }
buildClass tycon_name binders roles fds
(Just (sc_theta, at_items, sig_stuff, mindef))
= fixM $ \ rec_clas ->
do { traceIf (text "buildClass")
; datacon_name <- newImplicitBinder tycon_name mkClassDataConOcc
; tc_rep_name <- newTyConRepName tycon_name
; op_items <- mapM (mk_op_item rec_clas) sig_stuff
; sc_sel_names <- mapM (newImplicitBinder tycon_name . mkSuperDictSelOcc)
(takeList sc_theta [fIRST_TAG..])
; let sc_sel_ids = [ mkDictSelId sc_name rec_clas
| sc_name <- sc_sel_names]
; let use_newtype = isSingleton arg_tys
args = sc_sel_names ++ op_names
op_tys = [ty | (_,ty,_) <- sig_stuff]
op_names = [op | (op,_,_) <- sig_stuff]
arg_tys = sc_theta ++ op_tys
rec_tycon = classTyCon rec_clas
univ_bndrs = tyConTyVarBinders binders
univ_tvs = binderVars univ_bndrs
; rep_nm <- newTyConRepName datacon_name
; dict_con <- buildDataCon (panic "buildClass: FamInstEnvs")
datacon_name
False
rep_nm
(map (const no_bang) args)
(Just (map (const HsLazy) args))
[]
univ_tvs
[]
univ_bndrs
[]
[]
arg_tys
(mkTyConApp rec_tycon (mkTyVarTys univ_tvs))
rec_tycon
(mkTyConTagMap rec_tycon)
; rhs <- case () of
_ | use_newtype
-> mkNewTyConRhs tycon_name rec_tycon dict_con
| isCTupleTyConName tycon_name
-> return (TupleTyCon { data_con = dict_con
, tup_sort = ConstraintTuple })
| otherwise
-> return (mkDataTyConRhs [dict_con])
; let { tycon = mkClassTyCon tycon_name binders roles
rhs rec_clas tc_rep_name
; result = mkClass tycon_name univ_tvs fds
sc_theta sc_sel_ids at_items
op_items mindef tycon
}
; traceIf (text "buildClass" <+> ppr tycon)
; return result }
where
no_bang = HsSrcBang NoSourceText NoSrcUnpack NoSrcStrict
mk_op_item :: Class -> TcMethInfo -> TcRnIf n m ClassOpItem
mk_op_item rec_clas (op_name, _, dm_spec)
= do { dm_info <- mk_dm_info op_name dm_spec
; return (mkDictSelId op_name rec_clas, dm_info) }
mk_dm_info :: Name -> Maybe (DefMethSpec (SrcSpan, Type))
-> TcRnIf n m (Maybe (Name, DefMethSpec Type))
mk_dm_info _ Nothing
= return Nothing
mk_dm_info op_name (Just VanillaDM)
= do { dm_name <- newImplicitBinder op_name mkDefaultMethodOcc
; return (Just (dm_name, VanillaDM)) }
mk_dm_info op_name (Just (GenericDM (loc, dm_ty)))
= do { dm_name <- newImplicitBinderLoc op_name mkDefaultMethodOcc loc
; return (Just (dm_name, GenericDM dm_ty)) }
newImplicitBinder :: Name
-> (OccName -> OccName)
-> TcRnIf m n Name
newImplicitBinder base_name mk_sys_occ
= newImplicitBinderLoc base_name mk_sys_occ (nameSrcSpan base_name)
newImplicitBinderLoc :: Name
-> (OccName -> OccName)
-> SrcSpan
-> TcRnIf m n Name
newImplicitBinderLoc base_name mk_sys_occ loc
| Just mod <- nameModule_maybe base_name
= newGlobalBinder mod occ loc
| otherwise
= do { uniq <- newUnique
; return (mkInternalName uniq occ loc) }
where
occ = mk_sys_occ (nameOccName base_name)
newTyConRepName :: Name -> TcRnIf gbl lcl TyConRepName
newTyConRepName tc_name
| Just mod <- nameModule_maybe tc_name
, (mod, occ) <- tyConRepModOcc mod (nameOccName tc_name)
= newGlobalBinder mod occ noSrcSpan
| otherwise
= newImplicitBinder tc_name mkTyConRepOcc