Source file micheline_printer.ml
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
open Micheline
type location = {comment : string option}
type node = (location, string) Micheline.node
let printable ?( = fun _ -> None) map_prim expr =
let map_loc loc = {comment = comment loc} in
map_node map_loc map_prim (root expr)
let ppf text =
Format.fprintf ppf "/* @[<h>%a@] */" Format.pp_print_text text
let print_string ppf text =
Format.fprintf ppf "\"" ;
String.iter
(function
| '"' -> Format.fprintf ppf "\\\""
| '\n' -> Format.fprintf ppf "\\n"
| '\r' -> Format.fprintf ppf "\\r"
| '\b' -> Format.fprintf ppf "\\b"
| '\t' -> Format.fprintf ppf "\\t"
| '\\' -> Format.fprintf ppf "\\\\"
| c -> Format.fprintf ppf "%c" c)
text ;
Format.fprintf ppf "\""
let print_annotations =
Format.pp_print_list ~pp_sep:Format.pp_print_space Format.pp_print_string
let preformat root =
let preformat_loc = function
| {comment = None} -> (false, 0)
| {comment = Some text} ->
(String.contains text '\n', String.length text + 1)
in
let preformat_annots = function
| [] -> 0
| annots -> String.length (String.concat " " annots) + 2
in
let rec preformat_expr = function
| Int (loc, value) ->
let (cml, csz) = preformat_loc loc in
Int ((cml, String.length (Big_int.string_of_big_int value) + csz, loc), value)
| String (loc, value) ->
let (cml, csz) = preformat_loc loc in
String ((cml, String.length value + csz, loc), value)
| Bytes (loc, value) ->
let (cml, csz) = preformat_loc loc in
Bytes ((cml, (Bytes.length value * 2) + 2 + csz, loc), value)
| Prim (loc, name, items, annots) ->
let (cml, csz) = preformat_loc loc in
let asz = preformat_annots annots in
let items = List.map preformat_expr items in
let (ml, sz) =
List.fold_left
(fun (tml, tsz) e ->
let (ml, sz, _) = location e in
(tml || ml, tsz + 1 + sz))
(cml, String.length name + csz + asz)
items
in
Prim ((ml, sz, loc), name, items, annots)
| Seq (loc, items) ->
let (cml, csz) = preformat_loc loc in
let items = List.map preformat_expr items in
let (ml, sz) =
List.fold_left
(fun (tml, tsz) e ->
let (ml, sz, _) = location e in
(tml || ml, tsz + 3 + sz))
(cml, 4 + csz)
items
in
Seq ((ml, sz, loc), items)
in
preformat_expr root
let rec print_expr_unwrapped ppf = function
| Prim ((ml, s, {}), name, args, annot) ->
let name =
match annot with
| [] -> name
| annots -> Format.asprintf "%s @[<h>%a@]" name print_annotations annots
in
if (not ml) && s < 80 then (
if args = [] then Format.fprintf ppf "%s" name
else
Format.fprintf
ppf
"@[<h>%s %a@]"
name
(Format.pp_print_list ~pp_sep:Format.pp_print_space print_expr)
args ;
match comment with
| None -> ()
| Some text -> Format.fprintf ppf "@ /* %s */" text)
else (
if args = [] then Format.fprintf ppf "%s" name
else if String.length name <= 4 then
Format.fprintf
ppf
"%s @[<v 0>%a@]"
name
(Format.pp_print_list print_expr)
args
else
Format.fprintf
ppf
"@[<v 2>%s@,%a@]"
name
(Format.pp_print_list print_expr)
args ;
match comment with
| None -> ()
| Some -> Format.fprintf ppf "@ %a" print_comment comment)
| Int ((_, _, {}), value) -> (
match comment with
| None -> Format.fprintf ppf "%s" (Big_int.string_of_big_int value)
| Some ->
Format.fprintf ppf "%s@ %a" (Big_int.string_of_big_int value) print_comment comment)
| String ((_, _, {}), value) -> (
match comment with
| None -> print_string ppf value
| Some ->
Format.fprintf ppf "%a@ %a" print_string value print_comment comment)
| Bytes ((_, _, {}), value) -> (
match comment with
| None -> Format.fprintf ppf "0x%a" Hex.pp (Hex.of_bytes value)
| Some ->
Format.fprintf
ppf
"0x%a@ %a"
Hex.pp
(Hex.of_bytes value)
print_comment
comment)
| Seq ((_, _, {comment = None}), []) -> Format.fprintf ppf "{}"
| Seq ((ml, s, {}), items) ->
if (not ml) && s < 80 then Format.fprintf ppf "{ @[<h 0>"
else Format.fprintf ppf "{ @[<v 0>" ;
(match (comment, items) with
| (None, _) -> ()
| (Some , []) -> Format.fprintf ppf "%a" print_comment comment
| (Some , _) -> Format.fprintf ppf "%a@ " print_comment comment) ;
Format.pp_print_list
~pp_sep:(fun ppf () -> Format.fprintf ppf " ;@ ")
print_expr_unwrapped
ppf
items ;
Format.fprintf ppf "@] }"
and print_expr ppf = function
| (Prim (_, _, _ :: _, _) | Prim (_, _, [], _ :: _)) as expr ->
Format.fprintf ppf "(%a)" print_expr_unwrapped expr
| expr -> print_expr_unwrapped ppf expr
let with_unbounded_formatter ppf f x =
let buf = Buffer.create 10000 in
let sppf = Format.formatter_of_buffer buf in
Format.pp_set_margin sppf 199999 ;
Format.pp_set_max_indent sppf 99999 ;
Format.pp_set_max_boxes sppf 99999 ;
f sppf x ;
Format.fprintf sppf "%!" ;
let lines = String.split_on_char '\n' (Buffer.contents buf) in
Format.pp_print_list
~pp_sep:Format.pp_force_newline
Format.pp_print_string
ppf
lines
let print_expr_unwrapped ppf expr =
with_unbounded_formatter ppf print_expr_unwrapped (preformat expr)
let print_expr ppf expr =
with_unbounded_formatter ppf print_expr (preformat expr)