-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPrint.hs
137 lines (110 loc) · 3.38 KB
/
Print.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
module Rcl.Print (ppStmts, prStmt, ppStmt, ppTerm, ppSet, ppVar,
Form (..), pStmts, rStmt, pSet, Doc, render, lineStmt) where
import Rcl.Ast
import Text.PrettyPrint
data Form = Form { format :: Format, prParen :: Bool }
ppStmts :: [Let] -> String
ppStmts = render . pStmts form
prStmt :: (Stmt, Vars) -> String
prStmt = render . rStmt form
ppStmt :: Stmt -> String
ppStmt = render . pStmt form
lineStmt :: Let -> String
lineStmt = renderStyle style {mode = OneLineMode} . pLet form
ppTerm :: Term -> String
ppTerm = render . pTerm form
ppSet :: Set -> String
ppSet = render . pSet form
ppVar :: (Var, Set) -> String
ppVar = render . pVar form
form :: Form
form = Form Uni True
pStmts :: Form -> [Let] -> Doc
pStmts m = vcat . map (lLet m)
rStmt :: Form -> (Stmt, Vars) -> Doc
rStmt m (s, vs) = sep [cat . map (pVar m) $ reverse vs, pStmt m s]
pVar :: Form -> (Var, Set) -> Doc
pVar m (i, e) = let f = format m in hcat $ map text [sAll f, stVar i, sIn f]
++ [pSet m e, text $ sDot f]
pLet :: Form -> Let -> Doc
pLet m (Let as s) = let d = pStmt m s in
if null as then d else sep
[text "let" <+> fsep (punctuate semi $ map (pAss m) as), text "in" <+> d]
pAss :: Form -> (String, Set) -> Doc
pAss m (s, r) = text (s ++ " =") <+> pSet m r
lLet :: Form -> Let -> Doc
lLet m s = let d = pLet m s in case format m of
LaTeX -> hcat [dollar, d, dollar, text "\n"]
_ -> d
dollar :: Doc
dollar = text "$"
pStmt :: Form -> Stmt -> Doc
pStmt m = let f = format m in foldStmt FoldStmt
{ foldBool = \ _ o d1 d2 ->
sep [d1, pBoolOp f o <+> d2]
, foldCmp = \ _ o d1 d2 ->
sep [d1, pCmpOp f o <+> d2] }
$ pTerm m
pBoolOp :: Format -> BoolOp -> Doc
pBoolOp m o = text $ case o of
And -> sAnd m
Impl -> sImpl m
pCmpOp :: Format -> CmpOp -> Doc
pCmpOp m = text . sCmpOp m
pTerm :: Form -> Term -> Doc
pTerm m t = case t of
Term b s -> let d = pSet m s in case b of
Card -> hcat [pBar, d, pBar]
TheSet -> d
EmptySet -> text . sEmpty $ format m
Num i -> int i
pSet :: Form -> Set -> Doc
pSet m = let f = format m in foldSet FoldSet
{ foldBin = \ (BinOp _ s1 s2) o d1 d2 -> let
p = pBinOp f o
a1 = pParenSet o s1 d1
a2 = pParenSet o s2 d2
in case o of
Operations _ -> cat [p, parens $ cat [d1, text "," <+> d2]]
Minus -> cat [a1, hcat [p, a2]]
_ -> sep [a1, p <+> a2]
, foldUn = \ (UnOp _ s) o d -> case o of
Typed ex ts -> case ex of
Derived -> d
Explicit -> cat [case untyped s of
PrimSet _ -> d
Var _ -> d
_ -> parens d
, text $ ':' : ppType ts]
_ -> let b = prParen m in (if b || f == LaTeX then cat else sep)
[pUnOp m o, if b then parens d else d]
, foldBraced = \ _ ds -> braces . fsep $ punctuate comma ds
, foldPrim = pPrimSet }
pPrimSet :: Set -> Doc
pPrimSet s = text $ case s of
PrimSet t -> t
Var v -> stVar v
_ -> error "pPrimSet"
pParenSet :: BinOp -> Set -> Doc -> Doc
pParenSet o s = case untyped s of
BinOp i _ _ -> case o of
Minus -> parens
Inter -> case i of
Union -> parens
_ -> id
_ -> id
_ -> id
pBinOp :: Format -> BinOp -> Doc
pBinOp m o = text $ case o of
Union -> sUnion m
Inter -> sInter m
Minus -> "-"
_ -> case m of
LaTeX -> lUnOp o
_ -> stUnOp o
pBar :: Doc
pBar = text "|"
pUnOp :: Form -> UnOp -> Doc
pUnOp m = text . case format m of
LaTeX -> (if prParen m then id else (++ "~")) . lUnOp
_ -> stUnOp