\begin{code}
-module Convert( convertToHsExpr, convertToHsDecls ) where
+module Convert( convertToHsExpr, convertToHsDecls, convertToHsType ) where
#include "HsVersions.h"
-import Language.Haskell.THSyntax as Meta
+import Language.Haskell.TH as TH hiding (sigP)
+import Language.Haskell.TH.Syntax as TH
import HsSyn as Hs
- ( HsExpr(..), HsLit(..), ArithSeqInfo(..),
- HsStmtContext(..),
- Match(..), GRHSs(..), GRHS(..), HsPred(..),
- HsDecl(..), TyClDecl(..), InstDecl(..), ConDecl(..),
- Stmt(..), HsBinds(..), MonoBinds(..), Sig(..),
- Pat(..), HsConDetails(..), HsOverLit, BangType(..),
- placeHolderType, HsType(..), HsTupCon(..),
- HsTyVarBndr(..), HsContext,
- mkSimpleMatch
- )
-
-import RdrName ( RdrName, mkRdrUnqual, mkRdrQual, mkOrig )
-import Module ( mkModuleName )
-import RdrHsSyn ( mkHsIntegral, mkClassDecl, mkTyData )
-import OccName
-import SrcLoc ( SrcLoc, generatedSrcLoc )
-import TyCon ( DataConDetails(..) )
+import qualified Class (FunDep)
+import RdrName ( RdrName, mkRdrUnqual, mkRdrQual, mkOrig, getRdrName )
+import Module ( Module, mkModule )
+import RdrHsSyn ( mkClassDecl, mkTyData )
+import qualified OccName
+import SrcLoc ( generatedSrcLoc, noLoc, unLoc, Located(..),
+ SrcSpan, srcLocSpan )
import Type ( Type )
-import BasicTypes( Boxity(..), RecFlag(Recursive),
- NewOrData(..), StrictnessMark(..) )
-import FastString( mkFastString )
-import Char ( ord, isAlphaNum )
+import TysWiredIn ( unitTyCon, tupleTyCon, trueDataCon )
+import BasicTypes( Boxity(..), RecFlag(Recursive) )
+import ForeignCall ( Safety(..), CCallConv(..), CCallTarget(..),
+ CExportSpec(..))
+import Char ( isAscii, isAlphaNum, isAlpha )
import List ( partition )
+import Unique ( mkUniqueGrimily )
+import ErrUtils (Message)
+import GLAEXTS ( Int(..) )
+import Bag ( emptyBag, consBag )
+import FastString
import Outputable
-------------------------------------------------------------------
-convertToHsDecls :: [Meta.Dec] -> [HsDecl RdrName]
-convertToHsDecls ds
- = ValD (cvtdecs binds_and_sigs) : map cvt_top top_decls
- where
- (binds_and_sigs, top_decls) = partition sigOrBindP ds
+convertToHsDecls :: [TH.Dec] -> [Either (LHsDecl RdrName) Message]
+convertToHsDecls ds = map cvt_ltop ds
-cvt_top (Data tc tvs constrs derivs)
- = TyClD (mkTyData DataType
- (noContext, tconName tc, cvt_tvs tvs)
- (DataCons (map mk_con constrs))
- (mk_derivs derivs) loc0)
+mk_con con = L loc0 $ mk_nlcon con
where
- mk_con (Constr c tys)
- = ConDecl (cName c) noExistentials noContext
- (PrefixCon (map mk_arg tys)) loc0
-
- mk_arg ty = BangType NotMarkedStrict (cvtType ty)
-
- mk_derivs [] = Nothing
- mk_derivs cs = Just [HsClassP (tconName c) [] | c <- cs]
-
-cvt_top (Class ctxt cl tvs decs)
- = TyClD (mkClassDecl (cvt_context ctxt, tconName cl, cvt_tvs tvs)
- noFunDeps
- sigs (Just binds) loc0)
+ mk_nlcon con = case con of
+ NormalC c strtys
+ -> ConDecl (noLoc (cName c)) noExistentials noContext
+ (PrefixCon (map mk_arg strtys))
+ RecC c varstrtys
+ -> ConDecl (noLoc (cName c)) noExistentials noContext
+ (RecCon (map mk_id_arg varstrtys))
+ InfixC st1 c st2
+ -> ConDecl (noLoc (cName c)) noExistentials noContext
+ (InfixCon (mk_arg st1) (mk_arg st2))
+ ForallC tvs ctxt (ForallC tvs' ctxt' con')
+ -> mk_nlcon (ForallC (tvs ++ tvs') (ctxt ++ ctxt') con')
+ ForallC tvs ctxt con' -> case mk_nlcon con' of
+ ConDecl l [] (L _ []) x ->
+ ConDecl l (cvt_tvs tvs) (cvt_context ctxt) x
+ c -> panic "ForallC: Can't happen"
+ mk_arg (IsStrict, ty) = noLoc $ HsBangTy HsStrict (cvtType ty)
+ mk_arg (NotStrict, ty) = cvtType ty
+
+ mk_id_arg (i, IsStrict, ty)
+ = (noLoc (vName i), noLoc $ HsBangTy HsStrict (cvtType ty))
+ mk_id_arg (i, NotStrict, ty)
+ = (noLoc (vName i), cvtType ty)
+
+mk_derivs [] = Nothing
+mk_derivs cs = Just [noLoc $ HsPredTy $ HsClassP (tconName c) [] | c <- cs]
+
+cvt_ltop :: TH.Dec -> Either (LHsDecl RdrName) Message
+cvt_ltop d = case cvt_top d of
+ Left d -> Left (L loc0 d)
+ Right m -> Right m
+
+cvt_top :: TH.Dec -> Either (HsDecl RdrName) Message
+cvt_top d@(TH.ValD _ _ _) = Left $ Hs.ValD (unLoc (cvtd d))
+cvt_top d@(TH.FunD _ _) = Left $ Hs.ValD (unLoc (cvtd d))
+
+cvt_top (TySynD tc tvs rhs)
+ = Left $ TyClD (TySynonym (noLoc (tconName tc)) (cvt_tvs tvs) (cvtType rhs))
+
+cvt_top (DataD ctxt tc tvs constrs derivs)
+ = Left $ TyClD (mkTyData DataType
+ (noLoc (cvt_context ctxt, noLoc (tconName tc), cvt_tvs tvs))
+ Nothing (map mk_con constrs)
+ (mk_derivs derivs))
+
+cvt_top (NewtypeD ctxt tc tvs constr derivs)
+ = Left $ TyClD (mkTyData NewType
+ (noLoc (cvt_context ctxt, noLoc (tconName tc), cvt_tvs tvs))
+ Nothing [mk_con constr]
+ (mk_derivs derivs))
+
+cvt_top (ClassD ctxt cl tvs fds decs)
+ = Left $ TyClD $ mkClassDecl (cvt_context ctxt,
+ noLoc (tconName cl),
+ cvt_tvs tvs)
+ (map (noLoc . cvt_fundep) fds)
+ sigs
+ binds
where
(binds,sigs) = cvtBindsAndSigs decs
-cvt_top (Instance tys ty decs)
- = InstD (InstDecl inst_ty binds sigs Nothing loc0)
+cvt_top (InstanceD tys ty decs)
+ = Left $ InstD (InstDecl (noLoc inst_ty) binds sigs)
where
(binds, sigs) = cvtBindsAndSigs decs
- inst_ty = HsForAllTy Nothing
- (cvt_context tys)
- (HsPredTy (cvt_pred ty))
-
-noContext = []
+ inst_ty = mkImplicitHsForAllTy (cvt_context tys) (noLoc (HsPredTy (cvt_pred ty)))
+
+cvt_top (TH.SigD nm typ) = Left $ Hs.SigD (Sig (noLoc (vName nm)) (cvtType typ))
+
+cvt_top (ForeignD (ImportF callconv safety from nm typ))
+ = case parsed of
+ Just (c_header, cis) ->
+ let i = CImport callconv' safety' c_header nilFS cis
+ in Left $ ForD (ForeignImport (noLoc (vName nm)) (cvtType typ) i False)
+ Nothing -> Right $ text (show from)
+ <+> ptext SLIT("is not a valid ccall impent")
+ where callconv' = case callconv of
+ CCall -> CCallConv
+ StdCall -> StdCallConv
+ safety' = case safety of
+ Unsafe -> PlayRisky
+ Safe -> PlaySafe False
+ Threadsafe -> PlaySafe True
+ parsed = parse_ccall_impent (TH.nameBase nm) from
+
+cvt_top (ForeignD (ExportF callconv as nm typ))
+ = let e = CExport (CExportStatic (mkFastString as) callconv')
+ in Left $ ForD (ForeignExport (noLoc (vName nm)) (cvtType typ) e False)
+ where callconv' = case callconv of
+ CCall -> CCallConv
+ StdCall -> StdCallConv
+
+cvt_fundep :: FunDep -> Class.FunDep RdrName
+cvt_fundep (FunDep xs ys) = (map tName xs, map tName ys)
+
+parse_ccall_impent :: String -> String -> Maybe (FastString, CImportSpec)
+parse_ccall_impent nm s
+ = case lex_ccall_impent s of
+ Just ["dynamic"] -> Just (nilFS, CFunction DynamicTarget)
+ Just ["wrapper"] -> Just (nilFS, CWrapper)
+ Just ("static":ts) -> parse_ccall_impent_static nm ts
+ Just ts -> parse_ccall_impent_static nm ts
+ Nothing -> Nothing
+
+parse_ccall_impent_static :: String
+ -> [String]
+ -> Maybe (FastString, CImportSpec)
+parse_ccall_impent_static nm ts
+ = let ts' = case ts of
+ [ "&", cid] -> [ cid]
+ [fname, "&" ] -> [fname ]
+ [fname, "&", cid] -> [fname, cid]
+ _ -> ts
+ in case ts' of
+ [ cid] | is_cid cid -> Just (nilFS, mk_cid cid)
+ [fname, cid] | is_cid cid -> Just (mkFastString fname, mk_cid cid)
+ [ ] -> Just (nilFS, mk_cid nm)
+ [fname ] -> Just (mkFastString fname, mk_cid nm)
+ _ -> Nothing
+ where is_cid :: String -> Bool
+ is_cid x = all (/= '.') x && (isAlpha (head x) || head x == '_')
+ mk_cid :: String -> CImportSpec
+ mk_cid = CFunction . StaticTarget . mkFastString
+
+lex_ccall_impent :: String -> Maybe [String]
+lex_ccall_impent "" = Just []
+lex_ccall_impent ('&':xs) = fmap ("&":) $ lex_ccall_impent xs
+lex_ccall_impent (' ':xs) = lex_ccall_impent xs
+lex_ccall_impent ('\t':xs) = lex_ccall_impent xs
+lex_ccall_impent xs = case span is_valid xs of
+ ("", _) -> Nothing
+ (t, xs') -> fmap (t:) $ lex_ccall_impent xs'
+ where is_valid :: Char -> Bool
+ is_valid c = isAscii c && (isAlphaNum c || c `elem` "._")
+
+noContext = noLoc []
noExistentials = []
-noFunDeps = []
-------------------------------------------------------------------
-convertToHsExpr :: Meta.Exp -> HsExpr RdrName
-convertToHsExpr = cvt
+convertToHsExpr :: TH.Exp -> LHsExpr RdrName
+convertToHsExpr = cvtl
-cvt (Var s) = HsVar(vName s)
-cvt (Con s) = HsVar(cName s)
-cvt (Lit l)
+cvtl e = noLoc (cvt e)
+
+cvt (VarE s) = HsVar (vName s)
+cvt (ConE s) = HsVar (cName s)
+cvt (LitE l)
| overloadedLit l = HsOverLit (cvtOverLit l)
| otherwise = HsLit (cvtLit l)
-cvt (App x y) = HsApp (cvt x) (cvt y)
-cvt (Lam ps e) = HsLam (mkSimpleMatch (map cvtp ps) (cvt e) void loc0)
-cvt (Tup es) = ExplicitTuple(map cvt es) Boxed
-cvt (Cond x y z) = HsIf (cvt x) (cvt y) (cvt z) loc0
-cvt (Let ds e) = HsLet (cvtdecs ds) (cvt e)
-cvt (Case e ms) = HsCase (cvt e) (map cvtm ms) loc0
-cvt (Do ss) = HsDo DoExpr (cvtstmts ss) [] void loc0
-cvt (Comp ss) = HsDo ListComp (cvtstmts ss) [] void loc0
-cvt (ArithSeq dd) = ArithSeqIn (cvtdd dd)
-cvt (ListExp xs) = ExplicitList void (map cvt xs)
-cvt (Infix (Just x) s (Just y)) = OpApp (cvt x) (HsVar(vName s)) undefined (cvt y)
-cvt (Infix Nothing s (Just y)) = SectionR (HsVar(vName s)) (cvt y)
-cvt (Infix (Just x) s Nothing ) = SectionL (cvt x) (HsVar(vName s))
-cvt (Infix Nothing s Nothing ) = HsVar(vName s) -- Can I indicate this is an infix thing?
-
-
-cvtdecs :: [Meta.Dec] -> HsBinds RdrName
-cvtdecs [] = EmptyBinds
-cvtdecs ds = MonoBind binds sigs Recursive
+cvt (AppE x y) = HsApp (cvtl x) (cvtl y)
+cvt (LamE ps e) = HsLam (mkMatchGroup [mkSimpleMatch (map cvtlp ps) (cvtl e)])
+cvt (TupE [e]) = cvt e
+cvt (TupE es) = ExplicitTuple(map cvtl es) Boxed
+cvt (CondE x y z) = HsIf (cvtl x) (cvtl y) (cvtl z)
+cvt (LetE ds e) = HsLet (cvtdecs ds) (cvtl e)
+cvt (CaseE e ms) = HsCase (cvtl e) (mkMatchGroup (map cvtm ms))
+cvt (DoE ss) = HsDo DoExpr (cvtstmts ss) [] void
+cvt (CompE ss) = HsDo ListComp (cvtstmts ss) [] void
+cvt (ArithSeqE dd) = ArithSeqIn (cvtdd dd)
+cvt (ListE xs) = ExplicitList void (map cvtl xs)
+cvt (InfixE (Just x) s (Just y))
+ = HsPar (noLoc $ OpApp (cvtl x) (cvtl s) undefined (cvtl y))
+cvt (InfixE Nothing s (Just y)) = SectionR (cvtl s) (cvtl y)
+cvt (InfixE (Just x) s Nothing ) = SectionL (cvtl x) (cvtl s)
+cvt (InfixE Nothing s Nothing ) = cvt s -- Can I indicate this is an infix thing?
+cvt (SigE e t) = ExprWithTySig (cvtl e) (cvtType t)
+cvt (RecConE c flds) = RecordCon (noLoc (cName c)) (map (\(x,y) -> (noLoc (vName x), cvtl y)) flds)
+cvt (RecUpdE e flds) = RecordUpd (cvtl e) (map (\(x,y) -> (noLoc (vName x), cvtl y)) flds)
+
+cvtdecs :: [TH.Dec] -> [HsBindGroup RdrName]
+cvtdecs [] = []
+cvtdecs ds = [HsBindGroup binds sigs Recursive]
where
(binds, sigs) = cvtBindsAndSigs ds
where
(sigs, non_sigs) = partition sigP ds
-cvtSig (Proto nm typ) = Sig (vName nm) (cvtType typ) loc0
+cvtSig (TH.SigD nm typ) = noLoc (Hs.Sig (noLoc (vName nm)) (cvtType typ))
-cvtds :: [Meta.Dec] -> MonoBinds RdrName
-cvtds [] = EmptyMonoBinds
-cvtds (d:ds) = AndMonoBinds (cvtd d) (cvtds ds)
+cvtds :: [TH.Dec] -> LHsBinds RdrName
+cvtds [] = emptyBag
+cvtds (d:ds) = cvtd d `consBag` cvtds ds
-cvtd :: Meta.Dec -> MonoBinds RdrName
+cvtd :: TH.Dec -> LHsBind RdrName
-- Used only for declarations in a 'let/where' clause,
-- not for top level decls
-cvtd (Val (Pvar s) body ds) = FunMonoBind (vName s) False
- (panic "what now?") loc0
-cvtd (Fun nm cls) = FunMonoBind (vName nm) False (map cvtclause cls) loc0
-cvtd (Val p body ds) = PatMonoBind (cvtp p) (GRHSs (cvtguard body)
- (cvtdecs ds)
- void) loc0
-cvtd x = panic "Illegal kind of declaration in where clause"
+cvtd (TH.ValD (TH.VarP s) body ds)
+ = noLoc $ FunBind (noLoc (vName s)) False (mkMatchGroup [cvtclause (Clause [] body ds)])
+cvtd (FunD nm cls)
+ = noLoc $ FunBind (noLoc (vName nm)) False (mkMatchGroup (map cvtclause cls))
+cvtd (TH.ValD p body ds)
+ = noLoc $ PatBind (cvtlp p) (GRHSs (cvtguard body) (cvtdecs ds)) void
+
+cvtd d = cvtPanic "Illegal kind of declaration in where clause"
+ (text (TH.pprint d))
-cvtclause :: Meta.Clause (Meta.Pat) (Meta.Exp) (Meta.Dec) -> Hs.Match RdrName
-cvtclause (ps,body,wheres) = Match (map cvtp ps) Nothing
- (GRHSs (cvtguard body) (cvtdecs wheres) void)
+cvtclause :: TH.Clause -> Hs.LMatch RdrName
+cvtclause (Clause ps body wheres)
+ = noLoc $ Hs.Match (map cvtlp ps) Nothing (GRHSs (cvtguard body) (cvtdecs wheres))
-cvtdd :: Meta.DDt -> ArithSeqInfo RdrName
-cvtdd (Meta.From x) = (Hs.From (cvt x))
-cvtdd (Meta.FromThen x y) = (Hs.FromThen (cvt x) (cvt y))
-cvtdd (Meta.FromTo x y) = (Hs.FromTo (cvt x) (cvt y))
-cvtdd (Meta.FromThenTo x y z) = (Hs.FromThenTo (cvt x) (cvt y) (cvt z))
+cvtdd :: Range -> ArithSeqInfo RdrName
+cvtdd (FromR x) = (From (cvtl x))
+cvtdd (FromThenR x y) = (FromThen (cvtl x) (cvtl y))
+cvtdd (FromToR x y) = (FromTo (cvtl x) (cvtl y))
+cvtdd (FromThenToR x y z) = (FromThenTo (cvtl x) (cvtl y) (cvtl z))
-cvtstmts :: [Meta.Stm] -> [Hs.Stmt RdrName]
-cvtstmts [] = [] -- this is probably an error as every [stmt] should end with ResultStmt
-cvtstmts [NoBindSt e] = [ResultStmt (cvt e) loc0] -- when its the last element use ResultStmt
-cvtstmts (NoBindSt e : ss) = ExprStmt (cvt e) void loc0 : cvtstmts ss
-cvtstmts (BindSt p e : ss) = BindStmt (cvtp p) (cvt e) loc0 : cvtstmts ss
-cvtstmts (LetSt ds : ss) = LetStmt (cvtdecs ds) : cvtstmts ss
-cvtstmts (ParSt dss : ss) = ParStmt(map cvtstmts dss) : cvtstmts ss
+cvtstmts :: [TH.Stmt] -> [Hs.LStmt RdrName]
+cvtstmts [] = [] -- this is probably an error as every [stmt] should end with ResultStmt
+cvtstmts [NoBindS e] = [nlResultStmt (cvtl e)] -- when its the last element use ResultStmt
+cvtstmts (NoBindS e : ss) = nlExprStmt (cvtl e) : cvtstmts ss
+cvtstmts (TH.BindS p e : ss) = nlBindStmt (cvtlp p) (cvtl e) : cvtstmts ss
+cvtstmts (TH.LetS ds : ss) = nlLetStmt (cvtdecs ds) : cvtstmts ss
+cvtstmts (TH.ParS dss : ss) = nlParStmt [(cvtstmts ds, undefined) | ds <- dss] : cvtstmts ss
+cvtm :: TH.Match -> Hs.LMatch RdrName
+cvtm (TH.Match p body wheres)
+ = noLoc (Hs.Match [cvtlp p] Nothing (GRHSs (cvtguard body) (cvtdecs wheres)))
-cvtm :: Meta.Mat -> Hs.Match RdrName
-cvtm (p,body,wheres) = Match [cvtp p] Nothing
- (GRHSs (cvtguard body) (cvtdecs wheres) void)
-
-cvtguard :: Meta.Rhs -> [GRHS RdrName]
-cvtguard (Guarded pairs) = map cvtpair pairs
-cvtguard (Normal e) = [GRHS [ ResultStmt (cvt e) loc0 ] loc0]
+cvtguard :: TH.Body -> [LGRHS RdrName]
+cvtguard (GuardedB pairs) = map cvtpair pairs
+cvtguard (NormalB e) = [noLoc (GRHS [ nlResultStmt (cvtl e) ])]
-cvtpair :: (Meta.Exp,Meta.Exp) -> GRHS RdrName
-cvtpair (x,y) = GRHS [BindStmt truePat (cvt x) loc0,
- ResultStmt (cvt y) loc0] loc0
+cvtpair :: (TH.Guard,TH.Exp) -> LGRHS RdrName
+cvtpair (NormalG x,y) = noLoc (GRHS [nlBindStmt truePat (cvtl x),
+ nlResultStmt (cvtl y)])
+cvtpair (PatG x,y) = noLoc (GRHS (cvtstmts x ++ [nlResultStmt (cvtl y)]))
cvtOverLit :: Lit -> HsOverLit
-cvtOverLit (Int i) = mkHsIntegral (fromInt i)
--- An Int is like an an (overloaded) '3' in a Haskell source program
+cvtOverLit (IntegerL i) = mkHsIntegral i
+cvtOverLit (RationalL r) = mkHsFractional r
+-- An Integer is like an an (overloaded) '3' in a Haskell source program
+-- Similarly 3.5 for fractionals
cvtLit :: Lit -> HsLit
-cvtLit (Char c) = HsChar (ord c)
-cvtLit (CrossStage s) = error "What do we do about crossStage constants?"
+cvtLit (IntPrimL i) = HsIntPrim i
+cvtLit (FloatPrimL f) = HsFloatPrim f
+cvtLit (DoublePrimL f) = HsDoublePrim f
+cvtLit (CharL c) = HsChar c
+cvtLit (StringL s) = HsString (mkFastString s)
+
+cvtlp :: TH.Pat -> Hs.LPat RdrName
+cvtlp pat = noLoc (cvtp pat)
-cvtp :: Meta.Pat -> Hs.Pat RdrName
-cvtp (Plit l)
+cvtp :: TH.Pat -> Hs.Pat RdrName
+cvtp (TH.LitP l)
| overloadedLit l = NPatIn (cvtOverLit l) Nothing -- Not right for negative
-- patterns; need to think
-- about that!
- | otherwise = LitPat (cvtLit l)
-cvtp (Pvar s) = VarPat(vName s)
-cvtp (Ptup ps) = TuplePat (map cvtp ps) Boxed
-cvtp (Pcon s ps) = ConPatIn (cName s) (PrefixCon (map cvtp ps))
-cvtp (Ptilde p) = LazyPat (cvtp p)
-cvtp (Paspat s p) = AsPat (vName s) (cvtp p)
-cvtp Pwild = WildPat void
+ | otherwise = Hs.LitPat (cvtLit l)
+cvtp (TH.VarP s) = Hs.VarPat(vName s)
+cvtp (TupP [p]) = cvtp p
+cvtp (TupP ps) = TuplePat (map cvtlp ps) Boxed
+cvtp (ConP s ps) = ConPatIn (noLoc (cName s)) (PrefixCon (map cvtlp ps))
+cvtp (InfixP p1 s p2)
+ = ConPatIn (noLoc (cName s)) (InfixCon (cvtlp p1) (cvtlp p2))
+cvtp (TildeP p) = LazyPat (cvtlp p)
+cvtp (TH.AsP s p) = AsPat (noLoc (vName s)) (cvtlp p)
+cvtp TH.WildP = WildPat void
+cvtp (RecP c fs) = ConPatIn (noLoc (cName c)) $ Hs.RecCon (map (\(s,p) -> (noLoc (vName s),cvtlp p)) fs)
+cvtp (ListP ps) = ListPat (map cvtlp ps) void
+cvtp (SigP p t) = SigPatIn (cvtlp p) (cvtType t)
-----------------------------------------------------------
-- Types and type variables
-cvt_tvs :: [String] -> [HsTyVarBndr RdrName]
-cvt_tvs tvs = map (UserTyVar . tName) tvs
+cvt_tvs :: [TH.Name] -> [LHsTyVarBndr RdrName]
+cvt_tvs tvs = map (noLoc . UserTyVar . tName) tvs
-cvt_context :: Context -> HsContext RdrName
-cvt_context tys = map cvt_pred tys
+cvt_context :: Cxt -> LHsContext RdrName
+cvt_context tys = noLoc (map (noLoc . cvt_pred) tys)
-cvt_pred :: Typ -> HsPred RdrName
+cvt_pred :: TH.Type -> HsPred RdrName
cvt_pred ty = case split_ty_app ty of
- (Tvar tc, tys) -> HsClassP (tconName tc) (map cvtType tys)
- other -> panic "Malformed predicate"
-
-cvtType :: Meta.Typ -> HsType RdrName
-cvtType (Tvar nm) = HsTyVar(tName nm)
-cvtType (Tapp x y) = trans (root x [y])
- where root (Tapp a b) zs = root a (b:zs)
- root t zs = (t,zs)
- trans (Tcon (Tuple n),args) = HsTupleTy (HsTupCon Boxed n) (map cvtType args)
- trans (Tcon Arrow,[x,y]) = HsFunTy (cvtType x) (cvtType y)
- trans (Tcon List,[x]) = HsListTy (cvtType x)
- trans (Tcon (Name nm),args) = HsTyVar(tconName nm)
- trans (t,args) = panic "bad type application"
-
-split_ty_app :: Typ -> (Typ, [Typ])
+ (ConT tc, tys) -> HsClassP (tconName tc) (map cvtType tys)
+ (VarT tv, tys) -> HsClassP (tName tv) (map cvtType tys)
+ other -> cvtPanic "Malformed predicate" (text (TH.pprint ty))
+
+convertToHsType = cvtType
+
+cvtType :: TH.Type -> LHsType RdrName
+cvtType ty = trans (root ty [])
+ where root (AppT a b) zs = root a (cvtType b : zs)
+ root t zs = (t,zs)
+
+ trans (TupleT n,args)
+ | length args == n = noLoc (HsTupleTy Boxed args)
+ | n == 0 = foldl nlHsAppTy (nlHsTyVar (getRdrName unitTyCon)) args
+ | otherwise = foldl nlHsAppTy (nlHsTyVar (getRdrName (tupleTyCon Boxed n))) args
+ trans (ArrowT, [x,y]) = nlHsFunTy x y
+ trans (ListT, [x]) = noLoc (HsListTy x)
+
+ trans (VarT nm, args) = foldl nlHsAppTy (nlHsTyVar (tName nm)) args
+ trans (ConT tc, args) = foldl nlHsAppTy (nlHsTyVar (tconName tc)) args
+
+ trans (ForallT tvs cxt ty, []) = noLoc $ mkExplicitHsForAllTy
+ (cvt_tvs tvs) (cvt_context cxt) (cvtType ty)
+
+split_ty_app :: TH.Type -> (TH.Type, [TH.Type])
split_ty_app ty = go ty []
where
- go (Tapp f a) as = go f (a:as)
+ go (AppT f a) as = go f (a:as)
go f as = (f,as)
-----------------------------------------------------------
sigP :: Dec -> Bool
-sigP (Proto _ _) = True
+sigP (TH.SigD _ _) = True
sigP other = False
-sigOrBindP :: Dec -> Bool
-sigOrBindP (Proto _ _) = True
-sigOrBindP (Val _ _ _) = True
-sigOrBindP (Fun _ _) = True
-sigOrBindP other = False
+-----------------------------------------------------------
+cvtPanic :: String -> SDoc -> b
+cvtPanic herald thing
+ = pprPanic herald (thing $$ ptext SLIT("When splicing generated code into the program"))
-----------------------------------------------------------
-- some useful things
-truePat = ConPatIn (cName "True") (PrefixCon [])
-falsePat = ConPatIn (cName "False") (PrefixCon [])
+truePat = nlConPat (getRdrName trueDataCon) []
overloadedLit :: Lit -> Bool
-- True for literals that Haskell treats as overloaded
-overloadedLit (Int l) = True
-overloadedLit l = False
+overloadedLit (IntegerL l) = True
+overloadedLit (RationalL l) = True
+overloadedLit l = False
void :: Type.Type
void = placeHolderType
-loc0 :: SrcLoc
-loc0 = generatedSrcLoc
+loc0 :: SrcSpan
+loc0 = srcLocSpan generatedSrcLoc
-fromInt :: Int -> Integer
-fromInt x = toInteger x
+--------------------------------------------------------------------
+-- Turning Name back into RdrName
+--------------------------------------------------------------------
-- variable names
-vName :: String -> RdrName
-vName = mkName varName
+vName :: TH.Name -> RdrName
+vName = thRdrName OccName.varName
--- Constructor function names
-cName :: String -> RdrName
-cName = mkName dataName
+-- Constructor function names; this is Haskell source, hence srcDataName
+cName :: TH.Name -> RdrName
+cName = thRdrName OccName.srcDataName
-- Type variable names
-tName :: String -> RdrName
-tName = mkName tvName
+tName :: TH.Name -> RdrName
+tName = thRdrName OccName.tvName
-- Type Constructor names
-tconName = mkName tcName
+tconName = thRdrName OccName.tcName
-mkName :: NameSpace -> String -> RdrName
--- Parse the string to see if it has a "." or ":" in it
--- so we know whether to generate a qualified or original name
+thRdrName :: OccName.NameSpace -> TH.Name -> RdrName
+-- This turns a Name into a RdrName
+
+thRdrName ns (TH.Name occ (TH.NameG ns' mod)) = mkOrig (mk_mod mod) (mk_occ ns occ)
+thRdrName ns (TH.Name occ TH.NameS) = mkDynName ns occ
+thRdrName ns (TH.Name occ (TH.NameU uniq))
+ = mkRdrUnqual (OccName.mkOccName ns uniq_str)
+ where
+ uniq_str = TH.occString occ ++ '[' : shows (mkUniqueGrimily (I# uniq)) "]"
+ -- The idea here is to make a name that
+ -- a) the user could not possibly write, and
+ -- b) cannot clash with another NameU
+ -- Previously I generated an Exact RdrName with mkInternalName.
+ -- This works fine for local binders, but does not work at all for
+ -- top-level binders, which must have External Names, since they are
+ -- rapidly baked into data constructors and the like. Baling out
+ -- and generating an unqualified RdrName here is the simple solution
+
+-- The packing and unpacking is rather turgid :-(
+mk_occ :: OccName.NameSpace -> TH.OccName -> OccName.OccName
+mk_occ ns occ = OccName.mkOccFS ns (mkFastString (TH.occString occ))
+
+mk_mod :: TH.ModName -> Module
+mk_mod mod = mkModule (TH.modString mod)
+
+mkDynName :: OccName.NameSpace -> TH.OccName -> RdrName
+-- Parse the string to see if it has a "." in it
+-- so we know whether to generate a qualified or unqualified name
-- It's a bit tricky because we need to parse
-- Foo.Baz.x as Qual Foo.Baz x
-- So we parse it from back to front
-mkName ns str
- = split [] (reverse str)
+mkDynName ns th_occ
+ = split [] (reverse (TH.occString th_occ))
where
- split occ [] = mkRdrUnqual (mk_occ occ)
- split occ (c:d:rev) -- 'd' is the last char before the separator
- | is_sep c -- E.g. Fo.x d='o'
- && isAlphaNum d -- Fo.+: d='+' perhaps
- = mk_qual (reverse (d:rev)) c occ
- split occ (c:rev) = split (c:occ) rev
-
- mk_qual mod '.' occ = mkRdrQual (mk_mod mod) (mk_occ occ)
- mk_qual mod ':' occ = mkOrig (mk_mod mod) (mk_occ occ)
-
- mk_occ occ = mkOccFS ns (mkFastString occ)
- mk_mod mod = mkModuleName mod
-
- is_sep '.' = True
- is_sep ':' = True
- is_sep other = False
+ split occ [] = mkRdrUnqual (mk_occ occ)
+ split occ ('.':rev) = mkRdrQual (mk_mod (reverse rev)) (mk_occ occ)
+ split occ (c:rev) = split (c:occ) rev
+
+ mk_occ occ = OccName.mkOccFS ns (mkFastString occ)
+ mk_mod mod = mkModule mod
\end{code}
+