diff --git a/src/automata.ml b/src/automata.ml
new file mode 100755
index 0000000000000000000000000000000000000000..c412e82a925561277ad2244e211e6482d7966230
--- /dev/null
+++ b/src/automata.ml
@@ -0,0 +1,94 @@
+(********************************************************************)
+(*                                                                  *)
+(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
+(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
+(*                                                                  *)
+(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
+(*  under the terms of the GNU Lesser General Public License        *)
+(*  version 2.1.                                                    *)
+(*                                                                  *)
+(********************************************************************)
+
+open LustreSpec
+open Corelang
+
+let mkbool loc b =
+ mkexpr loc (Expr_const (const_of_bool b))
+
+let mkident loc id =
+ mkexpr loc (Expr_ident id)
+
+let init (loc, restart, st) =
+ mkexpr loc (Expr_tuple [mkbool loc restart; mkident loc st])
+
+let add_branch expr (loc, restart, st) cont =
+ mkexpr loc (Expr_ite (expr, init (loc, restart, st), cont))
+
+let mkhandler loc st unless until locals eqs =
+ {hand_state = st;
+  hand_unless = unless;
+  hand_until = until;
+  hand_locals = locals;
+  hand_eqs = eqs;
+  hand_loc = loc}
+
+let mkautomata loc id handlers =
+  {aut_id = id;
+   aut_handlers = handlers;
+   aut_loc = loc}
+
+let pp_restart fmt restart =
+  Format.fprintf fmt "%s" (if restart then "restart" else "resume")
+
+let pp_unless fmt (expr, restart, st) =
+  Format.fprintf fmt "unless %a %a %s"
+    Printers.pp_expr expr
+    pp_restart restart
+    st
+
+let pp_until fmt (expr, restart, st) =
+  Format.fprintf fmt "until %a %a %s"
+    Printers.pp_expr expr
+    pp_restart restart
+    st
+
+let pp_handler fmt handler =
+  Format.fprintf fmt "state %s -> %a %a let %a tel %a"
+    handler.hand_state
+    (Utils.fprintf_list ~sep:"@ " pp_unless) handler.hand_unless
+    (fun fmt locals ->
+      match locals with [] -> () | _ ->
+	Format.fprintf fmt "@[<v 4>var %a@]@ " 
+	  (Utils.fprintf_list ~sep:"@ " 
+	     (fun fmt v -> Format.fprintf fmt "%a;" Printers.pp_node_var v))
+	  locals)
+    handler.hand_locals
+    Printers.pp_node_eqs handler.hand_eqs
+    (Utils.fprintf_list ~sep:"@ " pp_until) handler.hand_until
+
+let pp_automata fmt aut =
+  Format.fprintf fmt "automaton %s %a"
+    aut.aut_id
+    (Utils.fprintf_list ~sep:"@ " pp_handler) aut.aut_handlers
+
+(*
+let rec extract_node expr top_decls =
+  match expr.expr_desc with
+  | Expr_const _
+  | Expr_ident _
+  | Expr_tuple _
+  | Expr_ite   of expr * expr * expr
+  | Expr_arrow of expr * expr
+  | Expr_fby of expr * expr
+  | Expr_array of expr list
+  | Expr_access of expr * Dimension.dim_expr
+  | Expr_power of expr * Dimension.dim_expr
+  | Expr_pre of expr
+  | Expr_when of expr * ident * label
+  | Expr_merge of ident * (label * expr) list
+  | Expr_appl
+*)
+
+(* Local Variables: *)
+(* compile-command:"make -C .." *)
+(* End: *)
diff --git a/src/backends/C/c_backend.ml b/src/backends/C/c_backend.ml
index 932e8033a0f5529c5cb932548db896a401060ce1..832066200be7290f0a454be7a6690d7ce3f3ca70 100644
--- a/src/backends/C/c_backend.ml
+++ b/src/backends/C/c_backend.ml
@@ -13,7 +13,7 @@ open Format
 (********************************************************************************************)
 (*                         Translation function                                             *)
 (********************************************************************************************)
-
+(* USELESS
 let makefile_opt print basename dependencies makefile_fmt machines =
   (* If a main node is identified, generate a main target for it *)
   match !Options.main_node with
@@ -23,7 +23,7 @@ let makefile_opt print basename dependencies makefile_fmt machines =
     | None -> Format.eprintf "Unable to find a main node named %s@.@?" main_node; ()
     | Some _ -> print basename !Options.main_node dependencies makefile_fmt
   )
-
+*)
 
 let gen_files funs basename prog machines dependencies header_file source_lib_file source_main_file makefile_file machines =
   let header_out = open_out header_file in
@@ -33,11 +33,14 @@ let gen_files funs basename prog machines dependencies header_file source_lib_fi
   
   let print_header, print_lib_c, print_main_c, print_makefile = funs in
   (* Generating H file *)
-  print_header header_fmt basename prog machines;
+  print_header header_fmt basename prog machines dependencies;
   
   (* Generating Lib C file *)
   print_lib_c source_lib_fmt basename prog machines dependencies;
 
+  close_out header_out;
+  close_out source_lib_out;
+
   match !Options.main_node with
   | "" ->  () (* No main node: we do not genenrate main nor makefile *)
   | main_node -> (
@@ -53,11 +56,13 @@ let gen_files funs basename prog machines dependencies header_file source_lib_fi
       print_main_c source_main_fmt m basename prog machines dependencies;
       
       (* Generating Makefile *)
-     print_makefile basename main_node dependencies makefile_fmt
+     print_makefile basename main_node dependencies makefile_fmt;
+
+     close_out source_main_out;
+     close_out makefile_out
+
     end
   )
-    
-
 
 let translate_to_c header source_lib source_main makefile basename prog machines dependencies =
 
@@ -73,7 +78,7 @@ let translate_to_c header source_lib source_main makefile basename prog machines
     let module SourceMain = C_backend_main.Main (SourceMainMod) in
     let module Makefile = C_backend_makefile.Main (MakefileMod) in
         
-    let funs = Header.print_header, Source.print_lib_c, SourceMain.print_main_c, Makefile.print_makefile in
+    let funs = Header.print_alloc_header, Source.print_lib_c, SourceMain.print_main_c, Makefile.print_makefile in
     gen_files funs basename prog machines dependencies header source_lib source_main makefile machines
 
   end
@@ -89,7 +94,7 @@ let translate_to_c header source_lib source_main makefile basename prog machines
     let module SourceMain = C_backend_main.Main (SourceMainMod) in
     let module Makefile = C_backend_makefile.Main (MakefileMod) in
         
-    let funs = Header.print_header, Source.print_lib_c, SourceMain.print_main_c, Makefile.print_makefile in
+    let funs = Header.print_alloc_header, Source.print_lib_c, SourceMain.print_main_c, Makefile.print_makefile in
     gen_files funs basename prog machines dependencies header source_lib source_main makefile machines
 
   end
diff --git a/src/backends/C/c_backend_common.ml b/src/backends/C/c_backend_common.ml
index 0299ea40688ec563c58edbcf9a9552d101c54531..cced6a9831272da62a94a4f06adfbe2749b562b6 100644
--- a/src/backends/C/c_backend_common.ml
+++ b/src/backends/C/c_backend_common.ml
@@ -21,8 +21,7 @@ let print_version fmt =
     (Filename.basename Sys.executable_name) 
     Version.number 
     (if !Options.ansi then "ANSI C90" else "C99")
-
-
+ 
 (* Generation of a non-clashing name for the self memory variable (for step and reset functions) *)
 let mk_self m =
   mk_new_name (m.mstep.step_inputs@m.mstep.step_outputs@m.mstep.step_locals@m.mmemory) "self"
@@ -235,6 +234,43 @@ let pp_c_checks self fmt m =
     fmt 
     m.mstep.step_checks
 
+(********************************************************************************************)
+(*                       Struct Printing functions                                          *)
+(********************************************************************************************)
+
+let pp_registers_struct fmt m =
+  if m.mmemory <> []
+  then
+    fprintf fmt "@[%a {@[%a; @]}@] _reg; "
+      pp_machine_regtype_name m.mname.node_id
+      (Utils.fprintf_list ~sep:"; " pp_c_decl_struct_var) m.mmemory
+  else
+    ()
+
+let print_machine_struct fmt m =
+  if fst (get_stateless_status m) then
+    begin
+    end
+  else
+    begin
+      (* Define struct *)
+      fprintf fmt "@[%a {@[%a%a%t@]};@]@."
+	pp_machine_memtype_name m.mname.node_id
+	pp_registers_struct m
+	(Utils.fprintf_list ~sep:"; " pp_c_decl_instance_var) m.minstances
+	(Utils.pp_final_char_if_non_empty "; " m.minstances)
+    end
+
+let print_machine_struct_from_header fmt inode =
+  if inode.nodei_stateless then
+    begin
+    end
+  else
+    begin
+      (* Declare struct *)
+      fprintf fmt "@[%a;@]@."
+	pp_machine_memtype_name inode.nodei_id
+    end
 
 (********************************************************************************************)
 (*                      Prototype Printing functions                                        *)
@@ -271,9 +307,20 @@ let print_step_prototype self fmt (name, inputs, outputs) =
     pp_machine_memtype_name name
     self
 
-let print_import_prototype fmt (s, _, _) =
+let print_import_prototype fmt (_, s, _) =
   fprintf fmt "#include \"%s.h\"@," s
 
+let print_import_alloc_prototype fmt (_, s, _) =
+  fprintf fmt "#include \"%s_alloc.h\"@," s
+
+let print_extern_alloc_prototypes fmt (_,_, header) =
+  List.iter (fun decl -> match decl.top_decl_desc with
+  | ImportedNode ind when not ind.nodei_stateless ->
+    let static = List.filter (fun v -> v.var_dec_const) ind.nodei_inputs
+    in fprintf fmt "extern %a;@." print_alloc_prototype (ind.nodei_id, static)
+  | _                -> ()
+  ) header
+
 (* Local Variables: *)
 (* compile-command:"make -C ../../.." *)
 (* End: *)
diff --git a/src/backends/C/c_backend_header.ml b/src/backends/C/c_backend_header.ml
index 1147e9a93d7a2223d01b6f87d5ec827136f76e9b..3a7d50d1d1a2ab7365c8ca25234d137de556b514 100644
--- a/src/backends/C/c_backend_header.ml
+++ b/src/backends/C/c_backend_header.ml
@@ -36,30 +36,6 @@ struct
 let print_import_standard fmt =
   fprintf fmt "#include \"%s/include/lustrec/arrow.h\"@.@." Version.prefix
 
-    
-let pp_registers_struct fmt m =
-  if m.mmemory <> []
-  then
-    fprintf fmt "@[%a {@[%a; @]}@] _reg; "
-      pp_machine_regtype_name m.mname.node_id
-      (Utils.fprintf_list ~sep:"; " pp_c_decl_struct_var) m.mmemory
-  else
-    ()
-
-let print_machine_struct fmt m =
-  if fst (get_stateless_status m) then
-    begin
-    end
-  else
-    begin
-      (* Define struct *)
-      fprintf fmt "@[%a {@[%a%a%t@]};@]@."
-	pp_machine_memtype_name m.mname.node_id
-	pp_registers_struct m
-	(Utils.fprintf_list ~sep:"; " pp_c_decl_instance_var) m.minstances
-	(Utils.pp_final_char_if_non_empty "; " m.minstances)
-    end
-
 let print_static_declare_instance attr fmt (i, (m, static)) =
   fprintf fmt "%a(%s, %a%t%s)"
     pp_machine_static_declare_name (node_name m)
@@ -161,15 +137,54 @@ let print_machine_decl fmt m =
 	(m.mname.node_id, m.mstep.step_inputs, m.mstep.step_outputs)
     end
 
+let print_machine_alloc_decl fmt m =
+  Mod.print_machine_decl_prefix fmt m;
+  if fst (get_stateless_status m) then
+    begin
+    end
+  else
+    begin
+      if !Options.static_mem
+      then
+	begin
+	  (* Static allocation *)
+	  fprintf fmt "%a@.%a@.%a@."
+		  print_static_declare_macro m
+		  print_static_link_macro m
+		  print_static_alloc_macro m
+	end
+      else
+	begin 
+          (* Dynamic allocation *)
+	  fprintf fmt "extern %a;@."
+		  print_alloc_prototype (m.mname.node_id, m.mstatic)
+	end
+    end
+
+let print_machine_decl_from_header fmt inode =
+  (*Mod.print_machine_decl_prefix fmt m;*)
+  if inode.nodei_stateless then
+    begin
+      fprintf fmt "extern %a;@.@."
+	print_stateless_prototype
+	(inode.nodei_id, inode.nodei_inputs, inode.nodei_outputs)
+    end
+  else
+    begin
+      let static_inputs = List.filter (fun v -> v.var_dec_const) inode.nodei_inputs in
+      let self = mk_new_name (inode.nodei_inputs@inode.nodei_outputs) "self" in
+      fprintf fmt "extern %a;@.@."
+	(print_reset_prototype self) (inode.nodei_id, static_inputs);
+
+      fprintf fmt "extern %a;@.@."
+	(print_step_prototype self)
+	(inode.nodei_id, inode.nodei_inputs, inode.nodei_outputs)
+    end
+
 let print_const_decl fmt cdecl =
   fprintf fmt "extern %a;@." 
     (pp_c_type cdecl.const_id) cdecl.const_type
 
-(********************************************************************************************)
-(*                      Struct/TypeDef Printing functions                                   *)
-(********************************************************************************************)
-
-
 let rec pp_c_struct_type_field filename cpt fmt (label, tdesc) =
   fprintf fmt "%a;" (pp_c_type_decl filename cpt label) tdesc
 and pp_c_type_decl filename cpt var fmt tdecl =
@@ -195,49 +210,143 @@ and pp_c_type_decl filename cpt var fmt tdecl =
 
 let print_type_definitions fmt filename =
   let cpt_type = ref 0 in
-  Hashtbl.iter (fun typ def ->
-    match typ with
-    | Tydec_const var ->
-      fprintf fmt "typedef %a;@.@."
-	(pp_c_type_decl filename cpt_type var) def
-    | _        -> ()) type_table
+  Hashtbl.iter (fun typ decl ->
+		match typ with
+		| Tydec_const var ->
+		   (match decl.top_decl_desc with
+		    | TypeDef tdef ->
+		       fprintf fmt "typedef %a;@.@."
+			       (pp_c_type_decl filename cpt_type var) tdef.tydef_desc
+		    | _ -> assert false)
+		| _        -> ()) type_table
+
+let reset_type_definitions, print_type_definition_from_header =
+  let cpt_type =ref 0 in
+  ((fun () -> cpt_type := 0),
+   (fun fmt typ filename ->
+    fprintf fmt "typedef %a;@.@."
+	(pp_c_type_decl filename cpt_type typ.tydef_id) typ.tydef_desc))
 
 (********************************************************************************************)
 (*                         MAIN Header Printing functions                                   *)
 (********************************************************************************************)
-let print_header header_fmt basename prog machines =
+let print_header header_fmt basename prog machines dependencies =
   (* Include once: start *)
   let baseNAME = String.uppercase basename in
   let baseNAME = Str.global_replace (Str.regexp "\\.\\|\\ ") "_" baseNAME in
-  (* Print the svn version number and the supported C standard (C90 or C99) *)
-  print_version header_fmt;
-  fprintf header_fmt "#ifndef _%s@.#define _%s@." baseNAME baseNAME;
-  pp_print_newline header_fmt ();
-  fprintf header_fmt "/* Imports standard library */@.";
-  (* imports standard library definitions (arrow) *)
-  print_import_standard header_fmt;
-  pp_print_newline header_fmt ();
-  fprintf header_fmt "/* Types definitions */@.";
-  (* Print the type definitions from the type table *)
-  print_type_definitions header_fmt basename;
-  pp_print_newline header_fmt ();
-  (* Print the global constant declarations. *)
-  fprintf header_fmt "/* Global constant (declarations, definitions are in C file) */@.";
-  List.iter (fun c -> print_const_decl header_fmt c) (get_consts prog);
-  pp_print_newline header_fmt ();
-  (* Print the struct declarations of all machines. *)
-  fprintf header_fmt "/* Struct declarations */@.";
-  List.iter (print_machine_struct header_fmt) machines;
-  pp_print_newline header_fmt ();
-  (* Print the prototypes of all machines *)
-  fprintf header_fmt "/* Nodes declarations */@.";
-  List.iter (print_machine_decl header_fmt) machines;
-  pp_print_newline header_fmt ();
-  (* Include once: end *)
-  fprintf header_fmt "#endif@.";
-  pp_print_newline header_fmt ()
-end
+  begin
+    (* Print the svn version number and the supported C standard (C90 or C99) *)
+    print_version header_fmt;
+    fprintf header_fmt "#ifndef _%s@.#define _%s@." baseNAME baseNAME;
+    pp_print_newline header_fmt ();
+    fprintf header_fmt "/* Imports standard library */@.";
+    (* imports standard library definitions (arrow) *)
+    print_import_standard header_fmt;
+    pp_print_newline header_fmt ();
+    (* imports dependencies *)
+    fprintf header_fmt "/* Import Dependencies */@.";
+    fprintf header_fmt "@[<v>";
+    List.iter (print_import_prototype header_fmt) dependencies;
+    fprintf header_fmt "@]@.";
+    fprintf header_fmt "/* Types definitions */@.";
+    (* Print the type definitions from the type table *)
+    print_type_definitions header_fmt basename;
+    pp_print_newline header_fmt ();
+    (* Print the global constant declarations. *)
+    fprintf header_fmt "/* Global constant (declarations, definitions are in C file) */@.";
+    List.iter (fun c -> print_const_decl header_fmt (const_of_top c)) (get_consts prog);
+    pp_print_newline header_fmt ();
+    (* Print the struct declarations of all machines. *)
+    fprintf header_fmt "/* Struct declarations */@.";
+    List.iter (print_machine_struct header_fmt) machines;
+    pp_print_newline header_fmt ();
+    (* Print the prototypes of all machines *)
+    fprintf header_fmt "/* Nodes declarations */@.";
+    List.iter (print_machine_decl header_fmt) machines;
+    pp_print_newline header_fmt ();
+    (* Include once: end *)
+    fprintf header_fmt "#endif@.";
+    pp_print_newline header_fmt ()
+  end
+
+let print_alloc_header header_fmt basename prog machines dependencies =
+  (* Include once: start *)
+  let baseNAME = String.uppercase basename in
+  let baseNAME = Str.global_replace (Str.regexp "\\.\\|\\ ") "_" baseNAME in
+  begin
+    (* Print the svn version number and the supported C standard (C90 or C99) *)
+    print_version header_fmt;
+    fprintf header_fmt "#ifndef _%s_alloc@.#define _%s_alloc@." baseNAME baseNAME;
+    pp_print_newline header_fmt ();
+    (* Import the header *)
+    fprintf header_fmt "/* Import header from %s */@." basename;
+    fprintf header_fmt "@[<v>";
+    print_import_prototype header_fmt (true, basename, []);
+    fprintf header_fmt "@]@.";
+    fprintf header_fmt "/* Import dependencies */@.";
+    fprintf header_fmt "@[<v>";
+    List.iter (print_import_alloc_prototype header_fmt) dependencies;
+    fprintf header_fmt "@]@.";
+    (* Print the struct definitions of all machines. *)
+    fprintf header_fmt "/* Struct definitions */@.";
+    List.iter (print_machine_struct header_fmt) machines;
+    pp_print_newline header_fmt ();
+    (* Print the prototypes of all machines *)
+    fprintf header_fmt "/* Node allocation function/macro prototypes */@.";
+    List.iter (print_machine_alloc_decl header_fmt) machines;
+    pp_print_newline header_fmt ();
+    (* Include once: end *)
+    fprintf header_fmt "#endif@.";
+    pp_print_newline header_fmt ()
+  end
 
+let print_header_from_header header_fmt basename header =
+  (* Include once: start *)
+  let baseNAME = String.uppercase basename in
+  let baseNAME = Str.global_replace (Str.regexp "\\.\\|\\ ") "_" baseNAME in
+  let types = get_typedefs header in
+  let consts = get_consts header in
+  let nodes = get_imported_nodes header in
+  let dependencies = get_dependencies header in
+  begin
+    (* Print the svn version number and the supported C standard (C90 or C99) *)
+    print_version header_fmt;
+    fprintf header_fmt "#ifndef _%s@.#define _%s@." baseNAME baseNAME;
+    pp_print_newline header_fmt ();
+    fprintf header_fmt "/* Imports standard library */@.";
+    (* imports standard library definitions (arrow) *)
+    print_import_standard header_fmt;
+    pp_print_newline header_fmt ();
+    (* imports dependencies *)
+    fprintf header_fmt "/* Import dependencies */@.";
+    fprintf header_fmt "@[<v>";
+    List.iter
+      (fun dep -> let (local, s) = dependency_of_top dep in print_import_prototype header_fmt (local, s, []))
+      dependencies;
+    fprintf header_fmt "@]@.";
+    fprintf header_fmt "/* Types definitions */@.";
+    (* Print the type definitions from the type table *)
+    reset_type_definitions ();
+    List.iter (fun typ -> print_type_definition_from_header header_fmt (typedef_of_top typ) basename) types;
+    pp_print_newline header_fmt ();
+    (* Print the global constant declarations. *)
+    fprintf header_fmt "/* Global constant (declarations, definitions are in C file) */@.";
+    List.iter (fun c -> print_const_decl header_fmt (const_of_top c)) consts;
+    pp_print_newline header_fmt ();
+    (* Print the struct declarations of all machines. *)
+    fprintf header_fmt "/* Struct declarations */@.";
+    List.iter (fun node -> print_machine_struct_from_header header_fmt (imported_node_of_top node)) nodes;
+    pp_print_newline header_fmt ();
+    (* Print the prototypes of all machines *)
+    fprintf header_fmt "/* Nodes declarations */@.";
+    List.iter (fun node -> print_machine_decl_from_header header_fmt (imported_node_of_top node)) nodes;
+    pp_print_newline header_fmt ();
+    (* Include once: end *)
+    fprintf header_fmt "#endif@.";
+    pp_print_newline header_fmt ()
+  end
+
+end
 (* Local Variables: *)
 (* compile-command:"make -C ../../.." *)
 (* End: *)
diff --git a/src/backends/C/c_backend_main.ml b/src/backends/C/c_backend_main.ml
index 2dde47a13702ff6b08c0ab2618d1f2f17e0e4cd3..66790707e89f27025f47c6922f8fa7a856317068 100644
--- a/src/backends/C/c_backend_main.ml
+++ b/src/backends/C/c_backend_main.ml
@@ -112,7 +112,10 @@ let print_main_header fmt =
 
 let print_main_c main_fmt main_machine basename prog machines dependencies =
   print_main_header main_fmt;
-  fprintf main_fmt "#include <stdlib.h>@.#include <assert.h>@.#include \"%s\"@.@." (basename^".h");
+  fprintf main_fmt "#include <stdlib.h>@.#include <assert.h>@.";
+  print_import_alloc_prototype main_fmt (true, basename, []);
+  pp_print_newline main_fmt ();
+
   (* Print the svn version number and the supported C standard (C90 or C99) *)
   print_version main_fmt;
   print_main_fun machines main_machine main_fmt
diff --git a/src/backends/C/c_backend_makefile.ml b/src/backends/C/c_backend_makefile.ml
index a4882e580effdcae666e4024ff566331b604cbe1..c0d6f76ad6bc77fc1c99e2b62291559554ca7e8e 100644
--- a/src/backends/C/c_backend_makefile.ml
+++ b/src/backends/C/c_backend_makefile.ml
@@ -17,7 +17,7 @@ let header_has_code header =
   List.exists 
     (fun top -> 
       match top.top_decl_desc with
-      | Consts _ -> true 
+      | Const _ -> true 
       | ImportedNode nd -> nd.nodei_in_lib = None
       | _ -> false
     )
@@ -46,13 +46,13 @@ let fprintf_dependencies fmt dep =
     fprintf fmt "\t${GCC} -I${INC} -c %s@." s)
     (("${INC}/io_frontend.c"):: (* IO functions when a main function is computed *)
 	(List.map 
-	   (fun (s, local, _) -> 
+	   (fun (local, s, _) -> 
 	     (if local then s else Version.prefix ^ "/include/lustrec/" ^ s) ^ ".c")
 	   compiled_dep))
 
 module type MODIFIERS_MKF =
 sig
-  val other_targets: Format.formatter -> string -> string -> (string * bool * top_decl list) list -> unit
+  val other_targets: Format.formatter -> string -> string -> (bool * string * top_decl list) list -> unit
 end
 
 module EmptyMod =
@@ -77,7 +77,7 @@ let print_makefile basename nodename dependencies fmt =
   fprintf fmt "\t${GCC} -I${INC} -I. -c %s_main.c@." basename;   
   fprintf_dependencies fmt dependencies;    
   fprintf fmt "\t${GCC} -o %s_%s io_frontend.o %a %s.o %s_main.o %a@." basename nodename 
-    (Utils.fprintf_list ~sep:" " (fun fmt (s, _, _) -> Format.fprintf fmt "%s.o" s)) (compiled_dependencies dependencies)
+    (Utils.fprintf_list ~sep:" " (fun fmt (_, s, _) -> Format.fprintf fmt "%s.o" s)) (compiled_dependencies dependencies)
     basename (* library .o *)
     basename (* main function . o *) 
     (Utils.fprintf_list ~sep:" " (fun fmt lib -> fprintf fmt "-l%s" lib)) (lib_dependencies dependencies)
diff --git a/src/backends/C/c_backend_spec.ml b/src/backends/C/c_backend_spec.ml
index e03f535bedde4a336df057a117e062b490efd553..52881a526539f1bd324bc3fba02be13e845398be 100644
--- a/src/backends/C/c_backend_spec.ml
+++ b/src/backends/C/c_backend_spec.ml
@@ -158,7 +158,7 @@ let makefile_targets fmt basename nodename dependencies =
   C_backend_makefile.fprintf_dependencies fmt dependencies; 
   fprintf fmt "\t${GCC} -Wno-attributes -o %s_main_eacsl io_frontend.o %a %s %s_main_eacsl.o %a@." 
     basename 
-    (Utils.fprintf_list ~sep:" " (fun fmt (s, _, _) -> Format.fprintf fmt "%s.o" s)) 
+    (Utils.fprintf_list ~sep:" " (fun fmt (_, s, _) -> Format.fprintf fmt "%s.o" s)) 
     (C_backend_makefile.compiled_dependencies dependencies)
     ("${FRAMACEACSL}/e_acsl.c " 
      ^ "${FRAMACEACSL}/memory_model/e_acsl_bittree.c " 
diff --git a/src/backends/C/c_backend_src.ml b/src/backends/C/c_backend_src.ml
index 02e213724f5b78b197a9fbf2079a5a8a684d1356..6857a54965a542e83426e29df32abea7e9593110 100644
--- a/src/backends/C/c_backend_src.ml
+++ b/src/backends/C/c_backend_src.ml
@@ -259,7 +259,7 @@ let print_alloc_code fmt m =
 
 let print_stateless_code dependencies fmt m =
   let self = "__ERROR__" in
-  if not (!Options.ansi && is_generic_node { top_decl_desc = Node m.mname; top_decl_loc = Location.dummy_loc })
+  if not (!Options.ansi && is_generic_node { top_decl_desc = Node m.mname; top_decl_loc = Location.dummy_loc; top_decl_owner = ""; top_decl_itf = false })
   then
     (* C99 code *)
     fprintf fmt "@[<v 2>%a {@,%a%t@,%a%a%t%t@]@,}@.@."
@@ -296,7 +296,7 @@ let print_reset_code dependencies fmt m self =
     (Utils.pp_newline_if_non_empty m.minit)
 
 let print_step_code dependencies fmt m self =
-  if not (!Options.ansi && is_generic_node { top_decl_desc = Node m.mname; top_decl_loc = Location.dummy_loc })
+  if not (!Options.ansi && is_generic_node { top_decl_desc = Node m.mname; top_decl_loc = Location.dummy_loc; top_decl_owner = ""; top_decl_itf = false })
   then
     (* C99 code *)
     let array_mems = List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory in
@@ -345,11 +345,11 @@ let print_machine dependencies fmt m =
     begin
       (* Alloc function, only if non static mode *)
       if (not !Options.static_mem) then  
-	(
+	begin
 	  fprintf fmt "@[<v 2>%a {@,%a@]@,}@.@."
 	    print_alloc_prototype (m.mname.node_id, m.mstatic)
 	    print_alloc_code m;
-	);
+	end;
       let self = mk_self m in
       (* Reset function *)
       print_reset_code dependencies fmt m self;
@@ -360,17 +360,41 @@ let print_machine dependencies fmt m =
 
 let print_lib_c source_fmt basename prog machines dependencies =
 
-  fprintf source_fmt "#include <stdlib.h>@.#include <assert.h>@.#include \"%s\"@.@." (basename^".h");
+  fprintf source_fmt "#include <assert.h>@.";
+  if not !Options.static_mem then
+    begin
+      fprintf source_fmt "#include <stdlib.h>@.";
+    end;
+  print_import_prototype source_fmt (true, basename, []);
+  pp_print_newline source_fmt ();
   (* Print the svn version number and the supported C standard (C90 or C99) *)
   print_version source_fmt;
   (* Print the prototype of imported nodes *)
-  fprintf source_fmt "/* Imported nodes declarations */@.";
+  fprintf source_fmt "/* Import dependencies */@.";
   fprintf source_fmt "@[<v>";
   List.iter (print_import_prototype source_fmt) dependencies;
   fprintf source_fmt "@]@.";
   (* Print consts *)
   fprintf source_fmt "/* Global constants (definitions) */@.";
-  List.iter (fun c -> print_const_def source_fmt c) (get_consts prog);
+  fprintf source_fmt "@[<v>";
+  List.iter (fun c -> print_const_def source_fmt (const_of_top c)) (get_consts prog);
+  fprintf source_fmt "@]@.";
+  if not !Options.static_mem then
+    begin
+      fprintf source_fmt "/* External allocation function prototypes */@.";
+      fprintf source_fmt "@[<v>";
+      List.iter (print_extern_alloc_prototypes source_fmt) dependencies;
+      fprintf source_fmt "@]@.";
+      fprintf source_fmt "/* Node allocation function prototypes */@.";
+      fprintf source_fmt "@[<v>";
+      List.iter (fun m -> fprintf source_fmt "%a;@." print_alloc_prototype (m.mname.node_id, m.mstatic)) machines;
+      fprintf source_fmt "@]@.";
+    end;
+  (* Print the struct definitions of all machines. *)
+  fprintf source_fmt "/* Struct definitions */@.";
+  fprintf source_fmt "@[<v>";
+  List.iter (print_machine_struct source_fmt) machines;
+  fprintf source_fmt "@]@.";
   pp_print_newline source_fmt ();
   (* Print nodes one by one (in the previous order) *)
   List.iter (print_machine dependencies source_fmt) machines;
diff --git a/src/basic_library.ml b/src/basic_library.ml
index 02dde4e6f81c1b16256eb992eafb623a7b775d5f..080e4c4e61d8ce73f7c7e711350fc67b54fb6e2b 100644
--- a/src/basic_library.ml
+++ b/src/basic_library.ml
@@ -27,7 +27,9 @@ let type_env =
     (fun env (op, op_type) -> TE.add_value env op op_type)
     TE.initial
     [
-       "+", (static_op type_bin_poly_op);
+      "true", (static_op type_bool);
+      "false", (static_op type_bool);
+      "+", (static_op type_bin_poly_op);
       "uminus", (static_op type_unary_poly_op); 
       "-", (static_op type_bin_poly_op); 
       "*", (static_op type_bin_poly_op);
@@ -51,9 +53,12 @@ module CE = Env
 
 let clock_env =
   let init_env = CE.initial in
+  let env' =
+    List.fold_right (fun op env -> CE.add_value env op ck_nullary_univ)
+      ["true"; "false"] init_env in
   let env' = 
     List.fold_right (fun op env -> CE.add_value env op ck_unary_univ)
-      ["uminus"; "not"] init_env in
+      ["uminus"; "not"] env' in
   let env' = 
     List.fold_right (fun op env -> CE.add_value env op ck_bin_univ)
       ["+"; "-"; "*"; "/"; "mod"; "&&"; "||"; "xor"; "equi"; "impl"; "<"; "<="; ">"; ">="; "!="; "="] env' in
@@ -63,9 +68,12 @@ module DE = Env
 
 let delay_env =
   let init_env = DE.initial in
-  let env' = 
+  let env' =
+    List.fold_right (fun op env -> DE.add_value env op delay_nullary_poly_op)
+      ["true"; "false"] init_env in
+  let env' =
     List.fold_right (fun op env -> DE.add_value env op delay_unary_poly_op)
-      ["uminus"; "not"] init_env in
+      ["uminus"; "not"] env' in
   let env' = 
     List.fold_right (fun op env -> DE.add_value env op delay_binary_poly_op)
       ["+"; "-"; "*"; "/"; "mod"; "&&"; "||"; "xor"; "equi"; "impl"; "<"; "<="; ">"; ">="; "!="; "="] env' in
diff --git a/src/clock_calculus.ml b/src/clock_calculus.ml
index 45e129b8ea132752b030c32685878f5caff61298..42556941af442772c112855714a2734680739665 100755
--- a/src/clock_calculus.ml
+++ b/src/clock_calculus.ml
@@ -832,25 +832,27 @@ let clock_imported_node env loc nd =
   nd.nodei_clock <- ck_node;
   Env.add_value env nd.nodei_id ck_node
 
-let clock_top_consts env clist =
-  List.fold_left (fun env cdecl ->
-    let ck = new_var false in
-    try_generalize ck cdecl.const_loc;
-    Env.add_value env cdecl.const_id ck) env clist
+let clock_top_const env cdecl=
+  let ck = new_var false in
+  try_generalize ck cdecl.const_loc;
+  Env.add_value env cdecl.const_id ck
 
-let clock_top_decl env decl =
+let clock_top_consts env clist =
+  List.fold_left clock_top_const env clist
+ 
+let rec clock_top_decl env decl =
   match decl.top_decl_desc with
   | Node nd ->
     clock_node env decl.top_decl_loc nd
   | ImportedNode nd ->
     clock_imported_node env decl.top_decl_loc nd
-  | Consts clist ->
-    clock_top_consts env clist
-  | Open _
-  | Type _ -> env
+  | Const c ->
+    clock_top_const env c
+  | TypeDef _ -> List.fold_left clock_top_decl env (consts_of_enum_type decl)
+  | Open _    -> env
 
 let clock_prog env decls =
-  List.fold_left (fun e decl -> clock_top_decl e decl) env decls
+  List.fold_left clock_top_decl env decls
 
 (* Once the Lustre program is fully clocked,
    we must get back to the original description of clocks,
@@ -878,9 +880,9 @@ let uneval_top_generics decl =
       uneval_node_generics (nd.node_inputs @ nd.node_locals @ nd.node_outputs)
   | ImportedNode nd ->
       uneval_node_generics (nd.nodei_inputs @ nd.nodei_outputs)
-  | Consts _
+  | Const _
   | Open _
-  | Type _   -> ()
+  | TypeDef _ -> ()
 
 let uneval_prog_generics prog =
  List.iter uneval_top_generics prog
diff --git a/src/clock_predef.ml b/src/clock_predef.ml
index 155dba080c949b93bbcc6d3deb51dbf8981ab7f8..7c1a0a5d790ad3f06d94e955fbeaa6482f4909b1 100644
--- a/src/clock_predef.ml
+++ b/src/clock_predef.ml
@@ -22,6 +22,10 @@ let ck_ite =
   let univ = new_univar () in
   new_ck (Carrow (new_ck (Ctuple [univ;univ;univ]) true, univ)) true
 
+let ck_nullary_univ =
+  let univ = new_univar () in
+  univ
+
 let ck_unary_univ =
   let univ = new_univar () in
   new_ck (Carrow (univ, univ)) true
diff --git a/src/compiler_common.ml b/src/compiler_common.ml
new file mode 100644
index 0000000000000000000000000000000000000000..5318993d63cbf7b0d17ca2484c80c364d7ca70ea
--- /dev/null
+++ b/src/compiler_common.ml
@@ -0,0 +1,214 @@
+(********************************************************************)
+(*                                                                  *)
+(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
+(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
+(*                                                                  *)
+(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
+(*  under the terms of the GNU Lesser General Public License        *)
+(*  version 2.1.                                                    *)
+(*                                                                  *)
+(********************************************************************)
+
+open Utils
+open Format 
+open LustreSpec
+open Corelang
+
+let create_dest_dir () =
+  begin
+    if not (Sys.file_exists !Options.dest_dir) then
+      begin
+	Log.report ~level:1 (fun fmt -> fprintf fmt ".. creating destination directory@,");
+	Unix.mkdir !Options.dest_dir (Unix.stat ".").Unix.st_perm
+      end;
+    if (Unix.stat !Options.dest_dir).Unix.st_kind <> Unix.S_DIR then
+      begin
+	eprintf "Failure: destination %s is not a directory.@.@." !Options.dest_dir;
+	exit 1
+      end
+  end
+
+(* Loading Lusi file and filling type tables with parsed
+   functions/nodes *)
+let parse_header own filename =
+  Location.set_input filename;
+  let h_in = open_in filename in
+  let lexbuf = Lexing.from_channel h_in in
+  Location.init lexbuf filename;
+  (* Parsing *)
+  Log.report ~level:1 (fun fmt -> fprintf fmt ".. parsing header file %s@ " filename);
+    try
+      let header = Parse.header Parser_lustre.header Lexer_lustre.token lexbuf in
+      ignore (Modules.load_header ISet.empty header);
+      close_in h_in;
+      header
+    with
+    | (Lexer_lustre.Error err) | (Parse.Syntax_err err) as exc -> 
+      Parse.report_error err;
+      raise exc
+    | Corelang.Error (loc, err) as exc -> (
+      eprintf "Parsing error: %a%a@."
+	Corelang.pp_error err
+	Location.pp_loc loc;
+      raise exc
+    )
+
+let parse_source source_name =
+  (* Loading the input file *)
+  Location.set_input source_name;
+  let s_in = open_in source_name in
+  let lexbuf = Lexing.from_channel s_in in
+  Location.init lexbuf source_name;
+
+  (* Parsing *)
+  Log.report ~level:1 
+    (fun fmt -> fprintf fmt ".. parsing source file %s@," source_name);
+  try
+    let prog = Parse.prog Parser_lustre.prog Lexer_lustre.token lexbuf in
+    ignore (Modules.load_program ISet.empty prog);
+    close_in s_in;
+    prog
+  with
+  | (Lexer_lustre.Error err) | (Parse.Syntax_err err) as exc -> 
+    Parse.report_error err;
+    raise exc
+  | Corelang.Error (loc, err) as exc ->
+    eprintf "Parsing error %a%a@."
+      Corelang.pp_error err
+      Location.pp_loc loc;
+    raise exc
+
+let check_stateless_decls decls =
+  Log.report ~level:1 (fun fmt -> fprintf fmt ".. checking stateless/stateful status@ ");
+  try
+    Stateless.check_prog decls
+  with (Stateless.Error (loc, err)) as exc ->
+    eprintf "Stateless status error %a%a@."
+      Stateless.pp_error err
+      Location.pp_loc loc;
+    raise exc
+
+let type_decls env decls =  
+  Log.report ~level:1 (fun fmt -> fprintf fmt ".. typing@ ");
+  let new_env = 
+    begin
+      try
+	Typing.type_prog env decls
+      with (Types.Error (loc,err)) as exc ->
+	eprintf "Typing error %a%a@."
+	  Types.pp_error err
+	  Location.pp_loc loc;
+	raise exc
+    end 
+  in
+  if !Options.print_types then
+    Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 2>  %a@]@ " Corelang.pp_prog_type decls);
+  new_env
+      
+let clock_decls env decls = 
+  Log.report ~level:1 (fun fmt -> fprintf fmt ".. clock calculus@ ");
+  let new_env =
+    begin
+      try
+	Clock_calculus.clock_prog env decls
+      with (Clocks.Error (loc,err)) as exc ->
+	eprintf "Clock calculus error %a%a@." Clocks.pp_error err Location.pp_loc loc;
+	raise exc
+    end
+  in
+  if !Options.print_clocks then
+    Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 2>  %a@]@ " Corelang.pp_prog_clock decls);
+  new_env
+
+let check_top_decls header =
+  let new_tenv = type_decls Basic_library.type_env header in   (* Typing *)
+  let new_cenv = clock_decls Basic_library.clock_env header in   (* Clock calculus *)
+  header, new_tenv, new_cenv
+
+let get_envs_from_const const_decl (ty_env, ck_env) =
+  (Env.add_value ty_env const_decl.const_id const_decl.const_type,
+   Env.add_value ck_env const_decl.const_id (Clocks.new_var true))
+
+let get_envs_from_consts const_decls (ty_env, ck_env) =
+  List.fold_right get_envs_from_const const_decls (ty_env, ck_env)
+
+let rec get_envs_from_top_decl (ty_env, ck_env) top_decl =
+ match top_decl.top_decl_desc with
+ | Node nd          -> (Env.add_value ty_env nd.node_id nd.node_type,
+			Env.add_value ck_env nd.node_id nd.node_clock)
+ | ImportedNode ind -> (Env.add_value ty_env ind.nodei_id ind.nodei_type,
+			Env.add_value ck_env ind.nodei_id ind.nodei_clock)
+ | Const c          -> get_envs_from_const c (ty_env, ck_env)
+ | TypeDef _        -> List.fold_left get_envs_from_top_decl (ty_env, ck_env) (consts_of_enum_type top_decl)
+ | Open _           -> (ty_env, ck_env)
+
+(* get type and clock environments from a header *)
+let get_envs_from_top_decls header =
+  List.fold_left get_envs_from_top_decl (Env.initial, Env.initial) header
+
+(*
+ List.fold_right
+   (fun top_decl (ty_env, ck_env) ->
+     match top_decl.top_decl_desc with
+     | Node nd          -> (Env.add_value ty_env nd.node_id nd.node_type,
+			    Env.add_value ck_env nd.node_id nd.node_clock)
+     | ImportedNode ind -> (Env.add_value ty_env ind.nodei_id ind.nodei_type,
+			    Env.add_value ck_env ind.nodei_id ind.nodei_clock)
+     | Const c          -> get_envs_from_const c (ty_env, ck_env)
+     | TypeDef _        -> List.fold_left (fun envs top -> consts_of_enum_type top_decl
+     | Open _           -> (ty_env, ck_env))
+   header
+   (Env.initial, Env.initial)
+ *)
+
+let check_compatibility (prog, computed_types_env, computed_clocks_env) (header, declared_types_env, declared_clocks_env) =
+  try
+    (* checking defined types are compatible with declared types*)
+    Typing.check_typedef_compat header;
+
+    (* checking type compatibility with computed types*)
+    Typing.check_env_compat header declared_types_env computed_types_env;
+
+    (* checking clocks compatibility with computed clocks*)
+    Clock_calculus.check_env_compat header declared_clocks_env computed_clocks_env;
+
+    (* checking stateless status compatibility *)
+    Stateless.check_compat header
+  with
+  | (Types.Error (loc,err)) as exc ->
+    eprintf "Type mismatch between computed type and declared type in lustre interface file: %a@."
+      Types.pp_error err;
+    raise exc
+  | Clocks.Error (loc, err) as exc ->
+    eprintf "Clock mismatch between computed clock and declared clock in lustre interface file: %a@."
+      Clocks.pp_error err;
+    raise exc
+  | Stateless.Error (loc, err) as exc ->
+    eprintf "Stateless status mismatch between defined status and declared status in lustre interface file: %a@."
+      Stateless.pp_error err;
+    raise exc
+
+
+
+let import_dependencies prog =
+  Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 2>.. extracting dependencies@,");
+  let dependencies = Corelang.get_dependencies prog in
+  let deps =
+  List.fold_left
+    (fun (compilation_dep, type_env, clock_env) dep ->
+      let (local, s) = Corelang.dependency_of_top dep in
+      let basename = Modules.name_dependency (local, s) in
+      Log.report ~level:1 (fun fmt -> Format.fprintf fmt "@[<v 0>Library %s@," basename);
+      let lusic = Modules.import_dependency dep.top_decl_loc (local, s) in
+      Log.report ~level:1 (fun fmt -> Format.fprintf fmt "@]@ ");
+      let (lusi_type_env, lusi_clock_env) = get_envs_from_top_decls lusic.Lusic.contents in
+      (local, s, lusic.Lusic.contents)::compilation_dep,
+      Env.overwrite type_env lusi_type_env,
+      Env.overwrite clock_env lusi_clock_env)
+    ([], Basic_library.type_env, Basic_library.clock_env)
+    dependencies in
+  begin
+    Log.report ~level:1 (fun fmt -> fprintf fmt "@]@ ");
+    deps
+  end
+
diff --git a/src/corelang.ml b/src/corelang.ml
index f8f0ebb65d52ea4230a263cbb337021ecad04845..16f4e3405b91b03f8fab6e07cd9d95631dbe2f89 100755
--- a/src/corelang.ml
+++ b/src/corelang.ml
@@ -28,8 +28,6 @@ module VSet = Set.Make(VDeclModule)
 
 let dummy_type_dec = {ty_dec_desc=Tydec_any; ty_dec_loc=Location.dummy_loc}
 
-
-
 let dummy_clock_dec = {ck_dec_desc=Ckdec_any; ck_dec_loc=Location.dummy_loc}
 
 
@@ -87,12 +85,46 @@ let mkassert loc expr =
     assert_expr = expr
   }
 
-let mktop_decl loc d =
-  { top_decl_desc = d; top_decl_loc = loc }
+let mktop_decl loc own itf d =
+  { top_decl_desc = d; top_decl_loc = loc; top_decl_owner = own; top_decl_itf = itf }
 
 let mkpredef_call loc funname args =
   mkexpr loc (Expr_appl (funname, mkexpr loc (Expr_tuple args), None))
 
+
+let const_of_top top_decl =
+  match top_decl.top_decl_desc with
+  | Const c -> c
+  | _ -> assert false
+
+let node_of_top top_decl =
+  match top_decl.top_decl_desc with
+  | Node nd -> nd
+  | _ -> assert false
+
+let imported_node_of_top top_decl =
+  match top_decl.top_decl_desc with
+  | ImportedNode ind -> ind
+  | _ -> assert false
+
+let typedef_of_top top_decl =
+  match top_decl.top_decl_desc with
+  | TypeDef tdef -> tdef
+  | _ -> assert false
+
+let dependency_of_top top_decl =
+  match top_decl.top_decl_desc with
+  | Open (local, dep) -> (local, dep)
+  | _ -> assert false
+
+let consts_of_enum_type top_decl =
+  match top_decl.top_decl_desc with
+  | TypeDef tdef ->
+    (match tdef.tydef_desc with
+     | Tydec_enum tags -> List.map (fun tag -> let cdecl = { const_id = tag; const_loc = top_decl.top_decl_loc; const_value = Const_tag tag; const_type = Type_predef.type_const tdef.tydef_id } in { top_decl with top_decl_desc = Const cdecl }) tags
+     | _               -> [])
+  | _ -> assert false
+
 (************************************************************)
 (*   Eexpr functions *)
 (************************************************************)
@@ -142,6 +174,28 @@ let update_expr_annot e annot =
 let (node_table : (ident, top_decl) Hashtbl.t) = Hashtbl.create 30
 let consts_table = Hashtbl.create 30
 
+let print_node_table fmt () =
+  begin
+    Format.fprintf fmt "{ /* node table */@.";
+    Hashtbl.iter (fun id nd ->
+      Format.fprintf fmt "%s |-> %a"
+	id
+	Printers.pp_short_decl nd
+    ) node_table;
+    Format.fprintf fmt "}@."
+  end
+
+let print_consts_table fmt () =
+  begin
+    Format.fprintf fmt "{ /* consts table */@.";
+    Hashtbl.iter (fun id const ->
+      Format.fprintf fmt "%s |-> %a"
+	id
+	Printers.pp_const_decl (const_of_top const)
+    ) consts_table;
+    Format.fprintf fmt "}@."
+  end
+
 let node_name td =
     match td.top_decl_desc with 
     | Node nd         -> nd.node_id
@@ -174,14 +228,31 @@ let is_imported_node td =
 
 
 (* alias and type definition table *)
+
+let top_int_type = mktop_decl Location.dummy_loc Version.prefix false (TypeDef {tydef_id = "int"; tydef_desc = Tydec_int})
+let top_bool_type = mktop_decl Location.dummy_loc Version.prefix false (TypeDef {tydef_id = "bool"; tydef_desc = Tydec_bool})
+let top_float_type = mktop_decl Location.dummy_loc Version.prefix false (TypeDef {tydef_id = "float"; tydef_desc = Tydec_float})
+let top_real_type = mktop_decl Location.dummy_loc Version.prefix false (TypeDef {tydef_id = "real"; tydef_desc = Tydec_real})
+
 let type_table =
   Utils.create_hashtable 20 [
-    Tydec_int  , Tydec_int;
-    Tydec_bool , Tydec_bool;
-    Tydec_float, Tydec_float;
-    Tydec_real , Tydec_real
+    Tydec_int  , top_int_type;
+    Tydec_bool , top_bool_type;
+    Tydec_float, top_float_type;
+    Tydec_real , top_real_type
   ]
 
+let print_type_table fmt () =
+  begin
+    Format.fprintf fmt "{ /* type table */@.";
+    Hashtbl.iter (fun tydec tdef ->
+      Format.fprintf fmt "%a |-> %a"
+	Printers.pp_var_type_dec_desc tydec
+	Printers.pp_typedef (typedef_of_top tdef)
+    ) type_table;
+    Format.fprintf fmt "}@."
+  end
+
 let rec is_user_type typ =
   match typ with
   | Tydec_int | Tydec_bool | Tydec_real 
@@ -190,16 +261,16 @@ let rec is_user_type typ =
   | _ -> true
 
 let get_repr_type typ =
-  let typ_def = Hashtbl.find type_table typ in
+  let typ_def = (typedef_of_top (Hashtbl.find type_table typ)).tydef_desc in
   if is_user_type typ_def then typ else typ_def
 
 let rec coretype_equal ty1 ty2 =
-  (*let res =*) 
+  let res =
   match ty1, ty2 with
   | Tydec_any           , _
   | _                   , Tydec_any             -> assert false
   | Tydec_const _       , Tydec_const _         -> get_repr_type ty1 = get_repr_type ty2
-  | Tydec_const _       , _                     -> let ty1' = Hashtbl.find type_table ty1
+  | Tydec_const _       , _                     -> let ty1' = (typedef_of_top (Hashtbl.find type_table ty1)).tydef_desc
 	       					   in (not (is_user_type ty1')) && coretype_equal ty1' ty2
   | _                   , Tydec_const _         -> coretype_equal ty2 ty1
   | Tydec_int           , Tydec_int
@@ -215,7 +286,7 @@ let rec coretype_equal ty1 ty2 =
       (List.sort (fun (f1,_) (f2,_) -> compare f1 f2) fl1)
       (List.sort (fun (f1,_) (f2,_) -> compare f1 f2) fl2)
   | _                                  -> false
-  (*in (Format.eprintf "coretype_equal %a %a = %B@." Printers.pp_var_type_dec_desc ty1 Printers.pp_var_type_dec_desc ty2 res; res)*)
+  in ((*Format.eprintf "coretype_equal %a %a = %B@." Printers.pp_var_type_dec_desc ty1 Printers.pp_var_type_dec_desc ty2 res;*) res)
 
 let tag_true = "true"
 let tag_false = "false"
@@ -262,8 +333,8 @@ let const_impl c1 c2 =
 (* To guarantee uniqueness of tags in enum types *)
 let tag_table =
   Utils.create_hashtable 20 [
-   tag_true, Tydec_bool;
-   tag_false, Tydec_bool
+   tag_true, top_bool_type;
+   tag_false, top_bool_type
   ]
 
 (* To guarantee uniqueness of fields in struct types *)
@@ -272,16 +343,17 @@ let field_table =
   ]
 
 let get_enum_type_tags cty =
+(*Format.eprintf "get_enum_type_tags %a@." Printers.pp_var_type_dec_desc cty;*)
  match cty with
  | Tydec_bool    -> [tag_true; tag_false]
- | Tydec_const _ -> (match Hashtbl.find type_table cty with
+ | Tydec_const _ -> (match (typedef_of_top (Hashtbl.find type_table cty)).tydef_desc with
                      | Tydec_enum tl -> tl
                      | _             -> assert false)
  | _            -> assert false
 
 let get_struct_type_fields cty =
  match cty with
- | Tydec_const _ -> (match Hashtbl.find type_table cty with
+ | Tydec_const _ -> (match (typedef_of_top (Hashtbl.find type_table cty)).tydef_desc with
                      | Tydec_struct fl -> fl
                      | _               -> assert false)
  | _            -> assert false
@@ -403,25 +475,41 @@ let get_nodes prog =
   List.fold_left (
     fun nodes decl ->
       match decl.top_decl_desc with
-	| Node nd -> nd::nodes
-	| Consts _ | ImportedNode _ | Open _ | Type _ -> nodes  
+	| Node _ -> decl::nodes
+	| Const _ | ImportedNode _ | Open _ | TypeDef _ -> nodes  
   ) [] prog
 
-let get_consts prog = 
+let get_imported_nodes prog = 
   List.fold_left (
-    fun consts decl ->
+    fun nodes decl ->
       match decl.top_decl_desc with
-	| Consts clist -> clist@consts
-	| Node _ | ImportedNode _ | Open _ | Type _ -> consts  
+	| ImportedNode _ -> decl::nodes
+	| Const _ | Node _ | Open _ | TypeDef _-> nodes  
   ) [] prog
 
-let get_types prog = 
-  List.fold_left (
-    fun types decl ->
+let get_consts prog = 
+  List.fold_right (
+    fun decl consts ->
       match decl.top_decl_desc with
-	| Type typ -> typ::types
-	| Node _ | ImportedNode _ | Open _ | Consts _ -> types  
-  ) [] prog
+	| Const _ -> decl::consts
+	| Node _ | ImportedNode _ | Open _ | TypeDef _ -> consts  
+  ) prog []
+
+let get_typedefs prog = 
+  List.fold_right (
+    fun decl types ->
+      match decl.top_decl_desc with
+	| TypeDef _ -> decl::types
+	| Node _ | ImportedNode _ | Open _ | Const _ -> types  
+  ) prog []
+
+let get_dependencies prog =
+  List.fold_right (
+    fun decl deps ->
+      match decl.top_decl_desc with
+	| Open _ -> decl::deps
+	| Node _ | ImportedNode _ | TypeDef _ | Const _ -> deps  
+  ) prog []
 
 let get_node_interface nd =
  {nodei_id = nd.node_id;
@@ -582,11 +670,11 @@ let rename_prog f_node f_var f_const prog =
       (match top.top_decl_desc with
       | Node nd -> 
 	{ top with top_decl_desc = Node (rename_node f_node f_var f_const nd) }
-      | Consts c -> 
-	{ top with top_decl_desc = Consts (List.map (rename_const f_const) c) }
+      | Const c -> 
+	{ top with top_decl_desc = Const (rename_const f_const c) }
       | ImportedNode _
       | Open _
-      | Type _ -> top)
+      | TypeDef _ -> top)
       ::accu
 ) [] prog
   )
@@ -604,7 +692,7 @@ let pp_decl_type fmt tdecl =
     fprintf fmt "%s: " ind.nodei_id;
     Utils.reset_names ();
     fprintf fmt "%a@ " Types.print_ty ind.nodei_type
-  | Consts _ | Open _ | Type _ -> ()
+  | Const _ | Open _ | TypeDef _ -> ()
 
 let pp_prog_type fmt tdecl_list =
   Utils.fprintf_list ~sep:"" pp_decl_type fmt tdecl_list
@@ -619,7 +707,7 @@ let pp_decl_clock fmt cdecl =
     fprintf fmt "%s: " ind.nodei_id;
     Utils.reset_names ();
     fprintf fmt "%a@ " Clocks.print_ck ind.nodei_clock
-  | Consts _ | Open _ | Type _ -> ()
+  | Const _ | Open _ | TypeDef _ -> ()
 
 let pp_prog_clock fmt prog =
   Utils.fprintf_list ~sep:"" pp_decl_clock fmt prog
@@ -642,6 +730,10 @@ let pp_error fmt = function
     fprintf fmt
       "%s is already defined.@."
       sym
+  | Unknown_library sym ->
+    fprintf fmt
+      "impossible to load library %s.@."
+      sym
 
 (* filling node table with internal functions *)
 let vdecls_of_typ_ck cpt ty =
@@ -659,7 +751,7 @@ let mk_internal_node id =
   let (tin, tout) = Types.split_arrow ty in
   (*eprintf "internal fun %s: %d -> %d@." id (List.length (Types.type_list_of_type tin)) (List.length (Types.type_list_of_type tout));*)
   let cpt = ref (-1) in
-  mktop_decl Location.dummy_loc
+  mktop_decl Location.dummy_loc Version.prefix false
     (ImportedNode
        {nodei_id = id;
 	nodei_type = ty;
diff --git a/src/corelang.mli b/src/corelang.mli
index f1f1989198337373c9d13627ef18baf623661d66..1dbf06b67b5d57a8b2b8b589a95733cfe5f6980b 100755
--- a/src/corelang.mli
+++ b/src/corelang.mli
@@ -24,32 +24,37 @@ val var_decl_of_const: const_desc -> var_decl
 val mkexpr: Location.t ->  expr_desc -> expr
 val mkeq: Location.t -> ident list * expr -> eq
 val mkassert: Location.t -> expr -> assert_t
-val mktop_decl: Location.t -> top_decl_desc -> top_decl
+val mktop_decl: Location.t -> ident -> bool -> top_decl_desc -> top_decl
 val mkpredef_call: Location.t -> ident -> expr list -> expr
 val mk_new_name: var_decl list -> ident -> ident
 
 
 val node_table : (ident, top_decl) Hashtbl.t
+val print_node_table:  Format.formatter -> unit -> unit
 val node_name: top_decl -> ident
 val node_inputs: top_decl -> var_decl list
 val node_from_name: ident -> top_decl
 val is_generic_node: top_decl -> bool
 val is_imported_node: top_decl -> bool
 
-val consts_table: (ident, const_desc) Hashtbl.t
-val type_table: (type_dec_desc, type_dec_desc) Hashtbl.t
+val consts_table: (ident, top_decl) Hashtbl.t
+val print_consts_table:  Format.formatter -> unit -> unit
+val type_table: (type_dec_desc, top_decl) Hashtbl.t
+val print_type_table:  Format.formatter -> unit -> unit
 val get_repr_type: type_dec_desc -> type_dec_desc
 val is_user_type: type_dec_desc -> bool
 val coretype_equal: type_dec_desc -> type_dec_desc -> bool
 val tag_true: label
 val tag_false: label
-val tag_table: (label, type_dec_desc) Hashtbl.t
-val field_table: (label, type_dec_desc) Hashtbl.t
+val tag_table: (label, top_decl) Hashtbl.t
+val field_table: (label, top_decl) Hashtbl.t
 
 val get_enum_type_tags: type_dec_desc -> label list
 
 val get_struct_type_fields: type_dec_desc -> (label * type_dec_desc) list
 
+val consts_of_enum_type: top_decl -> top_decl list
+
 val const_of_bool: bool -> constant
 val const_is_bool: constant -> bool
 val const_negation: constant -> constant
@@ -90,8 +95,17 @@ val pp_prog_type : Format.formatter -> program -> unit
 
 val pp_prog_clock : Format.formatter -> program -> unit
 
-val get_nodes : program -> node_desc list
- val get_consts : program -> const_desc list 
+val const_of_top: top_decl -> const_desc
+val node_of_top: top_decl -> node_desc
+val imported_node_of_top: top_decl -> imported_node_desc
+val typedef_of_top: top_decl -> typedef_desc
+val dependency_of_top: top_decl -> (bool * ident)
+
+val get_nodes : program -> top_decl list
+val get_imported_nodes : program -> top_decl list
+val get_consts : program -> top_decl list
+val get_typedefs: program -> top_decl list
+val get_dependencies : program -> top_decl list
 (* val prog_unfold_consts: program -> program *)
 
 val expr_replace_var: (ident -> ident) -> expr -> expr
diff --git a/src/delay_predef.ml b/src/delay_predef.ml
index 9c9051270e39b827d0829620c7d154cb4b3e0430..c03017f39f355f7a3e0070b003049077096a4c5c 100755
--- a/src/delay_predef.ml
+++ b/src/delay_predef.ml
@@ -17,6 +17,10 @@ let delay_zero () = new_univar ()
 let delay_un =
   new_delay Dundef
 
+let delay_nullary_poly_op =
+  let univ = new_univar () in
+  univ
+
 let delay_unary_poly_op =
   let univ = new_univar () in
   new_delay (Darrow (univ, univ))
diff --git a/src/inliner.ml b/src/inliner.ml
index e73b5ce2994cea3092e3cd23cc1feeef457c4043..08640119d1e70d59855cd43be20ec2507dafa64c 100644
--- a/src/inliner.ml
+++ b/src/inliner.ml
@@ -279,7 +279,7 @@ let witness filename main_name orig inlined type_env clock_env =
     node_annot = [];
   }
   in
-  let main = [{ top_decl_desc = Node main_node; top_decl_loc = loc }] in
+  let main = [{ top_decl_desc = Node main_node; top_decl_loc = loc; top_decl_owner = filename; top_decl_itf = false }] in
   let new_prog = others@nodes_origs@nodes_inlined@main in
   let _ = Typing.type_prog type_env new_prog in
   let _ = Clock_calculus.clock_prog clock_env new_prog in
diff --git a/src/lexer_lustre.mll b/src/lexer_lustre.mll
index 02a5255a8ced28229af9b459342cc114521b58da..6fa09b53675bcf7fb9888084e80b7496ab849656 100755
--- a/src/lexer_lustre.mll
+++ b/src/lexer_lustre.mll
@@ -53,6 +53,8 @@ let keyword_table =
   "clock", TCLOCK;
   "not", NOT;
   "tail", TAIL;
+  "true", TRUE;
+  "false", FALSE;
   "and", AND;
   "or", OR;
   "xor", XOR;
@@ -114,12 +116,18 @@ rule token = parse
 | "tel." {TEL}
 | "tel;" {TEL}
 | "#open" { OPEN }
-| ['_' 'a'-'z' 'A'-'Z'] [ '_' 'a'-'z' 'A'-'Z' '0'-'9']*
+| ['_' 'a'-'z'] [ '_' 'a'-'z' 'A'-'Z' '0'-'9']*
     {let s = Lexing.lexeme lexbuf in
     try
       Hashtbl.find keyword_table s
     with Not_found ->
       IDENT s}
+| ['A'-'Z'] [ '_' 'a'-'z' 'A'-'Z' '0'-'9']*
+    {let s = Lexing.lexeme lexbuf in
+    try
+      Hashtbl.find keyword_table s
+    with Not_found ->
+      UIDENT s}
 | "->" {ARROW}
 | "=>" {IMPL}
 | "<=" {LTE}
diff --git a/src/liveness.ml b/src/liveness.ml
index 9fc1dc8da52cbf95ddac2ab6cbbe5b9b7d8bca82..6fae8414f2263c97305cb38d2363b82c8a1441f1 100755
--- a/src/liveness.ml
+++ b/src/liveness.ml
@@ -65,11 +65,6 @@ let compute_unused_variables n g =
     (ISet.union outputs mems)
     (ISet.union inputs mems)
 
-(* checks whether a variable is aliasable,
-   depending on its (address) type *)
-let is_aliasable var =
- Types.is_address_type var.var_type
-
 (* computes the set of potentially reusable variables.
    We don't reuse input variables, due to possible aliasing *)
 let node_reusable_variables node =
diff --git a/src/location.ml b/src/location.ml
index 1dc6919aa3c7a2f40884e59ad8e6a5d02859fec0..31f25234eff0dff31a9706f36cff1b004a90ef79 100755
--- a/src/location.ml
+++ b/src/location.ml
@@ -10,9 +10,17 @@
 (********************************************************************)
 
 type t = { loc_start: Lexing.position; loc_end: Lexing.position }
+
+type filename = string
+
 let dummy_loc = {loc_start=Lexing.dummy_pos; loc_end=Lexing.dummy_pos}
 
-let input_name = ref ""
+let set_input, get_input, get_module =
+  let input_name : filename ref = ref "__UNINITIALIZED__" in
+  let module_name : filename ref = ref "__UNINITIALIZED__" in
+  (fun name -> input_name := name; module_name := Filename.chop_extension name),
+  (fun () -> !input_name),
+  (fun () -> !module_name)
 
 let curr lexbuf = {
   loc_start = lexbuf.Lexing.lex_start_p;
diff --git a/src/lusic.ml b/src/lusic.ml
new file mode 100644
index 0000000000000000000000000000000000000000..951081adbee95ccd053d6c1ecdb259e295953e07
--- /dev/null
+++ b/src/lusic.ml
@@ -0,0 +1,76 @@
+
+(********************************************************************)
+(*                                                                  *)
+(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
+(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
+(*                                                                  *)
+(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
+(*  under the terms of the GNU Lesser General Public License        *)
+(*  version 2.1.                                                    *)
+(*                                                                  *)
+(********************************************************************)
+
+open Format 
+open LustreSpec
+open Corelang
+
+(********************************************************************************************)
+(*                      Lusic to/from Header Printing functions                             *)
+(********************************************************************************************)
+
+type lusic =
+{ from_lusi : bool;
+  contents  : top_decl list;
+}
+
+module HeaderMod = C_backend_header.EmptyMod
+module Header = C_backend_header.Main (HeaderMod)
+
+(* extracts a header from a program representing module own *)
+let extract_header own prog =
+ List.fold_right
+   (fun decl header ->
+     if decl.top_decl_itf || decl.top_decl_owner <> own then header else
+    match decl.top_decl_desc with
+    | Node nd        -> { decl with top_decl_desc = ImportedNode (Corelang.get_node_interface nd) } :: header 
+    | ImportedNode _ -> header
+    | Const _
+    | TypeDef _
+    | Open _         -> decl :: header)
+   prog []
+
+(* encode and write a header in a file *)
+let write_lusic lusi (header : top_decl list) basename extension =
+  let basename' = !Options.dest_dir ^ "/" ^ basename in
+  let target_name = basename' ^ extension in
+  let outchan = open_out_bin target_name in
+  begin
+    Marshal.to_channel outchan {from_lusi = lusi; contents = header} [];
+    close_out outchan
+  end
+
+(* read and decode a header from a file *)
+let read_lusic basename extension =
+  let basename' = !Options.dest_dir ^ "/" ^ basename in
+  let source_name = basename' ^ extension in
+  let inchan = open_in_bin source_name in
+  let lusic = (Marshal.from_channel inchan : lusic) in
+  begin
+    close_in inchan;
+    lusic
+  end
+
+let print_lusic_to_h basename extension =
+  let basename' = !Options.dest_dir ^ "/" ^ basename in
+  let lusic = read_lusic basename extension in
+  let header_name = basename' ^ ".h" in
+  let h_out = open_out header_name in
+  let h_fmt = formatter_of_out_channel h_out in
+  begin
+    Typing.uneval_prog_generics lusic.contents;
+    Clock_calculus.uneval_prog_generics lusic.contents;
+    Header.print_header_from_header h_fmt basename lusic.contents;
+    close_out h_out
+  end
+
+
diff --git a/src/lustreSpec.ml b/src/lustreSpec.ml
index b2497c3e12e1aebeeb9ff220dd0fa9bba4cb8761..67058e71014833109f9b1bbb2d30fed98292452b 100644
--- a/src/lustreSpec.ml
+++ b/src/lustreSpec.ml
@@ -32,10 +32,12 @@ and type_dec_desc =
   | Tydec_struct of (ident * type_dec_desc) list
   | Tydec_array of Dimension.dim_expr * type_dec_desc
 
-type type_def =
-  {
-    ty_def_id: ident;
-    ty_def_desc: type_dec_desc}
+type typedec_desc =
+    {tydec_id: ident}
+
+type typedef_desc =
+    {tydef_id: ident;
+     tydef_desc: type_dec_desc}
 
 type clock_dec =
     {ck_dec_desc: clock_dec_desc;
@@ -99,12 +101,18 @@ and expr_desc =
   | Expr_when of expr * ident * label
   | Expr_merge of ident * (label * expr) list
   | Expr_appl of call_t
- and call_t = ident * expr * (ident * label) option 
+
+and call_t = ident * expr * (ident * label) option 
      (* The third part denotes the reseting clock label and value *)
-and 
+
+and eq =
+    {eq_lhs: ident list;
+     eq_rhs: expr;
+     eq_loc: Location.t}
+
   (* The tag of an expression is a unique identifier used to distinguish
      different instances of the same node *)
-  eexpr =
+and  eexpr =
     {eexpr_tag: tag;
      eexpr_qfexpr: expr;
      eexpr_quantifiers: (quantifier_type * var_decl list) list;
@@ -113,16 +121,9 @@ and
      mutable eexpr_normalized: (var_decl * eq list * var_decl list) option;
      eexpr_loc: Location.t}
 
-and expr_annot = {
-  annots: (string list * eexpr) list;
-  annot_loc: Location.t
-}
-and 
- eq =
-    {eq_lhs: ident list;
-     eq_rhs: expr;
-     eq_loc: Location.t}
-
+and expr_annot =
+ {annots: (string list * eexpr) list;
+  annot_loc: Location.t}
 
 type node_annot = {
   requires: eexpr list;
@@ -136,6 +137,23 @@ type assert_t =
       assert_loc: Location.t;
     } 
 
+type automata_desc =
+  {aut_id : ident;
+   aut_handlers: handler_desc list;
+   aut_loc: Location.t}
+
+and handler_desc =
+  {hand_state: ident;
+   hand_unless: (expr * bool * ident) list;
+   hand_until: (expr * bool * ident) list;
+   hand_locals: var_decl list;
+   hand_eqs: eq list;
+   hand_loc: Location.t}
+
+type statement =
+| Eq of eq
+| Aut of automata_desc
+
 type node_desc =
     {node_id: ident;
      mutable node_type: Types.type_expr;
@@ -174,15 +192,17 @@ type const_desc =
 
 type top_decl_desc =
 | Node of node_desc
-| Consts of const_desc list
+| Const of const_desc
 | ImportedNode of imported_node_desc
 | Open of bool * string (* the boolean set to true denotes a local 
 			   lusi vs a lusi installed at system level *)
-| Type of type_def
+| TypeDef of typedef_desc
 
 type top_decl =
-    {top_decl_desc: top_decl_desc;
-     top_decl_loc: Location.t}
+    {top_decl_desc: top_decl_desc;      (* description of the symbol *)
+     top_decl_owner: Location.filename; (* the module where it is defined *)
+     top_decl_itf: bool;                (* header or source file ? *)
+     top_decl_loc: Location.t}          (* the location where it is defined *)
 
 type program = top_decl list
 
@@ -192,7 +212,7 @@ type error =
   | No_main_specified
   | Unbound_symbol of ident
   | Already_bound_symbol of ident
-
+  | Unknown_library of ident
 
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
diff --git a/src/machine_code.ml b/src/machine_code.ml
index 0e24b49c778322b459cb87b843d570293c49aca5..2b4b4ab4c0d840284622b6194b9c24a79da9e5ed 100644
--- a/src/machine_code.ml
+++ b/src/machine_code.ml
@@ -165,6 +165,8 @@ let arrow_desc =
 let arrow_top_decl =
   {
     top_decl_desc = Node arrow_desc;
+    top_decl_owner = Version.prefix;
+    top_decl_itf = false;
     top_decl_loc = Location.dummy_loc
   }
 
@@ -224,8 +226,12 @@ let translate_ident node (m, si, j, d, s) id =
     if ISet.exists (fun v -> v.var_id = id) m
     then StateVar var_id
     else LocalVar var_id
-  with Not_found -> (* id is a constant *)
-    LocalVar (Corelang.var_decl_of_const (Hashtbl.find Corelang.consts_table id))
+  with Not_found ->
+    try (* id is a constant *)
+      LocalVar (Corelang.var_decl_of_const (const_of_top (Hashtbl.find Corelang.consts_table id)))
+    with Not_found ->
+      (* id is a tag *)
+      Cst (Const_tag id)
 
 let rec control_on_clock node ((m, si, j, d, s) as args) ck inst =
  match (Clocks.repr ck).cdesc with
@@ -446,27 +452,6 @@ let translate_eqs node args eqs =
 let translate_decl nd sch =
   (*Log.report ~level:1 (fun fmt -> Printers.pp_node fmt nd);*)
 
-(*
-  let eqs_rev, remainder = 
-    List.fold_left 
-      (fun (accu, node_eqs_remainder) v -> 
-	  if List.exists (fun eq -> List.mem v eq.eq_lhs) accu
-	  then
-	    (accu, node_eqs_remainder)
-	  else
-	    (*if   List.exists (fun vdecl -> vdecl.var_id = v) nd.node_locals
-	      || List.exists (fun vdecl -> vdecl.var_id = v) nd.node_outputs
-	    then*)
-	      let eq_v, remainder = find_eq v node_eqs_remainder in
-	      eq_v::accu, remainder
-	    (* else it is a constant value, checked during typing phase
-	    else	 
-	      accu, node_eqs_remainder *)
-      ) 
-      ([], split_eqs) 
-      sch 
-  in
- *)
   let sorted_eqs = sort_equations_from_schedule nd sch in
 
   let init_args = ISet.empty, [], Utils.IMap.empty, List.fold_right (fun l -> ISet.add l) nd.node_locals ISet.empty, [] in
@@ -506,7 +491,8 @@ let translate_decl nd sch =
 let translate_prog decls node_schs =
   let nodes = get_nodes decls in 
   List.map 
-    (fun node -> 
+    (fun decl -> 
+     let node = node_of_top decl in
       let sch = (Utils.IMap.find node.node_id node_schs).Scheduling.schedule in
       translate_decl node sch 
     ) nodes
diff --git a/src/main_lustre_compiler.ml b/src/main_lustre_compiler.ml
index e8d491c86d2542839f3f8571a476e167ec70c7e6..9e18d620e7da4b4c1623cd5f24050f6ac7a8df75 100644
--- a/src/main_lustre_compiler.ml
+++ b/src/main_lustre_compiler.ml
@@ -1,445 +1,313 @@
-(********************************************************************)
-(*                                                                  *)
-(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
-(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
-(*                                                                  *)
-(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
-(*  under the terms of the GNU Lesser General Public License        *)
-(*  version 2.1.                                                    *)
-(*                                                                  *)
-(********************************************************************)
-
-open Format
-open Log
-
-open LustreSpec
-
-let usage = "Usage: lustrec [options] <source-file>"
-
-let extensions = [".ec"; ".lus"; ".lusi"]
-
-let check_stateless_decls decls =
-  Log.report ~level:1 (fun fmt -> fprintf fmt ".. checking stateless/stateful status@ ");
-  try
-    Stateless.check_prog decls
-  with (Stateless.Error (loc, err)) as exc ->
-    eprintf "Stateless status error %a%a@."
-      Stateless.pp_error err
-      Location.pp_loc loc;
-    raise exc
-
-let type_decls env decls =  
-  Log.report ~level:1 (fun fmt -> fprintf fmt ".. typing@ ");
-  let new_env = 
-    begin
-      try
-	Typing.type_prog env decls
-      with (Types.Error (loc,err)) as exc ->
-	eprintf "Typing error %a%a@."
-	  Types.pp_error err
-	  Location.pp_loc loc;
-	raise exc
-    end 
-  in
-  if !Options.print_types then
-    Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 2>  %a@]@ " Corelang.pp_prog_type decls);
-  new_env
-      
-let clock_decls env decls = 
-  Log.report ~level:1 (fun fmt -> fprintf fmt ".. clock calculus@ ");
-  let new_env =
-    begin
-      try
-	Clock_calculus.clock_prog env decls
-      with (Clocks.Error (loc,err)) as exc ->
-	eprintf "Clock calculus error %a%a@." Clocks.pp_error err Location.pp_loc loc;
-	raise exc
-    end
-  in
-  if !Options.print_clocks then
-    Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 2>  %a@]@ " Corelang.pp_prog_clock decls);
-  new_env
-
-(* Loading Lusi file and filling type tables with parsed
-   functions/nodes *)
-let load_lusi own filename =
-  Location.input_name := filename;
-  let lexbuf = Lexing.from_channel (open_in filename) in
-  Location.init lexbuf filename;
-  (* Parsing *)
-  Log.report ~level:1 (fun fmt -> fprintf fmt ".. parsing header file %s@ " filename);
-    try
-      Parse.header own Parser_lustre.header Lexer_lustre.token lexbuf
-    with
-    | (Lexer_lustre.Error err) | (Parse.Syntax_err err) as exc -> 
-      Parse.report_error err;
-      raise exc
-    | Corelang.Error (loc, err) as exc -> (
-      eprintf "Parsing error: %a%a@."
-	Corelang.pp_error err
-	Location.pp_loc loc;
-      raise exc
-    )
-
-
-let check_lusi header =
-  let new_tenv = type_decls Basic_library.type_env header in   (* Typing *)
-  let new_cenv = clock_decls Basic_library.clock_env header in   (* Clock calculus *)
-  header, new_tenv, new_cenv
-
-let load_n_check_lusi source_name lusi_name prog computed_types_env computed_clocks_env= 
-  try 
-    let _ = open_in lusi_name in
-    let header = load_lusi true lusi_name in
-    let _, declared_types_env, declared_clocks_env = check_lusi header in
-        
-   (* checking defined types are compatible with declared types*)
-    Typing.check_typedef_compat header;
-
-    (* checking type compatibility with computed types*)
-    Typing.check_env_compat header declared_types_env computed_types_env;
-    Typing.uneval_prog_generics prog;
-    
-    (* checking clocks compatibility with computed clocks*)
-    Clock_calculus.check_env_compat header declared_clocks_env computed_clocks_env;
-    Clock_calculus.uneval_prog_generics prog;
-
-    (* checking stateless status compatibility *)
-    Stateless.check_compat header
-
-    with Sys_error _ -> ( 
-      (* Printing lusi file is necessary *)
-      Log.report ~level:1 
-	(fun fmt -> 
-	  fprintf fmt 
-	    ".. generating lustre interface file %s@," lusi_name);
-      let lusi_out = open_out lusi_name in
-      let lusi_fmt = formatter_of_out_channel lusi_out in
-      Typing.uneval_prog_generics prog;
-      Clock_calculus.uneval_prog_generics prog;
-      Printers.pp_lusi_header lusi_fmt source_name prog
-    )
-    | (Types.Error (loc,err)) as exc ->
-      eprintf "Type mismatch between computed type and declared type in lustre interface file: %a@."
-	Types.pp_error err;
-      raise exc
-    | Clocks.Error (loc, err) as exc ->
-      eprintf "Clock mismatch between computed clock and declared clock in lustre interface file: %a@."
-	Clocks.pp_error err;
-      raise exc
-    | Stateless.Error (loc, err) as exc ->
-      eprintf "Stateless status mismatch between defined status and declared status in lustre interface file: %a@."
-	Stateless.pp_error err;
-      raise exc
-
-let extract_interface prog =
- List.fold_right
-   (fun decl header ->
-    match decl.top_decl_desc with
-    | Node nd        -> { decl with top_decl_desc = ImportedNode (Corelang.get_node_interface nd) } :: header 
-    | ImportedNode _ -> header
-    | Consts _
-    | Type _
-    | Open _         -> decl :: header)
-   prog []
-
-let write_compiled_header (header : top_decl list) basename extension =
-  let target_name = basename^extension in
-  let outchan = open_out_bin target_name in
-  begin
-    Marshal.to_channel outchan header [];
-    close_out outchan
-  end
-
-let read_compiled_header basename extension =
-  let source_name = basename^extension in
-  let inchan = open_in_bin source_name in
-  let header = (Marshal.from_channel inchan : top_decl list) in
-  begin
-    close_in inchan;
-    header
-  end
-
-let compile_header basename extension =
-   let header_name = basename^extension in
-   let header = load_lusi true header_name in
-   begin
-     ignore (check_lusi header);
-     write_compiled_header header basename (extension^"c")
-   end
-
-let compile_prog basename extension =
- ()
-
-let rec compile basename extension =
-
-  (* Loading the input file *)
-  let source_name = basename^extension in
-  Location.input_name := source_name;
-  let lexbuf = Lexing.from_channel (open_in source_name) in
-  Location.init lexbuf source_name;
-
-  (* Parsing *)
-  Log.report ~level:1 
-    (fun fmt -> fprintf fmt "@[<v>.. parsing file %s@," source_name);
-  let prog =
-    try
-      Parse.prog Parser_lustre.prog Lexer_lustre.token lexbuf
-    with
-    | (Lexer_lustre.Error err) | (Parse.Syntax_err err) as exc -> 
-      Parse.report_error err;
-      raise exc
-    | Corelang.Error (loc, err) as exc ->
-      eprintf "Parsing error %a%a@."
-	Corelang.pp_error err
-	Location.pp_loc loc;
-      raise exc
-  in
-
-  (* Extracting dependencies *)
-  Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 2>.. extracting dependencies@,");
-  let dependencies = 
-    List.fold_right 
-      (fun d accu -> match d.top_decl_desc with 
-      | Open (local, s) -> (s, local)::accu 
-      | _ -> accu) 
-      prog [] 
-  in
-  let dependencies, type_env, clock_env =
-    List.fold_left (fun (compilation_dep, type_env, clock_env) (s, local) -> 
-      try
-	let basename = (if local then s else Version.prefix ^ "/include/lustrec/" ^ s ) ^ ".lusi" in 
-	Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 0>Library %s@," basename);
-	let comp_dep, lusi_type_env, lusi_clock_env = check_lusi (load_lusi false basename) in 
-	Log.report ~level:1 (fun fmt -> fprintf fmt "@]@ ");
-	
-	(s, local, comp_dep)::compilation_dep,
-	Env.overwrite type_env lusi_type_env,
-	Env.overwrite clock_env lusi_clock_env      
-      with Sys_error msg -> (
-	eprintf "Failure: impossible to load library %s.@.%s@." s msg;
-	exit 1
-      )
-    )  ([], Basic_library.type_env, Basic_library.clock_env) dependencies
-  in
-  Log.report ~level:1 (fun fmt -> fprintf fmt "@]@ ");
-  
-  (* Sorting nodes *)
-  let prog = SortProg.sort prog in
-
-  (* Typing *)
-  let computed_types_env = type_decls type_env prog in
-  
-  (* Clock calculus *)
-  let computed_clocks_env = clock_decls clock_env prog in
-
-  (* Checking stateless/stateful status *)
-  check_stateless_decls prog;
-
-  (* Perform global inlining *)
-  let prog =
-    if !Options.global_inline && 
-      (match !Options.main_node with | "" -> false | _ -> true) then
-      Inliner.global_inline basename prog type_env clock_env
-    else
-      prog
-  in
-
-  (* Delay calculus *)
-  (*
-    if(!Options.delay_calculus)
-    then
-    begin
-    Log.report ~level:1 (fun fmt -> fprintf fmt ".. initialisation analysis@?");
-    try
-    Delay_calculus.delay_prog Basic_library.delay_env prog
-    with (Delay.Error (loc,err)) as exc ->
-    Location.print loc;
-    eprintf "%a" Delay.pp_error err;
-    Utils.track_exception ();
-    raise exc
-    end;
-  *)
-  (*
-    eprintf "Causality analysis@.@?";
-    (* Causality analysis *)
-    begin
-    try
-    Causality.check_causal_prog prog
-    with (Causality.Cycle v) as exc ->
-    Causality.pp_error err_formatter v;
-    raise exc
-    end;
-  *)
-
-  (* Compatibility with Lusi *)
-  (* Checking the existence of a lusi (Lustre Interface file) *)
-  let lusi_name = basename ^ ".lusi" in
-  load_n_check_lusi source_name lusi_name prog computed_types_env computed_clocks_env;
-
-  (* Computes and stores generic calls for each node,
-     only useful for ANSI C90 compliant generic node compilation *)
-  if !Options.ansi then Causality.NodeDep.compute_generic_calls prog;
-  (*Hashtbl.iter (fun id td -> match td.Corelang.top_decl_desc with Corelang.Node nd -> Format.eprintf "%s calls %a" id Causality.NodeDep.pp_generic_calls nd | _ -> ()) Corelang.node_table;*)
-
-  (* Normalization phase *)
-  Log.report ~level:1 (fun fmt -> fprintf fmt ".. normalization@,");
-  (* Special treatment of arrows in lustre backend. We want to keep them *)
-  if !Options.output = "lustre" then
-    Normalization.unfold_arrow_active := false;
-  let prog = Normalization.normalize_prog prog in
-  Log.report ~level:2 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Printers.pp_prog prog);
-
-  (* Checking array accesses *)
-  if !Options.check then
-    begin
-      Log.report ~level:1 (fun fmt -> fprintf fmt ".. array access checks@,");
-      Access.check_prog prog;
-    end;
-
-  (* Computation of node equation scheduling. It also breaks dependency cycles
-     and warns about unused input or memory variables *)
-  Log.report ~level:1 (fun fmt -> fprintf fmt ".. scheduling@,");
-  let prog, node_schs = Scheduling.schedule_prog prog in
-  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_warning_unused node_schs);
-  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_schedule node_schs);
-  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_fanin_table node_schs);
-  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Printers.pp_prog prog);
-
- (* Optimization of prog: 
-    - Unfold consts 
-    - eliminate trivial expressions
- *)
-  let prog = 
-    if !Options.optimization >= 2 then 
-      Optimize_prog.prog_unfold_consts prog 
-    else
-      prog
-  in
-
-  (* DFS with modular code generation *)
-  Log.report ~level:1 (fun fmt -> fprintf fmt ".. machines generation@,");
-  let machine_code = Machine_code.translate_prog prog node_schs in
-
-  (* Optimize machine code *)
-  let machine_code = 
-    if !Options.optimization >= 3 && !Options.output <> "horn" then
-      begin
-	Log.report ~level:1 (fun fmt -> fprintf fmt ".. machines optimization@,");
-	Optimize_machine.machines_reuse_variables machine_code node_schs
-      end
-    else
-      machine_code
- in  
-  let machine_code = 
-    if !Options.optimization >= 3 && !Options.output <> "horn" then
-      begin
-	Log.report ~level:1 (fun fmt -> fprintf fmt ".. machines optimization@,");
-	Optimize_machine.machines_fusion machine_code
-      end
-    else
-      machine_code
- in
-  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@,"
-  (Utils.fprintf_list ~sep:"@ " Machine_code.pp_machine)
-  machine_code);
-
-  (* Creating destination directory if needed *)
-  if not (Sys.file_exists !Options.dest_dir) then (
-    Log.report ~level:1 (fun fmt -> fprintf fmt ".. creating destination directory@,");
-    Unix.mkdir !Options.dest_dir (Unix.stat ".").Unix.st_perm
-  );
-  if (Unix.stat !Options.dest_dir).Unix.st_kind <> Unix.S_DIR then (
-    eprintf "Failure: destination %s is not a directory.@.@." !Options.dest_dir;
-    exit 1
-  );
-  (* Printing code *)
-  let basename    =  Filename.basename basename in
-  let destname = !Options.dest_dir ^ "/" ^ basename in
-  let _ = match !Options.output with
-      "C" -> 
-	begin
-	  let header_file = destname ^ ".h" in (* Could be changed *)
-	  let source_lib_file = destname ^ ".c" in (* Could be changed *)
-	  let source_main_file = destname ^ "_main.c" in (* Could be changed *)
-	  let makefile_file = destname ^ ".makefile" in (* Could be changed *)
-	  (* let spec_file_opt = if !Options.c_spec then  *)
-	  (*     ( *)
-	  (* 	let spec_file = basename ^ "_spec.c" in *)
-	  (* 	Log.report ~level:1 (fun fmt -> fprintf fmt ".. opening files %s, %s and %s@," header_file source_file spec_file); *)
-	  (* 	Some spec_file  *)
-	  (*     ) else ( *)
-	  (* 	Log.report ~level:1 (fun fmt -> fprintf fmt ".. opening files %s and %s@," header_file source_file); *)
-	  (* 	None  *)
-	  (*      ) *)
-	  (* in  *)
-	  Log.report ~level:1 (fun fmt -> fprintf fmt ".. C code generation@,");
-	  C_backend.translate_to_c 
-	    header_file source_lib_file source_main_file makefile_file
-	    basename prog machine_code dependencies
-	end
-    | "java" ->
-      begin
-	failwith "Sorry, but not yet supported !"
-    (*let source_file = basename ^ ".java" in
-      Log.report ~level:1 (fun fmt -> fprintf fmt ".. opening file %s@,@?" source_file);
-      let source_out = open_out source_file in
-      let source_fmt = formatter_of_out_channel source_out in
-      Log.report ~level:1 (fun fmt -> fprintf fmt ".. java code generation@,@?");
-      Java_backend.translate_to_java source_fmt basename normalized_prog machine_code;*)
-      end
-    | "horn" ->
-      begin
-	let source_file = destname ^ ".smt2" in (* Could be changed *)
-	let source_out = open_out source_file in
-	let fmt = formatter_of_out_channel source_out in
-	Horn_backend.translate fmt basename prog machine_code;
-	(* Tracability file if option is activated *)
-	if !Options.horntraces then (
-	let traces_file = destname ^ ".traces" in (* Could be changed *)
-	let traces_out = open_out traces_file in
-	let fmt = formatter_of_out_channel traces_out in
-	Horn_backend.traces_file fmt basename prog machine_code	  
-	)
-      end
-    | "lustre" -> 
-      begin
-	let source_file = destname ^ ".lustrec.lus" in (* Could be changed *)
-	let source_out = open_out source_file in
-	let fmt = formatter_of_out_channel source_out in
-	Printers.pp_prog fmt prog;
-(*	Lustre_backend.translate fmt basename normalized_prog machine_code *)
-	()
-      end
-
-    | _ -> assert false
-  in
-  begin
-    Log.report ~level:1 (fun fmt -> fprintf fmt ".. done !@ @]@.");
-  (* We stop the process here *)
-    exit 0
-  end
-  
-let anonymous filename =
-  let ok_ext, ext = List.fold_left (fun (ok, ext) ext' -> if not ok && Filename.check_suffix filename ext' then true, ext' else ok, ext) (false, "") extensions in
-  if ok_ext then
-    let basename = Filename.chop_suffix filename ext in
-    compile basename ext
-  else
-    raise (Arg.Bad ("Can only compile *.lusi, *.lus or *.ec files"))
-
-let _ =
-  Corelang.add_internal_funs ();
-  try
-    Printexc.record_backtrace true;
-    Arg.parse Options.options anonymous usage
-  with
-  | Parse.Syntax_err _ | Lexer_lustre.Error _ 
-  | Types.Error (_,_) | Clocks.Error (_,_)
-  | Corelang.Error _ (*| Task_set.Error _*) 
-  | Causality.Cycle _ -> exit 1
-  | exc -> (Utils.track_exception (); raise exc)
-
-(* Local Variables: *)
-(* compile-command:"make -C .." *)
-(* End: *)
+(********************************************************************)
+(*                                                                  *)
+(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
+(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
+(*                                                                  *)
+(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
+(*  under the terms of the GNU Lesser General Public License        *)
+(*  version 2.1.                                                    *)
+(*                                                                  *)
+(********************************************************************)
+
+open Format
+open Log
+
+open LustreSpec
+open Compiler_common
+
+let usage = "Usage: lustrec [options] <source-file>"
+
+let extensions = [".ec"; ".lus"; ".lusi"]
+
+(* print a .lusi header file from a source prog *)
+let print_lusi prog basename extension =
+  let header = Lusic.extract_header basename prog in
+  let header_name = basename ^ extension in
+  let h_out = open_out header_name in
+  let h_fmt = formatter_of_out_channel h_out in
+  begin
+    Printers.pp_lusi_header h_fmt basename header;
+    close_out h_out
+  end
+
+(* compile a .lusi header file *)
+let compile_header basename extension =
+   let header_name = basename ^ extension in
+   let lusic_ext = extension ^ "c" in
+   begin
+     Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v>");
+     let header = parse_header true header_name in
+     ignore (check_top_decls header);
+     create_dest_dir ();
+     Log.report ~level:1 (fun fmt -> fprintf fmt ".. generating compiled header file %sc@," header_name);
+     Lusic.write_lusic true header basename lusic_ext;
+     Lusic.print_lusic_to_h basename lusic_ext;
+     Log.report ~level:1 (fun fmt -> fprintf fmt ".. done !@ @]@.")
+   end
+
+(* check whether a source file has a compiled header,
+   if not, generate the compiled header *)
+let compile_source_to_header prog computed_types_env computed_clocks_env basename extension =
+  let basename' = !Options.dest_dir ^ "/" ^ basename in
+  let lusic_ext = extension ^ "c" in
+  let header_name = basename' ^ lusic_ext in
+  begin
+    if not (Sys.file_exists header_name) then
+      begin
+	Log.report ~level:1 (fun fmt -> fprintf fmt ".. generating compiled header file %s@," header_name);
+	Lusic.write_lusic false (Lusic.extract_header basename prog) basename lusic_ext;
+	Lusic.print_lusic_to_h basename lusic_ext
+      end
+    else
+      let lusic = Lusic.read_lusic basename lusic_ext in
+      if not lusic.Lusic.from_lusi then
+	begin
+	  Log.report ~level:1 (fun fmt -> fprintf fmt ".. generating compiled header file %s@," header_name);
+       	  Lusic.write_lusic false (Lusic.extract_header basename prog) basename lusic_ext;
+(*List.iter (fun top_decl -> Format.eprintf "lusic: %a@." Printers.pp_decl top_decl) lusic.Lusic.contents;*)
+	  Lusic.print_lusic_to_h basename lusic_ext
+	end
+      else
+	begin
+	  Log.report ~level:1 (fun fmt -> fprintf fmt ".. loading compiled header file %s@," header_name);
+	  let header = lusic.Lusic.contents in
+	  let (declared_types_env, declared_clocks_env) = get_envs_from_top_decls header in
+	  check_compatibility
+	    (prog, computed_types_env, computed_clocks_env)
+	    (header, declared_types_env, declared_clocks_env)
+	end
+  end
+
+(* compile a .lus source file *)
+let rec compile_source basename extension =
+  let source_name = basename ^ extension in
+
+  Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v>");
+
+  let prog = parse_source source_name in
+
+  (* Extracting dependencies *)
+  let dependencies, type_env, clock_env = import_dependencies prog in
+ 
+  (* Sorting nodes *)
+  let prog = SortProg.sort prog in
+
+  (* Typing *)
+  let computed_types_env = type_decls type_env prog in
+  
+  (* Clock calculus *)
+  let computed_clocks_env = clock_decls clock_env prog in
+
+  (* Checking stateless/stateful status *)
+  check_stateless_decls prog;
+
+  (* Generating a .lusi header file only *)
+  if !Options.lusi then
+    begin
+      let lusi_ext = extension ^ "i" in
+      Log.report ~level:1 (fun fmt -> fprintf fmt ".. generating interface file %s@," (basename ^ lusi_ext));
+      print_lusi prog basename lusi_ext;
+      Log.report ~level:1 (fun fmt -> fprintf fmt ".. done !@ @]@.");
+      exit 0
+    end;
+
+  (* Perform global inlining *)
+  let prog =
+    if !Options.global_inline && 
+      (match !Options.main_node with | "" -> false | _ -> true) then
+      Inliner.global_inline basename prog type_env clock_env
+    else
+      prog
+  in
+
+  (* Delay calculus *)
+  (*
+    if(!Options.delay_calculus)
+    then
+    begin
+    Log.report ~level:1 (fun fmt -> fprintf fmt ".. initialisation analysis@?");
+    try
+    Delay_calculus.delay_prog Basic_library.delay_env prog
+    with (Delay.Error (loc,err)) as exc ->
+    Location.print loc;
+    eprintf "%a" Delay.pp_error err;
+    Utils.track_exception ();
+    raise exc
+    end;
+  *)
+  (*
+    eprintf "Causality analysis@.@?";
+    (* Causality analysis *)
+    begin
+    try
+    Causality.check_causal_prog prog
+    with (Causality.Cycle v) as exc ->
+    Causality.pp_error err_formatter v;
+    raise exc
+    end;
+  *)
+
+  (* Creating destination directory if needed *)
+  create_dest_dir ();
+
+  (* Compatibility with Lusi *)
+  (* Checking the existence of a lusi (Lustre Interface file) *)
+  let extension = ".lusi" in
+  compile_source_to_header prog computed_types_env computed_clocks_env basename extension;
+
+  Typing.uneval_prog_generics prog;
+  Clock_calculus.uneval_prog_generics prog;
+
+  (* Computes and stores generic calls for each node,
+     only useful for ANSI C90 compliant generic node compilation *)
+  if !Options.ansi then Causality.NodeDep.compute_generic_calls prog;
+  (*Hashtbl.iter (fun id td -> match td.Corelang.top_decl_desc with Corelang.Node nd -> Format.eprintf "%s calls %a" id Causality.NodeDep.pp_generic_calls nd | _ -> ()) Corelang.node_table;*)
+
+  (* Normalization phase *)
+  Log.report ~level:1 (fun fmt -> fprintf fmt ".. normalization@,");
+  (* Special treatment of arrows in lustre backend. We want to keep them *)
+  if !Options.output = "lustre" then
+    Normalization.unfold_arrow_active := false;
+  let prog = Normalization.normalize_prog prog in
+  Log.report ~level:2 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Printers.pp_prog prog);
+
+  (* Checking array accesses *)
+  if !Options.check then
+    begin
+      Log.report ~level:1 (fun fmt -> fprintf fmt ".. array access checks@,");
+      Access.check_prog prog;
+    end;
+
+  (* Computation of node equation scheduling. It also breaks dependency cycles
+     and warns about unused input or memory variables *)
+  Log.report ~level:1 (fun fmt -> fprintf fmt ".. scheduling@,");
+  let prog, node_schs = Scheduling.schedule_prog prog in
+  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_warning_unused node_schs);
+  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_schedule node_schs);
+  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_fanin_table node_schs);
+  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Printers.pp_prog prog);
+
+ (* Optimization of prog: 
+    - Unfold consts 
+    - eliminate trivial expressions
+ *)
+  let prog = 
+    if !Options.optimization >= 2 then 
+      Optimize_prog.prog_unfold_consts prog 
+    else
+      prog
+  in
+
+  (* DFS with modular code generation *)
+  Log.report ~level:1 (fun fmt -> fprintf fmt ".. machines generation@,");
+  let machine_code = Machine_code.translate_prog prog node_schs in
+
+  (* Optimize machine code *)
+  let machine_code = 
+    if !Options.optimization >= 3 && !Options.output <> "horn" then
+      begin
+	Log.report ~level:1 (fun fmt -> fprintf fmt ".. machines optimization@,");
+	Optimize_machine.machines_reuse_variables machine_code node_schs
+      end
+    else
+      machine_code
+ in  
+  let machine_code = 
+    if !Options.optimization >= 3 && !Options.output <> "horn" then
+      begin
+	Optimize_machine.machines_fusion machine_code
+      end
+    else
+      machine_code
+ in
+  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@,"
+  (Utils.fprintf_list ~sep:"@ " Machine_code.pp_machine)
+  machine_code);
+
+  (* Printing code *)
+  let basename    =  Filename.basename basename in
+  let destname = !Options.dest_dir ^ "/" ^ basename in
+  let _ = match !Options.output with
+      "C" -> 
+	begin
+	  let alloc_header_file = destname ^ "_alloc.h" in (* Could be changed *)
+	  let source_lib_file = destname ^ ".c" in (* Could be changed *)
+	  let source_main_file = destname ^ "_main.c" in (* Could be changed *)
+	  let makefile_file = destname ^ ".makefile" in (* Could be changed *)
+	  Log.report ~level:1 (fun fmt -> fprintf fmt ".. C code generation@,");
+	  C_backend.translate_to_c 
+	    alloc_header_file source_lib_file source_main_file makefile_file
+	    basename prog machine_code dependencies
+	end
+    | "java" ->
+      begin
+	failwith "Sorry, but not yet supported !"
+    (*let source_file = basename ^ ".java" in
+      Log.report ~level:1 (fun fmt -> fprintf fmt ".. opening file %s@,@?" source_file);
+      let source_out = open_out source_file in
+      let source_fmt = formatter_of_out_channel source_out in
+      Log.report ~level:1 (fun fmt -> fprintf fmt ".. java code generation@,@?");
+      Java_backend.translate_to_java source_fmt basename normalized_prog machine_code;*)
+      end
+    | "horn" ->
+      begin
+	let source_file = destname ^ ".smt2" in (* Could be changed *)
+	let source_out = open_out source_file in
+	let fmt = formatter_of_out_channel source_out in
+	Horn_backend.translate fmt basename prog machine_code;
+	(* Tracability file if option is activated *)
+	if !Options.horntraces then (
+	let traces_file = destname ^ ".traces" in (* Could be changed *)
+	let traces_out = open_out traces_file in
+	let fmt = formatter_of_out_channel traces_out in
+	Horn_backend.traces_file fmt basename prog machine_code	  
+	)
+      end
+    | "lustre" -> 
+      begin
+	let source_file = destname ^ ".lustrec.lus" in (* Could be changed *)
+	let source_out = open_out source_file in
+	let fmt = formatter_of_out_channel source_out in
+	Printers.pp_prog fmt prog;
+(*	Lustre_backend.translate fmt basename normalized_prog machine_code *)
+	()
+      end
+
+    | _ -> assert false
+  in
+  begin
+    Log.report ~level:1 (fun fmt -> fprintf fmt ".. done !@ @]@.");
+  (* We stop the process here *)
+    exit 0
+  end
+
+let compile basename extension =
+  match extension with
+  | ".lusi"  -> compile_header basename extension
+  | ".lus"   -> compile_source basename extension
+  | _        -> assert false
+
+let anonymous filename =
+  let ok_ext, ext = List.fold_left (fun (ok, ext) ext' -> if not ok && Filename.check_suffix filename ext' then true, ext' else ok, ext) (false, "") extensions in
+  if ok_ext then
+    let basename = Filename.chop_suffix filename ext in
+    compile basename ext
+  else
+    raise (Arg.Bad ("Can only compile *.lusi, *.lus or *.ec files"))
+
+let _ =
+  Corelang.add_internal_funs ();
+  try
+    Printexc.record_backtrace true;
+    Arg.parse Options.options anonymous usage
+  with
+  | Parse.Syntax_err _ | Lexer_lustre.Error _ 
+  | Types.Error (_,_) | Clocks.Error (_,_)
+  | Corelang.Error _ (*| Task_set.Error _*) 
+  | Causality.Cycle _ -> exit 1
+  | Sys_error msg -> (eprintf "Failure: %s@." msg)
+  | exc -> (Utils.track_exception (); raise exc)
+
+(* Local Variables: *)
+(* compile-command:"make -C .." *)
+(* End: *)
diff --git a/src/modules.ml b/src/modules.ml
new file mode 100644
index 0000000000000000000000000000000000000000..7bfbc61db1e0dbb8ec06de9bf20f7375545d1d9a
--- /dev/null
+++ b/src/modules.ml
@@ -0,0 +1,159 @@
+(********************************************************************)
+(*                                                                  *)
+(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
+(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
+(*                                                                  *)
+(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
+(*  under the terms of the GNU Lesser General Public License        *)
+(*  version 2.1.                                                    *)
+(*                                                                  *)
+(********************************************************************)
+
+open Utils
+open LustreSpec
+open Corelang
+
+let add_symbol loc msg hashtbl name value =
+ if Hashtbl.mem hashtbl name
+ then raise (Error (loc, Already_bound_symbol msg))
+ else Hashtbl.add hashtbl name value
+
+let check_symbol loc msg hashtbl name =
+ if not (Hashtbl.mem hashtbl name)
+ then raise (Error (loc, Unbound_symbol msg))
+ else ()
+
+let add_imported_node name value =
+(*Format.eprintf "add_imported_node %s %a (owner=%s)@." name Printers.pp_imported_node (imported_node_of_top value) value.top_decl_owner;*)
+  try
+    let value' = Hashtbl.find node_table name in
+    let owner' = value'.top_decl_owner in
+    let itf' = value'.top_decl_itf in
+    let owner = value.top_decl_owner in
+    let itf = value.top_decl_itf in
+    match value'.top_decl_desc, value.top_decl_desc with
+    | Node _        , ImportedNode _  when owner = owner' && itf' && (not itf) -> Hashtbl.add node_table name value
+    | ImportedNode _, ImportedNode _            -> raise (Error (value.top_decl_loc, Already_bound_symbol ("node " ^ name)))
+    | _                                         -> assert false
+  with
+    Not_found                                   -> Hashtbl.add node_table name value
+
+let add_node name value =
+(*Format.eprintf "add_node %s %a (owner=%s)@." name Printers.pp_imported_node (get_node_interface (node_of_top value)) value.top_decl_owner;*)
+  try
+    let value' = Hashtbl.find node_table name in
+    let owner' = value'.top_decl_owner in
+    let itf' = value'.top_decl_itf in
+    let owner = value.top_decl_owner in
+    let itf = value.top_decl_itf in
+    match value'.top_decl_desc, value.top_decl_desc with
+    | ImportedNode _, Node _          when owner = owner' && itf' && (not itf) -> ()
+    | Node _        , Node _                    -> raise (Error (value.top_decl_loc, Already_bound_symbol ("node " ^ name)))
+    | _                                         -> assert false
+  with
+    Not_found                                   -> Hashtbl.add node_table name value
+
+
+let add_tag loc name typ =
+  if Hashtbl.mem tag_table name then
+    raise (Error (loc, Already_bound_symbol ("enum tag " ^ name)))
+  else Hashtbl.add tag_table name typ
+
+let add_field loc name typ =
+  if Hashtbl.mem field_table name then
+    raise (Error (loc, Already_bound_symbol ("struct field " ^ name)))
+  else Hashtbl.add field_table name typ
+
+let import_typedef name tydef =
+  let loc = tydef.top_decl_loc in
+  let rec import ty =
+    match ty with
+    | Tydec_enum tl   ->
+       List.iter (fun tag -> add_tag loc tag tydef) tl
+    | Tydec_struct fl -> 
+       List.iter (fun (field, ty) -> add_field loc field tydef; import ty) fl
+    | Tydec_clock ty      -> import ty
+    | Tydec_const c       ->
+       if not (Hashtbl.mem type_table (Tydec_const c))
+       then raise (Error (loc, Unbound_symbol ("type " ^ c)))
+       else ()
+    | Tydec_array (c, ty) -> import ty
+    | _                   -> ()
+  in import ((typedef_of_top tydef).tydef_desc)
+
+let add_type itf name value =
+(*Format.eprintf "add_type %B %s %a (owner=%s)@." itf name Printers.pp_typedef (typedef_of_top value) value.top_decl_owner;*)
+  try
+    let value' = Hashtbl.find type_table (Tydec_const name) in
+    let owner' = value'.top_decl_owner in
+    let itf' = value'.top_decl_itf in
+    let owner = value.top_decl_owner in
+    let itf = value.top_decl_itf in
+    match value'.top_decl_desc, value.top_decl_desc with
+    | TypeDef ty', TypeDef ty when coretype_equal ty'.tydef_desc ty.tydef_desc && owner' = owner && itf' && (not itf) -> ()
+    | TypeDef ty', TypeDef ty -> raise (Error (value.top_decl_loc, Already_bound_symbol ("type " ^ name)))
+    | _       -> assert false
+  with Not_found -> (import_typedef name value; Hashtbl.add type_table (Tydec_const name) value)
+
+let check_type loc name =
+ if not (Hashtbl.mem type_table (Tydec_const name))
+ then raise (Error (loc, Unbound_symbol ("type " ^ name)))
+ else ()
+
+let add_const itf name value =
+  try
+    let value' = Hashtbl.find consts_table name in
+    let owner' = value'.top_decl_owner in
+    let itf' = value'.top_decl_itf in
+    let owner = value.top_decl_owner in
+    let itf = value.top_decl_itf in
+    match value'.top_decl_desc, value.top_decl_desc with
+    | Const c', Const c when c.const_value = c'.const_value && owner' = owner && itf' && (not itf) -> ()
+    | Const c', Const c -> raise (Error (value.top_decl_loc, Already_bound_symbol ("const " ^ name)))
+    | _       -> assert false
+  with Not_found -> Hashtbl.add consts_table name value
+
+let name_dependency (local, dep) =
+  (if local then "" else Version.prefix ^ "/include/lustrec/") ^ dep
+
+let import_dependency loc (local, dep) =
+  let basename = name_dependency (local, dep) in
+  let extension = ".lusic" in 
+  try
+    Lusic.read_lusic basename extension
+  with Sys_error msg ->
+    raise (Error (loc, Unknown_library basename))
+(*
+    begin
+      Format.eprintf "Failure: impossible to load library %s.@.%s@." basename msg;
+      exit 1
+    end
+*)
+
+let rec load_header imported header =
+  List.fold_left (fun imp decl ->
+    match decl.top_decl_desc with
+    | Node nd -> assert false
+    | ImportedNode ind -> (add_imported_node ind.nodei_id decl; imp)
+    | Const c -> (add_const true c.const_id decl; imp)
+    | TypeDef tdef -> (add_type true tdef.tydef_id decl; imp)
+    | Open (local, dep) ->
+       let basename = name_dependency (local, dep) in
+       if ISet.mem basename imported then imp else
+	 let lusic = import_dependency decl.top_decl_loc (local, dep)
+	 in load_header (ISet.add basename imported) lusic.Lusic.contents
+		 ) imported header
+
+let rec load_program imported program =
+  List.fold_left (fun imp decl ->
+    match decl.top_decl_desc with
+    | Node nd -> (add_node nd.node_id decl; imp)
+    | ImportedNode ind -> assert false
+    | Const c -> (add_const false c.const_id decl; imp)
+    | TypeDef tdef -> (add_type false tdef.tydef_id decl; imp)
+    | Open (local, dep) ->
+       let basename = name_dependency (local, dep) in
+       if ISet.mem basename imported then imp else
+	 let lusic = import_dependency decl.top_decl_loc (local, dep)
+	 in load_header (ISet.add basename imported) lusic.Lusic.contents
+		 ) imported program
diff --git a/src/normalization.ml b/src/normalization.ml
index 4d189e3271b04bcadb45cbf1ed3a16aa43885f21..5aafac4da12a380b00de7d1d5da5c865aff70d06 100644
--- a/src/normalization.ml
+++ b/src/normalization.ml
@@ -401,7 +401,7 @@ let normalize_decl decl =
   match decl.top_decl_desc with
   | Node nd ->
     {decl with top_decl_desc = Node (normalize_node nd)}
-  | Open _ | ImportedNode _ | Consts _ | Type _ -> decl
+  | Open _ | ImportedNode _ | Const _ | TypeDef _ -> decl
   
 let normalize_prog decls = 
   List.map normalize_decl decls
diff --git a/src/optimize_prog.ml b/src/optimize_prog.ml
index b658953e242a97d97cae851e973802a149fa497e..3ee977109ce125d35ee01e3cb491e8fd827e7308 100644
--- a/src/optimize_prog.ml
+++ b/src/optimize_prog.ml
@@ -49,7 +49,7 @@ let node_unfold_consts consts node =
   { node with node_eqs = List.map (eq_unfold_consts consts) node.node_eqs }
 
 let prog_unfold_consts prog =
-  let consts = get_consts prog in
+  let consts = List.map const_of_top (get_consts prog) in
     List.map (
       fun decl -> match decl.top_decl_desc with 
 	| Node nd -> {decl with top_decl_desc = Node (node_unfold_consts consts nd)}
diff --git a/src/parse.ml b/src/parse.ml
index 23b38c554dc7a27796e2d86fcc8251f211fee0c4..0bd7e961720a77974906bca2d534e7a57f9dc659 100755
--- a/src/parse.ml
+++ b/src/parse.ml
@@ -15,89 +15,13 @@ open Format
 open LustreSpec
 open Corelang
 
-let add_symbol loc msg hashtbl name value =
- if Hashtbl.mem hashtbl name
- then raise (Error (loc, Already_bound_symbol msg))
- else Hashtbl.add hashtbl name value
-
-let check_symbol loc msg hashtbl name =
- if not (Hashtbl.mem hashtbl name)
- then raise (Error (loc, Unbound_symbol msg))
- else ()
-
-let add_node own name value =
-  try
-    match (Hashtbl.find node_table name).top_decl_desc, value.top_decl_desc with
-    | Node _        , ImportedNode _ when own   -> ()
-    | ImportedNode _, _                         -> Hashtbl.add node_table name value
-    | Node _        , _                         -> raise (Error (value.top_decl_loc, Already_bound_symbol ("node " ^ name)))
-    | _                                         -> assert false
-  with
-    Not_found                                   -> Hashtbl.add node_table name value
-
-
-let add_tag loc own name typ =
-  if Hashtbl.mem tag_table name && (not own) then
-    raise (Error (loc, Unbound_symbol ("enum tag " ^ name)))
-  else Hashtbl.add tag_table name typ
-
-let add_field loc own name typ =
-  if Hashtbl.mem field_table name && (not own) then
-    raise (Error (loc, Unbound_symbol ("struct field " ^ name)))
-  else Hashtbl.add field_table name typ
-
-let rec check_type_def loc own name ty =
-  match ty with
-  | Tydec_enum tl   ->
-    begin
-      List.iter (fun tag -> add_tag loc own tag (Tydec_const name)) tl;
-      ty
-    end
-  | Tydec_struct fl -> 
-    begin
-      List.iter (fun (field, _) -> add_field loc own field (Tydec_const name)) fl;
-      Tydec_struct (List.map (fun (f, ty) -> (f, check_type_def loc own name ty)) fl)
-    end
-  | Tydec_clock ty      -> Tydec_clock (check_type_def loc own name ty)
-  | Tydec_const c       ->
-    if not (Hashtbl.mem type_table (Tydec_const c))
-    then raise (Error (loc, Unbound_symbol ("type " ^ c)))
-    else get_repr_type ty
-  | Tydec_array (c, ty) -> Tydec_array (c, check_type_def loc own name ty)
-  | _                   -> ty
-
-let add_type own name value =
-(*Format.eprintf "add_type %B %s@." own name;*)
-  match value.top_decl_desc with
-  | Type ty ->
-    let loc = value.top_decl_loc in
-    if Hashtbl.mem type_table (Tydec_const name) && (not own)
-    then raise (Error (loc, Already_bound_symbol ("type " ^ name)))
-    else Hashtbl.add type_table (Tydec_const name) (check_type_def loc own name ty.ty_def_desc)
-  | _       -> assert false
-
-let check_type loc name =
- if not (Hashtbl.mem type_table (Tydec_const name))
- then raise (Error (loc, Unbound_symbol ("type " ^ name)))
- else ()
-
 let report_error loc =
   Location.print loc;
   print_string "Syntax error\n"
-(*
-let wrap own parsing_fun token_fun lexbuf =
-  try
-    let ast = parsing_fun token_fun lexbuf own in
-    Parsing.clear_parser ();
-    ast
-  with
-  | Parsing.Parse_error ->
-    let loc = Location.curr lexbuf in
-    raise (Syntax_err loc)
- *)
-let header own parsing_fun token_fun lexbuf =
+
+let header parsing_fun token_fun lexbuf =
   try
-    let ast = parsing_fun token_fun lexbuf own in
+    let ast = parsing_fun token_fun lexbuf in
     Parsing.clear_parser ();
     ast
   with
diff --git a/src/parser_lustre.mly b/src/parser_lustre.mly
index 3ec06fe423ecbd26455aacc79f917a382b91f48e..fd9f83b7f6d6d395a659b0e0fd8e1ced99d4253a 100755
--- a/src/parser_lustre.mly
+++ b/src/parser_lustre.mly
@@ -1,564 +1,595 @@
-/********************************************************************/
-/*                                                                  */
-/*  The LustreC compiler toolset   /  The LustreC Development Team  */
-/*  Copyright 2012 -    --   ONERA - CNRS - INPT                    */
-/*                                                                  */
-/*  LustreC is free software, distributed WITHOUT ANY WARRANTY      */
-/*  under the terms of the GNU Lesser General Public License        */
-/*  version 2.1.                                                    */
-/*                                                                  */
-/********************************************************************/
-
-%{
-open Utils
-open LustreSpec
-open Corelang
-open Dimension
-open Parse
-
-let get_loc () = Location.symbol_rloc ()
-let mktyp x = mktyp (get_loc ()) x
-let mkclock x = mkclock (get_loc ()) x
-let mkvar_decl x = mkvar_decl (get_loc ()) x
-let mkexpr x = mkexpr (get_loc ()) x
-let mkeexpr x = mkeexpr (get_loc ()) x 
-let mkeq x = mkeq (get_loc ()) x
-let mkassert x = mkassert (get_loc ()) x
-let mktop_decl x = mktop_decl (get_loc ()) x
-let mkpredef_call x = mkpredef_call (get_loc ()) x
-(*let mkpredef_unary_call x = mkpredef_unary_call (get_loc ()) x*)
-
-let mkdim_int i = mkdim_int (get_loc ()) i
-let mkdim_bool b = mkdim_bool (get_loc ()) b
-let mkdim_ident id = mkdim_ident (get_loc ()) id
-let mkdim_appl f args = mkdim_appl (get_loc ()) f args
-let mkdim_ite i t e = mkdim_ite (get_loc ()) i t e
-
-let mkannots annots = { annots = annots; annot_loc = get_loc () }
-
-%}
-
-%token <int> INT
-%token <string> REAL
-%token <float> FLOAT
-%token <string> STRING
-%token AUTOMATON STATE UNTIL UNLESS RESTART RESUME LAST
-%token STATELESS ASSERT OPEN QUOTE FUNCTION
-%token <string> IDENT
-%token <LustreSpec.expr_annot> ANNOT
-%token <LustreSpec.node_annot> NODESPEC
-%token LBRACKET RBRACKET LCUR RCUR LPAR RPAR SCOL COL COMMA COLCOL 
-%token AMPERAMPER BARBAR NOT POWER
-%token IF THEN ELSE
-%token UCLOCK DCLOCK PHCLOCK TAIL
-%token MERGE FBY WHEN WHENNOT EVERY
-%token NODE LET TEL RETURNS VAR IMPORTED SENSOR ACTUATOR WCET TYPE CONST
-%token STRUCT ENUM
-%token TINT TFLOAT TREAL TBOOL TCLOCK
-%token RATE DUE
-%token EQ LT GT LTE GTE NEQ
-%token AND OR XOR IMPL
-%token MULT DIV MOD
-%token MINUS PLUS UMINUS
-%token PRE ARROW
-%token REQUIRES ENSURES OBSERVER
-%token INVARIANT BEHAVIOR ASSUMES
-%token EXISTS FORALL
-%token PROTOTYPE LIB
-%token EOF
-
-%nonassoc prec_exists prec_forall
-%nonassoc COMMA
-%left MERGE IF
-%nonassoc ELSE
-%right ARROW FBY
-%left WHEN WHENNOT UCLOCK DCLOCK PHCLOCK
-%right COLCOL
-%right IMPL
-%left OR XOR BARBAR
-%left AND AMPERAMPER
-%left NOT
-%nonassoc INT
-%nonassoc EQ LT GT LTE GTE NEQ
-%left MINUS PLUS
-%left MULT DIV MOD
-%left UMINUS
-%left POWER
-%left PRE LAST
-%nonassoc RBRACKET
-%nonassoc LBRACKET
-
-%start prog
-%type <LustreSpec.top_decl list> prog
-
-%start header
-%type <bool -> LustreSpec.top_decl list> header
-
-%start lustre_annot
-%type <LustreSpec.expr_annot> lustre_annot
-
-%start lustre_spec
-%type <LustreSpec.node_annot> lustre_spec
-
-%%
-
-prog:
- open_list typ_def_prog top_decl_list EOF { $1 @ $2 @ (List.rev $3) }
-
-typ_def_prog:
- typ_def_list { $1 true }
-
-header:
- open_list typ_def_list top_decl_header_list EOF { (fun own -> ($1 @ let typs = $2 own in typs @ (List.rev ($3 own)))) }
-
-open_list:
-  { [] }
-| open_lusi open_list { $1 :: $2 }
-
-open_lusi:
-| OPEN QUOTE IDENT QUOTE { mktop_decl (Open (true, $3))}
-| OPEN LT IDENT GT { mktop_decl (Open (false, $3)) }
-
-top_decl_list:
-   {[]}
-| top_decl_list top_decl {$2::$1}
-
-
-top_decl_header_list:
-   {(fun own -> []) }
-| top_decl_header_list top_decl_header {(fun own -> let h1 = $1 own in ($2 own)::h1) }
-
-state_annot:
-  FUNCTION { true }
-| NODE { false }
-
-top_decl_header:
-| CONST cdecl_list { let top = mktop_decl (Consts (List.rev $2)) in fun _ -> top }
-| nodespec_list state_annot IDENT LPAR vdecl_list SCOL_opt RPAR RETURNS LPAR vdecl_list SCOL_opt RPAR  prototype_opt in_lib_opt SCOL
-    {let nd = mktop_decl (ImportedNode
-                            {nodei_id = $3;
-                             nodei_type = Types.new_var ();
-                             nodei_clock = Clocks.new_var true;
-                             nodei_inputs = List.rev $5;
-                             nodei_outputs = List.rev $10;
-			     nodei_stateless = $2;
-			     nodei_spec = $1;
-			     nodei_prototype = $13;
-			     nodei_in_lib = $14;})
-    in
-     (fun own -> add_node own $3 nd; nd) }
-
-prototype_opt:
- { None }
-| PROTOTYPE IDENT { Some $2}
-
-in_lib_opt:
-{ None }
-| LIB IDENT {Some $2} 
-
-top_decl:
-| CONST cdecl_list { mktop_decl (Consts (List.rev $2)) }
-| nodespec_list state_annot IDENT LPAR vdecl_list SCOL_opt RPAR RETURNS LPAR vdecl_list SCOL_opt RPAR SCOL_opt locals LET eq_list TEL 
-    {let eqs, asserts, annots = $16 in
-     let nd = mktop_decl (Node
-                            {node_id = $3;
-                             node_type = Types.new_var ();
-                             node_clock = Clocks.new_var true;
-                             node_inputs = List.rev $5;
-                             node_outputs = List.rev $10;
-                             node_locals = List.rev $14;
-			     node_gencalls = [];
-			     node_checks = [];
-			     node_asserts = asserts; 
-                             node_eqs = eqs;
-			     node_dec_stateless = $2;
-			     node_stateless = None;
-			     node_spec = $1;
-			     node_annot = annots})
-     in
-     add_node true $3 nd; nd}
-
-nodespec_list:
- { None }
-| NODESPEC nodespec_list { 
-  (function 
-  | None    -> (fun s1 -> Some s1) 
-  | Some s2 -> (fun s1 -> Some (merge_node_annot s1 s2))) $2 $1 }
-
-typ_def_list:
-    /* empty */             { (fun own -> []) }
-| typ_def SCOL typ_def_list { (fun own -> let ty1 = ($1 own) in ty1 :: ($3 own)) }
-
-typ_def:
-  TYPE IDENT EQ typ_def_rhs { let typ = mktop_decl (Type { ty_def_id = $2;
-							   ty_def_desc = $4
-							 })
-			      in (fun own -> add_type own $2 typ; typ) }
-
-typ_def_rhs:
-  typeconst                   { $1 }
-| ENUM LCUR tag_list RCUR     { Tydec_enum (List.rev $3) }
-| STRUCT LCUR field_list RCUR { Tydec_struct (List.rev $3) }
-
-array_typ_decl:
-                            { fun typ -> typ }
- | POWER dim array_typ_decl { fun typ -> $3 (Tydec_array ($2, typ)) }
-
-typeconst:
-  TINT array_typ_decl   { $2 Tydec_int }
-| TBOOL array_typ_decl  { $2 Tydec_bool  }
-| TREAL array_typ_decl  { $2 Tydec_real  }
-| TFLOAT array_typ_decl { $2 Tydec_float }
-| IDENT array_typ_decl  { $2 (Tydec_const $1) }
-| TBOOL TCLOCK          { Tydec_clock Tydec_bool }
-| IDENT TCLOCK          { Tydec_clock (Tydec_const $1) }
-
-tag_list:
-  IDENT                { $1 :: [] }
-| tag_list COMMA IDENT { $3 :: $1 }
-      
-field_list:                           { [] }
-| field_list IDENT COL typeconst SCOL { ($2, $4) :: $1 }
-      
-eq_list:
-  { [], [], [] }
-| eq eq_list {let eql, assertl, annotl = $2 in ($1::eql), assertl, annotl}
-| assert_ eq_list {let eql, assertl, annotl = $2 in eql, ($1::assertl), annotl}
-| ANNOT eq_list {let eql, assertl, annotl = $2 in eql, assertl, $1::annotl}
-| automaton eq_list {let eql, assertl, annotl = $2 in ($1::eql), assertl, annotl}
-
-automaton:
- AUTOMATON IDENT handler_list { failwith "not implemented" }
-
-handler_list:
-     { [] }
-| handler handler_list { $1::$2 }
-
-handler:
- STATE IDENT ARROW unless_list locals LET eq_list TEL until_list { () }
-
-unless_list:
-    { [] }
-| unless unless_list { $1::$2 }
-
-until_list:
-    { [] }
-| until until_list { $1::$2 }
-
-unless:
-  UNLESS expr RESTART IDENT { }
-| UNLESS expr RESUME IDENT  { }
-
-until:
-  UNTIL expr RESTART IDENT { }
-| UNTIL expr RESUME IDENT  { }
-
-assert_:
-| ASSERT expr SCOL {mkassert ($2)}
-
-eq:
-       ident_list      EQ expr SCOL {mkeq (List.rev $1,$3)}
-| LPAR ident_list RPAR EQ expr SCOL {mkeq (List.rev $2,$5)}
-
-lustre_spec:
-| contract EOF { $1 }
-
-contract:
-requires ensures behaviors { { requires = $1; ensures = $2; behaviors = $3; spec_loc = get_loc () } }
- 
-requires:
-{ [] }
-| REQUIRES qexpr SCOL requires { $2::$4 }
-
-ensures:
-{ [] }
-| ENSURES qexpr SCOL ensures { $2 :: $4 }
-| OBSERVER IDENT LPAR tuple_expr RPAR SCOL ensures { 
-  mkeexpr (mkexpr ((Expr_appl ($2, mkexpr (Expr_tuple $4), None)))) :: $7
-}
-
-behaviors:
-{ [] }
-| BEHAVIOR IDENT COL assumes ensures behaviors { ($2,$4,$5,get_loc ())::$6 }
-
-assumes:
-{ [] }
-| ASSUMES qexpr SCOL assumes { $2::$4 } 
-
-/* WARNING: UNUSED RULES */
-tuple_qexpr:
-| qexpr COMMA qexpr {[$3;$1]}
-| tuple_qexpr COMMA qexpr {$3::$1}
-
-qexpr:
-| expr { mkeexpr $1 }
-  /* Quantifiers */
-| EXISTS vdecl SCOL qexpr %prec prec_exists { extend_eexpr [Exists, $2] $4 } 
-| FORALL vdecl SCOL qexpr %prec prec_forall { extend_eexpr [Forall, $2] $4 }
-
-
-tuple_expr:
-    expr COMMA expr {[$3;$1]}
-| tuple_expr COMMA expr {$3::$1}
-
-// Same as tuple expr but accepting lists with single element
-array_expr:
-  expr {[$1]}
-| expr COMMA array_expr {$1::$3}
-
-dim_list:
-  dim RBRACKET { fun base -> mkexpr (Expr_access (base, $1)) }
-| dim RBRACKET LBRACKET dim_list { fun base -> $4 (mkexpr (Expr_access (base, $1))) }
-
-expr:
-/* constants */
-  INT {mkexpr (Expr_const (Const_int $1))}
-| REAL {mkexpr (Expr_const (Const_real $1))}
-| FLOAT {mkexpr (Expr_const (Const_float $1))}
-/* Idents or type enum tags */
-| IDENT {
-  if Hashtbl.mem tag_table $1
-  then mkexpr (Expr_const (Const_tag $1))
-  else mkexpr (Expr_ident $1)}
-| LPAR ANNOT expr RPAR
-    {update_expr_annot $3 $2}
-| LPAR expr RPAR
-    {$2}
-| LPAR tuple_expr RPAR
-    {mkexpr (Expr_tuple (List.rev $2))}
-
-/* Array expressions */
-| LBRACKET array_expr RBRACKET { mkexpr (Expr_array $2) }
-| expr POWER dim { mkexpr (Expr_power ($1, $3)) }
-| expr LBRACKET dim_list { $3 $1 }
-
-/* Temporal operators */
-| PRE expr 
-    {mkexpr (Expr_pre $2)}
-| expr ARROW expr 
-    {mkexpr (Expr_arrow ($1,$3))}
-| expr FBY expr 
-    {(*mkexpr (Expr_fby ($1,$3))*)
-      mkexpr (Expr_arrow ($1, mkexpr (Expr_pre $3)))}
-| expr WHEN IDENT 
-    {mkexpr (Expr_when ($1,$3,tag_true))}
-| expr WHENNOT IDENT
-    {mkexpr (Expr_when ($1,$3,tag_false))}
-| expr WHEN IDENT LPAR IDENT RPAR
-    {mkexpr (Expr_when ($1, $5, $3))}
-| MERGE IDENT handler_expr_list
-    {mkexpr (Expr_merge ($2,$3))}
-
-/* Applications */
-| IDENT LPAR expr RPAR
-    {mkexpr (Expr_appl ($1, $3, None))}
-| IDENT LPAR expr RPAR EVERY IDENT
-    {mkexpr (Expr_appl ($1, $3, Some ($6, tag_true)))}
-| IDENT LPAR expr RPAR EVERY IDENT LPAR IDENT RPAR
-    {mkexpr (Expr_appl ($1, $3, Some ($8, $6))) }
-| IDENT LPAR tuple_expr RPAR
-    {mkexpr (Expr_appl ($1, mkexpr (Expr_tuple (List.rev $3)), None))}
-| IDENT LPAR tuple_expr RPAR EVERY IDENT
-    {mkexpr (Expr_appl ($1, mkexpr (Expr_tuple (List.rev $3)), Some ($6, tag_true))) }
-| IDENT LPAR tuple_expr RPAR EVERY IDENT LPAR IDENT RPAR
-    {mkexpr (Expr_appl ($1, mkexpr (Expr_tuple (List.rev $3)), Some ($8, $6))) }
-
-/* Boolean expr */
-| expr AND expr 
-    {mkpredef_call "&&" [$1;$3]}
-| expr AMPERAMPER expr 
-    {mkpredef_call "&&" [$1;$3]}
-| expr OR expr 
-    {mkpredef_call "||" [$1;$3]}
-| expr BARBAR expr 
-    {mkpredef_call "||" [$1;$3]}
-| expr XOR expr 
-    {mkpredef_call "xor" [$1;$3]}
-| NOT expr 
-    {mkpredef_call "not" [$2]}
-| expr IMPL expr 
-    {mkpredef_call "impl" [$1;$3]}
-
-/* Comparison expr */
-| expr EQ expr 
-    {mkpredef_call "=" [$1;$3]}
-| expr LT expr 
-    {mkpredef_call "<" [$1;$3]}
-| expr LTE expr 
-    {mkpredef_call "<=" [$1;$3]}
-| expr GT expr 
-    {mkpredef_call ">" [$1;$3]}
-| expr GTE  expr 
-    {mkpredef_call ">=" [$1;$3]}
-| expr NEQ expr 
-    {mkpredef_call "!=" [$1;$3]}
-
-/* Arithmetic expr */
-| expr PLUS expr 
-    {mkpredef_call "+" [$1;$3]}
-| expr MINUS expr 
-    {mkpredef_call "-" [$1;$3]}
-| expr MULT expr 
-    {mkpredef_call "*" [$1;$3]}
-| expr DIV expr 
-    {mkpredef_call "/" [$1;$3]}
-| MINUS expr %prec UMINUS
-  {mkpredef_call "uminus" [$2]}
-| expr MOD expr 
-    {mkpredef_call "mod" [$1;$3]}
-
-/* If */
-| IF expr THEN expr ELSE expr
-    {mkexpr (Expr_ite ($2, $4, $6))}
-
-handler_expr_list:
-   { [] }
-| handler_expr handler_expr_list { $1 :: $2 }
-
-handler_expr:
- LPAR IDENT ARROW expr RPAR { ($2, $4) }
-
-signed_const_array:
-| signed_const { [$1] }
-| signed_const COMMA signed_const_array { $1 :: $3 }
-
-signed_const_struct:
-| IDENT EQ signed_const { [ ($1, $3) ] }
-| IDENT EQ signed_const COMMA signed_const_struct { ($1, $3) :: $5 }
-
-signed_const:
-  INT {Const_int $1}
-| REAL {Const_real $1}
-| FLOAT {Const_float $1}
-| IDENT {Const_tag $1}
-| MINUS INT {Const_int (-1 * $2)}
-| MINUS REAL {Const_real ("-" ^ $2)}
-| MINUS FLOAT {Const_float (-1. *. $2)}
-| LCUR signed_const_struct RCUR { Const_struct $2 }
-| LBRACKET signed_const_array RBRACKET { Const_array $2 }
-
-dim:
-   INT { mkdim_int $1 }
-| LPAR dim RPAR { $2 }
-| IDENT { mkdim_ident $1 }
-| dim AND dim 
-    {mkdim_appl "&&" [$1;$3]}
-| dim AMPERAMPER dim 
-    {mkdim_appl "&&" [$1;$3]}
-| dim OR dim 
-    {mkdim_appl "||" [$1;$3]}
-| dim BARBAR dim 
-    {mkdim_appl "||" [$1;$3]}
-| dim XOR dim 
-    {mkdim_appl "xor" [$1;$3]}
-| NOT dim 
-    {mkdim_appl "not" [$2]}
-| dim IMPL dim 
-    {mkdim_appl "impl" [$1;$3]}
-
-/* Comparison dim */
-| dim EQ dim 
-    {mkdim_appl "=" [$1;$3]}
-| dim LT dim 
-    {mkdim_appl "<" [$1;$3]}
-| dim LTE dim 
-    {mkdim_appl "<=" [$1;$3]}
-| dim GT dim 
-    {mkdim_appl ">" [$1;$3]}
-| dim GTE  dim 
-    {mkdim_appl ">=" [$1;$3]}
-| dim NEQ dim 
-    {mkdim_appl "!=" [$1;$3]}
-
-/* Arithmetic dim */
-| dim PLUS dim 
-    {mkdim_appl "+" [$1;$3]}
-| dim MINUS dim 
-    {mkdim_appl "-" [$1;$3]}
-| dim MULT dim 
-    {mkdim_appl "*" [$1;$3]}
-| dim DIV dim 
-    {mkdim_appl "/" [$1;$3]}
-| MINUS dim %prec UMINUS
-  {mkdim_appl "uminus" [$2]}
-| dim MOD dim 
-    {mkdim_appl "mod" [$1;$3]}
-/* If */
-| IF dim THEN dim ELSE dim
-    {mkdim_ite $2 $4 $6}
-
-locals:
-  {[]}
-| VAR vdecl_list SCOL {$2}
-
-vdecl_list:
-    vdecl {$1}
-| vdecl_list SCOL vdecl {$3 @ $1}
-
-vdecl:
-/* Useless no ?*/    ident_list
-    {List.map mkvar_decl 
-        (List.map (fun id -> (id, mktyp Tydec_any, mkclock Ckdec_any, false)) $1)}
-
-| ident_list COL typeconst clock 
-    {List.map mkvar_decl (List.map (fun id -> (id, mktyp $3, $4, false)) $1)}
-| CONST ident_list COL typeconst /* static parameters don't have clocks */
-    {List.map mkvar_decl (List.map (fun id -> (id, mktyp $4, mkclock Ckdec_any, true)) $2)}
-
-cdecl_list:
-  cdecl SCOL { [$1] }
-| cdecl_list cdecl SCOL { $2::$1 }
-
-cdecl:
-    IDENT EQ signed_const {
-      let c = {
-	const_id = $1;
-	const_loc = Location.symbol_rloc ();
-        const_type = Types.new_var ();
-	const_value = $3;
-      } in
-      Hashtbl.add consts_table $1 c; c
-    }
-
-clock:
-    {mkclock Ckdec_any}
-| when_list
-    {mkclock (Ckdec_bool (List.rev $1))}
-
-when_cond:
-    WHEN IDENT {($2, tag_true)}
-| WHENNOT IDENT {($2, tag_false)}
-| WHEN IDENT LPAR IDENT RPAR {($4, $2)}
-
-when_list:
-    when_cond {[$1]}
-| when_list when_cond {$2::$1}
-
-ident_list:
-  IDENT {[$1]}
-| ident_list COMMA IDENT {$3::$1}
-
-SCOL_opt:
-    SCOL {} | {}
-
-
-lustre_annot:
-lustre_annot_list EOF { { annots = $1; annot_loc = get_loc () } }
-
-lustre_annot_list:
-  { [] } 
-| kwd COL qexpr SCOL lustre_annot_list { ($1,$3)::$5 }
-| IDENT COL qexpr SCOL lustre_annot_list { ([$1],$3)::$5 }
-| INVARIANT COL qexpr SCOL lustre_annot_list{ (["invariant"],$3)::$5 }
-| OBSERVER COL qexpr SCOL lustre_annot_list { (["observer"],$3)::$5 }
-
-kwd:
-DIV { [] }
-| DIV IDENT kwd { $2::$3}
-
-%%
-(* Local Variables: *)
-(* compile-command:"make -C .." *)
-(* End: *)
-
-
+/********************************************************************/
+/*                                                                  */
+/*  The LustreC compiler toolset   /  The LustreC Development Team  */
+/*  Copyright 2012 -    --   ONERA - CNRS - INPT                    */
+/*                                                                  */
+/*  LustreC is free software, distributed WITHOUT ANY WARRANTY      */
+/*  under the terms of the GNU Lesser General Public License        */
+/*  version 2.1.                                                    */
+/*                                                                  */
+/********************************************************************/
+
+%{
+open Utils
+open LustreSpec
+open Corelang
+open Dimension
+open Parse
+
+let get_loc () = Location.symbol_rloc ()
+
+let mktyp x = mktyp (get_loc ()) x
+let mkclock x = mkclock (get_loc ()) x
+let mkvar_decl x = mkvar_decl (get_loc ()) x
+let mkexpr x = mkexpr (get_loc ()) x
+let mkeexpr x = mkeexpr (get_loc ()) x 
+let mkeq x = mkeq (get_loc ()) x
+let mkassert x = mkassert (get_loc ()) x
+let mktop_decl itf x = mktop_decl (get_loc ()) (Location.get_module ()) itf x
+let mkpredef_call x = mkpredef_call (get_loc ()) x
+(*let mkpredef_unary_call x = mkpredef_unary_call (get_loc ()) x*)
+
+let mkdim_int i = mkdim_int (get_loc ()) i
+let mkdim_bool b = mkdim_bool (get_loc ()) b
+let mkdim_ident id = mkdim_ident (get_loc ()) id
+let mkdim_appl f args = mkdim_appl (get_loc ()) f args
+let mkdim_ite i t e = mkdim_ite (get_loc ()) i t e
+
+let mkannots annots = { annots = annots; annot_loc = get_loc () }
+
+%}
+
+%token <int> INT
+%token <string> REAL
+%token <float> FLOAT
+%token <string> STRING
+%token AUTOMATON STATE UNTIL UNLESS RESTART RESUME LAST
+%token STATELESS ASSERT OPEN QUOTE FUNCTION
+%token <string> IDENT
+%token <string> UIDENT
+%token TRUE FALSE
+%token <LustreSpec.expr_annot> ANNOT
+%token <LustreSpec.node_annot> NODESPEC
+%token LBRACKET RBRACKET LCUR RCUR LPAR RPAR SCOL COL COMMA COLCOL 
+%token AMPERAMPER BARBAR NOT POWER
+%token IF THEN ELSE
+%token UCLOCK DCLOCK PHCLOCK TAIL
+%token MERGE FBY WHEN WHENNOT EVERY
+%token NODE LET TEL RETURNS VAR IMPORTED SENSOR ACTUATOR WCET TYPE CONST
+%token STRUCT ENUM
+%token TINT TFLOAT TREAL TBOOL TCLOCK
+%token RATE DUE
+%token EQ LT GT LTE GTE NEQ
+%token AND OR XOR IMPL
+%token MULT DIV MOD
+%token MINUS PLUS UMINUS
+%token PRE ARROW
+%token REQUIRES ENSURES OBSERVER
+%token INVARIANT BEHAVIOR ASSUMES
+%token EXISTS FORALL
+%token PROTOTYPE LIB
+%token EOF
+
+%nonassoc prec_exists prec_forall
+%nonassoc COMMA
+%left MERGE IF
+%nonassoc ELSE
+%right ARROW FBY
+%left WHEN WHENNOT UCLOCK DCLOCK PHCLOCK
+%right COLCOL
+%right IMPL
+%left OR XOR BARBAR
+%left AND AMPERAMPER
+%left NOT
+%nonassoc INT
+%nonassoc EQ LT GT LTE GTE NEQ
+%left MINUS PLUS
+%left MULT DIV MOD
+%left UMINUS
+%left POWER
+%left PRE LAST
+%nonassoc RBRACKET
+%nonassoc LBRACKET
+
+%start prog
+%type <LustreSpec.top_decl list> prog
+
+%start header
+%type <LustreSpec.top_decl list> header
+
+%start lustre_annot
+%type <LustreSpec.expr_annot> lustre_annot
+
+%start lustre_spec
+%type <LustreSpec.node_annot> lustre_spec
+
+%%
+
+module_ident:
+  UIDENT { $1 }
+| IDENT  { $1 }
+
+tag_ident:
+  UIDENT  { $1 }
+| TRUE    { tag_true }
+| FALSE   { tag_false }
+
+node_ident:
+  UIDENT { $1 }
+| IDENT  { $1 }
+
+vdecl_ident:
+  UIDENT { $1 }
+| IDENT  { $1 }
+
+const_ident:
+  UIDENT { $1 }
+| IDENT  { $1 }
+
+type_ident:
+  IDENT { $1 }
+
+prog:
+ open_list typ_def_prog top_decl_list EOF { $1 @ $2 @ (List.rev $3) }
+
+typ_def_prog:
+ typ_def_list { $1 false }
+
+header:
+ open_list typ_def_header top_decl_header_list EOF { $1 @ $2 @ (List.rev $3) }
+
+typ_def_header:
+ typ_def_list { $1 true }
+
+open_list:
+  { [] }
+| open_lusi open_list { $1 :: $2 }
+
+open_lusi:
+| OPEN QUOTE module_ident QUOTE { mktop_decl false (Open (true, $3))}
+| OPEN LT module_ident GT { mktop_decl false (Open (false, $3)) }
+
+top_decl_list:
+   {[]}
+| top_decl_list top_decl {$2@$1}
+
+
+top_decl_header_list:
+   { [] }
+| top_decl_header_list top_decl_header { $2@$1 }
+
+state_annot:
+  FUNCTION { true }
+| NODE { false }
+
+top_decl_header:
+| CONST cdecl_list { List.rev ($2 true) }
+| nodespec_list state_annot node_ident LPAR vdecl_list SCOL_opt RPAR RETURNS LPAR vdecl_list SCOL_opt RPAR  prototype_opt in_lib_opt SCOL
+    {let nd = mktop_decl true (ImportedNode
+				 {nodei_id = $3;
+				  nodei_type = Types.new_var ();
+				  nodei_clock = Clocks.new_var true;
+				  nodei_inputs = List.rev $5;
+				  nodei_outputs = List.rev $10;
+				  nodei_stateless = $2;
+				  nodei_spec = $1;
+				  nodei_prototype = $13;
+				  nodei_in_lib = $14;})
+     in
+     (*add_imported_node $3 nd;*) [nd] }
+
+prototype_opt:
+ { None }
+| PROTOTYPE node_ident { Some $2}
+
+in_lib_opt:
+{ None }
+| LIB module_ident {Some $2} 
+
+top_decl:
+| CONST cdecl_list { List.rev ($2 false) }
+| nodespec_list state_annot node_ident LPAR vdecl_list SCOL_opt RPAR RETURNS LPAR vdecl_list SCOL_opt RPAR SCOL_opt locals LET eq_list TEL 
+    {let eqs, asserts, annots = $16 in
+     let nd = mktop_decl false (Node
+				  {node_id = $3;
+				   node_type = Types.new_var ();
+				   node_clock = Clocks.new_var true;
+				   node_inputs = List.rev $5;
+				   node_outputs = List.rev $10;
+				   node_locals = List.rev $14;
+				   node_gencalls = [];
+				   node_checks = [];
+				   node_asserts = asserts; 
+				   node_eqs = eqs;
+				   node_dec_stateless = $2;
+				   node_stateless = None;
+				   node_spec = $1;
+				   node_annot = annots})
+     in
+     (*add_node $3 nd;*) [nd] }
+
+nodespec_list:
+ { None }
+| NODESPEC nodespec_list { 
+  (function 
+  | None    -> (fun s1 -> Some s1) 
+  | Some s2 -> (fun s1 -> Some (merge_node_annot s1 s2))) $2 $1 }
+
+typ_def_list:
+    /* empty */             { (fun itf -> []) }
+| typ_def SCOL typ_def_list { (fun itf -> let ty1 = ($1 itf) in ty1 :: ($3 itf)) }
+
+typ_def:
+  TYPE type_ident EQ typ_def_rhs { (fun itf ->
+			       let typ = mktop_decl itf (TypeDef { tydef_id = $2;
+								   tydef_desc = $4
+							})
+			       in (*add_type itf $2 typ;*) typ) }
+
+typ_def_rhs:
+  typeconst                   { $1 }
+| ENUM LCUR tag_list RCUR     { Tydec_enum (List.rev $3) }
+| STRUCT LCUR field_list RCUR { Tydec_struct (List.rev $3) }
+
+array_typ_decl:
+                            { fun typ -> typ }
+ | POWER dim array_typ_decl { fun typ -> $3 (Tydec_array ($2, typ)) }
+
+typeconst:
+  TINT array_typ_decl   { $2 Tydec_int }
+| TBOOL array_typ_decl  { $2 Tydec_bool  }
+| TREAL array_typ_decl  { $2 Tydec_real  }
+| TFLOAT array_typ_decl { $2 Tydec_float }
+| type_ident array_typ_decl  { $2 (Tydec_const $1) }
+| TBOOL TCLOCK          { Tydec_clock Tydec_bool }
+| IDENT TCLOCK          { Tydec_clock (Tydec_const $1) }
+
+tag_list:
+  UIDENT                { $1 :: [] }
+| tag_list COMMA UIDENT { $3 :: $1 }
+      
+field_list:                           { [] }
+| field_list IDENT COL typeconst SCOL { ($2, $4) :: $1 }
+      
+eq_list:
+  { [], [], [] }
+| eq eq_list {let eql, assertl, annotl = $2 in ($1::eql), assertl, annotl}
+| assert_ eq_list {let eql, assertl, annotl = $2 in eql, ($1::assertl), annotl}
+| ANNOT eq_list {let eql, assertl, annotl = $2 in eql, assertl, $1::annotl}
+| automaton eq_list {let eql, assertl, annotl = $2 in ($1::eql), assertl, annotl}
+
+automaton:
+ AUTOMATON type_ident handler_list { failwith "not implemented" }
+
+handler_list:
+     { [] }
+| handler handler_list { $1::$2 }
+
+handler:
+ STATE UIDENT ARROW unless_list locals LET eq_list TEL until_list { () }
+
+unless_list:
+    { Automata.init }
+| unless unless_list { let (expr1, case1) = $1 in (fun case -> Automata.add_branch expr1 case1 ($2 case)) }
+
+until_list:
+    { Automata.init }
+| until until_list { let (expr1, case1) = $1 in (fun case -> Automata.add_branch expr1 case1 ($2 case)) }
+
+unless:
+  UNLESS expr RESTART UIDENT { ($2, (get_loc (), true, $4))  }
+| UNLESS expr RESUME UIDENT  { ($2, (get_loc (), false, $4)) }
+
+until:
+  UNTIL expr RESTART UIDENT { ($2, (get_loc (), true, $4))  }
+| UNTIL expr RESUME UIDENT  { ($2, (get_loc (), false, $4)) }
+
+assert_:
+| ASSERT expr SCOL {mkassert ($2)}
+
+eq:
+       ident_list      EQ expr SCOL {mkeq (List.rev $1,$3)}
+| LPAR ident_list RPAR EQ expr SCOL {mkeq (List.rev $2,$5)}
+
+lustre_spec:
+| contract EOF { $1 }
+
+contract:
+requires ensures behaviors { { requires = $1; ensures = $2; behaviors = $3; spec_loc = get_loc () } }
+ 
+requires:
+{ [] }
+| REQUIRES qexpr SCOL requires { $2::$4 }
+
+ensures:
+{ [] }
+| ENSURES qexpr SCOL ensures { $2 :: $4 }
+| OBSERVER node_ident LPAR tuple_expr RPAR SCOL ensures { 
+  mkeexpr (mkexpr ((Expr_appl ($2, mkexpr (Expr_tuple $4), None)))) :: $7
+}
+
+behaviors:
+{ [] }
+| BEHAVIOR IDENT COL assumes ensures behaviors { ($2,$4,$5,get_loc ())::$6 }
+
+assumes:
+{ [] }
+| ASSUMES qexpr SCOL assumes { $2::$4 } 
+
+/* WARNING: UNUSED RULES */
+tuple_qexpr:
+| qexpr COMMA qexpr {[$3;$1]}
+| tuple_qexpr COMMA qexpr {$3::$1}
+
+qexpr:
+| expr { mkeexpr $1 }
+  /* Quantifiers */
+| EXISTS vdecl SCOL qexpr %prec prec_exists { extend_eexpr [Exists, $2] $4 } 
+| FORALL vdecl SCOL qexpr %prec prec_forall { extend_eexpr [Forall, $2] $4 }
+
+
+tuple_expr:
+    expr COMMA expr {[$3;$1]}
+| tuple_expr COMMA expr {$3::$1}
+
+// Same as tuple expr but accepting lists with single element
+array_expr:
+  expr {[$1]}
+| expr COMMA array_expr {$1::$3}
+
+dim_list:
+  dim RBRACKET { fun base -> mkexpr (Expr_access (base, $1)) }
+| dim RBRACKET LBRACKET dim_list { fun base -> $4 (mkexpr (Expr_access (base, $1))) }
+
+expr:
+/* constants */
+  INT {mkexpr (Expr_const (Const_int $1))}
+| REAL {mkexpr (Expr_const (Const_real $1))}
+| FLOAT {mkexpr (Expr_const (Const_float $1))}
+/* Idents or type enum tags */
+| IDENT { mkexpr (Expr_ident $1) }
+| tag_ident { mkexpr (Expr_ident $1) (*(Expr_const (Const_tag $1))*) }
+| LPAR ANNOT expr RPAR
+    {update_expr_annot $3 $2}
+| LPAR expr RPAR
+    {$2}
+| LPAR tuple_expr RPAR
+    {mkexpr (Expr_tuple (List.rev $2))}
+
+/* Array expressions */
+| LBRACKET array_expr RBRACKET { mkexpr (Expr_array $2) }
+| expr POWER dim { mkexpr (Expr_power ($1, $3)) }
+| expr LBRACKET dim_list { $3 $1 }
+
+/* Temporal operators */
+| PRE expr 
+    {mkexpr (Expr_pre $2)}
+| expr ARROW expr 
+    {mkexpr (Expr_arrow ($1,$3))}
+| expr FBY expr 
+    {(*mkexpr (Expr_fby ($1,$3))*)
+      mkexpr (Expr_arrow ($1, mkexpr (Expr_pre $3)))}
+| expr WHEN vdecl_ident
+    {mkexpr (Expr_when ($1,$3,tag_true))}
+| expr WHENNOT vdecl_ident
+    {mkexpr (Expr_when ($1,$3,tag_false))}
+| expr WHEN tag_ident LPAR vdecl_ident RPAR
+    {mkexpr (Expr_when ($1, $5, $3))}
+| MERGE vdecl_ident handler_expr_list
+    {mkexpr (Expr_merge ($2,$3))}
+
+/* Applications */
+| node_ident LPAR expr RPAR
+    {mkexpr (Expr_appl ($1, $3, None))}
+| node_ident LPAR expr RPAR EVERY vdecl_ident
+    {mkexpr (Expr_appl ($1, $3, Some ($6, tag_true)))}
+| node_ident LPAR expr RPAR EVERY tag_ident LPAR vdecl_ident RPAR
+    {mkexpr (Expr_appl ($1, $3, Some ($8, $6))) }
+| node_ident LPAR tuple_expr RPAR
+    {mkexpr (Expr_appl ($1, mkexpr (Expr_tuple (List.rev $3)), None))}
+| node_ident LPAR tuple_expr RPAR EVERY vdecl_ident
+    {mkexpr (Expr_appl ($1, mkexpr (Expr_tuple (List.rev $3)), Some ($6, tag_true))) }
+| node_ident LPAR tuple_expr RPAR EVERY tag_ident LPAR vdecl_ident RPAR
+    {mkexpr (Expr_appl ($1, mkexpr (Expr_tuple (List.rev $3)), Some ($8, $6))) }
+
+/* Boolean expr */
+| expr AND expr 
+    {mkpredef_call "&&" [$1;$3]}
+| expr AMPERAMPER expr 
+    {mkpredef_call "&&" [$1;$3]}
+| expr OR expr 
+    {mkpredef_call "||" [$1;$3]}
+| expr BARBAR expr 
+    {mkpredef_call "||" [$1;$3]}
+| expr XOR expr 
+    {mkpredef_call "xor" [$1;$3]}
+| NOT expr 
+    {mkpredef_call "not" [$2]}
+| expr IMPL expr 
+    {mkpredef_call "impl" [$1;$3]}
+
+/* Comparison expr */
+| expr EQ expr 
+    {mkpredef_call "=" [$1;$3]}
+| expr LT expr 
+    {mkpredef_call "<" [$1;$3]}
+| expr LTE expr 
+    {mkpredef_call "<=" [$1;$3]}
+| expr GT expr 
+    {mkpredef_call ">" [$1;$3]}
+| expr GTE  expr 
+    {mkpredef_call ">=" [$1;$3]}
+| expr NEQ expr 
+    {mkpredef_call "!=" [$1;$3]}
+
+/* Arithmetic expr */
+| expr PLUS expr 
+    {mkpredef_call "+" [$1;$3]}
+| expr MINUS expr 
+    {mkpredef_call "-" [$1;$3]}
+| expr MULT expr 
+    {mkpredef_call "*" [$1;$3]}
+| expr DIV expr 
+    {mkpredef_call "/" [$1;$3]}
+| MINUS expr %prec UMINUS
+  {mkpredef_call "uminus" [$2]}
+| expr MOD expr 
+    {mkpredef_call "mod" [$1;$3]}
+
+/* If */
+| IF expr THEN expr ELSE expr
+    {mkexpr (Expr_ite ($2, $4, $6))}
+
+handler_expr_list:
+   { [] }
+| handler_expr handler_expr_list { $1 :: $2 }
+
+handler_expr:
+ LPAR tag_ident ARROW expr RPAR { ($2, $4) }
+
+signed_const_array:
+| signed_const { [$1] }
+| signed_const COMMA signed_const_array { $1 :: $3 }
+
+signed_const_struct:
+| IDENT EQ signed_const { [ ($1, $3) ] }
+| IDENT EQ signed_const COMMA signed_const_struct { ($1, $3) :: $5 }
+
+signed_const:
+  INT {Const_int $1}
+| REAL {Const_real $1}
+| FLOAT {Const_float $1}
+| tag_ident {Const_tag $1}
+| MINUS INT {Const_int (-1 * $2)}
+| MINUS REAL {Const_real ("-" ^ $2)}
+| MINUS FLOAT {Const_float (-1. *. $2)}
+| LCUR signed_const_struct RCUR { Const_struct $2 }
+| LBRACKET signed_const_array RBRACKET { Const_array $2 }
+
+dim:
+   INT { mkdim_int $1 }
+| LPAR dim RPAR { $2 }
+| UIDENT { mkdim_ident $1 }
+| IDENT { mkdim_ident $1 }
+| dim AND dim 
+    {mkdim_appl "&&" [$1;$3]}
+| dim AMPERAMPER dim 
+    {mkdim_appl "&&" [$1;$3]}
+| dim OR dim 
+    {mkdim_appl "||" [$1;$3]}
+| dim BARBAR dim 
+    {mkdim_appl "||" [$1;$3]}
+| dim XOR dim 
+    {mkdim_appl "xor" [$1;$3]}
+| NOT dim 
+    {mkdim_appl "not" [$2]}
+| dim IMPL dim 
+    {mkdim_appl "impl" [$1;$3]}
+
+/* Comparison dim */
+| dim EQ dim 
+    {mkdim_appl "=" [$1;$3]}
+| dim LT dim 
+    {mkdim_appl "<" [$1;$3]}
+| dim LTE dim 
+    {mkdim_appl "<=" [$1;$3]}
+| dim GT dim 
+    {mkdim_appl ">" [$1;$3]}
+| dim GTE  dim 
+    {mkdim_appl ">=" [$1;$3]}
+| dim NEQ dim 
+    {mkdim_appl "!=" [$1;$3]}
+
+/* Arithmetic dim */
+| dim PLUS dim 
+    {mkdim_appl "+" [$1;$3]}
+| dim MINUS dim 
+    {mkdim_appl "-" [$1;$3]}
+| dim MULT dim 
+    {mkdim_appl "*" [$1;$3]}
+| dim DIV dim 
+    {mkdim_appl "/" [$1;$3]}
+| MINUS dim %prec UMINUS
+  {mkdim_appl "uminus" [$2]}
+| dim MOD dim 
+    {mkdim_appl "mod" [$1;$3]}
+/* If */
+| IF dim THEN dim ELSE dim
+    {mkdim_ite $2 $4 $6}
+
+locals:
+  {[]}
+| VAR vdecl_list SCOL {$2}
+
+vdecl_list:
+    vdecl {$1}
+| vdecl_list SCOL vdecl {$3 @ $1}
+
+vdecl:
+/* Useless no ?*/    ident_list
+    {List.map mkvar_decl 
+        (List.map (fun id -> (id, mktyp Tydec_any, mkclock Ckdec_any, false)) $1)}
+
+| ident_list COL typeconst clock 
+    {List.map mkvar_decl (List.map (fun id -> (id, mktyp $3, $4, false)) $1)}
+| CONST ident_list COL typeconst /* static parameters don't have clocks */
+    {List.map mkvar_decl (List.map (fun id -> (id, mktyp $4, mkclock Ckdec_any, true)) $2)}
+
+cdecl_list:
+  cdecl SCOL { (fun itf -> [$1 itf]) }
+| cdecl cdecl_list SCOL { (fun itf -> let c1 = ($1 itf) in c1::($2 itf)) }
+
+cdecl:
+    const_ident EQ signed_const {
+      (fun itf -> 
+       let c = mktop_decl itf (Const {
+				   const_id = $1;
+				   const_loc = Location.symbol_rloc ();
+				   const_type = Types.new_var ();
+				   const_value = $3})
+       in
+       (*add_const itf $1 c;*) c)
+    }
+
+clock:
+    {mkclock Ckdec_any}
+| when_list
+    {mkclock (Ckdec_bool (List.rev $1))}
+
+when_cond:
+  WHEN IDENT {($2, tag_true)}
+| WHENNOT IDENT {($2, tag_false)}
+| WHEN tag_ident LPAR IDENT RPAR {($4, $2)}
+
+when_list:
+    when_cond {[$1]}
+| when_list when_cond {$2::$1}
+
+ident_list:
+  vdecl_ident {[$1]}
+| ident_list COMMA vdecl_ident {$3::$1}
+
+SCOL_opt:
+    SCOL {} | {}
+
+
+lustre_annot:
+lustre_annot_list EOF { { annots = $1; annot_loc = get_loc () } }
+
+lustre_annot_list:
+  { [] } 
+| kwd COL qexpr SCOL lustre_annot_list { ($1,$3)::$5 }
+| IDENT COL qexpr SCOL lustre_annot_list { ([$1],$3)::$5 }
+| INVARIANT COL qexpr SCOL lustre_annot_list{ (["invariant"],$3)::$5 }
+| OBSERVER COL qexpr SCOL lustre_annot_list { (["observer"],$3)::$5 }
+
+kwd:
+DIV { [] }
+| DIV IDENT kwd { $2::$3}
+
+%%
+(* Local Variables: *)
+(* compile-command:"make -C .." *)
+(* End: *)
+
+
diff --git a/src/printers.ml b/src/printers.ml
index 22d457acf1705e76d910449f9da1960fad259a2c..504dd06a7dc31d1a64c917a49e2e32e78142e168 100644
--- a/src/printers.ml
+++ b/src/printers.ml
@@ -40,65 +40,6 @@ let pp_quantifiers fmt (q, vars) =
     | Forall -> fprintf fmt "forall %a" (fprintf_list ~sep:"; " pp_var) vars 
     | Exists -> fprintf fmt "exists %a" (fprintf_list ~sep:"; " pp_var) vars 
 
-(*
-let pp_econst fmt c = 
-  match c with
-    | EConst_int i -> pp_print_int fmt i
-    | EConst_real r -> pp_print_string fmt r
-    | EConst_float r -> pp_print_float fmt r
-    | EConst_tag  t -> pp_print_string fmt t
-    | EConst_string s -> pp_print_string fmt ("\"" ^ s ^ "\"")
-
-
-let rec pp_eexpr fmt eexpr = 
-  match eexpr.eexpr_desc with
-    | EExpr_const c -> pp_econst fmt c
-    | EExpr_ident id -> pp_print_string fmt id
-    | EExpr_tuple el -> fprintf_list ~sep:"," pp_eexpr fmt el
-    | EExpr_arrow (e1, e2) -> fprintf fmt "%a -> %a" pp_eexpr e1 pp_eexpr e2
-    | EExpr_fby (e1, e2) -> fprintf fmt "%a fby %a" pp_eexpr e1 pp_eexpr e2
-    (* | EExpr_concat (e1, e2) -> fprintf fmt "%a::%a" pp_eexpr e1 pp_eexpr e2 *)
-    (* | EExpr_tail e -> fprintf fmt "tail %a" pp_eexpr e *)
-    | EExpr_pre e -> fprintf fmt "pre %a" pp_eexpr e
-    | EExpr_when (e, id) -> fprintf fmt "%a when %s" pp_eexpr e id
-    | EExpr_merge (id, e1, e2) -> 
-      fprintf fmt "merge (%s, %a, %a)" id pp_eexpr e1 pp_eexpr e2
-    | EExpr_appl (id, e, r) -> pp_eapp fmt id e r
-    | EExpr_forall (vars, e) -> fprintf fmt "forall %a; %a" pp_node_args vars pp_eexpr e 
-    | EExpr_exists (vars, e) -> fprintf fmt "exists %a; %a" pp_node_args vars pp_eexpr e 
-
-
-    (* | EExpr_whennot _ *)
-    (* | EExpr_uclock _ *)
-    (* | EExpr_dclock _ *)
-    (* | EExpr_phclock _ -> assert false *)
-and pp_eapp fmt id e r =
-  match r with
-  | None ->
-    (match id, e.eexpr_desc with
-    | "+", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a + %a)" pp_eexpr e1 pp_eexpr e2
-    | "uminus", _ -> fprintf fmt "(- %a)" pp_eexpr e
-    | "-", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a - %a)" pp_eexpr e1 pp_eexpr e2
-    | "*", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a * %a)" pp_eexpr e1 pp_eexpr e2
-    | "/", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a / %a)" pp_eexpr e1 pp_eexpr e2
-    | "mod", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a mod %a)" pp_eexpr e1 pp_eexpr e2
-    | "&&", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a && %a)" pp_eexpr e1 pp_eexpr e2
-    | "||", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a || %a)" pp_eexpr e1 pp_eexpr e2
-    | "xor", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a ^^ %a)" pp_eexpr e1 pp_eexpr e2
-    | "impl", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a ==> %a)" pp_eexpr e1 pp_eexpr e2
-    | "<", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a < %a)" pp_eexpr e1 pp_eexpr e2
-    | "<=", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a <= %a)" pp_eexpr e1 pp_eexpr e2
-    | ">", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a > %a)" pp_eexpr e1 pp_eexpr e2
-    | ">=", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a >= %a)" pp_eexpr e1 pp_eexpr e2
-    | "!=", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a != %a)" pp_eexpr e1 pp_eexpr e2
-    | "=", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a == %a)" pp_eexpr e1 pp_eexpr e2
-    | "not", _ -> fprintf fmt "(! %a)" pp_eexpr e
-    | "ite", EExpr_tuple([e1;e2;e3]) -> fprintf fmt "(if %a then %a else %a)" pp_eexpr e1 pp_eexpr e2 pp_eexpr e3
-    | _ -> fprintf fmt "%s (%a)" id pp_eexpr e)
-  | Some x -> fprintf fmt "%s (%a) every %s" id pp_eexpr e x 
-*)
-
-
 let rec pp_struct_const_field fmt (label, c) =
   fprintf fmt "%a = %a;" pp_print_string label pp_const c
 and pp_const fmt c = 
