package ostap

  1. Overview
  2. Docs

Source file Reason.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
(*
 * Reason: error reasons tree implementation.
 * Copyright (C) 2008
 * Dmitri Boulytchev, St.Petersburg State University
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License version 2, as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU Library General Public License version 2 for more details
 * (enclosed in the file COPYING).
 *)

module Holder =
  struct

    module M = Map.Make (Msg.Locator)

    type t = [`Msg of Msg.t | `Comment of string * t] list M.t

    let empty = (M.empty : t)

    let add dst msg =
      let loc = Msg.loc msg in
      let msg = `Msg msg in
      try M.add loc (msg :: M.find loc dst) dst
      with Not_found -> M.add loc [msg] dst

    let merge dst src =
      M.fold
	(fun loc list dst ->
	  try
	    M.add loc (list @ M.find loc dst) dst
	  with Not_found -> M.add loc list dst
	)
	src dst

    let comment str dst =
      let Some loc =
	M.fold
	  (fun loc _ acc ->
	    Some (
	      match acc with
	      | None     -> loc
	      | Some acc -> if Msg.Locator.compare acc loc < 0 then acc else loc
	    )
	  )
	  dst
	  None
      in
      M.add loc [`Comment (str, dst)] empty

    let rec retrieve h limit order =
      let list = M.fold (fun loc list acc -> (loc, list) :: acc) h [] in
      let list =
	match order with
	| `Acc  -> List.rev list
	| `Desc -> list
      in
      let list =
	match limit with
	| `All     -> list
	| `First n ->
	    let rec take n = function
	      | []   -> []
	      | h::t -> if n = 0 then [] else h :: (take (n-1) t)
	    in
	    take n list
      in
      List.map
	(fun (loc, list) ->
	  (
	   loc,
	   List.map
	     (function
	       | `Msg msg -> `Msg msg
	       | `Comment (str, h) -> `Comment (str, retrieve h limit order)
	     ) list
	  )
	) list

    open Format

    let toString r =
      let module M = Set.Make (String) in
      let buf = Buffer.create 1024 in
      let ppf = formatter_of_buffer buf in
      let rec inner comment list =
	List.iter
	  (fun (loc, list) ->
	    if not comment then fprintf ppf "@[<v 3> Error at %s: " (Msg.Locator.toString loc);
	    ignore
	      (
	       List.fold_left
		 (fun fence item ->
	   match item with
		   | `Msg msg ->
		       let s = Msg.toString msg in
		       if M.mem s fence
		       then fence
		       else (
			 fprintf ppf "@, %s " s;
			 M.add s fence
		       )

		   | `Comment (str, r) ->
		       fprintf ppf "%s" str;
		       inner true r;
		       fence
		 )
		 M.empty
		 list
	      );
	    if not comment then fprintf ppf "@]@\n"
	  )
	  list
      in
      inner false r;
      pp_print_flush ppf ();
      Buffer.contents buf

  end

type p = Holder.t
type retrieved = (Msg.Locator.t * [`Msg of Msg.t | `Comment of string * 'a] list) list as 'a

class t msg =
  object (self : 'a)

    val tab = Holder.add Holder.empty msg

    method get = tab

    method add      (x   : 'a    ) = {< tab = Holder.merge tab x#get >}
    method comment  (str : string) = {< tab = Holder.comment str tab >}

    method retrieve (l : [`All | `First of int]) (o : [`Acc | `Desc]) = (Holder.retrieve tab l o : retrieved)
    method toString (l : [`All | `First of int]) (o : [`Acc | `Desc]) = (Holder.toString (self#retrieve l o))

  end

let reason msg   = Some (new t msg)
let toString l o = function None -> "no description" | Some x -> x#toString l o