Source file sertop_util.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 Format
open Sexplib
open Sexp
let must_escape str =
let len = String.length str in
len = 0 ||
let rec loop ix =
match str.[ix] with
| '"' | '(' | ')' | '[' | ']' | ';' | '\\' | '\''-> true
| ',' -> ix = 0 || loop (ix - 1)
| '|' -> ix > 0 && let next = ix - 1 in str.[next] = '#' || loop next
| '#' -> ix > 0 && let next = ix - 1 in str.[next] = '|' || loop next
| '\000' .. '\032' -> true
| '\248' .. '\255' -> true
| _ -> ix > 0 && loop (ix - 1)
in
loop (len - 1)
let st_escaped (s : string) =
let sget = String.unsafe_get in
let open Bytes in
let n = ref 0 in
for i = 0 to String.length s - 1 do
n := !n +
(match sget s i with
| '\"' | '\\' | '\n' | '\t' | '\r' | '\b' -> 2
| ' ' .. '~' -> 1
| '\000' .. '\032' -> 4
| '\248' .. '\255' -> 4
| _ -> 1)
done;
if !n = String.length s then Bytes.of_string s else begin
let s' = create !n in
n := 0;
for i = 0 to String.length s - 1 do
begin match sget s i with
| ('\"' | '\\') as c ->
unsafe_set s' !n '\\'; incr n; unsafe_set s' !n c
| '\n' ->
unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 'n'
| '\t' ->
unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 't'
| '\r' ->
unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 'r'
| '\b' ->
unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 'b'
| (' ' .. '~') as c -> unsafe_set s' !n c
| '\000' .. '\032'
| '\248' .. '\255' as c ->
let a = Char.code c in
unsafe_set s' !n '\\';
incr n;
unsafe_set s' !n (Char.chr (48 + a / 100));
incr n;
unsafe_set s' !n (Char.chr (48 + (a / 10) mod 10));
incr n;
unsafe_set s' !n (Char.chr (48 + a mod 10));
| c -> unsafe_set s' !n c
end;
incr n
done;
s'
end
let esc_str (str : string) =
let open Bytes in
let estr = st_escaped str in
let elen = length estr in
let res = create (elen + 2) in
blit estr 0 res 1 elen;
set res 0 '"';
set res (elen + 1) '"';
to_string res
let sertop_maybe_esc_str str =
if must_escape str then esc_str str else str
let rec pp_sertop_internal may_need_space ppf = function
| Atom str ->
let str' = sertop_maybe_esc_str str in
let new_may_need_space = str' == str in
if may_need_space && new_may_need_space then pp_print_string ppf " ";
pp_print_string ppf str';
new_may_need_space
| List (h :: t) ->
pp_print_string ppf "(";
let may_need_space = pp_sertop_internal false ppf h in
pp_sertop_rest may_need_space ppf t;
false
| List [] -> pp_print_string ppf "()"; false
and pp_sertop_rest may_need_space ppf = function
| h :: t ->
let may_need_space = pp_sertop_internal may_need_space ppf h in
pp_sertop_rest may_need_space ppf t
| [] -> pp_print_string ppf ")"
let pp_sertop ppf sexp = ignore (pp_sertop_internal false ppf sexp)
let rec coq_pp_opt (d : Pp.t) = let open Pp in
let rec flatten_glue l = match l with
| [] -> []
| (Ppcmd_glue g :: l) -> flatten_glue (List.map repr g @ flatten_glue l)
| (Ppcmd_string s1 :: Ppcmd_string s2 :: l) -> flatten_glue (Ppcmd_string (s1 ^ s2) :: flatten_glue l)
| (x :: l) -> x :: flatten_glue l
in
unrepr (match repr d with
| Ppcmd_glue [] -> Ppcmd_empty
| Ppcmd_glue [x] -> repr (coq_pp_opt x)
| Ppcmd_glue l -> Ppcmd_glue List.(map coq_pp_opt (map unrepr (flatten_glue (map repr l))))
| Ppcmd_box(bt,d) -> Ppcmd_box(bt, coq_pp_opt d)
| Ppcmd_tag(t, d) -> Ppcmd_tag(t, coq_pp_opt d)
| d -> d
)
module F = Feedback
let feedback_content_pos_filter txt (fbc : F.feedback_content) : F.feedback_content =
let adjust _txt loc = loc in
match (fbc : F.feedback_content) with
| F.Message (lvl,loc,msg) -> F.Message (lvl, adjust txt loc, msg)
| _ -> fbc
let feedback_pos_filter text (fb : F.feedback) : F.feedback =
{ fb with F.contents = feedback_content_pos_filter text fb.F.contents; }
type fb_filter_opts = {
pp_opt : bool;
}
let default_fb_filter_opts = {
pp_opt = true;
}
let feedback_content_tr (fb : F.feedback_content) : Serapi.Serapi_protocol.feedback_content =
match fb with
| F.Message (level, loc, pp) ->
let str = Pp.string_of_ppcmds pp in
Message { level; loc; pp; str }
| F.Processed -> Processed
| F.Incomplete -> Incomplete
| F.Complete -> Complete
| F.ProcessingIn s -> ProcessingIn s
| F.InProgress i -> InProgress i
| F.WorkerStatus (s1,s2) -> WorkerStatus (s1,s2)
| F.AddedAxiom -> AddedAxiom
| F.GlobRef (_, _, _, _, _) -> assert false
| F.GlobDef (_, _, _, _) -> assert false
| F.FileDependency (o, p) -> FileDependency (o,p)
| F.FileLoaded (o, p) -> FileLoaded (o, p)
| F.Custom (_, _, _) -> assert false
let feedback_tr (fb : Feedback.feedback) : Serapi.Serapi_protocol.feedback =
match fb with
| { doc_id; span_id; route; contents } ->
let contents = feedback_content_tr contents in
{ doc_id; span_id; route; contents }
let feedback_opt_filter ?(opts=default_fb_filter_opts) =
let open Feedback in function
| { F.contents = Message (lvl, loc, msg); _ } as fb ->
Some (if opts.pp_opt
then { fb with contents = Message(lvl, loc, coq_pp_opt msg) }
else fb)
| { F.contents = FileDependency _ ; _ } -> None
| fb -> Some fb