@@ -211,8 +152,11 @@ and pp_var_type_dec_desc fmt tdesc =
 let pp_var_type_dec fmt ty =
   pp_var_type_dec_desc fmt ty.ty_dec_desc
 
-let pp_type_def fmt ty =
-  fprintf fmt "type %s = %a;@ " ty.ty_def_id pp_var_type_dec_desc ty.ty_def_desc
+let pp_typedef fmt ty =
+  fprintf fmt "type %s = %a;@ " ty.tydef_id pp_var_type_dec_desc ty.tydef_desc
+
+let pp_typedec fmt ty =
+  fprintf fmt "type %s;@ " ty.tydec_id
 
 (* let rec pp_var_type fmt ty =  *)
 (*   fprintf fmt "%a" (match ty.tdesc with  *)
@@ -279,26 +223,26 @@ fprintf fmt "@[<v 0>%a%t%s %s (%a) returns (%a)@.%a%alet@.@[<h 2>   @ @[<v>%a@ %
 (*fprintf fmt "@ /* Scheduling: %a */ @ " (fprintf_list ~sep:", " pp_print_string) (Scheduling.schedule_node nd)*)
 
 let pp_imported_node fmt ind = 
-  fprintf fmt "@[<v>%s %s (%a) returns (%a) %t@]"
+  fprintf fmt "@[<v>%s %s (%a) returns (%a)@]"
     (if ind.nodei_stateless then "function" else "node")
     ind.nodei_id
     pp_node_args ind.nodei_inputs
     pp_node_args ind.nodei_outputs
-    (fun fmt -> if ind.nodei_stateless then Format.fprintf fmt "stateless") 
 
-let pp_const_list fmt clist = 
-  fprintf_list ~sep:"@ " (fun fmt cdecl ->
-    fprintf fmt "%s = %a;"
-      cdecl.const_id pp_const cdecl.const_value) fmt clist
+let pp_const_decl fmt cdecl =
+  fprintf fmt "%s = %a;" cdecl.const_id pp_const cdecl.const_value
+
+let pp_const_decl_list fmt clist = 
+  fprintf_list ~sep:"@ " pp_const_decl fmt clist
 
 let pp_decl fmt decl =
   match decl.top_decl_desc with
   | Node nd -> fprintf fmt "%a@ " pp_node nd
   | ImportedNode ind ->
     fprintf fmt "imported %a;@ " pp_imported_node ind
-  | Consts clist -> (fprintf fmt "const %a@ " pp_const_list clist)
-  | Open (local, s) -> if local then fprintf fmt "open \"%s\"@ " s else fprintf fmt "open <%s>@ " s
-  | Type tdef -> fprintf fmt "%a@ " pp_type_def tdef
+  | Const c -> fprintf fmt "const %a@ " pp_const_decl c
+  | Open (local, s) -> if local then fprintf fmt "#open \"%s\"@ " s else fprintf fmt "#open <%s>@ " s
+  | TypeDef tdef -> fprintf fmt "%a@ " pp_typedef tdef
 
 let pp_prog fmt prog = 
   fprintf_list ~sep:"@ " pp_decl fmt prog
@@ -307,26 +251,20 @@ let pp_short_decl fmt decl =
   match decl.top_decl_desc with
   | Node nd -> fprintf fmt "node %s@ " nd.node_id
   | ImportedNode ind -> fprintf fmt "imported node %s" ind.nodei_id
-  | Consts clist -> (fprintf fmt "const %a@ " pp_const_list clist)
-  | Open (local, s) -> if local then fprintf fmt "open \"%s\"@ " s else fprintf fmt "open <%s>@ " s
-  | Type tdef -> fprintf fmt "type %s;@ " tdef.ty_def_id
+  | Const c -> fprintf fmt "const %a@ " pp_const_decl c
+  | Open (local, s) -> if local then fprintf fmt "#open \"%s\"@ " s else fprintf fmt "#open <%s>@ " s
+  | TypeDef tdef -> fprintf fmt "type %s;@ " tdef.tydef_id
 
 let pp_lusi fmt decl = 
   match decl.top_decl_desc with
-  | Node nd ->  
-    fprintf fmt 
-      "@[<v>%s %s (%a) returns (%a);@ @]@ "
-      (if nd.node_dec_stateless then "function" else "node")
-      nd.node_id
-      pp_node_args nd.node_inputs
-      pp_node_args nd.node_outputs
-| Consts clist -> (fprintf fmt "const %a@ " pp_const_list clist)
-| Open (local, s) -> if local then fprintf fmt "open \"%s\"@ " s else fprintf fmt "open <%s>@ " s
-| Type tdef -> fprintf fmt "%a@ " pp_type_def tdef
-| ImportedNode _ -> ()
-
-let pp_lusi_header fmt filename prog =
-  fprintf fmt "(* Generated Lustre Interface file from %s *)@." filename;
+  | ImportedNode ind -> fprintf fmt "%a;@ " pp_imported_node ind
+  | Const c -> fprintf fmt "const %a@ " pp_const_decl c
+  | Open (local, s) -> if local then fprintf fmt "#open \"%s\"@ " s else fprintf fmt "#open <%s>@ " s
+  | TypeDef tdef -> fprintf fmt "%a@ " pp_typedef tdef
+  | Node _ -> assert false
+
+let pp_lusi_header fmt basename prog =
+  fprintf fmt "(* Generated Lustre Interface file from %s.lus *)@." basename;
   fprintf fmt "(* by Lustre-C compiler version %s, %a *)@." Version.number pp_date (Unix.gmtime (Unix.time ()));
   fprintf fmt "(* Feel free to mask some of the definitions by removing them from this file. *)@.@.";
   List.iter (fprintf fmt "%a@." pp_lusi) prog    
diff --git a/src/types.ml b/src/types.ml
index 1cf1a5e31e6052bf0f6a2cdfc47f1953dacd380a..04d17a74c92ab151fff36a40c5f4900499e69c12 100755
--- a/src/types.ml
+++ b/src/types.ml
@@ -163,7 +163,7 @@ let pp_error fmt = function
       (Utils.fprintf_list ~sep:"," pp_print_string)
       (fst (Utils.list_of_imap vmap))
   | Declared_but_undefined id ->
-     fprintf fmt "Node %s is declared but not defined@." id
+     fprintf fmt "%s is declared but not defined@." id
   | Type_clash (ty1,ty2) ->
       Utils.reset_names ();
     fprintf fmt "Expected type %a, got type %a@." print_ty ty1 print_ty ty2
diff --git a/src/typing.ml b/src/typing.ml
index 5c45975dea789c7b2e424f316a1f44ca0b93bde3..718f1d2c8237cc058d41d80e2b0fdb78fc76da20 100755
--- a/src/typing.ml
+++ b/src/typing.ml
@@ -130,11 +130,17 @@ let rec coretype_type ty =
  | Tstatic (_, t) -> coretype_type t
  | _         -> assert false
 
-let get_type_definition tname =
+let get_coretype_definition tname =
   try
-    type_coretype (fun d -> ()) (Hashtbl.find type_table (Tydec_const tname))
+    let top = Hashtbl.find type_table (Tydec_const tname) in
+    match top.top_decl_desc with
+    | TypeDef tdef -> tdef.tydef_desc
+    | _ -> assert false
   with Not_found -> raise (Error (Location.dummy_loc, Unbound_type tname))
 
+let get_type_definition tname =
+    type_coretype (fun d -> ()) (get_coretype_definition tname)
+
 (* Equality on ground types only *)
 (* Should be used between local variables which must have a ground type *)
 let rec eq_ground t1 t2 =
@@ -240,7 +246,8 @@ let try_unify ?(sub=false) ?(semi=false) ty1 ty2 loc =
 
 let rec type_struct_const_field loc (label, c) =
   if Hashtbl.mem field_table label
-  then let tydec = Hashtbl.find field_table label in
+  then let tydef = Hashtbl.find field_table label in
+       let tydec = (typedef_of_top tydef).tydef_desc in 
        let tydec_struct = get_struct_type_fields tydec in
        let ty_label = type_coretype (fun d -> ()) (List.assoc label tydec_struct) in
        begin
@@ -260,7 +267,13 @@ and type_const loc c =
 		      Type_predef.type_array d ty
   | Const_tag t     ->
     if Hashtbl.mem tag_table t
-    then type_coretype (fun d -> ()) (Hashtbl.find tag_table t)
+    then 
+      let tydef = typedef_of_top (Hashtbl.find tag_table t) in
+      let tydec =
+	if is_user_type tydef.tydef_desc
+	then Tydec_const tydef.tydef_id
+	else tydef.tydef_desc in
+      type_coretype (fun d -> ()) tydec
     else raise (Error (loc, Unbound_value ("enum tag " ^ t)))
   | Const_struct fl ->
     let ty_struct = new_var () in
@@ -642,19 +655,21 @@ let type_imported_node env nd loc =
   nd.nodei_type <- ty_node;
   new_env
 
+let type_top_const env cdecl =
+  let ty = type_const cdecl.const_loc cdecl.const_value in
+  let d =
+    if is_dimension_type ty
+    then dimension_of_const cdecl.const_loc cdecl.const_value
+    else Dimension.mkdim_var () in
+  let ty = Type_predef.type_static d ty in
+  let new_env = Env.add_value env cdecl.const_id ty in
+  cdecl.const_type <- ty;
+  new_env
+
 let type_top_consts env clist =
-  List.fold_left (fun env cdecl ->
-    let ty = type_const cdecl.const_loc cdecl.const_value in
-    let d =
-      if is_dimension_type ty
-      then dimension_of_const cdecl.const_loc cdecl.const_value
-      else Dimension.mkdim_var () in
-    let ty = Type_predef.type_static d ty in
-    let new_env = Env.add_value env cdecl.const_id ty in
-    cdecl.const_type <- ty;
-    new_env) env clist
-
-let type_top_decl env decl =
+  List.fold_left type_top_const env clist
+
+let rec type_top_decl env decl =
   match decl.top_decl_desc with
   | Node nd -> (
       try
@@ -668,9 +683,9 @@ let type_top_decl env decl =
   )
   | ImportedNode nd ->
       type_imported_node env nd decl.top_decl_loc
-  | Consts clist ->
-      type_top_consts env clist
-  | Type _
+  | Const c ->
+      type_top_const env c
+  | TypeDef _ -> List.fold_left type_top_decl env (consts_of_enum_type decl)
   | Open _  -> env
 
 let type_prog env decls =
@@ -702,39 +717,53 @@ let uneval_top_generics decl =
       uneval_node_generics (nd.node_inputs @ nd.node_outputs)
   | ImportedNode nd ->
       uneval_node_generics (nd.nodei_inputs @ nd.nodei_outputs)
-  | Consts _
-  | Type _
+  | Const _
+  | TypeDef _
   | Open _  -> ()
 
 let uneval_prog_generics prog =
  List.iter uneval_top_generics prog
 
-let rec get_imported_node decls id =
+let rec get_imported_symbol decls id =
   match decls with
   | [] -> assert false
   | decl::q ->
      (match decl.top_decl_desc with
-      | ImportedNode nd when id = nd.nodei_id -> decl
-      | _ -> get_imported_node q id)
+      | ImportedNode nd when id = nd.nodei_id && decl.top_decl_itf -> decl
+      | Const c when id = c.const_id && decl.top_decl_itf -> decl
+      | TypeDef _ -> get_imported_symbol (consts_of_enum_type decl @ q) id
+      | _ -> get_imported_symbol q id)
 
 let check_env_compat header declared computed = 
   uneval_prog_generics header;
