9 -- |An internal module for generating Haskell modules eith an
10 -- arbitrary file implanted.
11 module Network.HTTP.Lucu.Implant.PrettyPrint
15 import Codec.Compression.GZip
17 import Data.Ascii (CIAscii)
18 import qualified Data.Ascii as A
19 import qualified Data.ByteString.Lazy as L
21 import Data.Collections
22 import Data.List (intersperse)
25 import Language.Haskell.TH.Lib
26 import Language.Haskell.TH.Ppr
27 import Language.Haskell.TH.PprLib
28 import Language.Haskell.TH.Syntax
29 import Network.HTTP.Lucu.ETag
30 import Network.HTTP.Lucu.Implant
31 import Network.HTTP.Lucu.Implant.Rewrite
32 import Network.HTTP.Lucu.MIMEType
33 import Network.HTTP.Lucu.OrphanInstances ()
34 import Network.HTTP.Lucu.Resource
35 import Prelude hiding (head)
36 import Prelude.Unicode
40 = vcat [ text "{- DO NOT EDIT THIS FILE."
42 vcat [ text "This file is automatically generated by lucu-implant-file."
44 , text " Source:" <+> if iPath ≡ "-" then
48 , hsep [ text " Original Length:"
49 , integer (originalLen i)
53 vcat [ hsep [ text "Compressed Length:"
54 , integer (gzippedLen i)
57 , text " Compression: gzip"
60 text " Compression: disabled"
61 , text " MIME Type:" <+> mimeTypeToDoc iType
62 , text " ETag:" <+> eTagToDoc iETag
63 , text " Last Modified:" <+> text (show iLastMod)
66 , text "{-# LANGUAGE MagicHash #-}"
69 eTagToDoc ∷ ETag → Doc
70 eTagToDoc = text ∘ A.toString ∘ A.fromAsciiBuilder ∘ printETag
72 mimeTypeToDoc ∷ MIMEType → Doc
73 mimeTypeToDoc = text ∘ A.toString ∘ A.fromAsciiBuilder ∘ printMIMEType
75 moduleDecl ∷ ModName → Name → Doc
76 moduleDecl modName symName
77 = text "module" <+> text (modString modName) $+$
78 nest 4 (vcat [ lparen <+> ppr symName
83 importDecls ∷ Imports → Doc
84 importDecls = vcat ∘ map pprImport ∘ fromFoldable
86 pprImport ∷ ImportOp → Doc
87 pprImport (QualifiedImp {..})
88 = hsep [ text "import"
90 , text (modString impModule)
92 , text (modString impAlias)
94 pprImport (UnqualifiedImp {impNames = Nothing, ..})
95 = hsep [ text "import"
96 , text (modString impModule)
98 pprImport (UnqualifiedImp {impNames = Just ns, ..})
99 = hsep [ text "import"
100 , text (modString impModule)
102 , sep $ punctuate comma
103 $ map (uncurry pprImpName)
109 pprImpName ∷ NameSpace → OccName → Doc
110 pprImpName TcClsName (occString → o)
111 = hcat [text o, text "(..)"]
112 pprImpName _ (occString → o)
113 | needParen o = hcat [lparen, text o, rparen]
116 needParen ∷ String → Bool
118 | isPunctuation c = True
123 entityTag = mkName "entityTag"
126 lastModified = mkName "lastModified"
129 contentType = mkName "contentType"
132 rawData = mkName "rawData"
135 gzippedData = mkName "gzippedData"
138 gzipEncoding = mkName "gzipEncoding"
140 resourceDecl ∷ Input → Name → Q [Dec]
141 resourceDecl i symName
142 = sequence [ sigD symName [t| ResourceDef |]
143 , valD (varP symName) (normalB (resourceE i)) decls
148 = [ sigD gzipEncoding [t| CIAscii |]
149 , valD (varP gzipEncoding) (normalB (lift ("gzip" ∷ CIAscii))) []
154 resourceE ∷ Input → Q Exp
155 resourceE i = [| emptyResource {
156 resGet = $(resGetE i)
157 , resHead = $(resHeadE i)
161 resGetE ∷ Input → Q Exp
164 = [| Just ( do foundEntity $(varE entityTag) $(varE lastModified)
165 setContentType $(varE contentType)
167 gzipAllowed ← isEncodingAcceptable $(varE gzipEncoding)
169 do setContentEncoding [$(varE gzipEncoding)]
170 putChunks $(varE gzippedData)
172 putChunks (decompress $(varE gzippedData))
176 = [| Just ( do foundEntity $(varE entityTag) $(varE lastModified)
177 setContentType $(varE contentType)
178 putChunks $(varE rawData)
182 resHeadE ∷ Input → Q Exp
185 = [| Just ( do foundEntity $(varE entityTag) $(varE lastModified)
186 setContentType $(varE contentType)
188 gzipAllowed ← isEncodingAcceptable $(varE gzipEncoding)
189 when gzipAllowed (setContentEncoding [$(varE gzipEncoding)])
193 = [| Just ( do foundEntity $(varE entityTag) $(varE lastModified)
194 setContentType $(varE contentType)
198 eTagDecl ∷ Input → Q [Dec]
199 eTagDecl (Input {..})
200 = sequence [ sigD entityTag [t| ETag |]
201 , valD (varP entityTag) (normalB (lift iETag)) []
204 lastModDecl ∷ Input → Q [Dec]
205 lastModDecl (Input {..})
206 = sequence [ sigD lastModified [t| UTCTime |]
207 , valD (varP lastModified) (normalB (lift iLastMod)) []
210 contTypeDecl ∷ Input → Q [Dec]
211 contTypeDecl (Input {..})
212 = sequence [ sigD contentType [t| MIMEType |]
213 , valD (varP contentType) (normalB (lift iType)) []
216 binDecl ∷ Input → Q [Dec]
217 binDecl i@(Input {..})
219 = sequence [ sigD gzippedData [t| L.ByteString |]
220 , valD (varP gzippedData) (normalB (lift iGZipped)) []
223 = sequence [ sigD rawData [t| L.ByteString |]
224 , valD (varP rawData) (normalB (lift iRawData)) []
228 rules = [ qualifyAll "Codec.Compression.GZip" "G"
229 , unqualify ''CIAscii "Data.Ascii"
230 , qualifyAll "Data.Ascii" "A"
231 , qualifyAll "Data.ByteString.Char8" "B"
232 , qualifyAll "Data.ByteString.Lazy.Internal" "L"
233 , qualifyAll "Data.CaseInsensitive" "CI"
234 , qualifyAll "Data.Collections" "C"
235 , qualifyAll "Data.Text" "T"
236 , unqualifyAll "Network.HTTP.Lucu.ETag" "Network.HTTP.Lucu"
237 , unqualifyAll "Network.HTTP.Lucu.Resource" "Network.HTTP.Lucu"
238 , unqualifyAll "Network.HTTP.Lucu.Resource.Internal" "Network.HTTP.Lucu"
239 , unqualifyAll "Network.HTTP.Lucu.MIMEParams" "Network.HTTP.Lucu"
240 , unqualifyAll "Network.HTTP.Lucu.MIMEType" "Network.HTTP.Lucu"
241 , unqualify 'when "Control.Monad"
242 , unqualify '(%) "Data.Ratio"
243 , unqualify ''DiffTime "Data.Time"
244 , unqualifyIn 'ModifiedJulianDay ''Day "Data.Time"
245 , unqualifyIn 'UTCTime ''UTCTime "Data.Time"
246 , unqualifyIn 'False ''Bool "Prelude"
247 , unqualifyIn 'Just ''Maybe "Prelude"
248 , unqualify 'fromRational "Prelude"
251 pprInput ∷ Quasi m ⇒ Input → ModName → Name → m Doc
252 pprInput i modName symName
253 = do decls ← runQ $ sequence [ resourceDecl i symName
259 let (decls', mods) = rewriteNames rules decls
260 return $ vcat [ header i
261 , moduleDecl modName symName
264 , vcat $ intersperse (text "") $ map ppr decls'