Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

lustrec / src / main_lustre_compiler.ml @ 521e2a6b

History | View | Annotate | Download (17.2 KB)

1 6efbcb73 xthirioux
(********************************************************************)
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 Format
13
open Log
14
15
open Utils
16
open LustreSpec
17
open Compiler_common
18 04a63d25 xthirioux
 
19
exception StopPhase1 of program
20 6efbcb73 xthirioux
21 04a63d25 xthirioux
let usage = "Usage: lustrec [options] \x1b[4msource file\x1b[0m"
22 6efbcb73 xthirioux
23
let extensions = [".ec"; ".lus"; ".lusi"]
24
25
(* print a .lusi header file from a source prog *)
26
let print_lusi prog dirname basename extension =
27
  let header = Lusic.extract_header dirname basename prog in
28
  let header_name = dirname ^ "/" ^ basename ^ extension in
29
  let h_out = open_out header_name in
30
  let h_fmt = formatter_of_out_channel h_out in
31
  begin
32 77a61575 xthirioux
    Typing.uneval_prog_generics header;
33
    Clock_calculus.uneval_prog_generics header;
34 6efbcb73 xthirioux
    Printers.pp_lusi_header h_fmt basename header;
35
    close_out h_out
36
  end
37
38
(* compile a .lusi header file *)
39
let compile_header dirname  basename extension =
40
  let destname = !Options.dest_dir ^ "/" ^ basename in
41
  let header_name = basename ^ extension in
42
  let lusic_ext = extension ^ "c" in
43
  begin
44
    Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v>");
45
    let header = parse_header true (dirname ^ "/" ^ header_name) in
46
    ignore (Modules.load_header ISet.empty header);
47
    ignore (check_top_decls header);
48
    create_dest_dir ();
49
    Log.report ~level:1
50
      (fun fmt -> fprintf fmt ".. generating compiled header file %sc@," (destname ^ extension));
51
    Lusic.write_lusic true header destname lusic_ext;
52
    Lusic.print_lusic_to_h destname lusic_ext;
53 521e2a6b ploc
    Log.report ~level:1 (fun fmt -> fprintf fmt ".. done !@ @]@ ")
54 6efbcb73 xthirioux
  end
55
56
(* check whether a source file has a compiled header,
57
   if not, generate the compiled header *)
58
let compile_source_to_header prog computed_types_env computed_clocks_env dirname basename extension =
59
  let destname = !Options.dest_dir ^ "/" ^ basename in
60
  let lusic_ext = extension ^ "c" in
61
  let header_name = destname ^ lusic_ext in
62
  begin
63
    if not (Sys.file_exists header_name) then
64
      begin
65
	Log.report ~level:1 (fun fmt -> fprintf fmt ".. generating compiled header file %s@," header_name);
66
	Lusic.write_lusic false (Lusic.extract_header dirname basename prog) destname lusic_ext;
67
	Lusic.print_lusic_to_h destname lusic_ext
68
      end
69
    else
70
      let lusic = Lusic.read_lusic destname lusic_ext in
71
      if not lusic.Lusic.from_lusi then
72
	begin
73
	  Log.report ~level:1 (fun fmt -> fprintf fmt ".. generating compiled header file %s@," header_name);
74
       	  Lusic.write_lusic false (Lusic.extract_header dirname basename prog) destname lusic_ext;
75 843bc20f ploc
	  (*List.iter (fun top_decl -> Format.eprintf "lusic: %a@." Printers.pp_decl top_decl) lusic.Lusic.contents;*)
76 6efbcb73 xthirioux
	  Lusic.print_lusic_to_h destname lusic_ext
77
	end
78
      else
79
	begin
80
	  Log.report ~level:1 (fun fmt -> fprintf fmt ".. loading compiled header file %s@," header_name);
81 a28d1ba7 xthirioux
	  Modules.check_dependency lusic destname;
82 6efbcb73 xthirioux
	  let header = lusic.Lusic.contents in
83
	  let (declared_types_env, declared_clocks_env) = get_envs_from_top_decls header in
84
	  check_compatibility
85
	    (prog, computed_types_env, computed_clocks_env)
