Skip to content

Commit 25658ef

Browse files
committed
CHC: add locations to diagnostic messages
1 parent 48ca571 commit 25658ef

File tree

2 files changed

+189
-36
lines changed

2 files changed

+189
-36
lines changed

CodeHawk/CHC/cchpre/cCHPreTypes.mli

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,14 +1009,35 @@ class type podictionary_int =
10091009
end
10101010

10111011

1012+
(** Diagnostic information
1013+
1014+
Proof obligations that cannot (yet) be proven valid are annotated with
1015+
diagnostic messages that contain relevant information about the state
1016+
where the proof obligation is situated, including invariants, both
1017+
general invariants applicable to the state, and invariants specific to
1018+
the arguments of the proof obligation predicate.
1019+
*)
1020+
type ocode_location_t = {
1021+
ocode_file: string;
1022+
ocode_line: int;
1023+
ocode_detail: string
1024+
}
1025+
1026+
1027+
type situated_msg_t = {
1028+
smsg_msg: string;
1029+
smsg_loc: ocode_location_t option
1030+
}
1031+
1032+
10121033
class type diagnostic_int =
10131034
object
10141035
method clear: unit
10151036
method set_invariants: int -> int list -> unit (* expression index *)
10161037
method get_invariants: (int * int list) list
1017-
method add_msg: string -> unit
1018-
method add_arg_msg: int -> string -> unit
1019-
method add_key_msg: string -> string -> unit
1038+
method add_msg: situated_msg_t -> unit
1039+
method add_arg_msg: int -> situated_msg_t -> unit
1040+
method add_key_msg: string -> situated_msg_t -> unit
10201041
method is_empty: bool
10211042
method write_xml: xml_element_int -> unit
10221043
method read_xml: xml_element_int -> unit
@@ -1041,13 +1062,17 @@ class type proof_obligation_int =
10411062

10421063
method set_dependencies: dependencies_t -> unit
10431064

1044-
method set_explanation: string -> unit
1065+
method set_explanation:
1066+
?site:(string * int * string) option -> string -> unit
10451067

1046-
method add_diagnostic_msg: string -> unit
1068+
method add_diagnostic_msg:
1069+
?site:(string * int * string) option -> string -> unit
10471070

1048-
method add_diagnostic_arg_msg: int -> string -> unit
1071+
method add_diagnostic_arg_msg:
1072+
?site:(string * int * string) option -> int -> string -> unit
10491073

1050-
method add_diagnostic_key_msg: string -> string -> unit
1074+
method add_diagnostic_key_msg:
1075+
?site:(string * int * string) option -> string -> string -> unit
10511076

10521077
method set_diagnostic_invariants: int -> int list -> unit
10531078

@@ -1061,7 +1086,7 @@ class type proof_obligation_int =
10611086

10621087
method get_dependencies: dependencies_t option
10631088

1064-
method get_explanation: string
1089+
method get_explanation: situated_msg_t option
10651090

10661091
method get_diagnostic: diagnostic_int
10671092

CodeHawk/CHC/cchpre/cCHProofObligation.ml

Lines changed: 156 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ open CCHPreTypes
4646
module H = Hashtbl
4747

4848

49+
let cd = CCHDictionary.cdictionary
50+
51+
4952
let join_invs (invs1:int list) (invs2:int list):int list =
5053
let s = new IntCollections.set_t in
5154
begin
@@ -175,13 +178,32 @@ let get_po_type_predicate (pt:po_type_t) =
175178
| SPO (LocalSPO (_, _, pred)) -> pred
176179

177180

181+
let situated_msg_to_pretty (m: situated_msg_t) =
182+
match m.smsg_loc with
183+
| Some c ->
184+
LBLOCK [
185+
STR m.smsg_msg;
186+
STR " ("; INT c.ocode_line; STR ", "; STR c.ocode_detail; STR ")"]
187+
| _ ->
188+
LBLOCK [STR m.smsg_msg]
189+
190+
191+
module SituatedMsgCollections =
192+
CHCollections.Make
193+
(struct
194+
type t = situated_msg_t
195+
let compare = (fun m1 m2 -> Stdlib.compare m1.smsg_msg m2.smsg_msg)
196+
let toPretty = situated_msg_to_pretty
197+
end)
198+
199+
178200
class diagnostic_t =
179201
object (self)
180202

