Project

General

Profile

Download (13.3 KB) Statistics
| Branch: | Tag: | Revision:
1
(********************************************************************)
2
(*                                                                  *)
3
(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
4
(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
5
(*                                                                  *)
6
(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
7
(*  under the terms of the GNU Lesser General Public License        *)
8
(*  version 2.1.                                                    *)
9
(*                                                                  *)
10
(********************************************************************)
11

    
12
open Graph
13

    
14
type rat = int * int
15

    
16
type ident = string
17

    
18
type tag = int
19

    
20
type longident = (string * tag) list
21

    
22
exception TransposeError of int * int
23

    
24
(** General utility functions. *)
25
let create_hashtable size init =
26
  let tbl = Hashtbl.create size in
27
  List.iter (fun (key, data) -> Hashtbl.add tbl key data) init;
28
  tbl
29

    
30
module IdentModule = struct
31
  (* Node module *)
32
  type t = ident
33

    
34
  let compare = compare
35

    
36
  let hash n = Hashtbl.hash n
37

    
38
  let equal n1 n2 = n1 = n2
39
end
40

    
41
module IMap = struct
42
  include Map.Make (IdentModule)
43

    
44
  let diff m1 m2 =
45
    merge
46
      (fun _ o1 o2 ->
47
        match o1, o2 with
48
        | Some v1, Some v2 ->
49
          if v1 = v2 then None else o1
50
        | _ ->
51
          o1)
52
      m1 m2
53

    
54
  let of_list l = List.fold_left (fun m (x, v) -> add x v m) empty l
55

    
56
  let pp ?(comment = "") pp_val fmt m =
57
    Format.fprintf fmt "@[<hv 0>@[<hv 2>{ %s" comment;
58
    iter (fun key v -> Format.fprintf fmt "@ %s -> %a" key pp_val v) m;
59
    Format.fprintf fmt "@]@ }@]"
60
end
61

    
62
module ISet = struct
63
  include Set.Make (IdentModule)
64

    
65
  let pp fmt t =
66
    let open Format in
67
    fprintf fmt "@[<hv 0>@[<hv 2>{";
68
    iter (fun s -> fprintf fmt "@ %s" s) t;
69
    fprintf fmt "@]@ }@]"
70
end
71

    
72
module IdentDepGraph = Imperative.Digraph.ConcreteBidirectional (IdentModule)
73
module TopologicalDepGraph = Topological.Make (IdentDepGraph)
74
module ComponentsDepGraph = Components.Make (IdentDepGraph)
75

    
76
(*module DotGraph = Graphviz.Dot (IdentDepGraph)*)
77
module Bfs = Traverse.Bfs (IdentDepGraph)
78

    
79
exception DeSome
80

    
81
let desome x = match x with Some x -> x | None -> raise DeSome
82

    
83
let option_map f o = match o with None -> None | Some e -> Some (f e)
84

    
85
let add_cons x l = if List.mem x l then l else x :: l
86

    
87
let rec remove_duplicates l =
88
  match l with [] -> [] | t :: q -> add_cons t (remove_duplicates q)
89

    
90
let position pred l =
91
  let rec pos p l =
92
    match l with
93
    | [] ->
94
      assert false
95
    | t :: q ->
96
      if pred t then p else pos (p + 1) q
97
  in
98
  pos 0 l
99

    
100
(* TODO: Lélio: why n+1? cf former def below *)
101
(* if n < 0 then [] else x :: duplicate x (n - 1) *)
102
let duplicate x n = List.init (n + 1) (fun _ -> x)
103

    
104
let enumerate n = List.init n (fun i -> i)
105

    
106
let rec repeat n f x = if n <= 0 then x else repeat (n - 1) f (f x)
107

    
108
let transpose_list ll =
109
  let rec transpose ll =
110
    match ll with
111
    | [] ->
112
      []
113
    | [ l ] ->
114
      List.map (fun el -> [ el ]) l
115
    | l :: q ->
116
      List.map2 (fun el eq -> el :: eq) l (transpose q)
117
  in
118
  match ll with
119
  | [] ->
120
    []
121
  | l :: q ->
122
    let length_l = List.length l in
123
    List.iter
124
      (fun l' ->
125
        let length_l' = List.length l' in
126
        if length_l <> length_l' then
127
          raise (TransposeError (length_l, length_l')))
128
      q;
129
    transpose ll
130

    
131
let rec filter_upto p n l =
132
  if n = 0 then []
133
  else
134
    match l with
135
    | [] ->
136
      []
137
    | t :: q ->
138
      if p t then t :: filter_upto p (n - 1) q else filter_upto p n q
139

    
140
(** [gcd a b] returns the greatest common divisor of [a] and [b]. *)
141
let rec gcd a b = if b = 0 then a else gcd b (a mod b)
142

    
143
(** [lcm a b] returns the least common multiple of [a] and [b]. *)
144
let lcm a b = if a = 0 && b = 0 then 0 else a * b / gcd a b
145

    
146
(** [sum_rat (a,b) (a',b')] returns the sum of rationals [(a,b)] and [(a',b')] *)
147
let sum_rat (a, b) (a', b') =
148
  if a = 0 && b = 0 then a', b'
149
  else if a' = 0 && b' = 0 then a, b
150
  else
151
    let lcm_bb' = lcm b b' in
152
    (a * lcm_bb' / b) + (a' * lcm_bb' / b'), lcm_bb'
153

    
154
let simplify_rat (a, b) =
155
  let gcd = gcd a b in
156
  if gcd = 0 then a, b else a / gcd, b / gcd
157

    
158
let max_rat (a, b) (a', b') =
159
  let ratio_ab = float_of_int a /. float_of_int b in
160
  let ratio_ab' = float_of_int a' /. float_of_int b' in
161
  if ratio_ab > ratio_ab' then a, b else a', b'
162

    
163
(** [list_union l1 l2] returns the union of list [l1] and [l2]. The result
164
    contains no duplicates. *)
165
let list_union l1 l2 =
166
  let rec aux l acc =
167
    match l with
168
    | [] ->
169
      acc
170
    | x :: tl ->
171
      if List.mem x acc then aux tl acc else aux tl (x :: acc)
172
  in
173
  let l1' = aux l1 [] in
174
  aux l2 l1'
175

    
176
(** [hashtbl_add h1 h2] adds all the bindings in [h2] to [h1]. If the
177
    intersection is not empty, it replaces the former binding *)
178
let hashtbl_add h1 h2 =
179
  Hashtbl.iter (fun key value -> Hashtbl.replace h1 key value) h2
180

    
181
let hashtbl_iterlast h f1 f2 =
182
  let l = Hashtbl.length h in
183
  ignore
184
    (Hashtbl.fold
185
       (fun k v cpt ->
186
         if cpt = l then (
187
           f2 k v;
188
           cpt + 1)
189
         else (
190
           f1 k v;
191
           cpt + 1))
192
       h 1)
193

    
194
(** Match types variables to 'a, 'b, ..., for pretty-printing. Type variables
195
    are identified by integers. *)
196
let tnames = ref ([] : (int * string) list)
197

    
198
let tname_counter = ref 0
199

    
200
(* Same for carriers *)
201
let crnames = ref ([] : (int * string) list)
202

    
203
let crname_counter = ref 0
204

    
205
(* Same for dimension *)
206
let dnames = ref ([] : (int * string) list)
207

    
208
let dname_counter = ref 0
209

    
210
(* Same for delays *)
211
let inames = ref ([] : (int * string) list)
212

    
213
let iname_counter = ref 0
214

    
215
let reset_names () =
216
  tnames := [];
217
  tname_counter := 0;
218
  crnames := [];
219
  crname_counter := 0;
220
  dnames := [];
221
  dname_counter := 0;
222
  inames := [];
223
  iname_counter := 0
224

    
225
(* From OCaml compiler *)
226
let new_tname () =
227
  let tname =
228
    if !tname_counter < 26 then String.make 1 (Char.chr (97 + !tname_counter))
229
    else
230
      String.make 1 (Char.chr (97 + (!tname_counter mod 26)))
231
      ^ string_of_int (!tname_counter / 26)
232
  in
233
  incr tname_counter;
234
  tname
235

    
236
let new_crname () =
237
  incr crname_counter;
238
  Format.sprintf "c%i" (!crname_counter - 1)
239

    
240
let name_of_type id =
241
  try List.assoc id !tnames
242
  with Not_found ->
243
    let name = new_tname () in
244
    tnames := (id, name) :: !tnames;
245
    name
246

    
247
let name_of_carrier id =
248
  let pp_id =
249
    try List.assoc id !crnames
250
    with Not_found ->
251
      let name = new_crname () in
252
      crnames := (id, name) :: !crnames;
253
      name
254
  in
255
  pp_id
256

    
257
let new_dname () =
258
  incr dname_counter;
259
  Format.sprintf "d%i" (!dname_counter - 1)
260

    
261
let name_of_dimension id =
262
  try List.assoc id !dnames
263
  with Not_found ->
264
    let name = new_dname () in
265
    dnames := (id, name) :: !dnames;
266
    name
267

    
268
let new_iname () =
269
  incr iname_counter;
270
  Format.sprintf "t%i" (!iname_counter - 1)
271

    
272
let name_of_delay id =
273
  try List.assoc id !inames
274
  with Not_found ->
275
    let name = new_iname () in
276
    inames := (id, name) :: !inames;
277
    name
278

    
279
open Format
280

    
281
let print_rat fmt (a, b) =
282
  if b = 1 then Format.fprintf fmt "%i" a
283
  else if b < 0 then Format.fprintf fmt "%i/%i" (-a) (-b)
284
  else Format.fprintf fmt "%i/%i" a b
285

    
286
(* Generic pretty printing *)
287

    
288
let pp_final_char_if_non_empty c l fmt =
289
  match l with [] -> () | _ -> Format.fprintf fmt "%(%)" c
290

    
291
let pp_newline_if_non_empty l fmt =
292
  match l with [] -> () | _ -> Format.fprintf fmt "@,"
293

    
294
module Format = struct
295
  include Format
296
  open Format
297

    
298
  let with_out_file file f =
299
    let oc = open_out file in
300
    let fmt = formatter_of_out_channel oc in
301
    f fmt;
302
    close_out oc
303

    
304
  let pp_print_nothing _fmt _ = ()
305

    
306
  let pp_print_cutcut fmt () = fprintf fmt "@,@,"
307

    
308
  let pp_print_endcut s fmt () = fprintf fmt "%s@," s
309

    
310
  let pp_print_opar fmt () = pp_print_string fmt "("
311

    
312
  let pp_print_cpar fmt () = pp_print_string fmt ")"
313

    
314
  let pp_print_obracket fmt () = pp_print_string fmt "["
315

    
316
  let pp_print_cbracket fmt () = pp_print_string fmt "]"
317

    
318
  let pp_print_obrace fmt () = pp_print_string fmt "{"
319

    
320
  let pp_print_cbrace fmt () = pp_print_string fmt "}"
321

    
322
  let pp_print_opar' fmt () = pp_print_string fmt "( "
323

    
324
  let pp_print_cpar' fmt () = pp_print_string fmt " )"
325

    
326
  let pp_print_obrace' fmt () = pp_print_string fmt "{ "
327

    
328
  let pp_print_cbrace' fmt () = pp_print_string fmt " }"
329

    
330
  let pp_print_comma fmt () = fprintf fmt ",@ "
331

    
332
  let pp_print_semicolon fmt () = fprintf fmt ";@ "
333

    
334
  let pp_print_comma' fmt () = fprintf fmt ","
335

    
336
  let pp_print_semicolon' fmt () = fprintf fmt ";"
337

    
338
  let pp_open_vbox0 fmt () = pp_open_vbox fmt 0
339

    
340
  let pp_print_list ?(pp_prologue = pp_print_nothing)
341
      ?(pp_epilogue = pp_print_nothing) ?(pp_op = pp_print_nothing)
342
      ?(pp_cl = pp_print_nothing)
343
      ?(pp_open_box = fun fmt () -> pp_open_box fmt 0)
344
      ?(pp_eol = pp_print_nothing) ?(pp_nil = pp_print_nothing) ?pp_sep pp_v fmt
345
      l =
346
    fprintf fmt "%a%a%a%a%a@]%a%a"
347
      (fun fmt l -> if l <> [] then pp_prologue fmt ())
348
      l pp_op () pp_open_box ()
349
      (fun fmt () ->
350
        if l = [] then pp_nil fmt () else pp_print_list ?pp_sep pp_v fmt l)
351
      ()
352
      (fun fmt l -> if l <> [] then pp_eol fmt ())
353
      l pp_cl ()
354
      (fun fmt l -> if l <> [] then pp_epilogue fmt ())
355
      l
356

    
357
  let pp_comma_list = pp_print_list ~pp_sep:pp_print_comma
358

    
359
  let pp_print_list_i ?pp_prologue ?pp_epilogue ?pp_op ?pp_cl ?pp_open_box
360
      ?pp_eol ?pp_nil ?pp_sep pp_v =
361
    let i = ref 0 in
362
    pp_print_list ?pp_prologue ?pp_epilogue ?pp_op ?pp_cl ?pp_open_box ?pp_eol
363
     ?pp_nil ?pp_sep (fun fmt x ->
364
        pp_v fmt !i x;
365
        incr i)
366

    
367
  let pp_print_list2 ?pp_prologue ?pp_epilogue ?pp_op ?pp_cl ?pp_open_box
368
      ?pp_eol ?pp_nil ?pp_sep pp_v fmt (l1, l2) =
369
    pp_print_list ?pp_prologue ?pp_epilogue ?pp_op ?pp_cl ?pp_open_box ?pp_eol
370
      ?pp_nil ?pp_sep pp_v fmt (List.combine l1 l2)
371

    
372
  let pp_print_list_i2 ?pp_prologue ?pp_epilogue ?pp_op ?pp_cl ?pp_open_box
373
      ?pp_eol ?pp_nil ?pp_sep pp_v fmt (l1, l2) =
374
    pp_print_list_i ?pp_prologue ?pp_epilogue ?pp_op ?pp_cl ?pp_open_box ?pp_eol
375
      ?pp_nil ?pp_sep
376
      (fun fmt i (x1, x2) -> pp_v fmt i x1 x2)
377
      fmt (List.combine l1 l2)
378

    
379
  let pp_print_parenthesized ?(pp_sep = pp_print_comma) =
380
    pp_print_list ~pp_op:pp_print_opar ~pp_cl:pp_print_cpar ~pp_sep
381

    
382
  let pp_print_bracketed ?(pp_sep = pp_print_comma) =
383
    pp_print_list ~pp_op:pp_print_obracket ~pp_cl:pp_print_cbracket ~pp_sep
384

    
385
  let pp_print_braced ?(pp_sep = pp_print_comma) =
386
    pp_print_list ~pp_op:pp_print_obrace ~pp_cl:pp_print_cbrace ~pp_sep
387

    
388
  let pp_print_braced' ?(pp_sep = pp_print_comma) =
389
    pp_print_list ~pp_op:pp_print_obrace' ~pp_cl:pp_print_cbrace' ~pp_sep
390
end
391

    
392
let fprintf_list ?(eol : ('a, formatter, unit) format = "") ~sep f fmt l =
393
  Format.(pp_print_list ~pp_sep:(fun fmt () -> fprintf fmt "%(%)" sep) f fmt l);
394
  if l <> [] then Format.fprintf fmt "%(%)" eol
395

    
396
let pp_list l pp_fun beg_str end_str sep_str =
397
  if beg_str = "\n" then print_newline () else print_string beg_str;
398
  let rec pp_l l =
399
    match l with
400
    | [] ->
401
      ()
402
    | [ hd ] ->
403
      pp_fun hd
404
    | hd :: tl ->
405
      pp_fun hd;
406
      if sep_str = "\n" then print_newline () else print_string sep_str;
407
      pp_l tl
408
  in
409
  pp_l l;
410
  if end_str = "\n" then print_newline () else print_string end_str
411

    
412
let pp_array a pp_fun beg_str end_str sep_str =
413
  if beg_str = "\n" then print_newline () else print_string beg_str;
414
  let n = Array.length a in
415
  if n > 0 then (
416
    Array.iter
417
      (fun x ->
418
        pp_fun x;
419
        print_string sep_str)
420
      (Array.sub a 0 (n - 1));
421
    pp_fun a.(n - 1));
422
  if end_str = "\n" then print_newline () else print_string end_str
423

    
424
let pp_hashtbl t pp_fun beg_str end_str sep_str =
425
  if beg_str = "\n" then print_newline () else print_string beg_str;
426
  let pp_fun1 k v =
427
    pp_fun k v;
428
    if sep_str = "\n" then print_newline () else print_string sep_str
429
  in
430
  hashtbl_iterlast t pp_fun1 pp_fun;
431
  if end_str = "\n" then print_newline () else print_string end_str
432

    
433
let pp_longident lid =
434
  let pp_fun (nid, tag) =
435
    print_string nid;
436
    print_string "(";
437
    print_int tag;
438
    print_string ")"
439
  in
440
  pp_list lid pp_fun "" "." "."
441

    
442
let pp_date fmt tm =
443
  let open Unix in
444
  Format.fprintf fmt "%i/%i/%i, %02i:%02i:%02i" (tm.tm_year + 1900) tm.tm_mon
445
    tm.tm_mday tm.tm_hour tm.tm_min tm.tm_sec
446

    
447
(* Used for uid in variables *)
448

    
449
let get_new_id =
450
  let var_id_cpt = ref 0 in
451
  fun () ->
452
    incr var_id_cpt;
453
    !var_id_cpt
454

    
455
let new_tag =
456
  let last_tag = ref (-1) in
457
  fun () ->
458
    incr last_tag;
459
    !last_tag
460

    
461
module List = struct
462
  include List
463

    
464
  let iteri2 f l1 l2 =
465
    if List.length l1 <> List.length l2 then
466
      raise (Invalid_argument "iteri2: lists have different lengths")
467
    else
468
      let rec run idx l1 l2 =
469
        match l1, l2 with
470
        | [], [] ->
471
          ()
472
        | hd1 :: tl1, hd2 :: tl2 ->
473
          f idx hd1 hd2;
474
          run (idx + 1) tl1 tl2
475
        | _ ->
476
          assert false
477
      in
478
      run 0 l1 l2
479

    
480
  let rec extract l fst last =
481
    if last < fst then assert false
482
    else
483
      match l, fst with
484
      | hd :: tl, 0 ->
485
        if last = 0 then [] else hd :: extract tl 0 (last - 1)
486
      | _ :: tl, _ ->
487
        extract tl (fst - 1) (last - 1)
488
      | [], 0 ->
489
        if last = 0 then [] else assert false (* List too short *)
490
      | _ ->
491
        assert false
492
end
493

    
494
let get_date () =
495
  let tm = Unix.localtime (Unix.time ()) in
496
  let fmt = Format.str_formatter in
497
  pp_date fmt tm;
498
  Format.flush_str_formatter ()
499

    
500
(* Local Variables: *)
501
(* compile-command:"make -C .." *)
502
(* End: *)
(10-10/11)