86
	    (header, declared_types_env, declared_clocks_env)
87
	end
88
  end
89
90 843bc20f ploc
91 45f0f48d xthirioux
92 04a63d25 xthirioux
(* From prog to prog *)
93
let stage1 prog dirname basename =
94 521e2a6b ploc
  (* Removing automata *)
95 04a63d25 xthirioux
  let prog = expand_automata prog in
96 521e2a6b ploc
  Log.report ~level:4 (fun fmt -> fprintf fmt ".. after automata expansion:@,  @[<v 2>@,%a@]@ " Printers.pp_prog prog);
97 60aab16d xthirioux
98 6efbcb73 xthirioux
  (* Importing source *)
99
  let _ = Modules.load_program ISet.empty prog in
100
101
  (* Extracting dependencies *)
102
  let dependencies, type_env, clock_env = import_dependencies prog in
103
104
  (* Sorting nodes *)
105
  let prog = SortProg.sort prog in
106
107 ec433d69 xthirioux
  (* Perform inlining before any analysis *)
108
  let orig, prog =
109
    if !Options.global_inline && !Options.main_node <> "" then
110
      (if !Options.witnesses then prog else []),
111
      Inliner.global_inline basename prog type_env clock_env
112
    else (* if !Option.has_local_inline *)
113
      [],
114
      Inliner.local_inline basename prog type_env clock_env
115
  in
116
117
  (* Checking stateless/stateful status *)
118 ca88e660 Ploc
  if Plugins.check_force_stateful () then
119 04a63d25 xthirioux
    force_stateful_decls prog
120
  else
121
    check_stateless_decls prog;
122 ec433d69 xthirioux
123 6efbcb73 xthirioux
  (* Typing *)
124
  let computed_types_env = type_decls type_env prog in
125 45f0f48d xthirioux
126 6efbcb73 xthirioux
  (* Clock calculus *)
127
  let computed_clocks_env = clock_decls clock_env prog in
128
129
  (* Generating a .lusi header file only *)
130
  if !Options.lusi then
131 04a63d25 xthirioux
    (* We stop here the processing and produce the current prog. It will be
132
       exported as a lusi *)
133
    raise (StopPhase1 prog);
134 6efbcb73 xthirioux
135 04a63d25 xthirioux
 (* Optimization of prog: 
136
     - Unfold consts 
137
     - eliminate trivial expressions
138
 *)
139
  (*
140
  let prog = 
141
    if !Options.const_unfold || !Options.optimization >= 5 then
142
      begin
143
	Log.report ~level:1 (fun fmt -> fprintf fmt ".. eliminating constants and aliases@,");
144
	Optimize_prog.prog_unfold_consts prog
145
      end
146
    else
147
      prog
148
  in
149
  *)
150 6efbcb73 xthirioux
  (* Delay calculus *)
151 45f0f48d xthirioux
  (* TO BE DONE LATER (Xavier)
152 6efbcb73 xthirioux
    if(!Options.delay_calculus)
153
    then
154
    begin
155
    Log.report ~level:1 (fun fmt -> fprintf fmt ".. initialisation analysis@?");
156
    try
157
    Delay_calculus.delay_prog Basic_library.delay_env prog
158
    with (Delay.Error (loc,err)) as exc ->
159
    Location.print loc;
160
    eprintf "%a" Delay.pp_error err;
161
    Utils.track_exception ();
162
    raise exc
163
    end;
164
  *)
165 8deaa2dd tkahsai
166 6efbcb73 xthirioux
  (* Creating destination directory if needed *)
167
  create_dest_dir ();
168
169
  (* Compatibility with Lusi *)
170
  (* Checking the existence of a lusi (Lustre Interface file) *)
171 04a63d25 xthirioux
  let extension = ".lusi" in
172
  compile_source_to_header prog computed_types_env computed_clocks_env dirname basename extension;
173 6efbcb73 xthirioux
174
  Typing.uneval_prog_generics prog;
175
  Clock_calculus.uneval_prog_generics prog;
176
177 ec433d69 xthirioux
  if !Options.global_inline && !Options.main_node <> "" && !Options.witnesses then