-  Env.iter declared (fun k decl_type_k -> 
-    let computed_t = instantiate (ref []) (ref []) 
-				 (try Env.lookup_value computed k
-				  with Not_found ->
-				    let loc = (get_imported_node header k).top_decl_loc in 
-				    raise (Error (loc, Declared_but_undefined k))) in
+  Env.iter declared (fun k decl_type_k ->
+    let loc = (get_imported_symbol header k).top_decl_loc in 
+    let computed_t =
+      instantiate (ref []) (ref []) 
+	(try Env.lookup_value computed k
+	 with Not_found -> raise (Error (loc, Declared_but_undefined k))) in
     (*Types.print_ty Format.std_formatter decl_type_k;
-    Types.print_ty Format.std_formatter computed_t;*)
-    try_unify ~sub:true ~semi:true decl_type_k computed_t Location.dummy_loc
-		    )
+      Types.print_ty Format.std_formatter computed_t;*)
+    try_unify ~sub:true ~semi:true decl_type_k computed_t loc
+  )
+
 let check_typedef_top decl =
+(*Format.eprintf "check_typedef %a@." Printers.pp_short_decl decl;*)
+(*Printers.pp_var_type_dec_desc (typedef_of_top decl).tydef_id*)
+(*Format.eprintf "%a" Corelang.print_type_table ();*)
   match decl.top_decl_desc with
