-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathUtility.sml
93 lines (67 loc) · 2.4 KB
/
Utility.sml
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
structure Utility =
struct
local open Wpp in
infixr 6 ^^
infix ^+^ ^/^ == ** ++ --
(* Some convenience functions for pp *)
val $ = text
val ws = group(break 1 0) (* space or break*)
val br = break 0 0
val sp = break 1 0
val nl = break 100000 0 (* an almost certain forced newline *)
val comma = $"," ^^ ws
val semi = $";" ^^ ws
val colon = $":" ^^ ws
(* Derived reusable combinators *)
fun x ^+^ y = x ^^ sp ^^ y
fun x ^/^ y = x ^^ ws ^^ y
fun block i = group o nest i
val block1 = block 1
fun around left right doc = block1 ((group (left ^^ doc)) ^^ right)
fun opt ppr NONE = Wpp.empty
| opt ppr (SOME x) = ppr x
fun list left right sep elem =
let fun elements [a] = elem a ^^ right
| elements (a::s) = group (elem a ^^ sep) ^^ elements s
| elements _ = raise Fail "Impossible"
fun list nil = left ^^ right
| list l = left ^^ nest 1 (elements l)
in list
end
fun list' sep elem =
let fun elements [] = empty
| elements [x] = elem x
| elements (x::xs) = group (elem x ^^ sep) ^^ elements xs
in elements
end
(* Some combinators from "A Prettier Printer" by Phil Wadler
in "The Fun of Programming", Jeremy Gibbons and Oege de Moor (eds)
Documentation comments adapted from the Haskell package
mainland-pretty by Geoffrey Mainland.
*)
(* The document `folddoc f ds` obeys the laws:
* `folddoc f [] = empty`
* `folddoc f [d1, d2, ..., dnm1, dn] = d1 `f` (d2 `f` ... (dnm1 `f` dn))`
*)
fun folddoc _ [] = empty
| folddoc _ [x] = x
| folddoc f (x :: xs) = f (x, folddoc f xs)
(* The document `spread ds` concatenates the documents `ds` with `sp`. *)
val spread = folddoc (op ^+^)
(* The document `stack ds` concatenates the documents `ds` with `newline`. *)
val stack = folddoc (fn (x,y) => x ^^ newline ^^ y)
(* The document `sep ds` concatenates the documents `ds` with the 'space'
document as long as there is room, and uses 'newline' when there isn't. *)
val sep = group o folddoc (op ^/^)
(* Example usage of the combinators *)
fun x == y = x ^^ text" = " ^^ y
fun x ** y = x ^^ text" *" ^/^ y
fun x ++ y = x ^^ text" +" ^/^ y
fun x -- y = x ^^ text" -" ^/^ y
val paren = around ($"(") ($")")
val curly = around ($"{") ($"}")
val brack = around ($"[") ($"]")
fun bin f opr (x, y) = paren(f x ^+^ opr ^+^ f y)
fun binnp f opr (x, y) = group(f x ^+^ opr ^+^ f y)
end
end