178
    begin
179
      let orig = Corelang.copy_prog orig in
180 e3a4e911 xthirioux
      Log.report ~level:1 (fun fmt -> fprintf fmt ".. generating witness file@,");
181 ec433d69 xthirioux
      check_stateless_decls orig;
182
      let _ = Typing.type_prog type_env orig in
183
      let _ = Clock_calculus.clock_prog clock_env orig in
184
      Typing.uneval_prog_generics orig;
185
      Clock_calculus.uneval_prog_generics orig;
186 8deaa2dd tkahsai
      Inliner.witness
187 ec433d69 xthirioux
	basename
188
	!Options.main_node
189 e3a4e911 xthirioux
	orig prog type_env clock_env
190 ec433d69 xthirioux
    end;
191 04a63d25 xthirioux
  
192 6efbcb73 xthirioux
  (* Computes and stores generic calls for each node,
193
     only useful for ANSI C90 compliant generic node compilation *)
194
  if !Options.ansi then Causality.NodeDep.compute_generic_calls prog;
195 04a63d25 xthirioux
  (*Hashtbl.iter (fun id td -> match td.Corelang.top_decl_desc with
196
    Corelang.Node nd -> Format.eprintf "%s calls %a" id
197
    Causality.NodeDep.pp_generic_calls nd | _ -> ()) Corelang.node_table;*)
198 6efbcb73 xthirioux
199
  (* Normalization phase *)
200
  Log.report ~level:1 (fun fmt -> fprintf fmt ".. normalization@,");
201
  (* Special treatment of arrows in lustre backend. We want to keep them *)
202
  if !Options.output = "lustre" then
203
    Normalization.unfold_arrow_active := false;
204
  let prog = Normalization.normalize_prog prog in
205 04a63d25 xthirioux
  Log.report ~level:2 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Printers.pp_prog prog);
206 fc886259 xthirioux
207 04a63d25 xthirioux
  let prog =
208
    if !Options.mpfr
209
    then
210
      begin
211
	Log.report ~level:1 (fun fmt -> fprintf fmt ".. targetting MPFR library@,");
212
	Mpfr.inject_prog prog
213
      end
214
    else
215
      begin
216 45f0f48d xthirioux
	Log.report ~level:1 (fun fmt -> fprintf fmt ".. keeping floating-point numbers@,");
217 04a63d25 xthirioux
	prog
218
      end in
219 6efbcb73 xthirioux
  Log.report ~level:2 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Printers.pp_prog prog);
220 04a63d25 xthirioux
221 6efbcb73 xthirioux
  (* Checking array accesses *)
222
  if !Options.check then
223
    begin
224 45f0f48d xthirioux
      Log.report ~level:1 (fun fmt -> fprintf fmt ".. checking array accesses@,");
225 6efbcb73 xthirioux
      Access.check_prog prog;
226
    end;
227
228 04a63d25 xthirioux
  prog, dependencies
229
230
(* from source to machine code, with optimization *)
231
let stage2 prog =    
232 6efbcb73 xthirioux
  (* Computation of node equation scheduling. It also breaks dependency cycles
233
     and warns about unused input or memory variables *)
234
  Log.report ~level:1 (fun fmt -> fprintf fmt ".. scheduling@,");
235
  let prog, node_schs = Scheduling.schedule_prog prog in
236 04a63d25 xthirioux
  Log.report ~level:1 (fun fmt -> fprintf fmt "%a"              Scheduling.pp_warning_unused node_schs);
237 6efbcb73 xthirioux
  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_schedule node_schs);
238
  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_fanin_table node_schs);
239 04a63d25 xthirioux
  Log.report ~level:5 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_dep_graph node_schs);
240 6efbcb73 xthirioux
  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Printers.pp_prog prog);
241
242 04a63d25 xthirioux
243
  (* TODO Salsa optimize prog: 
244
     - emits warning for programs with pre inside expressions
245
     - make sure each node arguments and memory is bounded by a local annotation
246
     - introduce fresh local variables for each real pure subexpression
247
  *)
