-
Notifications
You must be signed in to change notification settings - Fork 94
/
Copy pathPretty.hs
1655 lines (1399 loc) · 69.1 KB
/
Pretty.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{-# LANGUAGE CPP #-}
-----------------------------------------------------------------------------
-- |
-- Module : Language.Haskell.Exts.Pretty
-- Copyright : (c) Niklas Broberg 2004-2009,
-- (c) The GHC Team, Noel Winstanley 1997-2000
-- License : BSD-style (see the file LICENSE.txt)
--
-- Maintainer : Niklas Broberg, [email protected]
-- Stability : stable
-- Portability : portable
--
-- Pretty printer for Haskell with extensions.
--
-----------------------------------------------------------------------------
module Language.Haskell.Exts.Pretty (
-- * Pretty printing
Pretty,
prettyPrintStyleMode, prettyPrintWithMode, prettyPrint,
-- * Pretty-printing styles (from "Text.PrettyPrint.HughesPJ")
P.Style(..), P.style, P.Mode(..),
-- * Haskell formatting modes
PPHsMode(..), Indent, PPLayout(..), defaultMode
-- * Primitive Printers
, prettyPrim, prettyPrimWithMode
) where
import Language.Haskell.Exts.Syntax
import qualified Language.Haskell.Exts.ParseSyntax as P
import Language.Haskell.Exts.SrcLoc hiding (loc)
import Prelude hiding (exp)
import qualified Text.PrettyPrint as P
import Data.List (intersperse)
import Data.Maybe (isJust , fromMaybe)
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative (Applicative(..), (<$>))
#endif
import qualified Control.Monad as M (ap)
infixl 5 $$$
-----------------------------------------------------------------------------
-- | Varieties of layout we can use.
data PPLayout = PPOffsideRule -- ^ classical layout
| PPSemiColon -- ^ classical layout made explicit
| PPInLine -- ^ inline decls, with newlines between them
| PPNoLayout -- ^ everything on a single line
deriving Eq
type Indent = Int
-- | Pretty-printing parameters.
--
-- /Note:/ the 'onsideIndent' must be positive and less than all other indents.
data PPHsMode = PPHsMode {
-- | indentation of a class or instance
classIndent :: Indent,
-- | indentation of a @do@-expression
doIndent :: Indent,
-- | indentation of the body of a
-- @case@ expression
multiIfIndent :: Indent,
-- | indentation of the body of a
-- multi-@if@ expression
caseIndent :: Indent,
-- | indentation of the declarations in a
-- @let@ expression
letIndent :: Indent,
-- | indentation of the declarations in a
-- @where@ clause
whereIndent :: Indent,
-- | indentation added for continuation
-- lines that would otherwise be offside
onsideIndent :: Indent,
-- | blank lines between statements?
spacing :: Bool,
-- | Pretty-printing style to use
layout :: PPLayout,
-- | add GHC-style @LINE@ pragmas to output?
linePragmas :: Bool
}
-- | The default mode: pretty-print using the offside rule and sensible
-- defaults.
defaultMode :: PPHsMode
defaultMode = PPHsMode{
classIndent = 8,
doIndent = 3,
multiIfIndent = 3,
caseIndent = 4,
letIndent = 4,
whereIndent = 6,
onsideIndent = 2,
spacing = True,
layout = PPOffsideRule,
linePragmas = False
}
-- | Pretty printing monad
newtype DocM s a = DocM (s -> a)
instance Functor (DocM s) where
fmap f xs = do x <- xs; return (f x)
instance Applicative (DocM s) where
pure = retDocM
(<*>) = M.ap
instance Monad (DocM s) where
(>>=) = thenDocM
(>>) = then_DocM
return = retDocM
{-# INLINE thenDocM #-}
{-# INLINE then_DocM #-}
{-# INLINE retDocM #-}
{-# INLINE unDocM #-}
{-# INLINE getPPEnv #-}
thenDocM :: DocM s a -> (a -> DocM s b) -> DocM s b
thenDocM m k = DocM $ \s -> case unDocM m s of a -> unDocM (k a) s
then_DocM :: DocM s a -> DocM s b -> DocM s b
then_DocM m k = DocM $ \s -> case unDocM m s of _ -> unDocM k s
retDocM :: a -> DocM s a
retDocM a = DocM $ const a
unDocM :: DocM s a -> s -> a
unDocM (DocM f) = f
-- all this extra stuff, just for this one function.
getPPEnv :: DocM s s
getPPEnv = DocM id
-- So that pp code still looks the same
-- this means we lose some generality though
-- | The document type produced by these pretty printers uses a 'PPHsMode'
-- environment.
type Doc = DocM PPHsMode P.Doc
-- | Things that can be pretty-printed, including all the syntactic objects
-- in "Language.Haskell.Exts.Syntax".
class Pretty a where
-- | Pretty-print something in isolation.
pretty :: a -> Doc
-- | Pretty-print something in a precedence context.
prettyPrec :: Int -> a -> Doc
pretty = prettyPrec 0
prettyPrec _ = pretty
-- The pretty printing combinators
empty :: Doc
empty = return P.empty
nest :: Int -> Doc -> Doc
nest i m = m >>= return . P.nest i
-- Literals
text :: String -> Doc
text = return . P.text
char :: Char -> Doc
char = return . P.char
int :: Int -> Doc
int = return . P.int
integer :: Integer -> Doc
integer = return . P.integer
float :: Float -> Doc
float = return . P.float
double :: Double -> Doc
double = return . P.double
-- rational :: Rational -> Doc
-- rational = return . P.rational
-- Simple Combining Forms
parens, brackets, braces, doubleQuotes :: Doc -> Doc
parens d = d >>= return . P.parens
brackets d = d >>= return . P.brackets
braces d = d >>= return . P.braces
-- quotes :: Doc -> Doc
-- quotes d = d >>= return . P.quotes
doubleQuotes d = d >>= return . P.doubleQuotes
parensIf :: Bool -> Doc -> Doc
parensIf True = parens
parensIf False = id
-- Constants
semi,comma,space,equals :: Doc
semi = return P.semi
comma = return P.comma
-- colon :: Doc
-- colon = return P.colon
space = return P.space
equals = return P.equals
{-
lparen,rparen,lbrack,rbrack,lbrace,rbrace :: Doc
lparen = return P.lparen
rparen = return P.rparen
lbrack = return P.lbrack
rbrack = return P.rbrack
lbrace = return P.lbrace
rbrace = return P.rbrace
-}
-- Combinators
(<>),(<+>),($$) :: Doc -> Doc -> Doc
aM <> bM = do{a<-aM;b<-bM;return (a P.<> b)}
aM <+> bM = do{a<-aM;b<-bM;return (a P.<+> b)}
aM $$ bM = do{a<-aM;b<-bM;return (a P.$$ b)}
($+$) :: Doc -> Doc -> Doc
aM $+$ bM = do{a<-aM;b<-bM;return (a P.$+$ b)}
hcat,hsep,vcat,fsep :: [Doc] -> Doc
hcat dl = sequence dl >>= return . P.hcat
hsep dl = sequence dl >>= return . P.hsep
vcat dl = sequence dl >>= return . P.vcat
-- sep, cat, fcat :: [Doc] -> Doc
-- sep dl = sequence dl >>= return . P.sep
-- cat dl = sequence dl >>= return . P.cat
fsep dl = sequence dl >>= return . P.fsep
-- fcat dl = sequence dl >>= return . P.fcat
-- Some More
-- hang :: Doc -> Int -> Doc -> Doc
-- hang dM i rM = do{d<-dM;r<-rM;return $ P.hang d i r}
-- Yuk, had to cut-n-paste this one from Pretty.hs
punctuate :: Doc -> [Doc] -> [Doc]
punctuate _ [] = []
punctuate p (d1:ds) = go d1 ds
where
go d [] = [d]
go d (e:es) = (d <> p) : go e es
-- | render the document with a given style and mode.
renderStyleMode :: P.Style -> PPHsMode -> Doc -> String
renderStyleMode ppStyle ppMode d = P.renderStyle ppStyle . unDocM d $ ppMode
-- | render the document with a given mode.
-- renderWithMode :: PPHsMode -> Doc -> String
-- renderWithMode = renderStyleMode P.style
-- | render the document with 'defaultMode'.
-- render :: Doc -> String
-- render = renderWithMode defaultMode
-- | pretty-print with a given style and mode.
prettyPrintStyleMode :: Pretty a => P.Style -> PPHsMode -> a -> String
prettyPrintStyleMode ppStyle ppMode = renderStyleMode ppStyle ppMode . pretty
-- | pretty-print with the default style and a given mode.
prettyPrintWithMode :: Pretty a => PPHsMode -> a -> String
prettyPrintWithMode = prettyPrintStyleMode P.style
-- | pretty-print with the default style and 'defaultMode'.
prettyPrint :: Pretty a => a -> String
prettyPrint = prettyPrintWithMode defaultMode
-- fullRenderWithMode :: PPHsMode -> P.Mode -> Int -> Float ->
-- (P.TextDetails -> a -> a) -> a -> Doc -> a
-- fullRenderWithMode ppMode m i f fn e mD =
-- P.fullRender m i f fn e $ (unDocM mD) ppMode
-- fullRender :: P.Mode -> Int -> Float -> (P.TextDetails -> a -> a)
-- -> a -> Doc -> a
-- fullRender = fullRenderWithMode defaultMode
-- | pretty-print with the default style and 'defaultMode'.
prettyPrim :: Pretty a => a -> P.Doc
prettyPrim = prettyPrimWithMode defaultMode
-- | pretty-print with the default style and a given mode.
prettyPrimWithMode :: Pretty a => PPHsMode -> a -> P.Doc
prettyPrimWithMode pphs doc = unDocM (pretty doc) pphs
------------------------- Pretty-Print a Module --------------------
{-
instance Pretty (Module l) where
pretty (Module pos m os mbWarn mbExports imp decls) =
markLine pos $ (myVcat $ map pretty os) $$
myVcat (
(if m == ModuleName "" then id
else \x -> [topLevel (ppModuleHeader m mbWarn mbExports) x])
(map pretty imp ++
ppDecls (m /= ModuleName "" ||
not (null imp) ||
not (null os))
decls]-}
-------------------------- Module Header ------------------------------
instance Pretty (ModuleHead l) where
pretty (ModuleHead _ m mbWarn mbExportList) =
mySep [
text "module",
pretty m,
maybePP ppWarnTxt mbWarn,
maybePP pretty mbExportList,
text "where"]
instance Pretty (ExportSpecList l) where
pretty (ExportSpecList _ especs) = parenList $ map pretty especs
ppWarnTxt :: WarningText l -> Doc
ppWarnTxt (DeprText _ s) = mySep [text "{-# DEPRECATED", text (show s), text "#-}"]
ppWarnTxt (WarnText _ s) = mySep [text "{-# WARNING", text (show s), text "#-}"]
instance Pretty (ModuleName l) where
pretty (ModuleName _ modName) = text modName
instance Pretty (Namespace l) where
pretty NoNamespace {} = empty
pretty TypeNamespace {} = text "type"
pretty PatternNamespace {} = text "pattern"
instance Pretty (ExportSpec l) where
pretty (EVar _ name) = pretty name
pretty (EAbs _ ns name) = pretty ns <+> pretty name
pretty (EThingWith _ wc name nameList) =
let prettyNames = map pretty nameList
names = case wc of
NoWildcard {} -> prettyNames
EWildcard _ n ->
let (before,after) = splitAt n prettyNames
in before ++ [text ".."] ++ after
in pretty name <> (parenList names)
pretty (EModuleContents _ m) = text "module" <+> pretty m
instance Pretty (ImportDecl l) where
pretty (ImportDecl _ m qual src safe mbPkg mbName mbSpecs) =
mySep [text "import",
if src then text "{-# SOURCE #-}" else empty,
if safe then text "safe" else empty,
if qual then text "qualified" else empty,
maybePP (\s -> text (show s)) mbPkg,
pretty m,
maybePP (\m' -> text "as" <+> pretty m') mbName,
maybePP pretty mbSpecs]
instance Pretty (ImportSpecList l) where
pretty (ImportSpecList _ b ispecs) =
(if b then text "hiding" else empty)
<+> parenList (map pretty ispecs)
instance Pretty (ImportSpec l) where
pretty (IVar _ name ) = pretty name
pretty (IAbs _ ns name) = pretty ns <+> pretty name
pretty (IThingAll _ name) = pretty name <> text "(..)"
pretty (IThingWith _ name nameList) =
pretty name <> (parenList . map pretty $ nameList)
instance Pretty (TypeEqn l) where
pretty (TypeEqn _ pat eqn) = mySep [pretty pat, equals, pretty eqn]
------------------------- Declarations ------------------------------
class Pretty a => PrettyDeclLike a where
wantsBlankline :: a -> Bool
instance PrettyDeclLike (Decl l) where
wantsBlankline (FunBind {}) = False
wantsBlankline (PatBind {}) = False
wantsBlankline _ = True
condBlankline :: PrettyDeclLike a => a -> Doc
condBlankline d = (if wantsBlankline d then blankline else id) $ pretty d
ppDecls :: PrettyDeclLike a => Bool -> [a] -> [Doc]
ppDecls True ds = map condBlankline ds
ppDecls False (d:ds) = pretty d : map condBlankline ds
ppDecls _ _ = []
--ppDecls = map condBlankline
instance Pretty (InjectivityInfo l) where
pretty (InjectivityInfo _ from to) =
char '|' <+> pretty from <+> text "->" <+> hsep (map pretty to)
instance Pretty (ResultSig l) where
pretty (KindSig _ kind) = text "::" <+> pretty kind
pretty (TyVarSig _ tv) = char '=' <+> pretty tv
instance Pretty (Decl l) where
pretty (TypeDecl _ dHead htype) =
mySep ( [text "type", pretty dHead]
++ [equals, pretty htype])
pretty (DataDecl _ don context dHead constrList derives) =
mySep ( [pretty don, maybePP pretty context, pretty dHead])
<+> (myVcat (zipWith (<+>) (equals : repeat (char '|'))
(map pretty constrList))
$$$ maybePP pretty derives)
pretty (GDataDecl _ don context dHead optkind gadtList derives) =
mySep ( [pretty don, maybePP pretty context, pretty dHead]
++ ppOptKind optkind ++ [text "where"])
$$$ ppBody classIndent (map pretty gadtList)
$$$ ppIndent letIndent [maybePP pretty derives]
pretty (TypeFamDecl _ dHead optkind optinj) =
mySep ([text "type", text "family", pretty dHead
, maybePP pretty optkind, maybePP pretty optinj])
pretty (ClosedTypeFamDecl _ dHead optkind optinj eqns) =
mySep ([text "type", text "family", pretty dHead
, maybePP pretty optkind ,maybePP pretty optinj
, text "where"]) $$$ ppBody classIndent (map pretty eqns)
pretty (DataFamDecl _ context dHead optkind) =
mySep ( [text "data", text "family", maybePP pretty context, pretty dHead
, maybePP pretty optkind])
pretty (TypeInsDecl _ ntype htype) =
mySep [text "type", text "instance", pretty ntype, equals, pretty htype]
pretty (DataInsDecl _ don ntype constrList derives) =
mySep [pretty don, text "instance ", pretty ntype]
<+> (myVcat (zipWith (<+>) (equals : repeat (char '|'))
(map pretty constrList))
$$$ maybePP pretty derives)
pretty (GDataInsDecl _ don ntype optkind gadtList derives) =
mySep ( [pretty don, text "instance ", pretty ntype]
++ ppOptKind optkind ++ [text "where"])
$$$ ppBody classIndent (map pretty gadtList)
$$$ maybePP pretty derives
--m{spacing=False}
-- special case for empty class declaration
pretty (ClassDecl _ context dHead fundeps Nothing) =
mySep ( [text "class", maybePP pretty context, pretty dHead
, ppFunDeps fundeps])
pretty (ClassDecl _ context dHead fundeps declList) =
mySep ( [text "class", maybePP pretty context, pretty dHead
, ppFunDeps fundeps, text "where"])
$$$ ppBody classIndent (fromMaybe [] ((ppDecls False) <$> declList))
-- m{spacing=False}
-- special case for empty instance declaration
pretty (InstDecl _ moverlap iHead Nothing) =
mySep ( [text "instance", maybePP pretty moverlap, pretty iHead])
pretty (InstDecl _ overlap iHead declList) =
mySep ( [ text "instance", maybePP pretty overlap
, pretty iHead, text "where"])
$$$ ppBody classIndent (fromMaybe [] ((ppDecls False) <$> declList))
pretty (DerivDecl _ overlap irule) =
mySep ( [text "deriving"
, text "instance"
, maybePP pretty overlap
, pretty irule])
pretty (DefaultDecl _ htypes) =
text "default" <+> parenList (map pretty htypes)
pretty (SpliceDecl _ splice) =
pretty splice
pretty (TypeSig _ nameList qualType) =
mySep ((punctuate comma . map pretty $ nameList)
++ [text "::", pretty qualType])
-- Req can be ommitted if it is empty
-- We must print prov if req is nonempty
pretty (PatSynSig _ n mtvs prov req t) =
let contexts = map (maybePP pretty) [prov, req]
in
mySep ( [text "pattern", pretty n, text "::", ppForall mtvs] ++
contexts ++ [pretty t] )
pretty (FunBind _ matches) = do
e <- fmap layout getPPEnv
case e of PPOffsideRule -> foldr ($$$) empty (map pretty matches)
_ -> foldr (\x y -> x <> semi <> y) empty (map pretty matches)
pretty (PatBind _ pat rhs whereBinds) =
myFsep [pretty pat, pretty rhs] $$$ ppWhere whereBinds
pretty (InfixDecl _ assoc prec opList) =
mySep ([pretty assoc, maybePP int prec]
++ (punctuate comma . map pretty $ opList))
pretty (PatSyn _ pat rhs dir) =
let sep = case dir of
ImplicitBidirectional {} -> "="
ExplicitBidirectional {} -> "<-"
Unidirectional {} -> "<-"
in
(mySep ([text "pattern", pretty pat, text sep, pretty rhs])) $$$
(case dir of
ExplicitBidirectional _ ds ->
nest 2 (text "where" $$$ ppBody whereIndent (ppDecls False ds))
_ -> empty)
pretty (ForImp _ cconv saf str name typ) =
mySep [text "foreign import", pretty cconv, maybePP pretty saf,
maybe empty (text . show) str, pretty name, text "::", pretty typ]
pretty (ForExp _ cconv str name typ) =
mySep [text "foreign export", pretty cconv,
text (show str), pretty name, text "::", pretty typ]
pretty (RulePragmaDecl _ rules) =
myVcat $ text "{-# RULES" : map pretty rules ++ [text " #-}"]
pretty (DeprPragmaDecl _ deprs) =
myVcat $ text "{-# DEPRECATED" : map ppWarnDepr deprs ++ [text " #-}"]
pretty (WarnPragmaDecl _ deprs) =
myVcat $ text "{-# WARNING" : map ppWarnDepr deprs ++ [text " #-}"]
pretty (InlineSig _ inl activ name) =
mySep [text (if inl then "{-# INLINE" else "{-# NOINLINE")
, maybePP pretty activ, pretty name, text "#-}"]
pretty (InlineConlikeSig _ activ name) =
mySep [ text "{-# INLINE CONLIKE", maybePP pretty activ
, pretty name, text "#-}"]
pretty (SpecSig _ activ name types) =
mySep $ [text "{-# SPECIALISE", maybePP pretty activ
, pretty name, text "::"]
++ punctuate comma (map pretty types) ++ [text "#-}"]
pretty (SpecInlineSig _ inl activ name types) =
mySep $ [text "{-# SPECIALISE", text (if inl then "INLINE" else "NOINLINE"),
maybePP pretty activ, pretty name, text "::"]
++ (punctuate comma $ map pretty types) ++ [text "#-}"]
pretty (InstSig _ irule) =
mySep $ [ text "{-# SPECIALISE", text "instance", pretty irule
, text "#-}"]
pretty (AnnPragma _ annp) =
mySep [text "{-# ANN", pretty annp, text "#-}"]
pretty (MinimalPragma _ b) =
let bs = case b of { Just b' -> pretty b'; _ -> empty }
in myFsep [text "{-# MINIMAL", bs, text "#-}"]
pretty (RoleAnnotDecl _ qn rs) =
mySep ( [text "type", text "role", pretty qn]
++ map pretty rs )
instance Pretty (InstRule l) where
pretty (IRule _ tvs mctxt qn) =
mySep [ppForall tvs
, maybePP pretty mctxt, pretty qn]
pretty (IParen _ ih) = parens (pretty ih)
instance Pretty (InstHead l) where
pretty (IHCon _ qn) = pretty qn
pretty (IHInfix _ ta qn) = mySep [pretty ta, pretty qn]
pretty (IHParen _ ih) = parens (pretty ih)
pretty (IHApp _ ih t) = myFsep [pretty ih, pretty t]
instance Pretty (Annotation l) where
pretty (Ann _ n e) = myFsep [pretty n, pretty e]
pretty (TypeAnn _ n e) = myFsep [text "type", pretty n, pretty e]
pretty (ModuleAnn _ e) = myFsep [text "module", pretty e]
instance Pretty (BooleanFormula l) where
pretty (VarFormula _ n) = pretty n
pretty (AndFormula _ bs) = myFsep $ punctuate (text " ,") $ map pretty bs
pretty (OrFormula _ bs) = myFsep $ punctuate (text " |") $ map pretty bs
pretty (ParenFormula _ b) = parens $ pretty b
instance Pretty (Role l) where
pretty RoleWildcard{} = char '_'
pretty Nominal{} = text "nominal"
pretty Representational{} = text "representational"
pretty Phantom{} = text "phantom"
instance Pretty (DataOrNew l) where
pretty DataType{} = text "data"
pretty NewType{} = text "newtype"
instance Pretty (Assoc l) where
pretty AssocNone{} = text "infix"
pretty AssocLeft{} = text "infixl"
pretty AssocRight{} = text "infixr"
instance Pretty (Match l) where
pretty (InfixMatch _ l op rs rhs wbinds) =
let
lhs = case rs of
[] -> [] -- Should never reach
(r:rs') ->
let hd = [prettyPrec 2 l, ppNameInfix op, prettyPrec 2 r]
in if null rs'
then hd
else parens (myFsep hd) : map (prettyPrec 3) rs'
in myFsep (lhs ++ [pretty rhs]) $$$ ppWhere wbinds
pretty (Match _ f ps rhs whereBinds) =
myFsep (pretty f : map (prettyPrec 3) ps ++ [pretty rhs])
$$$ ppWhere whereBinds
ppWhere :: Maybe (Binds l) -> Doc
ppWhere Nothing = empty
ppWhere (Just (BDecls _ l)) = nest 2 (text "where" $$$ ppBody whereIndent (ppDecls False l))
ppWhere (Just (IPBinds _ b)) = nest 2 (text "where" $$$ ppBody whereIndent (ppDecls False b))
instance PrettyDeclLike (ClassDecl l) where
wantsBlankline (ClsDecl _ d) = wantsBlankline d
wantsBlankline (ClsDefSig {}) = True
wantsBlankline _ = False
instance Pretty (ClassDecl l) where
pretty (ClsDecl _ decl) = pretty decl
pretty (ClsDataFam _ context declHead optkind) =
mySep ( [text "data", maybePP pretty context, pretty declHead
, maybePP pretty optkind])
pretty (ClsTyFam _ declHead optkind optinj) =
mySep ( [text "type", pretty declHead
, maybePP pretty optkind, maybePP pretty optinj])
pretty (ClsTyDef _ ntype) =
mySep [text "type", pretty ntype]
pretty (ClsDefSig _ name typ) =
mySep [
text "default",
pretty name,
text "::",
pretty typ]
instance Pretty (DeclHead l) where
pretty (DHead _ n) = pretty n
pretty (DHInfix _ tv n) = pretty tv <+> ppNameInfix n
pretty (DHParen _ d) = parens (pretty d)
pretty (DHApp _ dh tv) = pretty dh <+> pretty tv
instance PrettyDeclLike (InstDecl l) where
wantsBlankline (InsDecl _ d) = wantsBlankline d
wantsBlankline _ = False
instance Pretty (InstDecl l) where
pretty (InsDecl _ decl) = pretty decl
pretty (InsType _ ntype htype) =
mySep [text "type", pretty ntype, equals, pretty htype]
pretty (InsData _ don ntype constrList derives) =
mySep [pretty don, pretty ntype]
<+> (myVcat (zipWith (<+>) (equals : repeat (char '|'))
(map pretty constrList))
$$$ maybePP pretty derives)
pretty (InsGData _ don ntype optkind gadtList derives) =
mySep ( [pretty don, pretty ntype]
++ ppOptKind optkind ++ [text "where"])
$$$ ppBody classIndent (map pretty gadtList)
$$$ maybePP pretty derives
-- pretty (InsInline loc inl activ name) =
-- markLine loc $
-- mySep [text (if inl then "{-# INLINE" else "{-# NOINLINE"), pretty activ, pretty name, text "#-}"]
------------------------- FFI stuff -------------------------------------
instance Pretty (Safety l) where
pretty PlayRisky {} = text "unsafe"
pretty (PlaySafe _ b) = text $ if b then "threadsafe" else "safe"
pretty PlayInterruptible {} = text "interruptible"
instance Pretty (CallConv l) where
pretty StdCall {} = text "stdcall"
pretty CCall {} = text "ccall"
pretty CPlusPlus {} = text "cplusplus"
pretty DotNet {} = text "dotnet"
pretty Jvm {} = text "jvm"
pretty Java {} = text "java"
pretty Js {} = text "js"
pretty JavaScript {} = text "javascript"
pretty CApi {} = text "capi"
------------------------- Pragmas ---------------------------------------
ppWarnDepr :: ([Name l], String) -> Doc
ppWarnDepr (names, txt) = mySep $ punctuate comma (map pretty names) ++ [text $ show txt]
instance Pretty (Rule l) where
pretty (Rule _ tag activ rvs rhs lhs) =
mySep [text $ show tag, maybePP pretty activ,
maybePP ppRuleVars rvs,
pretty rhs, char '=', pretty lhs]
ppRuleVars :: [RuleVar l] -> Doc
ppRuleVars [] = empty
ppRuleVars rvs = mySep $ text "forall" : map pretty rvs ++ [char '.']
instance Pretty (Activation l) where
pretty (ActiveFrom _ i) = char '[' <> int i <> char ']'
pretty (ActiveUntil _ i) = text "[~" <> int i <> char ']'
instance Pretty (Overlap l) where
pretty Overlap {} = text "{-# OVERLAP #-}"
pretty NoOverlap {} = text "{-# NO_OVERLAP #-}"
pretty Incoherent {} = text "{-# INCOHERENT #-}"
instance Pretty (RuleVar l) where
pretty (RuleVar _ n) = pretty n
pretty (TypedRuleVar _ n t) = parens $ mySep [pretty n, text "::", pretty t]
-- Spaces are stripped from the pragma text but other whitespace
-- is not.
ppOptionsPragma :: Doc -> String -> Doc
ppOptionsPragma opt s =
case s of
('\n':_) -> opt <> text s <> text "#-}"
_ -> myFsep [opt, text s <> text "#-}"]
instance Pretty (ModulePragma l) where
pretty (LanguagePragma _ ns) =
myFsep $ text "{-# LANGUAGE" : punctuate (char ',') (map pretty ns) ++ [text "#-}"]
pretty (OptionsPragma _ (Just tool) s) =
ppOptionsPragma (text "{-# OPTIONS_" <> pretty tool) s
pretty (OptionsPragma _ _ s) =
ppOptionsPragma (text "{-# OPTIONS") s
pretty (AnnModulePragma _ mann) =
myFsep [text "{-# ANN", pretty mann, text "#-}"]
instance Pretty Tool where
pretty (UnknownTool s) = text s
pretty t = text $ show t
------------------------- Data & Newtype Bodies -------------------------
instance Pretty (QualConDecl l) where
pretty (QualConDecl _pos tvs ctxt con) =
myFsep [ppForall tvs, maybePP pretty ctxt, pretty con]
instance Pretty (GadtDecl l) where
pretty (GadtDecl _pos name names ty) =
case names of
Nothing ->
myFsep [pretty name, text "::", pretty ty]
Just ts' ->
myFsep [pretty name, text "::" ,
braceList . map pretty $ ts', text "->", pretty ty]
instance Pretty (ConDecl l) where
pretty (RecDecl _ name fieldList) =
pretty name <> braceList (map pretty fieldList)
{- pretty (ConDecl name@(Symbol _) [l, r]) =
myFsep [prettyPrec prec_btype l, ppName name,
prettyPrec prec_btype r] -}
pretty (ConDecl _ name typeList) =
mySep $ pretty name : map (prettyPrec prec_atype) typeList
pretty (InfixConDecl _ l name r) =
myFsep [prettyPrec prec_btype l, ppNameInfix name,
prettyPrec prec_btype r]
instance Pretty (FieldDecl l) where
pretty (FieldDecl _ names ty) =
myFsepSimple $ (punctuate comma . map pretty $ names) ++
[text "::", pretty ty]
instance Pretty (BangType l) where
pretty BangedTy {} = char '!'
pretty LazyTy {} = char '~'
pretty NoStrictAnnot {} = empty
instance Pretty (Unpackedness l) where
pretty Unpack {} = text "{-# UNPACK #-} "
pretty NoUnpack {} = text "{-# NOUNPACK #-} "
pretty NoUnpackPragma {} = empty
instance Pretty (Deriving l) where
pretty (Deriving _ []) = empty
pretty (Deriving _ [d]) = text "deriving" <+> pretty d
pretty (Deriving _ d) = text "deriving" <+> parenList (map pretty d)
------------------------- Types -------------------------
ppBType :: Type l -> Doc
ppBType = prettyPrec prec_btype
ppAType :: Type l -> Doc
ppAType = prettyPrec prec_atype
-- precedences for types
prec_btype, prec_atype :: Int
prec_btype = 1 -- left argument of ->,
-- or either argument of an infix data constructor
prec_atype = 2 -- argument of type or data constructor, or of a class
instance Pretty (Type l) where
prettyPrec p (TyForall _ mtvs ctxt htype) = parensIf (p > 0) $
myFsep [ppForall mtvs, maybePP pretty ctxt, pretty htype]
prettyPrec p (TyFun _ a b) = parensIf (p > 0) $
myFsep [ppBType a, text "->", pretty b]
prettyPrec _ (TyTuple _ bxd l) =
let ds = map pretty l
in case bxd of
Boxed -> parenList ds
Unboxed -> hashParenList ds
prettyPrec _ (TyList _ t) = brackets $ pretty t
prettyPrec _ (TyParArray _ t) = bracketColonList [pretty t]
prettyPrec p (TyApp _ a b) =
{-
| a == list_tycon = brackets $ pretty b -- special case
| otherwise = -} parensIf (p > prec_btype) $
myFsep [pretty a, ppAType b]
prettyPrec _ (TyVar _ name) = pretty name
prettyPrec _ (TyCon _ name) = pretty name
prettyPrec _ (TyParen _ t) = parens (pretty t)
-- prettyPrec _ (TyPred asst) = pretty asst
prettyPrec _ (TyInfix _ a op b) = myFsep [pretty a, ppQNameInfix op, pretty b]
prettyPrec _ (TyKind _ t k) = parens (myFsep [pretty t, text "::", pretty k])
prettyPrec _ (TyPromoted _ p) = pretty p
prettyPrec p (TyEquals _ a b) = parensIf (p > 0) (myFsep [pretty a, text "~", pretty b])
prettyPrec _ (TySplice _ s) = pretty s
prettyPrec _ (TyBang _ b u t) = pretty u <> pretty b <> prettyPrec prec_atype t
prettyPrec _ (TyWildCard _ mn) = char '_' <> maybePP pretty mn
prettyPrec _ (TyQuasiQuote _ n qt) = text ("[" ++ n ++ "|" ++ qt ++ "|]")
instance Pretty (Promoted l) where
pretty p =
case p of
PromotedInteger _ n _ -> integer n
PromotedString _ s _ -> doubleQuotes $ text s
PromotedCon _ hasQuote qn ->
addQuote hasQuote $ maybe (pretty qn) pretty (getSpecialName qn)
PromotedList _ hasQuote list ->
addQuote hasQuote $ bracketList . punctuate comma . map pretty $ list
PromotedTuple _ list ->
addQuote True $ parenList $ map pretty list
PromotedUnit {} -> addQuote True $ text "()"
where
addQuote True doc = char '\'' <> doc
addQuote False doc = doc
instance Pretty (TyVarBind l) where
pretty (KindedVar _ var kind) = parens $ myFsep [pretty var, text "::", pretty kind]
pretty (UnkindedVar _ var) = pretty var
ppForall :: Maybe [TyVarBind l] -> Doc
ppForall Nothing = empty
ppForall (Just []) = empty
ppForall (Just vs) = myFsep (text "forall" : map pretty vs ++ [char '.'])
---------------------------- Kinds ----------------------------
instance Pretty (Kind l) where
prettyPrec _ KindStar{} = text "*"
prettyPrec n (KindFn _ a b) = parensIf (n > 0) $ myFsep [prettyPrec 1 a, text "->", pretty b]
prettyPrec _ (KindParen _ k) = parens $ pretty k
prettyPrec _ (KindVar _ n) = pretty n
prettyPrec _ (KindTuple _ t) = parenList . map pretty $ t
prettyPrec _ (KindList _ l) = brackets . pretty $ l
prettyPrec n (KindApp _ a b) =
parensIf (n > 3) $ myFsep [prettyPrec 3 a, prettyPrec 4 b]
ppOptKind :: Maybe (Kind l) -> [Doc]
ppOptKind Nothing = []
ppOptKind (Just k) = [text "::", pretty k]
------------------- Functional Dependencies -------------------
instance Pretty (FunDep l) where
pretty (FunDep _ from to) =
myFsep $ map pretty from ++ [text "->"] ++ map pretty to
ppFunDeps :: [FunDep l] -> Doc
ppFunDeps [] = empty
ppFunDeps fds = myFsep $ (char '|':) . punctuate comma . map pretty $ fds
------------------------- Expressions -------------------------
instance Pretty (Rhs l) where
pretty (UnGuardedRhs _ e) = equals <+> pretty e
pretty (GuardedRhss _ guardList) = myVcat . map pretty $ guardList
instance Pretty (GuardedRhs l) where
pretty (GuardedRhs _pos guards ppBody') =
myFsep $ [char '|'] ++ (punctuate comma . map pretty $ guards) ++ [equals, pretty ppBody']
newtype GuardedAlts l = GuardedAlts (Rhs l)
newtype GuardedAlt l = GuardedAlt (GuardedRhs l)
instance Pretty (GuardedAlts l) where
pretty (GuardedAlts (UnGuardedRhs _ e)) = text "->" <+> pretty e
pretty (GuardedAlts (GuardedRhss _ guardList)) = myVcat . map (pretty . GuardedAlt) $ guardList
instance Pretty (GuardedAlt l) where
pretty (GuardedAlt (GuardedRhs _pos guards ppBody')) =
myFsep $ [char '|'] ++ (punctuate comma . map pretty $ guards) ++ [text "->", pretty ppBody']
instance Pretty (Literal l) where
pretty (Int _ i _) = integer i
pretty (Char _ c _) = text (show c)
pretty (String _ s _) = text (show s)
pretty (Frac _ r _) = double (fromRational r)
-- GHC unboxed literals:
pretty (PrimChar _ c _) = text (show c) <> char '#'
pretty (PrimString _ s _) = text (show s) <> char '#'
pretty (PrimInt _ i _) = integer i <> char '#'
pretty (PrimWord _ w _) = integer w <> text "##"
pretty (PrimFloat _ r _) = float (fromRational r) <> char '#'
pretty (PrimDouble _ r _) = double (fromRational r) <> text "##"
instance Pretty (Exp l) where
prettyPrec _ (Lit _ l) = pretty l
-- lambda stuff
-- WARNING: This stuff is fragile. See #152 for one example of how
-- things can break.
prettyPrec p (InfixApp _ a op b) = parensIf (p > 2) $ myFsep [prettyPrec 1 a, pretty op, prettyPrec 1 b]
prettyPrec p (NegApp _ e) = parensIf (p > 0) $ char '-' <> prettyPrec 2 e
prettyPrec p (App _ a b) = parensIf (p > 3) $ myFsep [prettyPrec 3 a, prettyPrec 4 b]
prettyPrec p (Lambda _loc patList ppBody') = parensIf (p > 1) $ myFsep $
char '\\' : map (prettyPrec 3) patList ++ [text "->", pretty ppBody']
-- keywords
-- two cases for lets
prettyPrec p (Let _ (BDecls _ declList) letBody) =
parensIf (p > 1) $ ppLetExp declList letBody
prettyPrec p (Let _ (IPBinds _ bindList) letBody) =
parensIf (p > 1) $ ppLetExp bindList letBody
prettyPrec p (If _ cond thenexp elsexp) = parensIf (p > 1) $
myFsep [text "if", pretty cond,
text "then", pretty thenexp,
text "else", pretty elsexp]
prettyPrec p (MultiIf _ alts) = parensIf (p > 1) $
text "if"
$$$ ppBody multiIfIndent (map (pretty . GuardedAlt) alts)
prettyPrec p (Case _ cond altList) = parensIf (p > 1) $
myFsep ([text "case", pretty cond, text "of"] ++
if null altList then [text "{", text "}"] else [])
$$$ ppBody caseIndent (map pretty altList)
prettyPrec p (Do _ stmtList) = parensIf (p > 1) $
text "do" $$$ ppBody doIndent (map pretty stmtList)
prettyPrec p (MDo _ stmtList) = parensIf (p > 1) $
text "mdo" $$$ ppBody doIndent (map pretty stmtList)
-- Constructors & Vars
prettyPrec _ (Var _ name) = pretty name
prettyPrec _ (OverloadedLabel _ name) = text ('#':name)
prettyPrec _ (IPVar _ ipname) = pretty ipname
prettyPrec _ (Con _ name) = pretty name
prettyPrec _ (Tuple _ bxd expList) =
let ds = map pretty expList
in case bxd of
Boxed -> parenList ds
Unboxed -> hashParenList ds
prettyPrec _ (TupleSection _ bxd mExpList) =
let ds = map (maybePP pretty) mExpList
in case bxd of
Boxed -> parenList ds
Unboxed -> hashParenList ds
-- weird stuff
prettyPrec _ (Paren _ e) = parens . pretty $ e
prettyPrec _ (LeftSection _ e op) = parens (pretty e <+> pretty op)
prettyPrec _ (RightSection _ op e) = parens (pretty op <+> pretty e)
prettyPrec _ (RecConstr _ c fieldList) =
pretty c <> (braceList . map pretty $ fieldList)
prettyPrec _ (RecUpdate _ e fieldList) =
pretty e <> (braceList . map pretty $ fieldList)
-- Lists and parallel arrays
prettyPrec _ (List _ list) =
bracketList . punctuate comma . map pretty $ list
prettyPrec _ (ParArray _ arr) =
bracketColonList . map pretty $ arr
prettyPrec _ (EnumFrom _ e) =
bracketList [pretty e, text ".."]
prettyPrec _ (EnumFromTo _ from to) =
bracketList [pretty from, text "..", pretty to]
prettyPrec _ (EnumFromThen _ from thenE) =
bracketList [pretty from <> comma, pretty thenE, text ".."]
prettyPrec _ (EnumFromThenTo _ from thenE to) =
bracketList [pretty from <> comma, pretty thenE,
text "..", pretty to]
prettyPrec _ (ParArrayFromTo _ from to) =
bracketColonList [pretty from, text "..", pretty to]
prettyPrec _ (ParArrayFromThenTo _ from thenE to) =
bracketColonList [pretty from <> comma, pretty thenE,