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 (snd hd1) (snd 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 (snd 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_nth n = function
43 | [] -> raise_error ET.ENoEntry
44 | (_,hd)::tl -> if n = 0 then hd else list_nth (pred n) tl
46 let rec list_select n = function
47 | [] -> raise_error ET.ENoEntry
48 | (b,hd)::tl -> if n = 0 then (not b,hd)::tl else (b,hd)::list_select (pred n) tl
50 let rec list_select_all = function
52 | (b,hd)::tl -> (not b,hd)::list_select_all tl
54 let rec list_split = function
56 | (b,a) as hd :: tl ->
57 let fs,ts = list_split tl in
58 if fst hd then fs,((false,a)::ts)
61 let rec list_find_selected r = function
65 | false, _ -> list_find_selected r tl
66 | true , None -> list_find_selected (Some hd) tl
67 | true , Some _ -> raise_error (ET.EWrongSelect)
70 let rec list_exists compare = function
74 if b <= 0 then b = 0 else
75 list_exists compare tl
77 let rec list_count s c = function
79 | (b, _)::tl -> list_count (s + if b then 1 else 0) (succ c) tl
81 let string_of_version v =
82 String.concat "." (List.map string_of_int v)
84 let version_of_string s =
85 List.map int_of_string (String.split_on_char '.' s)
87 let compare_versions v1 v2 =
88 list_compare compare v1 v2
90 let string_of_name n =
93 let name_of_string s =
94 String.split_on_char '_' s
96 let compare_names n1 n2 =
97 list_compare compare n1 n2
99 let names_union ns1 ns2 =
100 let error n = ET.ENameClash n in
101 list_union error compare_names ns1 ns2
103 let rec match_names oi ni os ns =
107 | (_,o)::otl,(_,n)::ntl ->
108 let b = compare_names (snd o) n in
109 if b > 0 then match_names oi (succ ni) os ntl else
110 if b < 0 then match_names (succ oi) ni otl ns else
113 let string_of_obj (v,n) =
114 Printf.sprintf "%s/%s" (string_of_version v) (string_of_name n)
116 let obj_of_string s =
117 match String.split_on_char '/' s with
118 | [sv;sn] -> version_of_string sv, name_of_string sn
119 | _ -> failwith "obj_of_string"
121 let compare_objs (v1,n1) (v2,n2) =
122 let b = compare_versions v1 v2 in
123 if b = 0 then compare_names n1 n2 else b
125 let objs_union os1 os2 =
126 let error o = ET.EObjClash o in
127 list_union error compare_objs os1 os2
129 let rec rev_objs_of_names v os = function
131 | (b,n)::tl -> rev_objs_of_names v ((b,(v,n))::os) tl
133 let rec get_tops v = function
136 let ds, ts = get_tops v tl in
137 if compare_versions v r.ET.v = 0 then begin
138 if r.ET.n = [] then objs_union r.ET.o ds, ts else
139 let tops = rev_objs_of_names v [] r.ET.n in
140 ds, objs_union (List.rev tops) ts
145 let n = match r.ET.n with
151 let string_of_role r =
152 string_of_obj (obj_of_role r)
154 let compare_roles r1 r2 =
155 compare_objs (obj_of_role r1) (obj_of_role r2)
157 let roles_union rs1 rs2 =
158 let error r = ET.ERoleClash r in
159 list_union error compare_roles rs1 rs2
161 let roles_expand_all rs =
162 let map (b, r) = r.ET.x <- not r.ET.x in
165 let rec roles_expand n = function
168 if n = 0 then r.ET.x <- not r.ET.x else
169 roles_expand (pred n) tl
171 let exists_role_deleted v r =
173 let compare r = compare_objs o (obj_of_role r) in
174 list_exists compare r
176 let roles_split s rs =
177 let rec aux rs os ns = function
178 | [] -> List.rev rs, os, ns
180 if compare_versions s r.ET.v <> 0 then aux ((b, r)::rs) os ns tl else
181 if b then aux rs (objs_union os r.ET.o) (names_union ns r.ET.n) tl else
182 let ro, so = list_split r.ET.o in
183 let rn, sn = list_split r.ET.n in
184 if ro = [] && rn = [] then aux rs (objs_union os so) (names_union ns sn) tl else begin
185 r.ET.o <- ro; r.ET.o <- ro;
186 aux ((b, r)::rs) (objs_union os so) (names_union ns sn) tl
192 ET.m = false; ET.r = []; ET.s = []; ET.t = []; ET.w = [];
195 let string_of_pointer = string_of_version
197 let pointer_of_string = version_of_string
199 let list_visit before each visit after string_of p l =
200 let ptr p = string_of_pointer (List.rev p) in
201 let rec aux i = function
204 each (ptr (i::p)) b (string_of x);
208 let s, c = list_count 0 0 l in
209 let count = Printf.sprintf "%u/%u" s c in
210 before (ptr p) count;
214 let string_of_error = function
216 Printf.sprintf "unknown input file type %S" x
218 Printf.sprintf "current stage %S" (string_of_version v)
220 Printf.sprintf "current stage not defined"
222 Printf.sprintf "current stage not finished"
224 Printf.sprintf "name clash %S" (string_of_name n)
226 Printf.sprintf "object clash %S" (string_of_obj o)
228 Printf.sprintf "role clash %S" (string_of_role r)
230 Printf.sprintf "entry not found"
232 Printf.sprintf "selected role is not unique"
233 | ET.EWrongVersion ->
234 Printf.sprintf "selected role is not in the current stage"
236 Printf.sprintf "top objects already computed"
237 | ET.EWrongRequest (r,a) ->
238 Printf.sprintf "unknown request \"%s=%s\"" r a