248 6efbcb73 xthirioux
  (* DFS with modular code generation *)
249 521e2a6b ploc
  Log.report ~level:1 (fun fmt -> fprintf fmt ".. machines generation@,");
250 6efbcb73 xthirioux
  let machine_code = Machine_code.translate_prog prog node_schs in
251
252 521e2a6b ploc
  Log.report ~level:3 (fun fmt -> fprintf fmt ".. generated machines (unoptimized):@ %a@ "Machine_code.pp_machines machine_code);
253
254
  (* Optimize machine code *)
255 6efbcb73 xthirioux
  let machine_code =
256 cf9cc6f9 Ploc
    if !Options.optimization >= 4 (* && !Options.output <> "horn" *) then
257 c287ba28 xthirioux
      begin
258 cf9cc6f9 Ploc
	Log.report ~level:1 
259
	  (fun fmt -> fprintf fmt ".. machines optimization: sub-expression elimination@,");
260 521e2a6b ploc
	let machine_code = Optimize_machine.machines_cse machine_code in
261
	Log.report ~level:3 (fun fmt -> fprintf fmt ".. generated machines (sub-expr elim):@ %a@ "Machine_code.pp_machines machine_code);
262
	machine_code
263 c287ba28 xthirioux
      end
264
    else
265
      machine_code
266
  in
267
  (* Optimize machine code *)
268 04a63d25 xthirioux
  let machine_code, removed_table = 
269 ca88e660 Ploc
    if !Options.optimization >= 2 (*&& !Options.output <> "horn"*) then
270 6efbcb73 xthirioux
      begin
271 ca88e660 Ploc
	Log.report ~level:1 (fun fmt -> fprintf fmt 
272 521e2a6b ploc
	  ".. machines optimization: const. inlining (partial eval. with const)@,");
273
	let machine_code, removed_table = Optimize_machine.machines_unfold (Corelang.get_consts prog) node_schs machine_code in
274
	Log.report ~level:3 (fun fmt -> fprintf fmt "\t@[Eliminated constants: @[%a@]@]@ "
275
	  (pp_imap Optimize_machine.pp_elim) removed_table);
276
	Log.report ~level:3 (fun fmt -> fprintf fmt ".. generated machines (const inlining):@ %a@ "Machine_code.pp_machines machine_code);	
277
	machine_code, removed_table
278 6efbcb73 xthirioux
      end
279
    else
280 04a63d25 xthirioux
      machine_code, IMap.empty
281
  in  
282 6efbcb73 xthirioux
  (* Optimize machine code *)
283 85da3a4b ploc
  let machine_code =
284
    if !Options.optimization >= 3 && not (Corelang.functional_backend ()) then
285 6efbcb73 xthirioux
      begin
286 45f0f48d xthirioux
	Log.report ~level:1 (fun fmt -> fprintf fmt ".. machines optimization: minimize stack usage by reusing variables@,");
287 04a63d25 xthirioux
	let node_schs    = Scheduling.remove_prog_inlined_locals removed_table node_schs in
288
	let reuse_tables = Scheduling.compute_prog_reuse_table node_schs in
289
	Optimize_machine.machines_fusion (Optimize_machine.machines_reuse_variables machine_code reuse_tables)
290 6efbcb73 xthirioux
      end
291
    else
292
      machine_code
293 ec433d69 xthirioux
  in
294 04a63d25 xthirioux
  
295
  (* Salsa optimize machine code *)
296
  (*
297
  let machine_code = 
298
    if !Options.salsa_enabled then
299
      begin
300
	check_main ();
301 45f0f48d xthirioux
	Log.report ~level:1 (fun fmt -> fprintf fmt ".. salsa machines optimization: optimizing floating-point accuracy with Salsa@,");
302 04a63d25 xthirioux
	(* Selecting float constants for Salsa *)
303
	let constEnv = List.fold_left (
304
	  fun accu c_topdecl ->
305
	    match c_topdecl.top_decl_desc with
306
	    | Const c when Types.is_real_type c.const_type  ->
307
	      (c.const_id, c.const_value) :: accu
308
	    | _ -> accu
309
	) [] (Corelang.get_consts prog) 
310
	in
311
	List.map 
312
	  (Machine_salsa_opt.machine_t2machine_t_optimized_by_salsa constEnv) 
313
	  machine_code 
314
      end
315
    else
316
      machine_code
317
  in
318
  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@ "
319
    (Utils.fprintf_list ~sep:"@ " Machine_code.pp_machine)
320
    machine_code);