-  | Type ty ->
-Format.eprintf "check_typedef %a %a@." Printers.pp_var_type_dec_desc ty.ty_def_desc Printers.pp_var_type_dec_desc (Hashtbl.find type_table (Tydec_const ty.ty_def_id));
-    if coretype_equal ty.ty_def_desc (Hashtbl.find type_table (Tydec_const ty.ty_def_id)) then ()
-    else raise (Error (decl.top_decl_loc, Type_mismatch ty.ty_def_id))
+  | TypeDef ty ->
+     let owner = decl.top_decl_owner in
+     let itf = decl.top_decl_itf in
+     let decl' =
+       try Hashtbl.find type_table (Tydec_const (typedef_of_top decl).tydef_id)
+       with Not_found -> raise (Error (decl.top_decl_loc, Declared_but_undefined ("type "^ ty.tydef_id))) in
+     let owner' = decl'.top_decl_owner in
+     let itf' = decl'.top_decl_itf in
+     (match decl'.top_decl_desc with
+     | Const _ | Node _ | ImportedNode _ -> assert false
+     | TypeDef ty' when coretype_equal ty'.tydef_desc ty.tydef_desc && owner' = owner && itf && (not itf') -> ()
+     | _ -> raise (Error (decl.top_decl_loc, Type_mismatch ty.tydef_id)))
   | _  -> ()
 
 let check_typedef_compat header =