2 ||M|| This file is part of HELM, an Hypertextual, Electronic
3 ||A|| Library of Mathematics, developed at the Computer Science
4 ||T|| Department, University of Bologna, Italy.
6 ||T|| HELM is free software; you can redistribute it and/or
7 ||A|| modify it under the terms of the GNU General Public License
8 \ / version 2 or (at your option) any later version.
9 \ / This software is distributed as is, NO WARRANTY.
10 V_______________________________________________________________ *)
12 module ET = RolesTypes
17 let list_union error compare l1 l2 =
18 let rec aux l1 l2 = match l1 with
20 | hd1::tl1 -> match l2 with
23 let b = compare hd1 hd2 in
24 if b > 0 then hd2 :: aux l1 tl2
25 else if b < 0 then hd1 :: aux tl1 l2
26 else raise_error (error hd1)
30 let list_compare compare l1 l2 =
31 let rec aux l1 l2 = match l1 with
33 if l2 = [] then 0 else -1
34 | hd1::tl1 -> match l2 with
37 let b = compare hd1 hd2 in
38 if b = 0 then aux tl1 tl2 else b
42 let rec list_apply prop map n = function
45 if prop n hd then begin map hd; true end
46 else list_apply prop map (succ n) tl
48 let list_nth map n l =
49 let prop m _ = m = n in
50 if list_apply prop map 0 l then () else raise_error ET.ENoEntry
52 let list_split prop map l =
53 let lt, lf = List.partition prop l in
54 List.iter map lt; lf, lt
56 let rec list_count p s c = function
58 | x :: tl -> list_count p (s + if p x then 1 else 0) (succ c) tl
62 let string_of_stage v =
63 String.concat "." (List.map string_of_int v)
65 let stage_of_string s =
66 List.map int_of_string (String.split_on_char '.' s)
68 let stage_compare v1 v2 =
69 list_compare compare v1 v2
73 let string_of_name n =
76 let name_of_string s =
77 String.split_on_char '_' s
79 let name_compare n1 n2 =
80 list_compare compare n1 n2
84 let string_of_nobj n =
85 string_of_name n.ET.nn
87 let nobj_of_string s = {
88 ET.nb = false; ET.nn = name_of_string s;
91 let nobj_selected n = n.ET.nb
94 n.ET.nb <- not n.ET.nb
96 let nobj_compare n1 n2 =
97 name_compare n1.ET.nn n2.ET.nn
99 let nobj_union ns1 ns2 =
100 let error n = ET.ENClash n in
101 list_union error nobj_compare ns1 ns2
105 let string_of_oobj o =
106 Printf.sprintf "%s/%s" (string_of_stage o.ET.os) (string_of_name o.ET.on)
108 let oobj_of_string s =
109 match String.split_on_char '/' s with
110 | [ss;sn] -> {ET.ob = false; ET.os = stage_of_string ss; ET.on = name_of_string sn}
111 | _ -> failwith "oobj_of_string"
113 let oobj_selected o = o.ET.ob
116 o.ET.ob <- not o.ET.ob
118 let oobj_compare o1 o2 =
119 let b = stage_compare o1.ET.os o2.ET.os in
120 if b = 0 then name_compare o1.ET.on o2.ET.on else b
122 let oobj_union os1 os2 =
123 let error o = ET.EOClash o in
124 list_union error oobj_compare os1 os2
126 let oobj_of_nobj v n =
127 {ET.ob = n.ET.nb; ET.os = v; ET.on = n.ET.nn}
129 let rec oobj_match oi ni os ns =
133 | o :: otl, n :: ntl ->
134 let b = name_compare o.ET.on n.ET.nn in
135 if b > 0 then oobj_match oi (succ ni) os ntl else
136 if b < 0 then oobj_match (succ oi) ni otl ns else
142 let n = match r.ET.rn with
146 {ET.ob = r.ET.rb; ET.os = r.ET.rs; ET.on = n}
148 let string_of_robj r =
149 string_of_oobj (oobj_of_robj r)
151 let robj_selected r = r.ET.rb
154 r.ET.rb <- not r.ET.rb
157 r.ET.rx <- not r.ET.rx
159 let robj_compare r1 r2 =
160 oobj_compare (oobj_of_robj r1) (oobj_of_robj r2)
162 let robj_union rs1 rs2 =
163 let error r = ET.ERClash r in
164 list_union error robj_compare rs1 rs2
166 let rec robj_tops v = function
169 let ds, ts = robj_tops v tl in
170 if stage_compare v r.ET.rs = 0 then begin
171 if r.ET.rn = [] then oobj_union r.ET.ro ds, ts else
172 let tops = List.rev_map (oobj_of_nobj v) r.ET.rn in
173 ds, oobj_union (List.rev tops) ts
177 let robj_split s rs =
178 let rec aux rs os ns = function
179 | [] -> List.rev rs, os, ns
181 if stage_compare s r.ET.rs <> 0 then aux (r :: rs) os ns tl else
182 if r.ET.rb then aux rs (oobj_union os r.ET.ro) (nobj_union ns r.ET.rn) tl else
183 let ro, so = list_split oobj_selected oobj_select r.ET.ro in
184 let rn, sn = list_split nobj_selected nobj_select r.ET.rn in
185 if ro = [] && rn = [] then aux rs (oobj_union os so) (nobj_union ns sn) tl else begin
186 r.ET.ro <- ro; r.ET.rn <- rn;
187 aux (r :: rs) (oobj_union os so) (nobj_union ns sn) tl
195 ET.sm = false; ET.sr = []; ET.ss = []; ET.so = []; ET.sn = [];
200 let string_of_pointer = string_of_stage
202 let pointer_of_string = stage_of_string
204 let list_visit before each visit after selected string_of p l =
205 let ptr p = string_of_pointer (List.rev p) in
206 let rec aux i = function
209 each (ptr (i::p)) (selected x) (string_of x);
213 let s, c = list_count selected 0 0 l in
214 let count = Printf.sprintf "%u/%u" s c in
215 before (ptr p) count;
221 let string_of_error = function
223 Printf.sprintf "unknown input file type %S" x
225 Printf.sprintf "current stage %S" (string_of_stage v)
227 Printf.sprintf "current stage not defined"
229 Printf.sprintf "current stage not finished"
231 Printf.sprintf "name clash %S" (string_of_nobj n)
233 Printf.sprintf "object clash %S" (string_of_oobj o)
235 Printf.sprintf "role clash %S" (string_of_robj r)
237 Printf.sprintf "entry not found"
239 Printf.sprintf "selected role is not unique"
240 | ET.EWrongVersion ->
241 Printf.sprintf "selected role is not in the current stage"
243 Printf.sprintf "top objects already computed"
244 | ET.EWrongRequest (r,a) ->
245 Printf.sprintf "unknown request \"%s=%s\"" r a