321
  *)
322
  machine_code
323 c287ba28 xthirioux
324 8deaa2dd tkahsai
325 04a63d25 xthirioux
(* printing code *)
326
let stage3 prog machine_code dependencies basename =
327 6efbcb73 xthirioux
  let basename    =  Filename.basename basename in
328 04a63d25 xthirioux
  match !Options.output with
329 dc893173 ploc
    "C" -> 
330 6efbcb73 xthirioux
      begin
331 dc893173 ploc
	Log.report ~level:1 (fun fmt -> fprintf fmt ".. C code generation@,");
332
	C_backend.translate_to_c
333
	  (* alloc_header_file source_lib_file source_main_file makefile_file *)
334
	  basename prog machine_code dependencies
335 6efbcb73 xthirioux
      end
336 dc893173 ploc
  | "java" ->
337
     begin
338
       (Format.eprintf "internal error: sorry, but not yet supported !"; assert false)
339
     (*let source_file = basename ^ ".java" in
340
       Log.report ~level:1 (fun fmt -> fprintf fmt ".. opening file %s@,@?" source_file);
341
       let source_out = open_out source_file in
342
       let source_fmt = formatter_of_out_channel source_out in
343
       Log.report ~level:1 (fun fmt -> fprintf fmt ".. java code generation@,@?");
344
       Java_backend.translate_to_java source_fmt basename normalized_prog machine_code;*)
345
     end
346
  | "horn" ->
347
     begin
348
       let destname = !Options.dest_dir ^ "/" ^ basename in
349
       let source_file = destname ^ ".smt2" in (* Could be changed *)
350
       let source_out = open_out source_file in
351
       let fmt = formatter_of_out_channel source_out in
352
       Log.report ~level:1 (fun fmt -> fprintf fmt ".. hornification@,");
353
       Horn_backend.translate fmt basename prog (Machine_code.arrow_machine::machine_code);
354
       (* Tracability file if option is activated *)
355
       if !Options.traces then (
356
	 let traces_file = destname ^ ".traces.xml" in (* Could be changed *)
357
	 let traces_out = open_out traces_file in
358
	 let fmt = formatter_of_out_channel traces_out in
359
         Log.report ~level:1 (fun fmt -> fprintf fmt ".. tracing info@,");
360
	 Horn_backend_traces.traces_file fmt basename prog machine_code;
361
       )
362
     end
363
  | "lustre" ->
364
     begin
365
       let destname = !Options.dest_dir ^ "/" ^ basename in
366
       let source_file = destname ^ ".lustrec.lus" in (* Could be changed *)
367
       let source_out = open_out source_file in
368
       let fmt = formatter_of_out_channel source_out in
369
       Printers.pp_prog fmt prog;
370
       (*	Lustre_backend.translate fmt basename normalized_prog machine_code *)
371
       ()
372
     end
373
374
  | _ -> assert false
375 04a63d25 xthirioux
376
(* compile a .lus source file *)
377
let rec compile_source dirname basename extension =
378
  let source_name = dirname ^ "/" ^ basename ^ extension in
379
380 521e2a6b ploc
  Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 0>");
381 04a63d25 xthirioux
382
  (* Parsing source *)
383
  let prog = parse_source source_name in
384
385
  let prog =
386
    if !Options.mpfr then
387
      Mpfr.mpfr_module::prog
388
    else
389
      prog
390
  in
391
  let prog, dependencies = 
392 521e2a6b ploc
    Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 2>.. Phase 1 : Normalisation@,");
393 04a63d25 xthirioux
    try 
394
      stage1 prog dirname basename