181203
val invarianttable = H.create 1
182-
val argmessages = H.create 1 (* arg index -> msg list *)
183-
val keymessages = H.create 1 (* key -> msg list *)
184-
val messages = new StringCollections.set_t
204+
val argmessages = H.create 1 (* arg index -> situated_msg_t list *)
205+
val keymessages = H.create 1 (* key -> situated_msg_t list *)
206+
val messages = new SituatedMsgCollections.set_t
185207

186208
method clear =
187209
begin
@@ -195,27 +217,27 @@ object (self)
195217
method get_invariants =
196218
H.fold (fun k v acc -> (k,v) :: acc) invarianttable []
197219

198-
method add_msg (s:string): unit =
220+
method add_msg (s: situated_msg_t): unit =
199221
messages#add s
200222

201-
method add_arg_msg (index:int) (s:string): unit =
223+
method add_arg_msg (index:int) (s: situated_msg_t): unit =
202224
let entry =
203225
if H.mem argmessages index then
204226
H.find argmessages index
205227
else
206-
let entry = new StringCollections.set_t in
228+
let entry = new SituatedMsgCollections.set_t in
207229
begin
208230
H.add argmessages index entry;
209231
entry
210232
end in
211233
entry#add s
212234

213-
method add_key_msg (key:string) (s:string): unit =
235+
method add_key_msg (key:string) (s: situated_msg_t): unit =
214236
let entry =
215237
if H.mem keymessages key then
216238
H.find keymessages key
217239
else
218-
let entry = new StringCollections.set_t in
240+
let entry = new SituatedMsgCollections.set_t in
219241
begin
220242
H.add keymessages key entry;
221243
entry
@@ -232,19 +254,49 @@ object (self)
232254
let arg_messages = self#get_arg_messages in
233255
let flat_messages = List.map ( fun(_, x) -> x) arg_messages in
234256
let flat_messages = List.flatten flat_messages in
235-
LBLOCK (List.map (fun s -> LBLOCK [STR s; NL]) flat_messages)
257+
LBLOCK (
258+
List.map (fun s -> LBLOCK [situated_msg_to_pretty s; NL]) flat_messages)
236259

237260
method key_messages_to_pretty: pretty_t =
238261
let key_messages = self#get_key_messages in
239262
let flat_messages = List.map ( fun(_, x) -> x) key_messages in
240263
let flat_messages = List.flatten flat_messages in
241-
LBLOCK (List.map (fun s -> LBLOCK [STR s; NL]) flat_messages)
264+
LBLOCK (
265+
List.map (fun s -> LBLOCK [situated_msg_to_pretty s; NL]) flat_messages)
242266

243267
method is_empty =
244268
(H.length invarianttable) = 0
245269
&& (H.length argmessages = 0)
246270
&& messages#isEmpty
247271

