File: tree_adv.ml

package info (click to toggle)
mlpost 0.8.2-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 3,976 kB
  • sloc: ml: 19,575; javascript: 4,047; makefile: 608; ansic: 34; lisp: 19; sh: 15
file content (169 lines) | stat: -rw-r--r-- 5,297 bytes parent folder | download
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
(**************************************************************************)
(*                                                                        *)
(*  Copyright (C) Johannes Kanig, Stephane Lescuyer                       *)
(*  Jean-Christophe Filliatre, Romain Bardou and Francois Bobot           *)
(*                                                                        *)
(*  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.1, with the special exception on linking            *)
(*  described in file LICENSE.                                            *)
(*                                                                        *)
(*  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.                  *)
(*                                                                        *)
(**************************************************************************)

type 'a t = Node of 'a * 'a t list

let rec map f (Node (x,l)) = Node (f x, List.map (map f) l)

let rec map2 f (Node (x,l1)) (Node (y,l2)) =
  Node (f x y, List.map2 (map2 f) l1 l2)

let rec combine (Node (x,l1)) (Node (y,l2)) =
  Node ((x,y), List.map2 combine l1 l2)

let rec split (Node ((x,y),l)) =
  let l1,l2 = List.split (List.map split l) in
  Node (x,l1), Node (y,l2)

let rec fold f acc (Node (x,l)) =
  let acc = List.fold_left (fold f) acc l in
  f acc x

let rec fold_child f acc (Node (x,l)) =
  List.fold_left (fun acc (Node(y,_) as n) -> fold_child f (f acc x y) n) acc l

let filter_option f t =
  let rec aux (Node (x,l)) =
    match f x with
      | None -> None
      | Some x ->
	  let l = List.map aux l in
	  let l = List.filter (function None -> false | Some _ -> true) l in
	  let l = List.map (function None -> assert false | Some x -> x) l in
	  Some (Node (x,l)) in
  match aux t with
    | None -> invalid_arg "Tree_adv.filter"
    | Some x -> x

let filter f t =
  filter_option (fun a -> if f a then None else Some a) t

let root_map f t =
  let rec aux r (Node (x,l)) = Node (f r x, List.map (aux (Some x)) l) in
  aux None t

let map_children f t =
  let rec aux (Node (x,l)) =
    let child = List.map (function Node (x,_) -> x) l in
    Node (f x child, List.map aux l) in
  aux t

module Place (X : Signature.Boxlike) = struct
  let gen_place ~place t =
    let box_from_a z = Box.empty ~width:(X.width z) ~height:(X.height z) () in
    let box_tree = map box_from_a t in
    let b = place box_tree in
    map2 (fun z e -> X.set_pos (Box.ctr (Box.sub e b)) z) t box_tree


  let place ?(cs=Num.bp 5.) ?(ls=Num.bp 12.) ?(valign=`Center) ?(halign=`North)
      t =
    let rec aux (Node (x,l)) =
      let l = Box.hbox ~padding:cs ~pos:halign (List.map aux l) in
      Box.vbox ~padding:ls ~pos:valign [x;l] in
    aux t

  let place ?ls ?cs ?valign ?halign t =
    gen_place ~place:(place ?ls ?cs ?valign ?halign) t

end

open Command
let draw to_box t =
  fold (fun acc x -> acc ++ Box.draw (to_box x)) Command.nop t

let gen_draw_arrows default ~style ~corner t =
  root_map (fun a b ->
    match a with
    | None -> default
    | Some a -> style (corner `South a) (corner `North b)) t


let wrap_whs_box give_box mod_box f =
  let width a = Box.width (give_box a) in
  let height a = Box.height (give_box a) in
  let set_pos p a = mod_box a (Box.center p (give_box a)) in
  f ~width ~height ~set_pos

let wrap_corner_box give_box f =
  let corner p a = Box.corner p (give_box a) in
  f ~corner


module Overlays =
struct
    type interval = | Bet of int * int (** [|a,b|] *)
                    | Bef of int       (** ]|-oo,a|] *)
                    | Aft of int       (** [|a,+oo|[ *)
                    | Nev              (** emptyset *)
                    | Alw              (** N *)

    let in_interval i = function
      | Bet (x,y) when x<=i && i<=y -> true
      | Bef x when i<=x -> true
      | Aft x when x<=i -> true
      | Alw -> true
      | _ -> false

    let min_interval n = function
      | Bet (a,_) -> min a n
      | Bef a -> min a n
      | Aft a -> min a n
      | _ -> n

    let max_interval n = function
      | Bet (_,b) -> max b n
      | Bef b -> max b n
      | Aft b -> max b n
      | _ -> n

    let min_tree to_interval t =
      let f n a = min_interval n (to_interval a) in
      fold f max_int t

    let max_tree to_interval t =
      let f n a = max_interval n (to_interval a) in
      fold f min_int t

    type 'a spec = (interval * 'a) list

    let rec assoq n = function
      | [] -> raise Not_found
      | (i,a)::l when in_interval n i -> a
      | _::l -> assoq n l

    let max to_num = function
      | [] -> invalid_arg "Tree_adv.Overlays.width"
      | (_,a)::l ->
	  List.fold_left (fun w (_,p) -> Num.maxn w (to_num p)) (to_num a) l

    let set_pos sp pos =
	List.map (fun (i,b) -> i,sp pos b)

end

module Overlays_Boxlike (X : Signature.Boxlike)
  : Signature.Boxlike with type t = X.t Overlays.spec

=
struct
  open Overlays
  type t = X.t spec

  let width = max X.width
  let height = max X.height
  let set_pos = set_pos X.set_pos
end