2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
5 This module converts Template Haskell syntax into HsSyn
9 module Convert( convertToHsExpr, convertToHsDecls ) where
11 #include "HsVersions.h"
13 import Language.Haskell.TH.THSyntax as TH
14 import Language.Haskell.TH.THLib as TH -- Pretty printing
17 ( HsExpr(..), HsLit(..), ArithSeqInfo(..),
18 HsStmtContext(..), TyClDecl(..), HsBang(..),
19 Match(..), GRHSs(..), GRHS(..), HsPred(..),
20 HsDecl(..), TyClDecl(..), InstDecl(..), ConDecl(..),
21 Stmt(..), HsBinds(..), MonoBinds(..), Sig(..),
22 Pat(..), HsConDetails(..), HsOverLit, BangType(..),
23 placeHolderType, HsType(..), HsExplicitForAll(..),
24 HsTyVarBndr(..), HsContext,
25 mkSimpleMatch, mkImplicitHsForAllTy, mkExplicitHsForAllTy
28 import RdrName ( RdrName, mkRdrUnqual, mkRdrQual, mkOrig, nameRdrName, getRdrName )
29 import Module ( ModuleName, mkModuleName )
30 import RdrHsSyn ( mkHsIntegral, mkHsFractional, mkClassDecl, mkTyData )
31 import Name ( mkInternalName )
32 import qualified OccName
33 import SrcLoc ( SrcLoc, generatedSrcLoc )
35 import TysWiredIn ( unitTyCon, tupleTyCon, trueDataCon, falseDataCon )
36 import BasicTypes( Boxity(..), RecFlag(Recursive), NewOrData(..) )
37 import ForeignCall ( Safety(..), CCallConv(..), CCallTarget(..),
39 import HsDecls ( CImportSpec(..), ForeignImport(..), ForeignExport(..),
41 import FastString( FastString, mkFastString, nilFS )
42 import Char ( ord, isAscii, isAlphaNum, isAlpha )
43 import List ( partition )
44 import SrcLoc ( noSrcLoc )
45 import Unique ( Unique, mkUniqueGrimily )
46 import ErrUtils (Message)
47 import GLAEXTS ( Int#, Int(..) )
51 -------------------------------------------------------------------
52 convertToHsDecls :: [TH.Dec] -> [Either (HsDecl RdrName) Message]
53 convertToHsDecls ds = map cvt_top ds
55 mk_con con = case con of
57 -> ConDecl (cName c) noExistentials noContext
58 (PrefixCon (map mk_arg strtys)) loc0
60 -> ConDecl (cName c) noExistentials noContext
61 (RecCon (map mk_id_arg varstrtys)) loc0
63 -> ConDecl (cName c) noExistentials noContext
64 (InfixCon (mk_arg st1) (mk_arg st2)) loc0
66 mk_arg (IsStrict, ty) = BangType HsStrict (cvtType ty)
67 mk_arg (NotStrict, ty) = BangType HsNoBang (cvtType ty)
69 mk_id_arg (i, IsStrict, ty)
70 = (vName i, BangType HsStrict (cvtType ty))
71 mk_id_arg (i, NotStrict, ty)
72 = (vName i, BangType HsNoBang (cvtType ty))
74 mk_derivs [] = Nothing
75 mk_derivs cs = Just [HsClassP (tconName c) [] | c <- cs]
77 cvt_top :: TH.Dec -> Either (HsDecl RdrName) Message
78 cvt_top d@(TH.ValD _ _ _) = Left $ Hs.ValD (cvtd d)
79 cvt_top d@(TH.FunD _ _) = Left $ Hs.ValD (cvtd d)
81 cvt_top (TySynD tc tvs rhs)
82 = Left $ TyClD (TySynonym (tconName tc) (cvt_tvs tvs) (cvtType rhs) loc0)
84 cvt_top (DataD ctxt tc tvs constrs derivs)
85 = Left $ TyClD (mkTyData DataType
86 (cvt_context ctxt, tconName tc, cvt_tvs tvs)
88 (mk_derivs derivs) loc0)
90 cvt_top (NewtypeD ctxt tc tvs constr derivs)
91 = Left $ TyClD (mkTyData NewType
92 (cvt_context ctxt, tconName tc, cvt_tvs tvs)
94 (mk_derivs derivs) loc0)
96 cvt_top (ClassD ctxt cl tvs decs)
97 = Left $ TyClD (mkClassDecl (cvt_context ctxt, tconName cl, cvt_tvs tvs)
101 (binds,sigs) = cvtBindsAndSigs decs
103 cvt_top (InstanceD tys ty decs)
104 = Left $ InstD (InstDecl inst_ty binds sigs loc0)
106 (binds, sigs) = cvtBindsAndSigs decs
107 inst_ty = mkImplicitHsForAllTy (cvt_context tys) (HsPredTy (cvt_pred ty))
109 cvt_top (TH.SigD nm typ) = Left $ Hs.SigD (Sig (vName nm) (cvtType typ) loc0)
111 cvt_top (ForeignD (ImportF callconv safety from nm typ))
113 Just (c_header, cis) ->
114 let i = CImport callconv' safety' c_header nilFS cis
115 in Left $ ForD (ForeignImport (vName nm) (cvtType typ) i False loc0)
116 Nothing -> Right $ text (show from)
117 <+> ptext SLIT("is not a valid ccall impent")
118 where callconv' = case callconv of
120 StdCall -> StdCallConv
121 safety' = case safety of
123 Safe -> PlaySafe False
124 Threadsafe -> PlaySafe True
125 parsed = parse_ccall_impent (TH.nameBase nm) from
127 cvt_top (ForeignD (ExportF callconv as nm typ))
128 = let e = CExport (CExportStatic (mkFastString as) callconv')
129 in Left $ ForD (ForeignExport (vName nm) (cvtType typ) e False loc0)
130 where callconv' = case callconv of
132 StdCall -> StdCallConv
134 parse_ccall_impent :: String -> String -> Maybe (FastString, CImportSpec)
135 parse_ccall_impent nm s
136 = case lex_ccall_impent s of
137 Just ["dynamic"] -> Just (nilFS, CFunction DynamicTarget)
138 Just ["wrapper"] -> Just (nilFS, CWrapper)
139 Just ("static":ts) -> parse_ccall_impent_static nm ts
140 Just ts -> parse_ccall_impent_static nm ts
143 parse_ccall_impent_static :: String
145 -> Maybe (FastString, CImportSpec)
146 parse_ccall_impent_static nm ts
147 = let ts' = case ts of
148 [ "&", cid] -> [ cid]
149 [fname, "&" ] -> [fname ]
150 [fname, "&", cid] -> [fname, cid]
153 [ cid] | is_cid cid -> Just (nilFS, mk_cid cid)
154 [fname, cid] | is_cid cid -> Just (mkFastString fname, mk_cid cid)
155 [ ] -> Just (nilFS, mk_cid nm)
156 [fname ] -> Just (mkFastString fname, mk_cid nm)
158 where is_cid :: String -> Bool
159 is_cid x = all (/= '.') x && (isAlpha (head x) || head x == '_')
160 mk_cid :: String -> CImportSpec
161 mk_cid = CFunction . StaticTarget . mkFastString
163 lex_ccall_impent :: String -> Maybe [String]
164 lex_ccall_impent "" = Just []
165 lex_ccall_impent ('&':xs) = fmap ("&":) $ lex_ccall_impent xs
166 lex_ccall_impent (' ':xs) = lex_ccall_impent xs
167 lex_ccall_impent ('\t':xs) = lex_ccall_impent xs
168 lex_ccall_impent xs = case span is_valid xs of
170 (t, xs') -> fmap (t:) $ lex_ccall_impent xs'
171 where is_valid :: Char -> Bool
172 is_valid c = isAscii c && (isAlphaNum c || c `elem` "._")
178 -------------------------------------------------------------------
179 convertToHsExpr :: TH.Exp -> HsExpr RdrName
180 convertToHsExpr = cvt
182 cvt (VarE s) = HsVar (vName s)
183 cvt (ConE s) = HsVar (cName s)
185 | overloadedLit l = HsOverLit (cvtOverLit l)
186 | otherwise = HsLit (cvtLit l)
188 cvt (AppE x y) = HsApp (cvt x) (cvt y)
189 cvt (LamE ps e) = HsLam (mkSimpleMatch (map cvtp ps) (cvt e) void loc0)
190 cvt (TupE [e]) = cvt e
191 cvt (TupE es) = ExplicitTuple(map cvt es) Boxed
192 cvt (CondE x y z) = HsIf (cvt x) (cvt y) (cvt z) loc0
193 cvt (LetE ds e) = HsLet (cvtdecs ds) (cvt e)
194 cvt (CaseE e ms) = HsCase (cvt e) (map cvtm ms) loc0
195 cvt (DoE ss) = HsDo DoExpr (cvtstmts ss) [] void loc0
196 cvt (CompE ss) = HsDo ListComp (cvtstmts ss) [] void loc0
197 cvt (ArithSeqE dd) = ArithSeqIn (cvtdd dd)
198 cvt (ListE xs) = ExplicitList void (map cvt xs)
199 cvt (InfixE (Just x) s (Just y))
200 = HsPar (OpApp (cvt x) (cvt s) undefined (cvt y))
201 cvt (InfixE Nothing s (Just y)) = SectionR (cvt s) (cvt y)
202 cvt (InfixE (Just x) s Nothing ) = SectionL (cvt x) (cvt s)
203 cvt (InfixE Nothing s Nothing ) = cvt s -- Can I indicate this is an infix thing?
204 cvt (SigE e t) = ExprWithTySig (cvt e) (cvtType t)
205 cvt (RecConE c flds) = RecordCon (cName c) (map (\(x,y) -> (vName x, cvt y)) flds)
206 cvt (RecUpdE e flds) = RecordUpd (cvt e) (map (\(x,y) -> (vName x, cvt y)) flds)
208 cvtdecs :: [TH.Dec] -> HsBinds RdrName
209 cvtdecs [] = EmptyBinds
210 cvtdecs ds = MonoBind binds sigs Recursive
212 (binds, sigs) = cvtBindsAndSigs ds
215 = (cvtds non_sigs, map cvtSig sigs)
217 (sigs, non_sigs) = partition sigP ds
219 cvtSig (TH.SigD nm typ) = Hs.Sig (vName nm) (cvtType typ) loc0
221 cvtds :: [TH.Dec] -> MonoBinds RdrName
222 cvtds [] = EmptyMonoBinds
223 cvtds (d:ds) = AndMonoBinds (cvtd d) (cvtds ds)
225 cvtd :: TH.Dec -> MonoBinds RdrName
226 -- Used only for declarations in a 'let/where' clause,
227 -- not for top level decls
228 cvtd (TH.ValD (TH.VarP s) body ds) = FunMonoBind (vName s) False
229 [cvtclause (Clause [] body ds)] loc0
230 cvtd (FunD nm cls) = FunMonoBind (vName nm) False (map cvtclause cls) loc0
231 cvtd (TH.ValD p body ds) = PatMonoBind (cvtp p) (GRHSs (cvtguard body)
235 cvtd d = cvtPanic "Illegal kind of declaration in where clause"
236 (text (show (TH.pprDec d)))
239 cvtclause :: TH.Clause -> Hs.Match RdrName
240 cvtclause (Clause ps body wheres)
241 = Hs.Match (map cvtp ps) Nothing (GRHSs (cvtguard body) (cvtdecs wheres) void)
245 cvtdd :: Range -> ArithSeqInfo RdrName
246 cvtdd (FromR x) = (From (cvt x))
247 cvtdd (FromThenR x y) = (FromThen (cvt x) (cvt y))
248 cvtdd (FromToR x y) = (FromTo (cvt x) (cvt y))
249 cvtdd (FromThenToR x y z) = (FromThenTo (cvt x) (cvt y) (cvt z))
252 cvtstmts :: [TH.Stmt] -> [Hs.Stmt RdrName]
253 cvtstmts [] = [] -- this is probably an error as every [stmt] should end with ResultStmt
254 cvtstmts [NoBindS e] = [ResultStmt (cvt e) loc0] -- when its the last element use ResultStmt
255 cvtstmts (NoBindS e : ss) = ExprStmt (cvt e) void loc0 : cvtstmts ss
256 cvtstmts (TH.BindS p e : ss) = BindStmt (cvtp p) (cvt e) loc0 : cvtstmts ss
257 cvtstmts (TH.LetS ds : ss) = LetStmt (cvtdecs ds) : cvtstmts ss
258 cvtstmts (TH.ParS dss : ss) = ParStmt [(cvtstmts ds, undefined) | ds <- dss] : cvtstmts ss
260 cvtm :: TH.Match -> Hs.Match RdrName
261 cvtm (TH.Match p body wheres)
262 = Hs.Match [cvtp p] Nothing (GRHSs (cvtguard body) (cvtdecs wheres) void)
264 cvtguard :: TH.Body -> [GRHS RdrName]
265 cvtguard (GuardedB pairs) = map cvtpair pairs
266 cvtguard (NormalB e) = [GRHS [ ResultStmt (cvt e) loc0 ] loc0]
268 cvtpair :: (TH.Exp,TH.Exp) -> GRHS RdrName
269 cvtpair (x,y) = GRHS [Hs.BindStmt truePat (cvt x) loc0,
270 ResultStmt (cvt y) loc0] loc0
272 cvtOverLit :: Lit -> HsOverLit
273 cvtOverLit (IntegerL i) = mkHsIntegral i
274 cvtOverLit (RationalL r) = mkHsFractional r
275 -- An Integer is like an an (overloaded) '3' in a Haskell source program
276 -- Similarly 3.5 for fractionals
278 cvtLit :: Lit -> HsLit
279 cvtLit (IntPrimL i) = HsIntPrim i
280 cvtLit (FloatPrimL f) = HsFloatPrim f
281 cvtLit (DoublePrimL f) = HsDoublePrim f
282 cvtLit (CharL c) = HsChar (ord c)
283 cvtLit (StringL s) = HsString (mkFastString s)
285 cvtp :: TH.Pat -> Hs.Pat RdrName
287 | overloadedLit l = NPatIn (cvtOverLit l) Nothing -- Not right for negative
288 -- patterns; need to think
290 | otherwise = Hs.LitPat (cvtLit l)
291 cvtp (TH.VarP s) = Hs.VarPat(vName s)
292 cvtp (TupP [p]) = cvtp p
293 cvtp (TupP ps) = TuplePat (map cvtp ps) Boxed
294 cvtp (ConP s ps) = ConPatIn (cName s) (PrefixCon (map cvtp ps))
295 cvtp (TildeP p) = LazyPat (cvtp p)
296 cvtp (TH.AsP s p) = AsPat (vName s) (cvtp p)
297 cvtp TH.WildP = WildPat void
298 cvtp (RecP c fs) = ConPatIn (cName c) $ Hs.RecCon (map (\(s,p) -> (vName s,cvtp p)) fs)
299 cvtp (ListP ps) = ListPat (map cvtp ps) void
301 -----------------------------------------------------------
302 -- Types and type variables
304 cvt_tvs :: [TH.Name] -> [HsTyVarBndr RdrName]
305 cvt_tvs tvs = map (UserTyVar . tName) tvs
307 cvt_context :: Cxt -> HsContext RdrName
308 cvt_context tys = map cvt_pred tys
310 cvt_pred :: TH.Type -> HsPred RdrName
311 cvt_pred ty = case split_ty_app ty of
312 (ConT tc, tys) -> HsClassP (tconName tc) (map cvtType tys)
313 (VarT tv, tys) -> HsClassP (tName tv) (map cvtType tys)
314 other -> cvtPanic "Malformed predicate" (text (show (TH.pprType ty)))
316 cvtType :: TH.Type -> HsType RdrName
317 cvtType ty = trans (root ty [])
318 where root (AppT a b) zs = root a (cvtType b : zs)
321 trans (TupleT n,args)
322 | length args == n = HsTupleTy Boxed args
323 | n == 0 = foldl HsAppTy (HsTyVar (getRdrName unitTyCon)) args
324 | otherwise = foldl HsAppTy (HsTyVar (getRdrName (tupleTyCon Boxed n))) args
325 trans (ArrowT, [x,y]) = HsFunTy x y
326 trans (ListT, [x]) = HsListTy x
328 trans (VarT nm, args) = foldl HsAppTy (HsTyVar (tName nm)) args
329 trans (ConT tc, args) = foldl HsAppTy (HsTyVar (tconName tc)) args
331 trans (ForallT tvs cxt ty, []) = mkExplicitHsForAllTy
332 (cvt_tvs tvs) (cvt_context cxt) (cvtType ty)
334 split_ty_app :: TH.Type -> (TH.Type, [TH.Type])
335 split_ty_app ty = go ty []
337 go (AppT f a) as = go f (a:as)
340 -----------------------------------------------------------
342 sigP (TH.SigD _ _) = True
346 -----------------------------------------------------------
347 cvtPanic :: String -> SDoc -> b
348 cvtPanic herald thing
349 = pprPanic herald (thing $$ ptext SLIT("When splicing generated code into the program"))
351 -----------------------------------------------------------
352 -- some useful things
354 truePat = ConPatIn (getRdrName trueDataCon) (PrefixCon [])
355 falsePat = ConPatIn (getRdrName falseDataCon) (PrefixCon [])
357 overloadedLit :: Lit -> Bool
358 -- True for literals that Haskell treats as overloaded
359 overloadedLit (IntegerL l) = True
360 overloadedLit (RationalL l) = True
361 overloadedLit l = False
364 void = placeHolderType
367 loc0 = generatedSrcLoc
369 --------------------------------------------------------------------
370 -- Turning Name back into RdrName
371 --------------------------------------------------------------------
374 vName :: TH.Name -> RdrName
375 vName = mk_name OccName.varName
377 -- Constructor function names; this is Haskell source, hence srcDataName
378 cName :: TH.Name -> RdrName
379 cName = mk_name OccName.srcDataName
381 -- Type variable names
382 tName :: TH.Name -> RdrName
383 tName = mk_name OccName.tvName
385 -- Type Constructor names
386 tconName = mk_name OccName.tcName
388 mk_name :: OccName.NameSpace -> TH.Name -> RdrName
390 -- This turns a Name into a RdrName
391 -- The last case is slightly interesting. It constructs a
392 -- unique name from the unique in the TH thingy, so that the renamer
393 -- won't mess about. I hope. (Another possiblity would be to generate
394 -- "x_77" etc, but that could conceivably clash.)
396 mk_name ns (TH.Name occ (TH.NameG ns' mod)) = mkOrig (mk_mod mod) (mk_occ ns occ)
397 mk_name ns (TH.Name occ TH.NameS) = mkRdrUnqual (mk_occ ns occ)
398 mk_name ns (TH.Name occ (TH.NameU uniq)) = nameRdrName (mkInternalName (mk_uniq uniq) (mk_occ ns occ) noSrcLoc)
400 mk_uniq :: Int# -> Unique
401 mk_uniq u = mkUniqueGrimily (I# u)
403 -- The packing and unpacking is rather turgid :-(
404 mk_occ :: OccName.NameSpace -> TH.OccName -> OccName.OccName
405 mk_occ ns occ = OccName.mkOccFS ns (mkFastString (TH.occString occ))
407 mk_mod :: TH.ModName -> ModuleName
408 mk_mod mod = mkModuleName (TH.modString mod)