272+
method private write_xml_situated_msg
273+
(node: xml_element_int) (m: situated_msg_t) =
274+
begin
275+
node#setAttribute "t" m.smsg_msg;
276+
(match m.smsg_loc with
277+
| Some c ->
278+
begin
279+
node#setIntAttribute "file" (cd#index_string c.ocode_file);
280+
node#setIntAttribute "line" c.ocode_line;
281+
node#setIntAttribute "detail" (cd#index_string c.ocode_detail)
282+
end
283+
| _ -> ())
284+
end
285+
286+
method private read_xml_situated_msg (node: xml_element_int): situated_msg_t =
287+
let get = node#getAttribute in
288+
let geti = node#getIntAttribute in
289+
let ocode =
290+
if node#hasNamedAttribute "file" then
291+
Some {
292+
ocode_file = cd#get_string (geti "file");
293+
ocode_line = geti "linenr";
294+
ocode_detail = cd#get_string (geti "detail")
295+
}
296+
else
297+
None in
298+
{ smsg_msg = get "t"; smsg_loc = ocode }
299+
248300
method write_xml (node:xml_element_int) =
249301
let inode = xmlElement "invs" in
250302
let mnode = xmlElement "msgs" in
@@ -269,7 +321,7 @@ object (self)
269321
(List.map (fun msg ->
270322
let snode = xmlElement "msg" in
271323
begin
272-
snode#setAttribute "t" msg;
324+
self#write_xml_situated_msg snode msg;
273325
snode
274326
end) msgs);
275327
xnode
@@ -283,16 +335,16 @@ object (self)
283335
(List.map (fun msg ->
284336
let snode = xmlElement "msg" in
285337
begin
286-
snode#setAttribute "t" msg;
338+
self#write_xml_situated_msg snode msg;
287339
snode
288340
end) msgs);
289341
xnode
290342
end) self#get_key_messages));
291343
(mnode#appendChildren
292-
(List.map (fun s ->
344+
(List.map (fun msg ->
293345
let snode = xmlElement "msg" in
294346
begin
295-
snode#setAttribute "t" s;
347+
self#write_xml_situated_msg snode msg;
296348
snode
297349
end) messages#toList));
298350
node#appendChildren [inode; mnode; anode; knode]
@@ -311,21 +363,22 @@ object (self)
311363
(inode#getTaggedChildren "arg"));
312364
(List.iter (fun n ->
313365
let amsgs =
314-
List.map (fun k -> k#getAttribute "t") (n#getTaggedChildren "msg") in
366+
List.map self#read_xml_situated_msg (n#getTaggedChildren "msg") in
315367
List.iter (self#add_arg_msg (n#getIntAttribute "a")) amsgs)
316368
(anode#getTaggedChildren "arg"));
317369
(List.iter (fun n ->
318370
let kmsgs =
319-
List.map (fun k -> k#getAttribute "t") (n#getTaggedChildren "msg") in
371+
List.map self#read_xml_situated_msg (n#getTaggedChildren "msg") in
320372
List.iter (self#add_key_msg (n#getAttribute "k")) kmsgs)
321373
(knode#getTaggedChildren "key"));
322374
(List.iter
323-
(fun n -> self#add_msg (n#getAttribute "t"))
375+
(fun n -> self#add_msg (self#read_xml_situated_msg n))
324376
(mnode#getTaggedChildren "msg"))
325377
end
326378

327379
method toPretty =
328-
LBLOCK (List.map (fun s -> LBLOCK [STR s; NL]) messages#toList)
380+
LBLOCK (
381+
List.map (fun s -> LBLOCK [situated_msg_to_pretty s; NL]) messages#toList)
329382

330383

331384
end
@@ -354,15 +407,63 @@ object (self)
354407

355408
method set_dependencies d = dependencies <- Some d
356409

357-
method set_explanation e = explanation <- Some e
358-
359-
method add_diagnostic_msg = diagnostic#add_msg
410+
method set_explanation
411+
?(site: (string * int * string) option = None) (e: string) =
412+
let ocode =
413+
match site with
414+
| Some (file, linenr, detail) -> Some {
415+
ocode_file = file;
416+
ocode_line = linenr;
417+
ocode_detail = detail
418+
}
419+
| _ -> None in
420+
let smsg = { smsg_msg = e; smsg_loc = ocode } in
421+
explanation <- Some smsg
422+
423+
method add_diagnostic_msg
424+
?(site: (string * int * string) option = None) (msg: string) =
425+
let ocode =
426+
match site with
427+
| Some (file, linenr, detail) -> Some {
428+
ocode_file = file;
429+
ocode_line = linenr;
430+
ocode_detail = detail
431+
}
432+
| _ -> None in
433+
let smsg = { smsg_msg = msg; smsg_loc = ocode } in
434+
diagnostic#add_msg smsg
360435

361436
method set_diagnostic_invariants = diagnostic#set_invariants
362437

363-
method add_diagnostic_arg_msg = diagnostic#add_arg_msg
364-
365-
method add_diagnostic_key_msg = diagnostic#add_key_msg
438+
method add_diagnostic_arg_msg
439+
?(site: (string * int * string) option = None)
440+
(argnr: int)
441+
(msg: string) =
442+
let ocode =
443+
match site with
444+
| Some (file, linenr, detail) -> Some {
445+
ocode_file = file;
446+
ocode_line = linenr;
447+
ocode_detail = detail
448+
}
449+
| _ -> None in
450+
let smsg = { smsg_msg = msg; smsg_loc = ocode } in
451+
diagnostic#add_arg_msg argnr smsg
452+
453+
method add_diagnostic_key_msg
454+
?(site: (string * int * string) option = None)
455+
(key: string)
456+
(msg: string) =
457+
let ocode =
458+
match site with
459+
| Some (file, linenr, detail) -> Some {
460+
ocode_file = file;
461+
ocode_line = linenr;
462+
ocode_detail = detail
463+
}
464+
| _ -> None in
465+
let smsg = { smsg_msg = msg; smsg_loc = ocode } in
466+
diagnostic#add_key_msg key smsg
366467

367468
method set_resolution_timestamp t = timestamp <- Some t
368469

@@ -380,8 +481,7 @@ object (self)
380481

381482
method get_predicate = get_po_type_predicate pt
382483

383-
method get_explanation =
384-
match explanation with Some t -> t | _ -> "none"
484+
method get_explanation = explanation
385485

386486
method get_diagnostic = diagnostic
387487

@@ -398,6 +498,20 @@ object (self)
398498
method is_ppo =
399499
match pt with | PPO _ -> true | _ -> false
400500

501+
method private write_xml_situated_msg
502+
(node: xml_element_int) (m: situated_msg_t) =
503+
begin
504+
node#setAttribute "txt" m.smsg_msg;
505+
(match m.smsg_loc with
506+
| Some c ->
507+
begin
508+
node#setIntAttribute "file" (cd#index_string c.ocode_file);
509+
node#setIntAttribute "line" c.ocode_line;
510+
node#setIntAttribute "detail" (cd#index_string c.ocode_detail)
511+
end
512+
| _ -> ())
513+
end
514+
401515
method write_xml (node:xml_element_int) =
402516
begin
403517
(if diagnostic#is_empty then
@@ -415,7 +529,7 @@ object (self)
415529
| Some e ->
416530
let enode = xmlElement "e" in
417531
begin
418-
enode#setAttribute "txt" e;
532+
self#write_xml_situated_msg enode e;
419533
node#appendChildren [enode]
420534
end
421535
| _ -> ());
@@ -539,6 +653,20 @@ end
539653
let mk_local_spo = new local_spo_t
540654

541655

656+
let read_xml_explanation (node: xml_element_int) (po: proof_obligation_int)=
657+
let get = node#getAttribute in
658+
let geti = node#getIntAttribute in
659+
let site =
660+
if node#hasNamedAttribute "file" then
661+
Some (
662+
cd#get_string (geti "file"),
663+
geti "linenr",
664+
cd#get_string (geti "detail"))
665+
else
666+
None in
667+
po#set_explanation ~site (get "txt")
668+
669+
542670
let read_xml_proof_obligation
543671
(node:xml_element_int)
544672
(pod:podictionary_int)
@@ -552,7 +680,7 @@ let read_xml_proof_obligation
552680
let status = po_status_mfts#fs (get "s") in
553681
po#set_status status);
554682
(if hasc "e" then
555-
po#set_explanation ((getc "e")#getAttribute "txt"));
683+
read_xml_explanation (getc "e") po);
556684
(if hasc "d" then
557685
po#get_diagnostic#read_xml (getc "d"));
558686
(if has "deps" then

0 commit comments

Comments
 (0)