-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgen-wrappers.hs
131 lines (106 loc) · 4.18 KB
/
gen-wrappers.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
{-# LANGUAGE FlexibleContexts #-}
import Language.Haskell.Exts
import System.Process
import Control.Exception
import Debug.Trace
import Data.Char
import Data.List
import qualified Data.Map as M
import Data.Map(Map)
import Control.Monad.State
import Control.Applicative
import Data.Maybe
main = do
bro <- readProcess "ghc" [
"-dsuppress-module-prefixes",
"-e",":bro Language.Haskell.TH.Lib"] ""
putStrLn (process bro)
process bro =
case parseModule bro of
ParseOk mod ->
unlines (
"{-# LANGUAGE NoMonomorphismRestriction, FlexibleContexts #-}" :
"{-# OPTIONS -Wall #-}" :
"module Language.Haskell.TH.Build.Wrappers where" :
"import Language.Haskell.TH hiding(Role)" :
"import Language.Haskell.TH.Lib" :
"import Language.Haskell.TH.Build.Convertible" :
"":
"-- AUTOGENERATED by gen-wrappers.hs!" :
"" :
processModule mod
)
e@(ParseFailed srcLoc _) -> error (unlines (
zipWith (\l i -> show i ++"\t"++l) (lines bro) [1..]
++
["Failed to parse :bro output: " ++ show e]
))
noSrcLoc = error "evaluated noSrcLoc"
processModule (Module _ _ _ _ _ _ decls) = concatMap processDecl decls
processDecl :: Decl -> [String]
processDecl (TypeSig _ [n] t)
| arity t == 0 = []
| otherwise =
case n of
Ident n'
-- exclude some functions which only have args of simple types
| "PrimL" `isSuffixOf` n' ||
n' `elem` ["stringL","integerL","rationalL","charL"
,"stringE","tupleT","unboxedTupleT"
,"inlineSpecNoPhase","inlineSpecPhase"
-- Deprecated:
,"global"
] -> []
| otherwise ->
mkWrapper t n'
_ -> trace ("Ignoring operator "++show n) []
processDecl (TypeSig _ _ _) = assert False undefined
processDecl _ = []
mkWrapper :: Type -> String -> [String]
mkWrapper t n =
let
n' = n ++ "'"
in
[ "-- | Argument-converting wrapper for '"++n++"'."
, n' ++ " :: " ++wrapperType t,
n' ++ " = preconvert"++show (arity t)++" "++n
]
arity (TyFun _ b) = 1 + arity b
arity _ = 0
wrapperType :: Type -> String
wrapperType t = "("++intercalate ", " (prettyPrint <$> cxt)++") => "++prettyPrint rhs
where
(cxt,rhs) = runToVar (go t)
go (TyFun a b) = do
v <- toVar a
(cxt',rhs') <- go b
return (
(TyApp (TyApp
(TyCon (UnQual (Ident "Convertible")))
v)
a) : cxt'
, TyFun v rhs'
)
go b = return ([], b)
runToVar :: State (Map k a) c -> c
runToVar = flip evalState M.empty
toVar :: (Functor m, MonadState (Map Type Int) m) => Type -> m Type
toVar t =
do
i <- fromMaybe 0 <$> gets (M.lookup t)
modify (M.insert t (i+1))
return (TyVar (Ident (go t ++ replicate i '\'')))
where
go (TyList t') = go t' ++ "s"
go (TyCon n) = case prettyPrint n of
c:cs -> toLower c : cs
go (TyApp (TyCon (UnQual (Ident "Q"))) t') = go t' ++ "Q"
go (TyTuple Boxed [TyCon (UnQual (Ident "Guard")),TyCon (UnQual (Ident "Exp"))])
= "guardedExp"
go (TyTuple Boxed [TyCon (UnQual (Ident "Strict")),TyCon (UnQual (Ident "Type"))])
= "strictType"
go (TyApp (TyCon (UnQual (Ident "Maybe"))) (TyCon (UnQual (Ident "ExpQ"))))
= "maybeExpQ"
go (TyTuple Boxed [TyCon (UnQual (Ident "Name")),TyCon (UnQual (Ident "Exp"))])
= "nameExpPair"
go t' = error ("toVar: don't know what to do with type "++show t')