module Vectorise.Type.TyConDecl (
vectTyConDecls
) where
import Vectorise.Type.Type
import Vectorise.Monad
import Vectorise.Env( GlobalEnv( global_fam_inst_env ) )
import BuildTyCl( TcMethInfo, buildClass, buildDataCon, newTyConRepName )
import OccName
import Class
import Type
import TyCon
import DataCon
import DynFlags
import BasicTypes( DefMethSpec(..) )
import SrcLoc( SrcSpan, noSrcSpan )
import Var
import Name
import Outputable
import Util
import Control.Monad
vectTyConDecls :: [TyCon] -> VM [TyCon]
vectTyConDecls tcs = fixV $ \tcs' ->
do { names' <- mapM (mkLocalisedName mkVectTyConOcc . tyConName) tcs
; mapM_ (uncurry (uncurry defTyConName)) (tcs `zip` names' `zipLazy` tcs')
; zipWithM vectTyConDecl tcs names'
}
vectTyConDecl :: TyCon -> Name -> VM TyCon
vectTyConDecl tycon name'
| Just cls <- tyConClass_maybe tycon
= do { unless (null $ classATs cls) $
do dflags <- getDynFlags
cantVectorise dflags "Associated types are not yet supported" (ppr cls)
; theta' <- mapM vectType (classSCTheta cls)
; let opItems = classOpItems cls
Just datacon = tyConSingleDataCon_maybe tycon
argTys = dataConRepArgTys datacon
opTys = drop (length argTys - length opItems) argTys
; methods' <- sequence [ vectMethod id meth ty | ((id, meth), ty) <- zip opItems opTys]
; cls' <- liftDs $
buildClass
name'
(tyConBinders tycon)
(map (const Nominal) (tyConRoles tycon))
(snd . classTvsFds $ cls)
(Just (
theta',
[],
methods',
(classMinimalDef cls)))
; let tycon' = classTyCon cls'
Just datacon = tyConSingleDataCon_maybe tycon
Just datacon' = tyConSingleDataCon_maybe tycon'
; defDataCon datacon datacon'
; let selIds = classAllSelIds cls
selIds' = classAllSelIds cls'
; zipWithM_ defGlobalVar selIds selIds'
; return tycon'
}
| isAlgTyCon tycon
= do { unless (all isVanillaDataCon (tyConDataCons tycon)) $
do dflags <- getDynFlags
cantVectorise dflags "Currently only Haskell 2011 datatypes are supported" (ppr tycon)
; rhs' <- vectAlgTyConRhs tycon (algTyConRhs tycon)
; let gadt_flag = isGadtSyntaxTyCon tycon
; tc_rep_name <- mkDerivedName mkTyConRepOcc name'
; return $ mkAlgTyCon
name'
(tyConBinders tycon)
(tyConResKind tycon)
(map (const Nominal) (tyConRoles tycon))
Nothing
[]
rhs'
(VanillaAlgTyCon tc_rep_name)
gadt_flag
}
| otherwise
= do dflags <- getDynFlags
cantVectorise dflags "Can't vectorise exotic type constructor" (ppr tycon)
vectMethod :: Id -> DefMethInfo -> Type -> VM TcMethInfo
vectMethod id defMeth ty
= do {
; ty' <- vectType ty
; id' <- mkVectId id ty'
; return (Var.varName id', ty', defMethSpecOfDefMeth defMeth)
}
defMethSpecOfDefMeth :: DefMethInfo -> Maybe (DefMethSpec (SrcSpan, Type))
defMethSpecOfDefMeth Nothing = Nothing
defMethSpecOfDefMeth (Just (_, VanillaDM)) = Just VanillaDM
defMethSpecOfDefMeth (Just (_, GenericDM ty)) = Just (GenericDM (noSrcSpan, ty))
vectAlgTyConRhs :: TyCon -> AlgTyConRhs -> VM AlgTyConRhs
vectAlgTyConRhs tc (AbstractTyCon {})
= do dflags <- getDynFlags
cantVectorise dflags "Can't vectorise imported abstract type" (ppr tc)
vectAlgTyConRhs _tc (DataTyCon { data_cons = data_cons
, is_enum = is_enum
})
= do { data_cons' <- mapM vectDataCon data_cons
; zipWithM_ defDataCon data_cons data_cons'
; return $ DataTyCon { data_cons = data_cons'
, is_enum = is_enum
}
}
vectAlgTyConRhs tc (TupleTyCon { data_con = con })
= vectAlgTyConRhs tc (DataTyCon { data_cons = [con], is_enum = False })
vectAlgTyConRhs tc (SumTyCon { data_cons = cons })
=
vectAlgTyConRhs tc (DataTyCon { data_cons = cons
, is_enum = all (((==) 0) . dataConRepArity) cons })
vectAlgTyConRhs tc (NewTyCon {})
= do dflags <- getDynFlags
cantVectorise dflags noNewtypeErr (ppr tc)
where
noNewtypeErr = "Vectorisation of newtypes not supported yet; please use a 'data' declaration"
vectDataCon :: DataCon -> VM DataCon
vectDataCon dc
| not . null $ ex_tvs
= do dflags <- getDynFlags
cantVectorise dflags "Can't vectorise constructor with existential type variables yet" (ppr dc)
| not . null $ eq_spec
= do dflags <- getDynFlags
cantVectorise dflags "Can't vectorise constructor with equality context yet" (ppr dc)
| not . null $ dataConFieldLabels dc
= do dflags <- getDynFlags
cantVectorise dflags "Can't vectorise constructor with labelled fields yet" (ppr dc)
| not . null $ theta
= do dflags <- getDynFlags
cantVectorise dflags "Can't vectorise constructor with constraint context yet" (ppr dc)
| otherwise
= do { name' <- mkLocalisedName mkVectDataConOcc name
; tycon' <- vectTyCon tycon
; arg_tys <- mapM vectType rep_arg_tys
; let ret_ty = mkFamilyTyConApp tycon' (mkTyVarTys univ_tvs)
; fam_envs <- readGEnv global_fam_inst_env
; rep_nm <- liftDs $ newTyConRepName name'
; liftDs $ buildDataCon fam_envs
name'
(dataConIsInfix dc)
rep_nm
(dataConSrcBangs dc)
(Just $ dataConImplBangs dc)
[]
univ_bndrs
[]
[]
[]
arg_tys
ret_ty
tycon'
}
where
name = dataConName dc
rep_arg_tys = dataConRepArgTys dc
tycon = dataConTyCon dc
(univ_tvs, ex_tvs, eq_spec, theta, _arg_tys, _res_ty) = dataConFullSig dc
univ_bndrs = dataConUnivTyVarBinders dc