1 (***********************************************************************)
4 (* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
6 (* Copyright 2001 Institut National de Recherche en Informatique et *)
7 (* en Automatique. All rights reserved. This file is distributed *)
8 (* under the terms of the Q Public License version 1.0. *)
10 (***********************************************************************)
14 (** The types and functions to create a html table representing a dag. Thanks to Daniel De Rauglaudre. *)
16 type 'a dag
= { mutable dag
: 'a node array
}
18 { mutable pare
: idag list
; valu
: 'a
; mutable chil
: idag list
}
22 external int_of_idag
: idag
-> int = "%identity";;
23 external idag_of_int
: int -> idag
= "%identity";;
25 type 'a table
= { mutable table
: 'a data array array
}
26 and 'a data
= { mutable elem
: 'a elem
; mutable span
: span_id
}
27 and 'a elem
= Elem
of 'a
| Ghost
of ghost_id
| Nothing
32 external span_id_of_int
: int -> span_id
= "%identity";;
33 external int_of_span_id
: span_id
-> int = "%identity";;
34 external ghost_id_of_int
: int -> ghost_id
= "%identity";;
35 external int_of_ghost_id
: ghost_id
-> int = "%identity";;
37 let new_span_id = let i = ref 0 in fun () -> incr
i; span_id_of_int
!i;;
39 let new_ghost_id = let i = ref 0 in fun () -> incr
i; ghost_id_of_int
!i;;
41 (** creating the html table structure *)
43 type align
= LeftA
| CenterA
| RightA
;;
44 type table_data
= TDstring
of string | TDhr
of align
;;
45 type html_table
= (int * align
* table_data
) array array
;;
47 let html_table_struct indi_txt phony d t
=
50 Elem e
-> phony d
.dag
.(int_of_idag e
)
56 Elem e
-> indi_txt d
.dag
.(int_of_idag e
)
62 Elem _
| Ghost _
-> "|"
67 if j
= Array.length t
.table
.(i) then true
69 match t
.table
.(i).(j
).elem
with
70 Nothing
-> loop (j
+ 1)
71 | e
-> if phony e
then loop (j
+ 1) else false
78 if j
= Array.length t
.table
.(i) then les
80 let x = t
.table
.(i).(j
) in
83 if j
= Array.length t
.table
.(i) then j
84 else if t
.table
.(i).(j
) = x then loop (j
+ 1)
89 let colspan = 3 * (next_j - j
) in
90 let les = (1, LeftA
, TDstring
" ") :: les in
93 if t
.table
.(i).(j
).elem
= Nothing
then " "
94 else elem_txt t
.table
.(i).(j
).elem
96 (colspan - 2, CenterA
, TDstring
s) :: les
98 let les = (1, LeftA
, TDstring
" ") :: les in loop les next_j
102 Array.of_list
(List.rev
les)
107 if j
= Array.length t
.table
.(i) then les
109 let x = t
.table
.(i).(j
) in
112 if j
= Array.length t
.table
.(i) then j
113 else if t
.table
.(i).(j
) = x then loop (j
+ 1)
118 let colspan = 3 * (next_j - j
) in
119 let les = (1, LeftA
, TDstring
" ") :: les in
122 if k
> 0 && t
.table
.(k
- 1).(j
).elem
= Nothing
||
123 t
.table
.(k
).(j
).elem
= Nothing
then
125 else if phony t
.table
.(i).(j
).elem
then " "
126 else bar_txt t
.table
.(i).(j
).elem
128 (colspan - 2, CenterA
, TDstring
s) :: les
130 let les = (1, LeftA
, TDstring
" ") :: les in loop les next_j
134 Array.of_list
(List.rev
les)
136 let alone_bar_txt i =
139 if j
= Array.length t
.table
.(i) then les
142 let x = t
.table
.(i).(j
).span
in
144 if j
= Array.length t
.table
.(i) then j
145 else if t
.table
.(i).(j
).span
= x then loop (j
+ 1)
150 let colspan = 3 * (next_j - j
) - 2 in
151 let les = (1, LeftA
, TDstring
" ") :: les in
153 if t
.table
.(i).(j
).elem
= Nothing
||
154 t
.table
.(i + 1).(j
).elem
= Nothing
then
155 (colspan, LeftA
, TDstring
" ") :: les
160 if j
= next_j then true
161 else if phony t
.table
.(i + 1).(j
).elem
then loop (j
+ 1)
166 if all_ph then " " else "|"
168 (colspan, CenterA
, TDstring
s) :: les
170 let les = (1, LeftA
, TDstring
" ") :: les in loop les next_j
174 Array.of_list
(List.rev
les)
176 let exist_several_branches i k
=
178 if j
= Array.length t
.table
.(i) then false
180 let x = t
.table
.(i).(j
).span
in
181 let e = t
.table
.(k
).(j
).elem
in
183 if j
= Array.length t
.table
.(i) then false
184 else if t
.table
.(i).(j
).elem
= Nothing
then loop j
185 else if t
.table
.(i).(j
).span
<> x then loop j
186 else if t
.table
.(k
).(j
).elem
<> e then true
196 if j
= Array.length t
.table
.(i) then les
199 let e = t
.table
.(i).(j
).elem
in
200 let x = t
.table
.(i).(j
).span
in
202 if j
= Array.length t
.table
.(i) then j
203 else if e = Nothing
&& t
.table
.(i).(j
).elem
= Nothing
then
205 else if t
.table
.(i).(j
).span
= x then loop (j
+ 1)
210 let rec loop1 les l
=
211 if l
= next_j then loop les next_j
214 let y = t
.table
.(k
).(l
) in
218 if l
= Array.length t
.table
.(i) then l
219 else if t
.table
.(k
).(l
) = y then loop (l
+ 1)
225 if next_l > next_j then
228 "assert false i %d k %d l %d next_l %d next_j %d\n" i k l
232 let next_l = min
next_l next_j in
233 let colspan = 3 * (next_l - l
) - 2 in
235 match t
.table
.(i).(l
).elem
, t
.table
.(i + 1).(l
).elem
with
236 Nothing
, _
| _
, Nothing
->
237 (colspan + 2, LeftA
, TDstring
" ") :: les
240 if phony t
.table
.(k
).(l
).elem
then TDstring
" "
243 if l
= j
&& next_l = next_j then
244 let les = (1, LeftA
, TDstring
" ") :: les in
245 let s = ph (TDstring
"|") in
246 let les = (colspan, CenterA
, s) :: les in
247 let les = (1, LeftA
, TDstring
" ") :: les in les
249 let les = (1, LeftA
, TDstring
" ") :: les in
250 let s = ph (TDhr RightA
) in
251 let les = (colspan, RightA
, s) :: les in
252 let s = ph (TDhr CenterA
) in
253 let les = (1, LeftA
, s) :: les in les
254 else if next_l = next_j then
255 let s = ph (TDhr CenterA
) in
256 let les = (1, LeftA
, s) :: les in
257 let s = ph (TDhr LeftA
) in
258 let les = (colspan, LeftA
, s) :: les in
259 let les = (1, LeftA
, TDstring
" ") :: les in les
261 let s = ph (TDhr CenterA
) in
262 (colspan + 2, LeftA
, s) :: les
270 Array.of_list
(List.rev
les)
274 if i = Array.length t
.table
then hts
275 else if i = Array.length t
.table
- 1 && all_empty i then hts
277 let hts = line_elem_txt i :: hts in
279 if i < Array.length t
.table
- 1 then
280 let hts = vbars_txt (i + 1) i :: hts in
282 if exist_several_branches i i then
283 alone_bar_txt i :: hbars_txt i i :: hts
287 if exist_several_branches i (i + 1) &&
288 (i < Array.length t
.table
- 2 ||
289 not
(all_empty (i + 1))) then
290 vbars_txt (i + 1) (i + 1) :: hbars_txt i (i + 1) :: hts
300 Array.of_list
(List.rev
hts)
303 (** transforming dag into table *)
307 if i = Array.length d
.dag
then []
310 if n.pare
= [] then idag_of_int
i :: loop (i + 1) else loop (i + 1)
315 let get_children d parents
=
316 let rec merge_children children el
=
318 (fun (x, _
) children
->
321 let e = d
.dag
.(int_of_idag
e) in
324 if List.mem c children
then children
else c
:: children
)
329 merge_children [] parents
332 let rec get_block t
i j
=
333 if j
= Array.length t
.table
.(i) then None
334 else if j
= Array.length t
.table
.(i) - 1 then
335 let x = t
.table
.(i).(j
) in Some
([x.elem
, 1], 1, x.span
)
337 let x = t
.table
.(i).(j
) in
338 let y = t
.table
.(i).(j
+ 1) in
339 if y.span
= x.span
then
340 match get_block t
i (j
+ 1) with
341 Some
((x1
, c1
) :: list
, mpc
, span
) ->
343 if x1
= x.elem
then (x1
, c1
+ 1) :: list
, max mpc
(c1
+ 1)
344 else (x.elem
, 1) :: (x1
, c1
) :: list
, max mpc c1
346 Some
(list
, mpc
, span
)
348 else Some
([x.elem
, 1], 1, x.span
)
351 let group_by_common_children d list
=
352 let module O
= struct type t
= idag
;; let compare = compare;; end
354 let module S
= Set.Make
(O
)
359 let n = d
.dag
.(int_of_idag id
) in
360 let cs = List.fold_right
S.add
n.chil
S.empty
in [id
], cs)
367 | (nl
, cs) :: rest
->
370 (nl1
, cs1
) :: rest1
->
371 if S.is_empty
(S.inter
cs cs1
) then
372 loop1 ((nl1
, cs1
) :: beg
) rest1
374 loop ((nl
@ nl1
, S.union
cs cs1
) :: (List.rev beg
@ rest1
))
375 | [] -> (nl
, cs) :: loop rest
383 let span = new_span_id () in
384 List.fold_right
(fun n a
-> {elem
= Elem
n; span = span} :: a
) nl a
)
388 let copy_data d
= {elem
= d
.elem
; span = d
.span};;
390 let insert_columns t nb j
=
391 let t1 = Array.create
(Array.length t
.table
) [| |] in
392 for i = 0 to Array.length t
.table
- 1 do
393 let line = t
.table
.(i) in
394 let line1 = Array.create
(Array.length
line + nb
) line.(0) in
397 if k
= Array.length
line then ()
400 if k
< j
then line1.(k
) <- copy_data line.(k
)
402 for r
= 0 to nb
do line1.(k
+ r
) <- copy_data line.(k
) done
403 else line1.(k
+ nb
) <- copy_data line.(k
);
413 if a
< b
then gcd b a
else if b
= 0 then a
else gcd b
(a
mod b
)
416 let treat_new_row d t
=
417 let i = Array.length t
.table
- 1 in
419 match get_block t
i j
with
420 Some
(parents
, max_parent_colspan
, span) ->
421 let children = get_children d parents
in
423 if children = [] then [{elem
= Nothing
; span = new_span_id ()}]
425 List.map
(fun n -> {elem
= Elem
n; span = new_span_id ()})
428 let simple_parents_colspan =
429 List.fold_left
(fun x (_
, c
) -> x + c
) 0 parents
431 if simple_parents_colspan mod List.length
children = 0 then
432 let j = j + simple_parents_colspan in
434 let cnt = simple_parents_colspan / List.length
children in
437 let rec loop cnt list
=
438 if cnt = 1 then d
:: list
439 else copy_data d
:: loop (cnt - 1) list
444 let (t
, children_rest
) = loop t
i j in t
, children @ children_rest
448 (fun scm
(_
, c
) -> let g = gcd scm c
in scm
/ g * c
)
449 max_parent_colspan parents
451 let (t
, parents
, _
) =
453 (fun (t
, parents
, j) (x, c
) ->
454 let to_add = parent_colspan / c
- 1 in
456 let rec loop cc
t j =
459 let t = insert_columns t to_add j in
460 loop (cc
- 1) t (j + to_add + 1)
464 t, (x, parent_colspan) :: parents
, j + parent_colspan)
467 let parents = List.rev
parents in
468 let parents_colspan = parent_colspan * List.length
parents in
469 let children_colspan = List.length
children in
470 let g = gcd parents_colspan children_colspan in
472 let cnt = children_colspan / g in
474 (fun (t, j) (_
, c
) ->
475 let rec loop cc
t j =
478 let t = insert_columns t (cnt - 1) j in
479 let j = j + cnt in loop (cc
- 1) t j
485 let cnt = parents_colspan / g in
488 let rec loop cnt list
=
489 if cnt = 0 then list
else d
:: loop (cnt - 1) list
494 let (t, children_rest
) = loop t i j in t, children @ children_rest
500 let down_it t i k
y =
501 t.table
.(Array.length
t.table
- 1).(k
) <- t.table
.(i).(k
);
502 for r
= i to Array.length
t.table
- 2 do
503 t.table
.(r
).(k
) <- {elem
= Ghost
(new_ghost_id ()); span = new_span_id ()}
508 in the last line, for all elem A, make fall all As, which are located at
509 its right side above, to its line,
511 i.e. transform all . into |
516 let ilast = Array.length
t.table
- 1 in
517 let last = t.table
.(ilast) in
518 let len = Array.length
last in
522 match last.(j).elem
with
525 if i = ilast then loop (j + 1)
528 if k
= len then loop1 (i + 1)
530 match t.table
.(i).(k
).elem
with
531 Elem
y when x = y -> down_it t i k
y; loop 0
543 transform all x y into x x
547 for i = 0 to Array.length
t.table
- 2 do
548 for j = 1 to Array.length
t.table
.(0) - 1 do
549 match t.table
.(i + 1).(j - 1).elem
, t.table
.(i + 1).(j).elem
with
550 Elem
x, Elem
y when x = y ->
551 t.table
.(i).(j).span <- t.table
.(i).(j - 1).span
559 transform all |a |b into |a |a and all x y into x x
563 for i = 0 to Array.length
t.table
- 2 do
564 for j = 1 to Array.length
t.table
.(0) - 1 do
565 begin match t.table
.(i + 1).(j - 1).elem
, t.table
.(i + 1).(j).elem
with
567 if t.table
.(i).(j - 1).span = t.table
.(i).(j).span then
568 t.table
.(i + 1).(j) <-
569 {elem
= Ghost
x; span = t.table
.(i + 1).(j - 1).span}
572 match t.table
.(i).(j - 1).elem
, t.table
.(i).(j).elem
with
574 if t.table
.(i + 1).(j - 1).elem
= t.table
.(i + 1).(j).elem
then
577 {elem
= Ghost
x; span = t.table
.(i).(j - 1).span};
579 t.table
.(i - 1).(j).span <- t.table
.(i - 1).(j - 1).span
587 transform all A A into A A
590 let group_children t =
591 for i = 0 to Array.length
t.table
- 1 do
592 let line = t.table
.(i) in
593 let len = Array.length
line in
594 for j = 1 to len - 1 do
595 if line.(j).elem
= line.(j - 1).elem
&& line.(j).elem
<> Nothing
then
596 line.(j).span <- line.(j - 1).span
601 (* group_span_by_common_children:
602 in the last line, transform all
605 if A and B have common children *)
607 let group_span_by_common_children d
t =
608 let module O
= struct type t = idag
;; let compare = compare;; end
610 let module S
= Set.Make
(O
)
612 let i = Array.length
t.table
- 1 in
613 let line = t.table
.(i) in
615 if j = Array.length
line then ()
617 match line.(j).elem
with
619 let n = d
.dag
.(int_of_idag id
) in
620 let curr_cs = List.fold_right
S.add
n.chil
S.empty
in
621 if S.is_empty
(S.inter
cs curr_cs) then loop (j + 1) curr_cs
624 line.(j).span <- line.(j - 1).span;
625 loop (j + 1) (S.union
cs curr_cs)
627 | _
-> loop (j + 1) S.empty
632 let find_same_parents t i j1 j2 j3 j4
=
633 let rec loop i j1 j2 j3 j4
=
634 if i = 0 then i, j1
, j2
, j3
, j4
636 let x1 = t.(i - 1).(j1
) in
637 let x2 = t.(i - 1).(j2
) in
638 let x3 = t.(i - 1).(j3
) in
639 let x4 = t.(i - 1).(j4
) in
640 if x1.span = x4.span then i, j1
, j2
, j3
, j4
645 else if t.(i - 1).(j).span = x1.span then loop (j - 1)
652 if j >= Array.length
t.(i) then j - 1
653 else if t.(i - 1).(j).span = x2.span then loop (j + 1)
661 else if t.(i - 1).(j).span = x3.span then loop (j - 1)
668 if j >= Array.length
t.(i) then j - 1
669 else if t.(i - 1).(j).span = x4.span then loop (j + 1)
674 loop (i - 1) j1 j2 j3 j4
679 let find_linked_children t i j1 j2 j3 j4 =
680 let rec loop i j1 j2 j3 j4 =
681 if i = Array.length
t - 1 then j1, j2, j3, j4
683 let x1 = t.(i).(j1) in
684 let x2 = t.(i).(j2) in
685 let x3 = t.(i).(j3) in
686 let x4 = t.(i).(j4) in
690 else if t.(i).(j).span = x1.span then loop (j - 1)
697 if j >= Array.length
t.(i) then j - 1
698 else if t.(i).(j).span = x2.span then loop (j + 1)
706 else if t.(i).(j).span = x3.span then loop (j - 1)
713 if j >= Array.length
t.(i) then j - 1
714 else if t.(i).(j).span = x4.span then loop (j + 1)
719 loop (i + 1) j1 j2 j3 j4
724 let mirror_block t i1 i2
j1 j2 =
731 line.(j1) <- line.(j2); line.(j2) <- v; loop (j1 + 1) (j2 - 1)
737 let exch_blocks t i1 i2
j1 j2 j3 j4 =
740 let saved = Array.copy
line in
741 for j = j1 to j2 do line.(j4 - j2 + j) <- saved.(j) done;
742 for j = j3 to j4 do line.(j1 - j3 + j) <- saved.(j) done
746 let find_block_with_parents t i jj1 jj2 jj3 jj4
=
747 let rec loop ii jj1 jj2 jj3 jj4
=
748 let (nii
, njj1
, njj2
, njj3
, njj4
) =
749 find_same_parents t i jj1 jj2 jj3 jj4
751 if nii
<> ii
|| njj1
<> jj1
|| njj2
<> jj2
|| njj3
<> jj3
||
753 let nii = min ii
nii in
754 let (jj1
, jj2
, jj3
, jj4
) =
755 find_linked_children t nii njj1 njj2 njj3 njj4
757 if njj1
<> jj1
|| njj2
<> jj2
|| njj3
<> jj3
|| njj4
<> jj4
then
758 loop nii jj1 jj2 jj3 jj4
759 else nii, jj1
, jj2
, jj3
, jj4
760 else ii
, jj1
, jj2
, jj3
, jj4
762 loop i jj1 jj2 jj3 jj4
765 let push_to_right d
t i j1 j2 =
771 match line.(j - 1).elem
with
774 let rec same_value j =
776 else if line.(j).elem
= x then same_value (j - 1)
785 match line.(j).elem
with
788 let rec same_value j =
789 if j >= Array.length
line then j - 1
790 else if line.(j).elem
= x then same_value (j + 1)
795 let (ii
, jj1, jj2, jj3, jj4) =
796 find_block_with_parents t i jj1 jj2 jj3 jj4
798 if jj4 < j2 && jj2 < jj3 then
799 begin exch_blocks t ii
i jj1 jj2 jj3 jj4; loop (jj4 + 1) end
800 else if jj4 < j2 && jj1 = ini_jj1 && jj2 <= jj4 then
801 begin mirror_block t ii
i jj1 jj4; loop (jj4 + 1) end
807 let push_to_left d
t i j1 j2 =
813 match line.(j).elem
with
816 let rec same_value j =
818 else if line.(j).elem
= x then same_value (j - 1)
826 match line.(j + 1).elem
with
829 let rec same_value j =
830 if j >= Array.length
line then j - 1
831 else if line.(j).elem
= x then same_value (j + 1)
837 let (ii
, jj1, jj2, jj3, jj4) =
838 find_block_with_parents t i jj1 jj2 jj3 jj4
840 if jj1 > j1 && jj2 < jj3 then
841 begin exch_blocks t ii
i jj1 jj2 jj3 jj4; loop (jj1 - 1) end
842 else if jj1 > j1 && jj4 = ini_jj4 && jj3 >= jj1 then
843 begin mirror_block t ii
i jj1 jj4; loop (jj1 - 1) end
849 let fill_gap d
t i j1 j2 =
851 let t1 = Array.copy
t.table
in
852 for i = 0 to Array.length
t.table
- 1 do
853 t1.(i) <- Array.copy
t.table
.(i);
854 for j = 0 to Array.length
t1.(i) - 1 do
855 t1.(i).(j) <- copy_data t.table
.(i).(j)
860 let j2 = push_to_left d
t1 i j1 j2 in
861 let j1 = push_to_right d
t1 i j1 j2 in
863 let line = t1.(i - 1) in
864 let x = line.(j1).span in
865 let y = line.(j2).span in
867 if j >= Array.length
line then ()
868 else if line.(j).span = y || t1.(i).(j).elem
= t1.(i).(j - 1).elem
then
869 let y = line.(j).span in
871 if i > 0 then t1.(i - 1).(j).span <- t1.(i - 1).(j - 1).span;
874 loop y j2; Some
({table
= t1}, true)
879 let i = Array.length
t.table
- 1 in
881 let line = t.table
.(i) in
882 if j = Array.length
line then t
884 match line.(j).elem
with
886 if y = line.(j - 1).elem
then loop t (j + 1)
889 if j1 < 0 then loop t (j + 1)
890 else if y = line.(j1).elem
then
891 match fill_gap d
t i j1 j with
892 Some
(t, ok
) -> if ok
then loop t 2 else loop t (j + 1)
893 | None
-> loop t (j + 1)
894 else loop1 t (j1 - 1)
897 | _
-> loop t (j + 1)
899 if Array.length
t.table
.(i) = 1 then t else loop t 2
902 let group_span_last_row t =
903 let row = t.table
.(Array.length
t.table
- 1) in
905 if i >= Array.length
row then ()
908 begin match row.(i).elem
with
909 Elem _
| Ghost _
as x ->
910 if x = row.(i - 1).elem
then row.(i).span <- row.(i - 1).span
919 let has_phony_children phony d
t =
920 let line = t.table
.(Array.length
t.table
- 1) in
922 if j = Array.length
line then false
924 match line.(j).elem
with
925 Elem
x -> if phony d
.dag
.(int_of_idag
x) then true else loop (j + 1)
931 let tablify phony no_optim no_group d
=
932 let a = ancestors d
in
933 let r = group_by_common_children d
a in
934 let t = {table
= [| Array.of_list
r |]} in
936 let (t, new_row
) = treat_new_row d
t in
937 if List.for_all
(fun x -> x.elem
= Nothing
) new_row
then t
939 let t = {table
= Array.append
t.table
[| Array.of_list new_row
|]} in
941 if no_group
&& not
(has_phony_children phony d
t) then t
943 let _ = if no_optim
then () else equilibrate t in
944 let _ = group_elem t in
945 let _ = group_ghost t in
946 let _ = group_children t in
947 let _ = group_span_by_common_children d
t in
948 let t = if no_optim
then t else treat_gaps d
t in
949 let _ = group_span_last_row t in t
957 for i = 1 to Array.length
t.table
- 1 do
958 let line = t.table
.(i) in
960 if j = Array.length
line then ()
962 match line.(j).elem
with
966 if j = Array.length
line then j - 1
968 match line.(j).elem
with
969 Ghost
y when y = x -> loop (j + 1)
978 let line = t.table
.(i) in
979 if (j = 0 || line.(j - 1).span <> line.(j).span) &&
980 (j2 = Array.length
line - 1 ||
981 line.(j2 + 1).span <> line.(j2).span) then
989 else if i1 = 0 then i1
990 else if t.table
.(i1).(j).elem
= Nothing
then i1
995 for k
= i downto i1 + 1 do
997 t.table
.(k
).(j).elem
<- t.table
.(k
- 1).(j).elem
;
999 t.table
.(k
).(j).span <- t.table
.(k
- 1).(j).span
1003 if i1 = 0 || t.table
.(i1 - 1).(l
).elem
= Nothing
then
1004 t.table
.(i1).(l
).elem
<- Nothing
1008 t.table
.(i1 - 1).(l
- 1).span <>
1009 t.table
.(i1 - 1).(l
).span then
1010 {elem
= Ghost
(new_ghost_id ());
1011 span = new_span_id ()}
1012 else copy_data t.table
.(i1).(l
- 1)
1022 let fall2_cool_right t i1 i2 i3
j1 j2 =
1023 let span = t.table
.(i2
- 1).(j1).span in
1024 for i = i2
- 1 downto 0 do
1025 for j = j1 to j2 - 1 do
1027 if i - i2
+ i1 >= 0 then t.table
.(i - i2
+ i1).(j)
1028 else {elem
= Nothing
; span = new_span_id ()}
1031 for i = Array.length
t.table
- 1 downto 0 do
1032 for j = j2 to Array.length
t.table
.(i) - 1 do
1034 if i - i2
+ i1 >= 0 then t.table
.(i - i2
+ i1).(j)
1035 else {elem
= Nothing
; span = new_span_id ()}
1038 let old_span = t.table
.(i2
- 1).(j1).span in
1040 if j = Array.length
t.table
.(i2
- 1) then ()
1041 else if t.table
.(i2
- 1).(j).span = old_span then
1042 begin t.table
.(i2
- 1).(j).span <- span; loop (j + 1) end
1047 let fall2_cool_left t i1 i2 i3
j1 j2 =
1048 let span = t.table
.(i2
- 1).(j2).span in
1049 for i = i2
- 1 downto 0 do
1050 for j = j1 + 1 to j2 do
1052 if i - i2
+ i1 >= 0 then t.table
.(i - i2
+ i1).(j)
1053 else {elem
= Nothing
; span = new_span_id ()}
1056 for i = Array.length
t.table
- 1 downto 0 do
1057 for j = j1 downto 0 do
1059 if i - i2
+ i1 >= 0 then t.table
.(i - i2
+ i1).(j)
1060 else {elem
= Nothing
; span = new_span_id ()}
1063 let old_span = t.table
.(i2
- 1).(j2).span in
1066 else if t.table
.(i2
- 1).(j).span = old_span then
1067 begin t.table
.(i2
- 1).(j).span <- span; loop (j - 1) end
1072 let do_fall2_right t i1 i2
j1 j2 =
1078 if j = Array.length
t.table
.(i) then loop_i (i - 1)
1080 match t.table
.(i).(j).elem
with
1081 Nothing
-> loop_j (j + 1)
1086 loop_i (Array.length
t.table
- 1)
1088 let new_height = i3 + i2
- i1 in
1090 if new_height > Array.length
t.table
then
1091 let rec loop cnt t =
1095 Array.init
(Array.length
t.table
.(0))
1096 (fun i -> {elem
= Nothing
; span = new_span_id ()})
1098 let t = {table
= Array.append
t.table
[| new_line |]} in
1101 loop (new_height - Array.length
t.table
) t
1104 fall2_cool_right t i1 i2
i3 j1 j2; t
1107 let do_fall2_left t i1 i2
j1 j2 =
1113 if j < 0 then loop_i (i - 1)
1115 match t.table
.(i).(j).elem
with
1116 Nothing
-> loop_j (j - 1)
1121 loop_i (Array.length
t.table
- 1)
1123 let new_height = i3 + i2
- i1 in
1125 if new_height > Array.length
t.table
then
1126 let rec loop cnt t =
1130 Array.init
(Array.length
t.table
.(0))
1131 (fun i -> {elem
= Nothing
; span = new_span_id ()})
1133 let t = {table
= Array.append
t.table
[| new_line |]} in
1136 loop (new_height - Array.length
t.table
) t
1139 fall2_cool_left t i1 i2
i3 j1 j2; t
1142 let do_shorten_too_long t i1 j1 j2 =
1143 for i = i1 to Array.length
t.table
- 2 do
1144 for j = j1 to j2 - 1 do t.table
.(i).(j) <- t.table
.(i + 1).(j) done
1146 let i = Array.length
t.table
- 1 in
1147 for j = j1 to j2 - 1 do
1148 t.table
.(i).(j) <- {elem
= Nothing
; span = new_span_id ()}
1153 let try_fall2_right t i j =
1154 match t.table
.(i).(j).elem
with
1160 match t.table
.(i).(j).elem
with
1161 Ghost
_ -> loop (i - 1)
1170 j > 0 && t.table
.(i).(j - 1).span = t.table
.(i).(j).span then
1177 let x = t.table
.(i).(j).span in
1179 if j2 = Array.length
t.table
.(i) then j2
1181 match t.table
.(i).(j2) with
1182 {elem
= Ghost
_; span = y} when y = x -> loop (j2 + 1)
1189 if i = Array.length
t.table
then true
1190 else if j2 = Array.length
t.table
.(i) then false
1191 else if t.table
.(i).(j2 - 1).span = t.table
.(i).(j2).span then false
1196 if not
separated1 || not
separated2 then None
1197 else Some
(do_fall2_right t i1 (i + 1) j j2)
1201 let try_fall2_left t i j =
1202 match t.table
.(i).(j).elem
with
1208 match t.table
.(i).(j).elem
with
1209 Ghost
_ -> loop (i - 1)
1218 j < Array.length
t.table
.(i) - 1 &&
1219 t.table
.(i).(j).span = t.table
.(i).(j + 1).span then
1226 let x = t.table
.(i).(j).span in
1230 match t.table
.(i).(j1) with
1231 {elem
= Ghost
_; span = y} when y = x -> loop (j1 - 1)
1238 if i = Array.length
t.table
then true
1239 else if j1 < 0 then false
1240 else if t.table
.(i).(j1).span = t.table
.(i).(j1 + 1).span then false
1245 if not
separated1 || not
separated2 then None
1246 else Some
(do_fall2_left t i1 (i + 1) j1 j)
1250 let try_shorten_too_long t i j =
1251 match t.table
.(i).(j).elem
with
1254 let x = t.table
.(i).(j).span in
1256 if j2 = Array.length
t.table
.(i) then j2
1258 match t.table
.(i).(j2) with
1259 {elem
= Ghost
_; span = y} when y = x -> loop (j2 + 1)
1266 if i = Array.length
t.table
then i
1268 match t.table
.(i).(j).elem
with
1269 Elem
_ -> loop (i + 1)
1276 if i = Array.length
t.table
then i
1278 match t.table
.(i).(j).elem
with
1279 Nothing
-> loop (i + 1)
1284 let separated_left =
1288 j > 0 && t.table
.(i).(j).span = t.table
.(i).(j - 1).span then
1294 let separated_right =
1298 j2 < Array.length
t.table
.(i) &&
1299 t.table
.(i).(j2 - 1).span = t.table
.(i).(j2).span then
1305 if not
separated_left || not
separated_right then None
1306 else if i2 < Array.length
t.table
then None
1307 else Some
(do_shorten_too_long t i j j2)
1312 let rec loop_i i t =
1315 let rec loop_j j t =
1316 if j < 0 then loop_i (i - 1) t
1318 match try_fall2_right t i j with
1319 Some
t -> loop_i (Array.length
t.table
- 1) t
1320 | None
-> loop_j (j - 1) t
1322 loop_j (Array.length
t.table
.(i) - 2) t
1324 loop_i (Array.length
t.table
- 1) t
1328 let rec loop_i i t =
1331 let rec loop_j j t =
1332 if j >= Array.length
t.table
.(i) then loop_i (i - 1) t
1334 match try_fall2_left t i j with
1335 Some
t -> loop_i (Array.length
t.table
- 1) t
1336 | None
-> loop_j (j + 1) t
1340 loop_i (Array.length
t.table
- 1) t
1343 let shorten_too_long t =
1344 let rec loop_i i t =
1347 let rec loop_j j t =
1348 if j >= Array.length
t.table
.(i) then loop_i (i - 1) t
1350 match try_shorten_too_long t i j with
1351 Some
t -> loop_i (Array.length
t.table
- 1) t
1352 | None
-> loop_j (j + 1) t
1356 loop_i (Array.length
t.table
- 1) t
1360 deletes all empty rows that might have appeared on top of the table
1366 if i = Array.length
t.table
then i
1369 if j = Array.length
t.table
.(i) then loop (i + 1)
1370 else if t.table
.(i).(j).elem
<> Nothing
then i
1379 for i = 0 to Array.length
t.table
- 1 - di do
1380 t.table
.(i) <- t.table
.(i + di)
1382 {table
= Array.sub
t.table
0 (Array.length
t.table
- di)}
1388 deletes all empty rows that might have appeared on bottom of the table
1391 let bottom_adjust t =
1397 if j = Array.length
t.table
.(i) then loop (i - 1)
1398 else if t.table
.(i).(j).elem
<> Nothing
then i
1403 loop (Array.length
t.table
- 1)
1405 if last_i < Array.length
t.table
- 1 then
1406 {table
= Array.sub
t.table
0 (last_i + 1)}
1413 let d = {dag
= Array.copy
d.dag
} in
1414 for i = 0 to Array.length
d.dag
- 1 do
1415 let n = d.dag
.(i) in
1417 {pare
= List.map
(fun x -> x) n.chil
; valu
= n.valu
;
1418 chil
= List.map
(fun x -> x) n.pare
}
1423 let invert_table t =
1424 let t'
= {table
= Array.copy
t.table
} in
1425 let len = Array.length
t.table
in
1426 for i = 0 to len - 1 do
1428 Array.init
(Array.length
t.table
.(0))
1430 let d = t.table
.(len - 1 - i).(j) in
1431 {elem
= d.elem
; span = d.span});
1433 for j = 0 to Array.length
t'
.table
.(i) - 1 do
1434 t'
.table
.(i).(j).span <- t.table
.(len - 2 - i).(j).span
1442 let table_of_dag phony no_optim invert no_group
d =
1443 let d = if invert
then invert_dag d else d in
1444 let t = tablify phony no_optim no_group
d in
1445 let t = if invert
then invert_table t else t in
1446 let _ = fall () t in
1447 let t = fall2_right t in
1448 let t = fall2_left t in
1449 let t = shorten_too_long t in
1450 let t = top_adjust t in let t = bottom_adjust t in t
1454 let version = "1.01";;
1458 let strip_spaces str
=
1461 if i == String.length str
then i
1464 ' '
| '
\013'
| '
\n'
| '
\t'
-> loop (i + 1)
1471 if i == -1 then i + 1
1474 ' '
| '
\013'
| '
\n'
| '
\t'
-> loop (i - 1)
1477 loop (String.length str
- 1)
1479 if start == 0 && stop == String.length str
then str
1480 else if start > stop then ""
1481 else String.sub str
start (stop - start)
1484 let rec get_line ic
=
1486 let line = input_line ic
in
1487 if String.length
line > 0 && line.[0] = '#'
then get_line ic
1488 else Some
(strip_spaces line)
1494 let rec find cnt s =
1497 if n.valu
= s then n, idag_of_int
cnt else find (cnt - 1) s nl
1498 | [] -> raise Not_found
1500 let add_node pl cl nl
cnt =
1501 let cl = List.rev
cl in
1502 let pl = List.rev
pl in
1503 let (pl, pnl
, nl
, cnt) =
1505 (fun (pl, pnl
, nl
, cnt) p
->
1507 let (n, p
) = find (cnt - 1) p nl
in p
:: pl, n :: pnl
, nl
, cnt
1510 let n = {pare
= []; valu
= p
; chil
= []} in
1511 let p = idag_of_int
cnt in p :: pl, n :: pnl
, n :: nl
, cnt + 1)
1512 ([], [], nl
, cnt) pl
1514 let pl = List.rev
pl in
1517 (fun (cl, nl
, cnt) c
->
1519 let (n, c
) = find (cnt - 1) c nl
in
1520 n.pare
<- n.pare
@ pl; c
:: cl, nl
, cnt
1523 let n = {pare
= pl; valu
= c
; chil
= []} in
1524 let c = idag_of_int
cnt in c :: cl, n :: nl
, cnt + 1)
1527 let cl = List.rev
cl in
1528 List.iter
(fun p -> p.chil
<- p.chil
@ cl) pnl
; nl
, cnt
1530 let rec input_parents nl
pl cnt =
1532 Some
"" -> input_parents nl
pl cnt (get_line ic
)
1534 begin match line.[0] with
1537 strip_spaces (String.sub
line 1 (String.length
line - 1))
1539 if p = "" then failwith
line
1540 else input_parents nl
(p :: pl) cnt (get_line ic
)
1542 if pl = [] then failwith
line
1543 else input_children nl
pl [] cnt (Some
line)
1544 | _ -> failwith
line
1546 | None
-> if pl = [] then nl
, cnt else failwith
"end of file 1"
1547 and input_children nl
pl cl cnt =
1549 Some
"" -> input_children nl
pl cl cnt (get_line ic
)
1551 begin match line.[0] with
1553 if cl = [] then failwith
line
1555 let (nl
, cnt) = add_node pl cl nl
cnt in
1556 input_parents nl
[] cnt (Some
line)
1559 strip_spaces (String.sub
line 1 (String.length
line - 1))
1561 if c = "" then failwith
line
1562 else input_children nl
pl (c :: cl) cnt (get_line ic
)
1563 | _ -> failwith
line
1566 if cl = [] then failwith
"end of file 2" else add_node pl cl nl
cnt
1568 let (nl
, _) = input_parents [] [] 0 (get_line ic
) in
1569 {dag
= Array.of_list
(List.rev nl
)}
1576 Array.map
(fun d -> {pare
= d.pare
; valu
= f
d.valu
; chil
= d.chil
}) d.dag
1587 if !c = 'Z'
then '
a'
1588 else if !c = 'z'
then '
1'
1589 else Char.chr
(Char.code
!c + 1);
1596 let phony _ = false;;
1597 let indi_txt n = n.valu
;;
1599 let string_table border
hts =
1600 let buf = Buffer.create
30 in
1601 Printf.bprintf
buf "<center><table border=%d" border
;
1602 Printf.bprintf
buf " cellspacing=0 cellpadding=0>\n";
1603 for i = 0 to Array.length
hts - 1 do
1604 Printf.bprintf
buf "<tr>\n";
1605 for j = 0 to Array.length
hts.(i) - 1 do
1606 let (colspan, align
, td
) = hts.(i).(j) in
1607 Printf.bprintf
buf "<td";
1608 if colspan = 1 && (td
= TDstring
" " || td
= TDhr CenterA
) then ()
1609 else Printf.bprintf
buf " colspan=%d" colspan;
1610 begin match align
, td
with
1611 LeftA
, TDhr LeftA
-> Printf.bprintf
buf " align=left"
1613 | CenterA
, _ -> Printf.bprintf
buf " align=center"
1614 | RightA
, _ -> Printf.bprintf
buf " align=right"
1616 Printf.bprintf
buf ">";
1618 TDstring
s -> Printf.bprintf
buf "%s" s
1620 Printf.bprintf
buf "<hr noshade size=1";
1621 begin match align
with
1622 LeftA
-> Printf.bprintf
buf " width=\"50%%\" align=left"
1623 | RightA
-> Printf.bprintf
buf " width=\"50%%\" align=right"
1626 Printf.bprintf
buf ">";
1629 Printf.bprintf
buf "</td>\n";
1633 Printf.bprintf
buf "</table></center>\n";
1637 let fname = ref "";;
1638 let invert = ref false;;
1639 let char = ref false;;
1640 let border = ref 0;;
1641 let no_optim = ref false;;
1642 let no_group = ref false;;
1645 let t = table_of_dag phony !no_optim !invert !no_group d in
1646 let hts = html_table_struct indi_txt phony d t in
1647 string_table !border hts
1651 (********************************* Max's code **********************************)
1652 (** This function takes a list of classes and a list of class types
1653 and create the associate dag. *)
1654 let create_class_dag cl_list clt_list
=
1655 let module M
= Odoc_info.Class
in
1656 (* the list of all the classes concerned *)
1657 let cl_list2 = List.map
(fun c -> (c.M.cl_name
, Some
(M.Cl
c))) cl_list
in
1658 let clt_list2 = List.map
(fun ct
-> (ct
.M.clt_name
, Some
(M.Cltype
(ct
, [])))) clt_list
in
1659 let list = cl_list2 @ clt_list2 in
1661 let rec iter list2
=
1663 (fun acc
-> fun (name
, cct_opt
) ->
1670 (fun inh
->(inh
.M.ic_name
, inh
.M.ic_class
))
1671 (match c.M.cl_kind
with
1672 M.Class_structure
(inher_l
, _) ->
1678 | Some
(M.Cltype
(ct
, _)) ->
1681 (fun inh
->(inh
.M.ic_name
, inh
.M.ic_class
))
1682 (match ct
.M.clt_kind
with
1683 M.Class_signature
(inher_l
, _) ->
1690 (name
, cct_opt
) :: (acc
@ l)
1697 let rec distinct acc
= function
1700 | (name
, cct_opt
) :: q
->
1701 if List.exists
(fun (name2
, _) -> name
= name2
) acc
then
1704 distinct ((name
, cct_opt
) :: acc
) q
1706 let distinct_classes = distinct [] all_classes in
1708 let rec f n = function
1710 | (name
, _) :: q
-> (name
, n) :: (f (n+1) q
)
1712 f 0 distinct_classes
1714 let array1 = Array.of_list
distinct_classes in
1715 (* create the dag array, filling parents and values *)
1716 let fmap (name
, cct_opt
) =
1718 (fun inh
-> List.assoc inh
.M.ic_name
liste_index )
1722 (match c.M.cl_kind
with
1723 M.Class_structure
(inher_l
, _) ->
1728 | Some
(M.Cltype
(ct
, _)) ->
1729 (match ct
.M.clt_kind
with
1730 M.Class_signature
(inher_l
, _) ->
1736 valu
= (name
, cct_opt
) ;
1740 let dag = { dag = Array.map
fmap array1 } in
1741 (* fill the children *)
1743 let l = Array.to_list
dag.dag in
1744 let l2 = List.map
(fun n -> n.valu
)
1745 (List.filter
(fun n -> List.mem
i n.pare
) l)
1747 node
.chil
<- List.map
(fun (name
,_) -> List.assoc name
liste_index) l2
1749 Array.iteri
fiter dag.dag;