395
    with StopPhase1 prog -> (
396
      if !Options.lusi then
397
	begin
398
	  let lusi_ext = extension ^ "i" in
399 521e2a6b ploc
	  Log.report ~level:1 (fun fmt -> fprintf fmt ".. generating interface file %s@ " (basename ^ lusi_ext));
400 04a63d25 xthirioux
	  print_lusi prog dirname basename lusi_ext;
401
	  Log.report ~level:1 (fun fmt -> fprintf fmt ".. done !@ @]@.");
402
	  exit 0
403
	end
404
      else
405
        assert false
406
    )
407 6efbcb73 xthirioux
  in
408 521e2a6b ploc
  Log.report ~level:1 (fun fmt -> fprintf fmt "@]@,");
409
  Log.report ~level:3 (fun fmt -> fprintf fmt ".. Normalized program:@ %a@ "Printers.pp_prog prog);
410
411
  Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 2>.. Phase 2 : Machines generation@,");
412 04a63d25 xthirioux
413
  let machine_code = 
414
    stage2 prog 
415
  in
416 521e2a6b ploc
417
  Log.report ~level:1 (fun fmt -> fprintf fmt "@]@ ");
418
  Log.report ~level:3 (fun fmt -> fprintf fmt ".. Generated machines:@ %a@ "Machine_code.pp_machines machine_code);
419
420 04a63d25 xthirioux
  if Scopes.Plugin.show_scopes () then
421
    begin
422
      let all_scopes = Scopes.compute_scopes prog !Options.main_node in
423
      (* Printing scopes *)
424
      if !Options.verbose_level >= 1 then
425
	Format.printf "Possible scopes are:@   ";
426 521e2a6b ploc
      Format.printf "@[<v>%a@ @]@ @?" Scopes.print_scopes all_scopes;
427 04a63d25 xthirioux
      exit 0
428
	
429
    end;
430
431 ca88e660 Ploc
  let machine_code = Plugins.refine_machine_code prog machine_code in
432 04a63d25 xthirioux
  
433
  stage3 prog machine_code dependencies basename;
434 f4acee4c xthirioux
  begin
435 ca88e660 Ploc
    Log.report ~level:1 (fun fmt -> fprintf fmt ".. done !@ @]@.");
436 04a63d25 xthirioux
    (* We stop the process here *)
437 f4acee4c xthirioux
    exit 0
438
  end
439 6efbcb73 xthirioux
440
let compile dirname basename extension =
441
  match extension with
442
  | ".lusi"  -> compile_header dirname basename extension
443
  | ".lus"   -> compile_source dirname basename extension
444
  | _        -> assert false
445
446
let anonymous filename =
447
  let ok_ext, ext = List.fold_left
448
    (fun (ok, ext) ext' ->
449
      if not ok && Filename.check_suffix filename ext' then
450
	true, ext'
451
      else
452
	ok, ext)
453
    (false, "") extensions in
454
  if ok_ext then
455
    let dirname = Filename.dirname filename in
456
    let basename = Filename.chop_suffix (Filename.basename filename) ext in
457
    compile dirname basename ext
458
  else
459
    raise (Arg.Bad ("Can only compile *.lusi, *.lus or *.ec files"))
460
461
let _ =
462 04a63d25 xthirioux
  Global.initialize ();
463 6efbcb73 xthirioux
  Corelang.add_internal_funs ();
464
  try
465
    Printexc.record_backtrace true;
466 04a63d25 xthirioux
467 09121c1a ploc
    let options = Options.lustrec_options @ (Plugins.options ()) in
468 04a63d25 xthirioux
    
469
    Arg.parse options anonymous usage
470 6efbcb73 xthirioux
  with
471 04a63d25 xthirioux
  | Parse.Error _
472 6efbcb73 xthirioux
  | Types.Error (_,_) | Clocks.Error (_,_)
473
  | Corelang.Error _ (*| Task_set.Error _*)
474 eb837d74 xthirioux
  | Causality.Error _ -> exit 1
475 6efbcb73 xthirioux
  | Sys_error msg -> (eprintf "Failure: %s@." msg)
476
  | exc -> (Utils.track_exception (); raise exc)
477
478
(* Local Variables: *)
479
(* compile-command:"make -C .." *)
480
(* End: *)