diff --git a/src/automata.ml b/src/automata.ml
index 42f547fb65180e178dfab7903f242ba001387125..d079e442d1ad2b6050dbc3003223d64cac90f0da 100755
--- a/src/automata.ml
+++ b/src/automata.ml
@@ -24,6 +24,9 @@ type aut_state =
       actual_s : var_decl
     }
 
+let cpvar_decl var_decl =
+ mkvar_decl var_decl.var_loc ~orig:var_decl.var_orig (var_decl.var_id, var_decl.var_dec_type, var_decl.var_dec_clock, var_decl.var_dec_const, var_decl.var_dec_value)
+
 let as_clock var_decl =
   let tydec = var_decl.var_dec_type in
   { var_decl with var_dec_type = { ty_dec_desc = Tydec_clock tydec.ty_dec_desc; ty_dec_loc = tydec.ty_dec_loc } }
@@ -99,12 +102,12 @@ let mkautomata_state used typedef loc id =
   let actual_r = mk_new_name used (id ^ "__restart_act") in
   let actual_s = mk_new_name used (id ^ "__state_act") in
   {
-    incoming_r' = mkvar_decl loc (incoming_r', tydec_bool, ckdec_any, false);
-    incoming_s' = mkvar_decl loc (incoming_s', tydec_state typedef.tydef_id, ckdec_any, false);
-    incoming_r = mkvar_decl loc (incoming_r, tydec_bool, ckdec_any, false);
-    incoming_s = mkvar_decl loc (incoming_s, tydec_state typedef.tydef_id, ckdec_any, false);
-    actual_r = mkvar_decl loc (actual_r  , tydec_bool, ckdec_any, false);
-    actual_s = mkvar_decl loc (actual_s  , tydec_state typedef.tydef_id, ckdec_any, false)
+    incoming_r' = mkvar_decl loc (incoming_r', tydec_bool, ckdec_any, false, None);
+    incoming_s' = mkvar_decl loc (incoming_s', tydec_state typedef.tydef_id, ckdec_any, false, None);
+    incoming_r = mkvar_decl loc (incoming_r, tydec_bool, ckdec_any, false, None);
+    incoming_s = mkvar_decl loc (incoming_s, tydec_state typedef.tydef_id, ckdec_any, false, None);
+    actual_r = mkvar_decl loc (actual_r  , tydec_bool, ckdec_any, false, None);
+    actual_s = mkvar_decl loc (actual_s  , tydec_state typedef.tydef_id, ckdec_any, false, None)
   }
 
 let vars_of_aut_state aut_state =
@@ -123,8 +126,8 @@ let node_of_unless nused used node aut_id aut_state handler =
     node_id = node_id;
     node_type = Types.new_var ();
     node_clock = Clocks.new_var true;
-    node_inputs = var_inputs;
-    node_outputs = var_outputs;
+    node_inputs = List.map cpvar_decl var_inputs;
+    node_outputs = List.map cpvar_decl var_outputs;
     node_locals = [];
     node_gencalls = [];
     node_checks = [];
@@ -173,9 +176,9 @@ let node_of_assign_until nused used node aut_id aut_state handler =
     node_id = node_id;
     node_type = Types.new_var ();
     node_clock = Clocks.new_var true;
-    node_inputs = var_inputs;
-    node_outputs = aut_state.incoming_r :: aut_state.incoming_s :: new_var_outputs;
-    node_locals = new_var_locals @ handler.hand_locals;
+    node_inputs = List.map cpvar_decl var_inputs;
+    node_outputs = List.map cpvar_decl (aut_state.incoming_r :: aut_state.incoming_s :: new_var_outputs);
+    node_locals = List.map cpvar_decl (new_var_locals @ handler.hand_locals);
     node_gencalls = [];
     node_checks = [];
     node_asserts = handler.hand_asserts; 
diff --git a/src/backends/C/c_backend.ml b/src/backends/C/c_backend.ml
index be30cc996819c4e491cf346dd16a90d0dff6a454..a6d1d711bb632c67e58a10406033b45cc095cb2a 100644
--- a/src/backends/C/c_backend.ml
+++ b/src/backends/C/c_backend.ml
@@ -26,18 +26,19 @@ let makefile_opt print basename dependencies makefile_fmt machines =
 *)
 
 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
   let header_fmt = formatter_of_out_channel header_out in
   let source_lib_out = open_out source_lib_file in
   let source_lib_fmt = formatter_of_out_channel source_lib_out in
-  
+
   let print_header, print_lib_c, print_main_c, print_makefile = funs in
   (* Generating H file *)
   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;
 
@@ -64,8 +65,7 @@ let gen_files funs basename prog machines dependencies header_file source_lib_fi
     end
   )
 
-let translate_to_c header source_lib source_main makefile basename prog machines dependencies  =
-
+let translate_to_c header source_lib source_main makefile basename prog machines dependencies =
   match !Options.spec with
   | "no" -> begin
     let module HeaderMod = C_backend_header.EmptyMod in
@@ -77,7 +77,7 @@ let translate_to_c header source_lib source_main makefile basename prog machines
     let module Source = C_backend_src.Main (SourceMod) in
     let module SourceMain = C_backend_main.Main (SourceMainMod) in
     let module Makefile = C_backend_makefile.Main (MakefileMod) in
-        
+
     let funs = 
       Header.print_alloc_header, 
       Source.print_lib_c, 
@@ -100,7 +100,7 @@ let translate_to_c header source_lib source_main makefile basename prog machines
     let module Source = C_backend_src.Main (SourceMod) in
     let module SourceMain = C_backend_main.Main (SourceMainMod) in
     let module Makefile = C_backend_makefile.Main (MakefileMod) in
-        
+
     let funs = 
       Header.print_alloc_header, 
       Source.print_lib_c,
diff --git a/src/backends/C/c_backend_common.ml b/src/backends/C/c_backend_common.ml
index 3ac37bc712e908ff55be9fa9a9da64ac6299ebae..82241ae23412fb9262a2711dbf81967f6029a5d6 100644
--- a/src/backends/C/c_backend_common.ml
+++ b/src/backends/C/c_backend_common.ml
@@ -51,6 +51,7 @@ let mk_call_var_decl loc id =
     var_dec_type = mktyp Location.dummy_loc Tydec_any;
     var_dec_clock = mkclock Location.dummy_loc Ckdec_any;
     var_dec_const = false;
+    var_dec_value = None;
     var_type = Type_predef.type_arrow (Types.new_var ()) (Types.new_var ());
     var_clock = Clocks.new_var true;
     var_loc = loc }
@@ -133,6 +134,73 @@ let rec pp_c_initialize fmt t =
       (Utils.duplicate 0 (Dimension.size_const_dimension d))
   | _ -> assert false
 
+
+let pp_c_tag fmt t =
+ pp_print_string fmt (if t = tag_true then "1" else if t = tag_false then "0" else t)
+
+(* Prints a constant value *)
+let rec pp_c_const fmt c =
+  match c with
+    | Const_int i     -> pp_print_int fmt i
+    | Const_real r    -> pp_print_string fmt r
+    | Const_float r   -> pp_print_float fmt r
+    | Const_tag t     -> pp_c_tag fmt t
+    | Const_array ca  -> fprintf fmt "{%a }" (Utils.fprintf_list ~sep:", " pp_c_const) ca
+    | Const_struct fl -> fprintf fmt "{%a }" (Utils.fprintf_list ~sep:", " (fun fmt (f, c) -> pp_c_const fmt c)) fl
+    | Const_string _ -> assert false (* string occurs in annotations not in C *)
+
+(* Prints a value expression [v], with internal function calls only.
+   [pp_var] is a printer for variables (typically [pp_c_var_read]),
+   but an offset suffix may be added for array variables
+*)
+let rec pp_c_val self pp_var fmt v =
+  match v with
+  | Cst c         -> pp_c_const fmt c
+  | Array vl      -> fprintf fmt "{%a}" (Utils.fprintf_list ~sep:", " (pp_c_val self pp_var)) vl
+  | Access (t, i) -> fprintf fmt "%a[%a]" (pp_c_val self pp_var) t (pp_c_val self pp_var) i
+  | Power (v, n)  -> assert false
+  | LocalVar v    -> pp_var fmt v
+  | StateVar v    ->
+    (* array memory vars are represented by an indirection to a local var with the right type,
+       in order to avoid casting everywhere. *)
+    if Types.is_array_type v.var_type
+    then fprintf fmt "%a" pp_var v
+    else fprintf fmt "%s->_reg.%a" self pp_var v
+  | Fun (n, vl)   -> Basic_library.pp_c n (pp_c_val self pp_var) fmt vl
+
+(* Access to the value of a variable:
+   - if it's not a scalar output, then its name is enough
+   - otherwise, dereference it (it has been declared as a pointer,
+     despite its scalar Lustre type)
+   - moreover, dereference memory array variables.
+*)
+let pp_c_var_read m fmt id =
+  if Types.is_address_type id.var_type
+  then
+    if is_memory m id
+    then fprintf fmt "(*%s)" id.var_id
+    else fprintf fmt "%s" id.var_id
+  else
+    if is_output m id
+    then fprintf fmt "*%s" id.var_id
+    else fprintf fmt "%s" id.var_id
+
+(* Addressable value of a variable, the one that is passed around in calls:
+   - if it's not a scalar non-output, then its name is enough
+   - otherwise, reference it (it must be passed as a pointer,
+     despite its scalar Lustre type)
+*)
+let pp_c_var_write m fmt id =
+  if Types.is_address_type id.var_type
+  then
+    fprintf fmt "%s" id.var_id
+  else
+    if is_output m id
+    then
+      fprintf fmt "%s" id.var_id
+    else
+      fprintf fmt "&%s" id.var_id
+
 (* Declaration of an input variable:
    - if its type is array/matrix/etc, then declare it as a mere pointer,
      in order to cope with unknown/parametric array dimensions, 
@@ -159,8 +227,15 @@ let pp_c_decl_output_var fmt id =
      known in order to statically allocate memory, 
      so we print the full type
 *)
-let pp_c_decl_local_var fmt id =
-  pp_c_type id.var_id fmt id.var_type
+let pp_c_decl_local_var m fmt id =
+  if id.var_dec_const
+  then
+    Format.fprintf fmt "%a = %a"
+      (pp_c_type id.var_id) id.var_type
+      (pp_c_val "" (pp_c_var_read m)) (get_const_assign m id)
+  else
+    Format.fprintf fmt "%a"
+      (pp_c_type id.var_id) id.var_type
 
 let pp_c_decl_array_mem self fmt id =
   fprintf fmt "%a = (%a) (%s->_reg.%s)"
@@ -177,75 +252,9 @@ let pp_c_decl_struct_var fmt id =
   then pp_c_type (sprintf "(*%s)" id.var_id) fmt (Types.array_base_type id.var_type)
   else pp_c_type                  id.var_id  fmt id.var_type
 
-(* Access to the value of a variable:
-   - if it's not a scalar output, then its name is enough
-   - otherwise, dereference it (it has been declared as a pointer,
-     despite its scalar Lustre type)
-   - moreover, dereference memory array variables.
-*)
-let pp_c_var_read m fmt id =
-  if Types.is_address_type id.var_type
-  then
-    if is_memory m id
-    then fprintf fmt "(*%s)" id.var_id
-    else fprintf fmt "%s" id.var_id
-  else
-    if is_output m id
-    then fprintf fmt "*%s" id.var_id
-    else fprintf fmt "%s" id.var_id
-
-(* Addressable value of a variable, the one that is passed around in calls:
-   - if it's not a scalar non-output, then its name is enough
-   - otherwise, reference it (it must be passed as a pointer,
-     despite its scalar Lustre type)
-*)
-let pp_c_var_write m fmt id =
-  if Types.is_address_type id.var_type
-  then
-    fprintf fmt "%s" id.var_id
-  else
-    if is_output m id
-    then
-      fprintf fmt "%s" id.var_id
-    else
-      fprintf fmt "&%s" id.var_id
-
 let pp_c_decl_instance_var fmt (name, (node, static)) = 
   fprintf fmt "%a *%s" pp_machine_memtype_name (node_name node) name
 
-let pp_c_tag fmt t =
- pp_print_string fmt (if t = tag_true then "1" else if t = tag_false then "0" else t)
-
-(* Prints a constant value *)
-let rec pp_c_const fmt c =
-  match c with
-    | Const_int i     -> pp_print_int fmt i
-    | Const_real r    -> pp_print_string fmt r
-    | Const_float r   -> pp_print_float fmt r
-    | Const_tag t     -> pp_c_tag fmt t
-    | Const_array ca  -> fprintf fmt "{%a }" (Utils.fprintf_list ~sep:", " pp_c_const) ca
-    | Const_struct fl -> fprintf fmt "{%a }" (Utils.fprintf_list ~sep:", " (fun fmt (f, c) -> pp_c_const fmt c)) fl
-    | Const_string _ -> assert false (* string occurs in annotations not in C *)
-
-(* Prints a value expression [v], with internal function calls only.
-   [pp_var] is a printer for variables (typically [pp_c_var_read]),
-   but an offset suffix may be added for array variables
-*)
-let rec pp_c_val self pp_var fmt v =
-  match v with
-  | Cst c         -> pp_c_const fmt c
-  | Array vl      -> fprintf fmt "{%a}" (Utils.fprintf_list ~sep:", " (pp_c_val self pp_var)) vl
-  | Access (t, i) -> fprintf fmt "%a[%a]" (pp_c_val self pp_var) t (pp_c_val self pp_var) i
-  | Power (v, n)  -> assert false
-  | LocalVar v    -> pp_var fmt v
-  | StateVar v    ->
-    (* array memory vars are represented by an indirection to a local var with the right type,
-       in order to avoid casting everywhere. *)
-    if Types.is_array_type v.var_type
-    then fprintf fmt "%a" pp_var v
-    else fprintf fmt "%s->_reg.%a" self pp_var v
-  | Fun (n, vl)   -> Basic_library.pp_c n (pp_c_val self pp_var) fmt vl
-
 let pp_c_checks self fmt m =
   Utils.fprintf_list ~sep:"" 
     (fun fmt (loc, check) -> 
diff --git a/src/backends/C/c_backend_header.ml b/src/backends/C/c_backend_header.ml
index 83d01f8ce72f7f0bbf7026743b35c4e68d1a74a3..50e156b80e079e760a77db772832262e9f301878 100644
--- a/src/backends/C/c_backend_header.ml
+++ b/src/backends/C/c_backend_header.ml
@@ -36,34 +36,65 @@ struct
 let print_import_standard fmt =
   fprintf fmt "#include \"%s/arrow.h\"@.@." Version.include_path
 
-let print_static_declare_instance attr fmt (i, (m, static)) =
+let rec print_static_val pp_var fmt v =
+  match v with
+  | Cst c         -> pp_c_const fmt c
+  | LocalVar v    -> pp_var fmt v
+  | Fun (n, vl)   -> Basic_library.pp_c n (print_static_val pp_var) fmt vl
+  | _             -> (Format.eprintf "Internal error: C_backend_header.print_static_val"; assert false)
+
+let print_constant m pp_var fmt v =
+  Format.fprintf fmt "inst ## %s = %a"
+    v.var_id
+    (print_static_val pp_var) (Machine_code.get_const_assign m v)
+
+let print_static_constant (m, attr, inst) fmt const_locals =
+  let pp_var fmt v =
+    if List.mem v const_locals
+    then
+      Format.fprintf fmt "%s ## %s" inst v.var_id
+    else 
+      Format.fprintf fmt "%s" v.var_id in
+  Format.fprintf fmt "%a%t"
+    (Utils.fprintf_list ~sep:";\\@," (print_constant m pp_var)) const_locals
+    (Utils.pp_final_char_if_non_empty ";\\@," const_locals)
+
+let print_static_declare_instance (m, attr, inst) const_locals fmt (i, (n, static)) =
+  let pp_var fmt v =
+    if List.mem v const_locals
+    then
+      Format.fprintf fmt "%s ## %s" inst v.var_id
+    else 
+      Format.fprintf fmt "%s" v.var_id in
+  let values = List.map (Machine_code.value_of_dimension m) static in
   fprintf fmt "%a(%s, %a%t%s)"
-    pp_machine_static_declare_name (node_name m)
+    pp_machine_static_declare_name (node_name n)
     attr
-    (Utils.fprintf_list ~sep:", " Dimension.pp_dimension) static
+    (Utils.fprintf_list ~sep:", " (print_static_val pp_var)) values
     (Utils.pp_final_char_if_non_empty ", " static)
     i
 
-let print_static_declare_macro fmt m =
+let print_static_declare_macro fmt (m, attr, inst) =
+  let const_locals = List.filter (fun vdecl -> vdecl.var_dec_const) m.mstep.step_locals in
   let array_mem = List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory in
-  let inst = mk_instance m in
-  let attr = mk_attribute m in
-  fprintf fmt "@[<v 2>#define %a(%s, %a%t%s)\\@,%s %a %s;\\@,%a%t%a;@,@]"
+  fprintf fmt "@[<v 2>#define %a(%s, %a%t%s)\\@,%a%s %a %s;\\@,%a%t%a;@,@]"
     pp_machine_static_declare_name m.mname.node_id
     attr
     (Utils.fprintf_list ~sep:", " (pp_c_var_read m)) m.mstatic
     (Utils.pp_final_char_if_non_empty ", " m.mstatic)
     inst
+    (* constants *)
+    (print_static_constant (m, attr, inst)) const_locals
     attr
     pp_machine_memtype_name m.mname.node_id
     inst
-    (Utils.fprintf_list ~sep:";\\@," pp_c_decl_local_var) array_mem
+    (Utils.fprintf_list ~sep:";\\@," (pp_c_decl_local_var m)) array_mem
     (Utils.pp_final_char_if_non_empty ";\\@," array_mem)
     (Utils.fprintf_list ~sep:";\\@,"
        (fun fmt (i',m') ->
-	 let path = sprintf "inst ## _%s" i' in
+	 let path = sprintf "%s ## _%s" inst i' in
 	 fprintf fmt "%a"
-	   (print_static_declare_instance attr) (path,m')
+	   (print_static_declare_instance (m, attr, inst) const_locals) (path, m')
        )) m.minstances
 
       
@@ -73,13 +104,15 @@ let print_static_link_instance fmt (i, (m, _)) =
 (* Allocation of a node struct:
    - if node memory is an array/matrix/etc, we cast it to a pointer (see pp_registers_struct)
 *)
-let print_static_link_macro fmt m =
+let print_static_link_macro fmt (m, attr, inst) =
   let array_mem = List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory in
-  fprintf fmt "@[<v>@[<v 2>#define %a(inst) do {\\@,%a%t%a;\\@]@,} while (0)@.@]"
+  fprintf fmt "@[<v>@[<v 2>#define %a(%s) do {\\@,%a%t%a;\\@]@,} while (0)@.@]"
     pp_machine_static_link_name m.mname.node_id
+    inst
     (Utils.fprintf_list ~sep:";\\@,"
        (fun fmt v ->
-	 fprintf fmt "inst._reg.%s = (%a*) &%s"
+	 fprintf fmt "%s._reg.%s = (%a*) &%s"
+	   inst
 	   v.var_id
            (fun fmt v -> pp_c_type "" fmt (Types.array_base_type v.var_type)) v
 	   v.var_id
@@ -87,24 +120,29 @@ let print_static_link_macro fmt m =
     (Utils.pp_final_char_if_non_empty ";\\@," array_mem)
     (Utils.fprintf_list ~sep:";\\@,"
        (fun fmt (i',m') ->
-	 let path = sprintf "inst ## _%s" i' in
-	 fprintf fmt "%a;\\@,inst.%s = &%s"
+	 let path = sprintf "%s ## _%s" inst i' in
+	 fprintf fmt "%a;\\@,%s.%s = &%s"
 	   print_static_link_instance (path,m')
+	   inst
 	   i'
 	   path
        )) m.minstances
-      
-let print_static_alloc_macro fmt m =
-  fprintf fmt "@[<v>@[<v 2>#define %a(attr,%a%tinst)\\@,%a(attr,%a%tinst);\\@,%a(inst);@]@,@]@."
+
+let print_static_alloc_macro fmt (m, attr, inst) =
+  fprintf fmt "@[<v>@[<v 2>#define %a(%s, %a%t%s)\\@,%a(%s, %a%t%s);\\@,%a(%s);@]@,@]@."
     pp_machine_static_alloc_name m.mname.node_id
+    attr
     (Utils.fprintf_list ~sep:", " (pp_c_var_read m)) m.mstatic
     (Utils.pp_final_char_if_non_empty ", " m.mstatic)
+    inst
     pp_machine_static_declare_name m.mname.node_id
+    attr
     (Utils.fprintf_list ~sep:", " (pp_c_var_read m)) m.mstatic
     (Utils.pp_final_char_if_non_empty ", " m.mstatic)
+    inst
     pp_machine_static_link_name m.mname.node_id
+    inst
 
- 
 let print_machine_decl fmt m =
   Mod.print_machine_decl_prefix fmt m;
   if fst (get_stateless_status m) then
@@ -117,17 +155,21 @@ let print_machine_decl fmt m =
     begin
       (* Static allocation *)
       if !Options.static_mem
-      then (
-	fprintf fmt "%a@.%a@.%a@."
-	  print_static_declare_macro m
-	  print_static_link_macro m
-	  print_static_alloc_macro m
-      )
-      else ( 
+      then
+	begin
+	  let inst = mk_instance m in
+	  let attr = mk_attribute m in
+	  fprintf fmt "%a@.%a@.%a@."
+	    print_static_declare_macro (m, attr, inst)
+	    print_static_link_macro (m, attr, inst)
+	    print_static_alloc_macro (m, attr, inst)
+	end
+      else
+	begin 
         (* Dynamic allocation *)
-	fprintf fmt "extern %a;@.@."
-	  print_alloc_prototype (m.mname.node_id, m.mstatic)
-      );
+	  fprintf fmt "extern %a;@.@."
+	    print_alloc_prototype (m.mname.node_id, m.mstatic)
+	end;
       let self = mk_self m in
       fprintf fmt "extern %a;@.@."
 	(print_reset_prototype self) (m.mname.node_id, m.mstatic);
@@ -148,10 +190,12 @@ let print_machine_alloc_decl fmt m =
       then
 	begin
 	  (* Static allocation *)
+	  let inst = mk_instance m in
+	  let attr = mk_attribute m in
 	  fprintf fmt "%a@.%a@.%a@."
-		  print_static_declare_macro m
-		  print_static_link_macro m
-		  print_static_alloc_macro m
+		  print_static_declare_macro (m, attr, inst)
+		  print_static_link_macro (m, attr, inst)
+		  print_static_alloc_macro (m, attr, inst)
 	end
       else
 	begin 
diff --git a/src/backends/C/c_backend_main.ml b/src/backends/C/c_backend_main.ml
index e767723fe8ca32b1ed678474206583b1b654720d..578c6a3e4e936fba9bce0280c176566db3c4d7d5 100644
--- a/src/backends/C/c_backend_main.ml
+++ b/src/backends/C/c_backend_main.ml
@@ -31,7 +31,7 @@ struct
 (********************************************************************************************)
 
 let print_get_input fmt v =
-  match v.var_type.Types.tdesc with
+  match (Types.repr v.var_type).Types.tdesc with
     | Types.Tint -> fprintf fmt "_get_int(\"%s\")" v.var_id
     | Types.Tbool -> fprintf fmt "_get_bool(\"%s\")" v.var_id
     | Types.Treal -> fprintf fmt "_get_double(\"%s\")" v.var_id
@@ -39,7 +39,7 @@ let print_get_input fmt v =
 
 let print_put_outputs fmt ol = 
   let po fmt o =
-    match o.var_type.Types.tdesc with
+    match (Types.repr o.var_type).Types.tdesc with
     | Types.Tint -> fprintf fmt "_put_int(\"%s\", %s)" o.var_id o.var_id
     | Types.Tbool -> fprintf fmt "_put_bool(\"%s\", %s)" o.var_id o.var_id
     | Types.Treal -> fprintf fmt "_put_double(\"%s\", %s)" o.var_id o.var_id
diff --git a/src/backends/C/c_backend_src.ml b/src/backends/C/c_backend_src.ml
index 230339752f1e9943badcf3a7ab0e4233ad43fc13..ba897830184f13741ef9edc443d6d6313c26e44a 100644
--- a/src/backends/C/c_backend_src.ml
+++ b/src/backends/C/c_backend_src.ml
@@ -293,6 +293,12 @@ let print_alloc_instance fmt (i, (m, static)) =
     pp_machine_alloc_name (node_name m)
     (Utils.fprintf_list ~sep:", " Dimension.pp_dimension) static
 
+let print_alloc_const fmt m =
+  let const_locals = List.filter (fun vdecl -> vdecl.var_dec_const) m.mstep.step_locals in
+  fprintf fmt "%a%t"
+    (Utils.fprintf_list ~sep:";@," (pp_c_decl_local_var m)) const_locals
+    (Utils.pp_final_char_if_non_empty ";@," const_locals)
+
 let print_alloc_array fmt vdecl =
   let base_type = Types.array_base_type vdecl.var_type in
   let size_types = Types.array_type_multi_dimension vdecl.var_type in
@@ -321,7 +327,7 @@ let print_stateless_code dependencies fmt m =
     fprintf fmt "@[<v 2>%a {@,%a%t@,%a%a%t%t@]@,}@.@."
       print_stateless_prototype (m.mname.node_id, m.mstep.step_inputs, m.mstep.step_outputs)
       (* locals *)
-      (Utils.fprintf_list ~sep:";@," pp_c_decl_local_var) m.mstep.step_locals
+      (Utils.fprintf_list ~sep:";@," (pp_c_decl_local_var m)) m.mstep.step_locals
       (Utils.pp_final_char_if_non_empty ";@," m.mstep.step_locals)
       (* check assertions *)
       (pp_c_checks self) m
@@ -336,7 +342,7 @@ let print_stateless_code dependencies fmt m =
     fprintf fmt "@[<v 2>%a {@,%a%t@,%a%a%t%t@]@,}@.@."
       print_stateless_prototype (m.mname.node_id, (m.mstep.step_inputs@gen_locals@gen_calls), m.mstep.step_outputs)
       (* locals *)
-      (Utils.fprintf_list ~sep:";@," pp_c_decl_local_var) base_locals
+      (Utils.fprintf_list ~sep:";@," (pp_c_decl_local_var m)) base_locals
       (Utils.pp_final_char_if_non_empty ";" base_locals)
       (* check assertions *)
       (pp_c_checks self) m
@@ -346,8 +352,13 @@ let print_stateless_code dependencies fmt m =
       (fun fmt -> fprintf fmt "return;")
 
 let print_reset_code dependencies fmt m self =
-  fprintf fmt "@[<v 2>%a {@,%a%treturn;@]@,}@.@."
+  let const_locals = List.filter (fun vdecl -> vdecl.var_dec_const) m.mstep.step_locals in
+  fprintf fmt "@[<v 2>%a {@,%a%t@,%a%treturn;@]@,}@.@."
     (print_reset_prototype self) (m.mname.node_id, m.mstatic)
+    (* constant locals decl *)
+    (Utils.fprintf_list ~sep:";@," (pp_c_decl_local_var m)) const_locals
+    (Utils.pp_final_char_if_non_empty ";" const_locals)
+    (* instrs *)
     (Utils.fprintf_list ~sep:"@," (pp_machine_instr dependencies m self)) m.minit
     (Utils.pp_newline_if_non_empty m.minit)
 
@@ -359,7 +370,7 @@ let print_step_code dependencies fmt m self =
     fprintf fmt "@[<v 2>%a {@,%a%t%a%t@,%a%a%t%t@]@,}@.@."
       (print_step_prototype self) (m.mname.node_id, m.mstep.step_inputs, m.mstep.step_outputs)
       (* locals *)
-      (Utils.fprintf_list ~sep:";@," pp_c_decl_local_var) m.mstep.step_locals
+      (Utils.fprintf_list ~sep:";@," (pp_c_decl_local_var m)) m.mstep.step_locals
       (Utils.pp_final_char_if_non_empty ";@," m.mstep.step_locals)
       (* array mems *)
       (Utils.fprintf_list ~sep:";@," (pp_c_decl_array_mem self)) array_mems
@@ -377,7 +388,7 @@ let print_step_code dependencies fmt m self =
     fprintf fmt "@[<v 2>%a {@,%a%t@,%a%a%t%t@]@,}@.@."
       (print_step_prototype self) (m.mname.node_id, (m.mstep.step_inputs@gen_locals@gen_calls), m.mstep.step_outputs)
       (* locals *)
-      (Utils.fprintf_list ~sep:";@," pp_c_decl_local_var) base_locals
+      (Utils.fprintf_list ~sep:";@," (pp_c_decl_local_var m)) base_locals
       (Utils.pp_final_char_if_non_empty ";" base_locals)
       (* check assertions *)
       (pp_c_checks self) m
@@ -402,8 +413,9 @@ let print_machine dependencies fmt m =
       (* Alloc function, only if non static mode *)
       if (not !Options.static_mem) then  
 	begin
-	  fprintf fmt "@[<v 2>%a {@,%a@]@,}@.@."
+	  fprintf fmt "@[<v 2>%a {@,%a%a@]@,}@.@."
 	    print_alloc_prototype (m.mname.node_id, m.mstatic)
+	    print_alloc_const m
 	    print_alloc_code m;
 	end;
       let self = mk_self m in
@@ -435,6 +447,7 @@ let print_lib_c source_fmt basename prog machines dependencies =
   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 */@.";
@@ -446,6 +459,7 @@ let print_lib_c source_fmt basename prog machines dependencies =
       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>";
diff --git a/src/causality.ml b/src/causality.ml
index 37b2184c21949caa46d507bc40b611b3c305879c..19c429e1bc1974f530fa90b740976505f45cf971 100644
--- a/src/causality.ml
+++ b/src/causality.ml
@@ -28,7 +28,7 @@ module IdentDepGraph = Graph.Imperative.Digraph.ConcreteBidirectional (IdentModu
    by duplication of some mem vars into local node vars.
    Thus, cylic dependency errors may only arise between no-mem vars.
    non-mem variables are:
-   - inputs: not needed for causality/scheduling, needed only for detecting useless vars
+   - constants/inputs: not needed for causality/scheduling, needed only for detecting useless vars
    - read mems (fake vars): same remark as above.
    - outputs: decoupled from mems, if necessary
    - locals
@@ -133,6 +133,9 @@ let node_input_variables nd =
 let node_local_variables nd =
  List.fold_left (fun locals v -> ISet.add v.var_id locals) ISet.empty nd.node_locals
 
+let node_constant_variables nd =
+  List.fold_left (fun locals v -> if v.var_dec_const then ISet.add v.var_id locals else locals) ISet.empty nd.node_locals
+
 let node_output_variables nd =
  List.fold_left (fun outputs v -> ISet.add v.var_id outputs) ISet.empty nd.node_outputs
 
@@ -533,7 +536,10 @@ let add_external_dependency outputs mems g =
 
 let global_dependency node =
   let mems = ExprDep.node_memory_variables node in
-  let inputs = ExprDep.node_input_variables node in
+  let inputs =
+    ISet.union
+      (ExprDep.node_input_variables node)
+      (ExprDep.node_constant_variables node) in
   let outputs = ExprDep.node_output_variables node in
   let node_vars = ExprDep.node_variables node in
   let (g_non_mems, g_mems) = ExprDep.dependence_graph mems inputs node_vars node in
diff --git a/src/clock_calculus.ml b/src/clock_calculus.ml
index 6f64ee073b95fecc77e5ee47fdf6b3b28f2cefa8..ee201a880f60b37691cf4e0f8e6ec1566000628b 100755
--- a/src/clock_calculus.ml
+++ b/src/clock_calculus.ml
@@ -779,7 +779,15 @@ let clock_var_decl scoped env vdecl =
       if Types.get_clock_base_type vdecl.var_type <> None
       then new_ck (Ccarrying ((new_carrier Carry_name scoped),ck)) scoped
       else ck in
-  vdecl.var_clock <- ck;
+  (if vdecl.var_dec_const
+   then match vdecl.var_dec_value with
+   | None   -> ()
+   | Some v ->
+     begin
+       let ck_static = clock_expr env v in
+       try_unify ck ck_static v.expr_loc
+     end);
+  try_unify ck vdecl.var_clock vdecl.var_loc;
   Env.add_value env vdecl.var_id ck
 
 (* Clocks a variable declaration list *)
diff --git a/src/clock_predef.ml b/src/clock_predef.ml
index 24669fd2f2f653b5e059d9a1c629aaa424136c55..a2cd3fedaadcb5333e3cb8f885b3b2e7b1853ce6 100644
--- a/src/clock_predef.ml
+++ b/src/clock_predef.ml
@@ -42,6 +42,8 @@ let ck_clock_to_bool =
   let cuniv = new_carrier Carry_var false in
   new_ck (Carrow (new_ck (Ccarrying (cuniv, univ)) false, univ))
 
+let ck_carrier id ck =
+ new_ck (Ccarrying (new_carrier (Carry_const id) true, ck)) true
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
 (* End: *)
diff --git a/src/compiler_common.ml b/src/compiler_common.ml
index e00a0c0ba4bf588240262c203b977b10437593e7..f375d06a707913c8bf92272e6a9b2aaf7a7d9922 100644
--- a/src/compiler_common.ml
+++ b/src/compiler_common.ml
@@ -73,7 +73,7 @@ let parse_source source_name =
     Parse.report_error err;
     raise exc
   | Corelang.Error (loc, err) as exc ->
-    eprintf "Parsing error %a%a@."
+    eprintf "Parsing error: %a%a@."
       Corelang.pp_error err
       Location.pp_loc loc;
     raise exc
@@ -83,7 +83,7 @@ let check_stateless_decls decls =
   try
     Stateless.check_prog decls
   with (Stateless.Error (loc, err)) as exc ->
-    eprintf "Stateless status error %a%a@."
+    eprintf "Stateless status error: %a%a@."
       Stateless.pp_error err
       Location.pp_loc loc;
     raise exc
@@ -95,7 +95,7 @@ let type_decls env decls =
       try
 	Typing.type_prog env decls
       with (Types.Error (loc,err)) as exc ->
-	eprintf "Typing error %a%a@."
+	eprintf "Typing error: %a%a@."
 	  Types.pp_error err
 	  Location.pp_loc loc;
 	raise exc
@@ -112,7 +112,7 @@ let clock_decls env decls =
       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;
+	eprintf "Clock calculus error: %a%a@." Clocks.pp_error err Location.pp_loc loc;
 	raise exc
     end
   in
diff --git a/src/corelang.ml b/src/corelang.ml
index 973f44decd5728b7bde260434d8c38e6ad8d55e5..9e39aac391d66dc5154820cc33aa252b1ffd3878 100755
--- a/src/corelang.ml
+++ b/src/corelang.ml
@@ -41,12 +41,14 @@ let mktyp loc d =
 let mkclock loc d =
   { ck_dec_desc = d; ck_dec_loc = loc }
 
-let mkvar_decl loc ?(orig=false) (id, ty_dec, ck_dec, is_const) =
+let mkvar_decl loc ?(orig=false) (id, ty_dec, ck_dec, is_const, value) =
+  assert (value = None || is_const);
   { var_id = id;
     var_orig = orig;
     var_dec_type = ty_dec;
     var_dec_clock = ck_dec;
     var_dec_const = is_const;
+    var_dec_value = value;
     var_type = Types.new_var ();
     var_clock = Clocks.new_var true;
     var_loc = loc }
@@ -66,6 +68,7 @@ let var_decl_of_const c =
     var_dec_type = { ty_dec_loc = c.const_loc; ty_dec_desc = Tydec_any };
     var_dec_clock = { ck_dec_loc = c.const_loc; ck_dec_desc = Ckdec_any };
     var_dec_const = true;
+    var_dec_value = None;
     var_type = c.const_type;
     var_clock = Clocks.new_var false;
     var_loc = c.const_loc }
@@ -93,6 +96,10 @@ let mktop_decl loc own itf d =
 let mkpredef_call loc funname args =
   mkexpr loc (Expr_appl (funname, mkexpr loc (Expr_tuple args), None))
 
+let is_clock_dec_type cty =
+  match cty with
+  | Tydec_clock _ -> true
+  | _             -> false
 
 let const_of_top top_decl =
   match top_decl.top_decl_desc with
@@ -578,6 +585,983 @@ let get_node_interface nd =
 (************************************************************************)
 (*        Renaming                                                      *)
 
+let rec rename_static rename cty =
+ match cty with
+ | Tydec_array (d, cty') -> Tydec_array (Dimension.expr_replace_expr rename d, rename_static rename cty')
+ | Tydec_clock cty       -> Tydec_clock (rename_static rename cty)
+ | Tydec_struct fl       -> Tydec_struct (List.map (fun (f, cty) -> f, rename_static rename cty) fl)
+ | _                      -> cty
+
+let rec rename_carrier rename cck =
+ match cck with
+ | Ckdec_bool cl -> Ckdec_bool (List.map (fun (c, l) -> rename c, l) cl)
+ | _             -> cck
+
+(*Format.eprintf "Types.rename_static %a = %a@." print_ty ty print_ty res; res*)
+
+(* applies the renaming function [fvar] to all variables of expression [expr] *)
+ let rec expr_replace_var fvar expr =
+  { expr with expr_desc = expr_desc_replace_var fvar expr.expr_desc }
+
+ and expr_desc_replace_var fvar expr_desc =
+   match expr_desc with
+   | Expr_const _ -> expr_desc
+   | Expr_ident i -> Expr_ident (fvar i)
+   | Expr_array el -> Expr_array (List.map (expr_replace_var fvar) el)
+   | Expr_access (e1, d) -> Expr_access (expr_replace_var fvar e1, d)
+   | Expr_power (e1, d) -> Expr_power (expr_replace_var fvar e1, d)
+   | Expr_tuple el -> Expr_tuple (List.map (expr_replace_var fvar) el)
+   | Expr_ite (c, t, e) -> Expr_ite (expr_replace_var fvar c, expr_replace_var fvar t, expr_replace_var fvar e)
+   | Expr_arrow (e1, e2)-> Expr_arrow (expr_replace_var fvar e1, expr_replace_var fvar e2) 
+   | Expr_fby (e1, e2) -> Expr_fby (expr_replace_var fvar e1, expr_replace_var fvar e2)
+   | Expr_pre e' -> Expr_pre (expr_replace_var fvar e')
+   | Expr_when (e', i, l)-> Expr_when (expr_replace_var fvar e', fvar i, l)
+   | Expr_merge (i, hl) -> Expr_merge (fvar i, List.map (fun (t, h) -> (t, expr_replace_var fvar h)) hl)
+   | Expr_appl (i, e', i') -> Expr_appl (i, expr_replace_var fvar e', Utils.option_map (expr_replace_var fvar) i')
+
+(* Applies the renaming function [fvar] to every rhs
+   only when the corresponding lhs satisfies predicate [pvar] *)
+ let eq_replace_rhs_var pvar fvar eq =
+   let pvar l = List.exists pvar l in
+   let rec replace lhs rhs =
+     { rhs with expr_desc = replace_desc lhs rhs.expr_desc }
+   and replace_desc lhs rhs_desc =
+     match lhs with
+     | []  -> assert false
+     | [_] -> if pvar lhs then expr_desc_replace_var fvar rhs_desc else rhs_desc
+     | _   ->
+       (match rhs_desc with
+       | Expr_tuple tl ->
+	 Expr_tuple (List.map2 (fun v e -> replace [v] e) lhs tl)
+       | Expr_appl (f, arg, None) when Basic_library.is_internal_fun f ->
+	 let args = expr_list_of_expr arg in
+	 Expr_appl (f, expr_of_expr_list arg.expr_loc (List.map (replace lhs) args), None)
+       | Expr_array _
+       | Expr_access _
+       | Expr_power _
+       | Expr_const _
+       | Expr_ident _
+       | Expr_appl _   ->
+	 if pvar lhs
+	 then expr_desc_replace_var fvar rhs_desc
+	 else rhs_desc
+       | Expr_ite (c, t, e)   -> Expr_ite (replace lhs c, replace lhs t, replace lhs e)
+       | Expr_arrow (e1, e2)  -> Expr_arrow (replace lhs e1, replace lhs e2) 
+       | Expr_fby (e1, e2)    -> Expr_fby (replace lhs e1, replace lhs e2)
+       | Expr_pre e'          -> Expr_pre (replace lhs e')
+       | Expr_when (e', i, l) -> let i' = if pvar lhs then fvar i else i
+				 in Expr_when (replace lhs e', i', l)
+       | Expr_merge (i, hl)   -> let i' = if pvar lhs then fvar i else i
+				 in Expr_merge (i', List.map (fun (t, h) -> (t, replace lhs h)) hl)
+       )
+   in { eq with eq_rhs = replace eq.eq_lhs eq.eq_rhs }
+
+
+ let rec rename_expr  f_node f_var f_const expr =
+   { expr with expr_desc = rename_expr_desc f_node f_var f_const expr.expr_desc }
+ and rename_expr_desc f_node f_var f_const expr_desc =
+   let re = rename_expr  f_node f_var f_const in
+   match expr_desc with
+   | Expr_const _ -> expr_desc
+   | Expr_ident i -> Expr_ident (f_var i)
+   | Expr_array el -> Expr_array (List.map re el)
+   | Expr_access (e1, d) -> Expr_access (re e1, d)
+   | Expr_power (e1, d) -> Expr_power (re e1, d)
+   | Expr_tuple el -> Expr_tuple (List.map re el)
+   | Expr_ite (c, t, e) -> Expr_ite (re c, re t, re e)
+   | Expr_arrow (e1, e2)-> Expr_arrow (re e1, re e2) 
+   | Expr_fby (e1, e2) -> Expr_fby (re e1, re e2)
+   | Expr_pre e' -> Expr_pre (re e')
+   | Expr_when (e', i, l)-> Expr_when (re e', f_var i, l)
+   | Expr_merge (i, hl) -> 
+     Expr_merge (f_var i, List.map (fun (t, h) -> (t, re h)) hl)
+   | Expr_appl (i, e', i') -> 
+     Expr_appl (f_node i, re e', Utils.option_map re i')
+  
+ let rename_node_annot f_node f_var f_const expr  =
+   expr
+ (* TODO assert false *)
+
+ let rename_expr_annot f_node f_var f_const annot =
+   annot
+ (* TODO assert false *)
+
+let rename_node f_node f_var f_const nd =
+  let rename_var v = { v with var_id = f_var v.var_id } in
+  let rename_eq eq = { eq with
+      eq_lhs = List.map f_var eq.eq_lhs; 
+      eq_rhs = rename_expr f_node f_var f_const eq.eq_rhs
+    } 
+  in
+  let inputs = List.map rename_var nd.node_inputs in
+  let outputs = List.map rename_var nd.node_outputs in
+  let locals = List.map rename_var nd.node_locals in
+  let gen_calls = List.map (rename_expr f_node f_var f_const) nd.node_gencalls in
+  let node_checks = List.map (Dimension.expr_replace_var f_var)  nd.node_checks in
+  let node_asserts = List.map 
+    (fun a -> 
+      {a with assert_expr = 
+	  let expr = a.assert_expr in
+	  rename_expr f_node f_var f_const expr})
+    nd.node_asserts
+  in
+  let node_stmts = List.map (fun eq -> Eq (rename_eq eq)) (get_node_eqs nd) in
+  let spec = 
+    Utils.option_map 
+      (fun s -> rename_node_annot f_node f_var f_const s) 
+      nd.node_spec 
+  in
+  let annot =
+    List.map 
+      (fun s -> rename_expr_annot f_node f_var f_const s) 
+      nd.node_annot
+  in
+  {
+    node_id = f_node nd.node_id;
+    node_type = nd.node_type;
+    node_clock = nd.node_clock;
+    node_inputs = inputs;
+    node_outputs = outputs;
+    node_locals = locals;
+    node_gencalls = gen_calls;
+    node_checks = node_checks;
+    node_asserts = node_asserts;
+    node_stmts = node_stmts;
+    node_dec_stateless = nd.node_dec_stateless;
+    node_stateless = nd.node_stateless;
+    node_spec = spec;
+    node_annot = annot;
+  }
+
+
+let rename_const f_const c =
+  { c with const_id = f_const c.const_id }
+
+let rename_typedef f_var t =
+  match t.tydef_desc with
+  | Tydec_enum tags -> { t with tydef_desc = Tydec_enum (List.map f_var tags) }
+  | _               -> t
+
+let rename_prog f_node f_var f_const prog =
+  List.rev (
+    List.fold_left (fun accu top ->
+      (match top.top_decl_desc with
+      | Node nd -> 
+	 { top with top_decl_desc = Node (rename_node f_node f_var f_const nd) }
+      | Const c -> 
+	 { top with top_decl_desc = Const (rename_const f_const c) }
+      | TypeDef tdef ->
+	 { top with top_decl_desc = TypeDef (rename_typedef f_var tdef) }
+      | ImportedNode _
+      | Open _       -> top)
+      ::accu
+) [] prog
+		   )
+
+(**********************************************************************)
+(* Pretty printers *)
+
+let pp_decl_type fmt tdecl =
+  match tdecl.top_decl_desc with
+  | Node nd ->
+    fprintf fmt "%s: " nd.node_id;
+    Utils.reset_names ();
+    fprintf fmt "%a@ " Types.print_ty nd.node_type
+  | ImportedNode ind ->
+    fprintf fmt "%s: " ind.nodei_id;
+    Utils.reset_names ();
+    fprintf fmt "%a@ " Types.print_ty ind.nodei_type
+  | Const _ | Open _ | TypeDef _ -> ()
+
+let pp_prog_type fmt tdecl_list =
+  Utils.fprintf_list ~sep:"" pp_decl_type fmt tdecl_list
+
+let pp_decl_clock fmt cdecl =
+  match cdecl.top_decl_desc with
+  | Node nd ->
+    fprintf fmt "%s: " nd.node_id;
+    Utils.reset_names ();
+    fprintf fmt "%a@ " Clocks.print_ck nd.node_clock
+  | ImportedNode ind ->
+    fprintf fmt "%s: " ind.nodei_id;
+    Utils.reset_names ();
+    fprintf fmt "%a@ " Clocks.print_ck ind.nodei_clock
+  | Const _ | Open _ | TypeDef _ -> ()
+
+let pp_prog_clock fmt prog =
+  Utils.fprintf_list ~sep:"" pp_decl_clock fmt prog
+
+let pp_error fmt = function
+    Main_not_found ->
+      fprintf fmt "Cannot compile node %s: could not find the node definition.@."
+	!Options.main_node
+  | Main_wrong_kind ->
+    fprintf fmt
+      "Name %s does not correspond to a (non-imported) node definition.@." 
+      !Options.main_node
+  | No_main_specified ->
+    fprintf fmt "No main node specified@."
+  | Unbound_symbol sym ->
+    fprintf fmt
+      "%s is undefined.@."
+      sym
+  | Already_bound_symbol sym -> 
+    fprintf fmt
+      "%s is already defined.@."
+      sym
+  | Unknown_library sym ->
+    fprintf fmt
+      "impossible to load library %s.lusic@.Please compile the corresponding interface or source file.@."
+      sym
+  | Wrong_number sym ->
+    fprintf fmt
+      "library %s.lusic has a different version number and may crash compiler@.Please recompile the corresponding interface or source file.@."
+      sym
+
+(* filling node table with internal functions *)
+let vdecls_of_typ_ck cpt ty =
+  let loc = Location.dummy_loc in
+  List.map
+    (fun _ -> incr cpt;
+              let name = sprintf "_var_%d" !cpt in
+              mkvar_decl loc (name, mktyp loc Tydec_any, mkclock loc Ckdec_any, false, None))
+    (Types.type_list_of_type ty)
+
+let mk_internal_node id =
+  let spec = None in
+  let ty = Env.lookup_value Basic_library.type_env id in
+  let ck = Env.lookup_value Basic_library.clock_env id in
+  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
+    (ImportedNode
+       {nodei_id = id;
+	nodei_type = ty;
+	nodei_clock = ck;
+	nodei_inputs = vdecls_of_typ_ck cpt tin;
+	nodei_outputs = vdecls_of_typ_ck cpt tout;
+	nodei_stateless = Types.get_static_value ty <> None;
+	nodei_spec = spec;
+	nodei_prototype = None;
+       	nodei_in_lib = None;
+       })
+
+let add_internal_funs () =
+  List.iter
+    (fun id -> let nd = mk_internal_node id in Hashtbl.add node_table id nd)
+    Basic_library.internal_funs
+
+
+
+(* Replace any occurence of a var in vars_to_replace by its associated
+   expression in defs until e does not contain any such variables *)
+let rec substitute_expr vars_to_replace defs e =
+  let se = substitute_expr vars_to_replace defs in
+  { e with expr_desc = 
+      let ed = e.expr_desc in
+      match ed with
+      | Expr_const _ -> ed
+      | Expr_array el -> Expr_array (List.map se el)
+      | Expr_access (e1, d) -> Expr_access (se e1, d)
+      | Expr_power (e1, d) -> Expr_power (se e1, d)
+      | Expr_tuple el -> Expr_tuple (List.map se el)
+      | Expr_ite (c, t, e) -> Expr_ite (se c, se t, se e)
+      | Expr_arrow (e1, e2)-> Expr_arrow (se e1, se e2) 
+      | Expr_fby (e1, e2) -> Expr_fby (se e1, se e2)
+      | Expr_pre e' -> Expr_pre (se e')
+      | Expr_when (e', i, l)-> Expr_when (se e', i, l)
+      | Expr_merge (i, hl) -> Expr_merge (i, List.map (fun (t, h) -> (t, se h)) hl)
+      | Expr_appl (i, e', i') -> Expr_appl (i, se e', i')
+      | Expr_ident i -> 
+	if List.exists (fun v -> v.var_id = i) vars_to_replace then (
+	  let eq_i eq = eq.eq_lhs = [i] in
+	  if List.exists eq_i defs then
+	    let sub = List.find eq_i defs in
+	    let sub' = se sub.eq_rhs in
+	    sub'.expr_desc
+	  else 
+	    assert false
+	)
+	else
+	  ed
+
+  }
+(* FAUT IL RETIRER ?
+  
+ let rec expr_to_eexpr  expr =
+   { eexpr_tag = expr.expr_tag;
+     eexpr_desc = expr_desc_to_eexpr_desc expr.expr_desc;
+     eexpr_type = expr.expr_type;
+     eexpr_clock = expr.expr_clock;
+     eexpr_loc = expr.expr_loc
+   }
+ and expr_desc_to_eexpr_desc expr_desc =
+   let conv = expr_to_eexpr in
+   match expr_desc with
+   | Expr_const c -> EExpr_const (match c with
+     | Const_int x -> EConst_int x 
+     | Const_real x -> EConst_real x 
+     | Const_float x -> EConst_float x 
+     | Const_tag x -> EConst_tag x 
+     | _ -> assert false
+
+   )
+   | Expr_ident i -> EExpr_ident i
+   | Expr_tuple el -> EExpr_tuple (List.map conv el)
+
+   | Expr_arrow (e1, e2)-> EExpr_arrow (conv e1, conv e2) 
+   | Expr_fby (e1, e2) -> EExpr_fby (conv e1, conv e2)
+   | Expr_pre e' -> EExpr_pre (conv e')
+   | Expr_appl (i, e', i') -> 
+     EExpr_appl 
+       (i, conv e', match i' with None -> None | Some(id, _) -> Some id)
+
+   | Expr_when _
+   | Expr_merge _ -> assert false
+   | Expr_array _ 
+   | Expr_access _ 
+   | Expr_power _  -> assert false
+   | Expr_ite (c, t, e) -> assert false 
+   | _ -> assert false
+
+     *)
+let rec get_expr_calls nodes e =
+  get_calls_expr_desc nodes e.expr_desc
+and get_calls_expr_desc nodes expr_desc =
+  let get_calls = get_expr_calls nodes in
+  match expr_desc with
+  | Expr_const _ 
+   | Expr_ident _ -> Utils.ISet.empty
+   | Expr_tuple el
+   | Expr_array el -> List.fold_left (fun accu e -> Utils.ISet.union accu (get_calls e)) Utils.ISet.empty el
+   | Expr_pre e1 
+   | Expr_when (e1, _, _) 
+   | Expr_access (e1, _) 
+   | Expr_power (e1, _) -> get_calls e1
+   | Expr_ite (c, t, e) -> Utils.ISet.union (Utils.ISet.union (get_calls c) (get_calls t)) (get_calls e) 
+   | Expr_arrow (e1, e2) 
+   | Expr_fby (e1, e2) -> Utils.ISet.union (get_calls e1) (get_calls e2)
+   | Expr_merge (_, hl) -> List.fold_left (fun accu (_, h) -> Utils.ISet.union accu (get_calls h)) Utils.ISet.empty  hl
+   | Expr_appl (i, e', i') -> 
+     if Basic_library.is_internal_fun i then 
+       (get_calls e') 
+     else
+       let calls =  Utils.ISet.add i (get_calls e') in
+       let test = (fun n -> match n.top_decl_desc with Node nd -> nd.node_id = i | _ -> false) in
+       if List.exists test nodes then
+	 match (List.find test nodes).top_decl_desc with
+	 | Node nd -> Utils.ISet.union (get_node_calls nodes nd) calls
+	 | _ -> assert false
+       else 
+	 calls
+
+and get_eq_calls nodes eq =
+  get_expr_calls nodes eq.eq_rhs
+and get_node_calls nodes node =
+  List.fold_left (fun accu eq -> Utils.ISet.union (get_eq_calls nodes eq) accu) Utils.ISet.empty (get_node_eqs node)
+
+let rec get_expr_vars vars e =
+  get_expr_desc_vars vars e.expr_desc
+and get_expr_desc_vars vars expr_desc =
+  match expr_desc with
+  | Expr_const _ -> vars
+  | Expr_ident x -> Utils.ISet.add x vars
+  | Expr_tuple el
+  | Expr_array el -> List.fold_left get_expr_vars vars el
+  | Expr_pre e1 -> get_expr_vars vars e1
+  | Expr_when (e1, c, _) -> get_expr_vars (Utils.ISet.add c vars) e1 
+  | Expr_access (e1, d) 
+  | Expr_power (e1, d)   -> List.fold_left get_expr_vars vars [e1; expr_of_dimension d]
+  | Expr_ite (c, t, e) -> List.fold_left get_expr_vars vars [c; t; e]
+  | Expr_arrow (e1, e2) 
+  | Expr_fby (e1, e2) -> List.fold_left get_expr_vars vars [e1; e2]
+  | Expr_merge (c, hl) -> List.fold_left (fun vars (_, h) -> get_expr_vars vars h) (Utils.ISet.add c vars) hl
+  | Expr_appl (_, arg, None)   -> get_expr_vars vars arg
+  | Expr_appl (_, arg, Some r) -> List.fold_left get_expr_vars vars [arg; r]
+
+
+let rec expr_has_arrows e =
+  expr_desc_has_arrows e.expr_desc
+and expr_desc_has_arrows expr_desc =
+  match expr_desc with
+  | Expr_const _ 
+  | Expr_ident _ -> false
+  | Expr_tuple el
+  | Expr_array el -> List.exists expr_has_arrows el
+  | Expr_pre e1 
+  | Expr_when (e1, _, _) 
+  | Expr_access (e1, _) 
+  | Expr_power (e1, _) -> expr_has_arrows e1
+  | Expr_ite (c, t, e) -> List.exists expr_has_arrows [c; t; e]
+  | Expr_arrow (e1, e2) 
+  | Expr_fby (e1, e2) -> true
+  | Expr_merge (_, hl) -> List.exists (fun (_, h) -> expr_has_arrows h) hl
+  | Expr_appl (i, e', i') -> expr_has_arrows e'
+
+and eq_has_arrows eq =
+  expr_has_arrows eq.eq_rhs
+and node_has_arrows node =
+  List.exists (fun eq -> eq_has_arrows eq) (get_node_eqs node)
+
+let mkvar_decl loc ?(orig=false) (id, ty_dec, ck_dec, is_const, value) =
+  assert (value = None || is_const);
+  { var_id = id;
+    var_orig = orig;
+    var_dec_type = ty_dec;
+    var_dec_clock = ck_dec;
+    var_dec_const = is_const;
+    var_dec_value = value;
+    var_type = Types.new_var ();
+    var_clock = Clocks.new_var true;
+    var_loc = loc }
+
+let mkexpr loc d =
+  { expr_tag = Utils.new_tag ();
+    expr_desc = d;
+    expr_type = Types.new_var ();
+    expr_clock = Clocks.new_var true;
+    expr_delay = Delay.new_var ();
+    expr_annot = None;
+    expr_loc = loc }
+
+let var_decl_of_const c =
+  { var_id = c.const_id;
+    var_orig = true;
+    var_dec_type = { ty_dec_loc = c.const_loc; ty_dec_desc = Tydec_any };
+    var_dec_clock = { ck_dec_loc = c.const_loc; ck_dec_desc = Ckdec_any };
+    var_dec_const = true;
+    var_dec_value = None;
+    var_type = c.const_type;
+    var_clock = Clocks.new_var false;
+    var_loc = c.const_loc }
+
+let mk_new_name used id =
+  let rec new_name name cpt =
+    if used name
+    then new_name (sprintf "_%s_%i" id cpt) (cpt+1)
+    else name
+  in new_name id 1
+
+let mkeq loc (lhs, rhs) =
+  { eq_lhs = lhs;
+    eq_rhs = rhs;
+    eq_loc = loc }
+
+let mkassert loc expr =
+  { assert_loc = loc;
+    assert_expr = expr
+  }
+
+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 is_clock_dec_type cty =
+  match cty with
+  | Tydec_clock _ -> true
+  | _             -> false
+
+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 *)
+(************************************************************)
+
+let merge_node_annot ann1 ann2 =
+  { requires = ann1.requires @ ann2.requires;
+    ensures = ann1.ensures @ ann2.ensures;
+    behaviors = ann1.behaviors @ ann2.behaviors;
+    spec_loc = ann1.spec_loc
+  }
+
+let mkeexpr loc expr =
+  { eexpr_tag = Utils.new_tag ();
+    eexpr_qfexpr = expr;
+    eexpr_quantifiers = [];
+    eexpr_type = Types.new_var ();
+    eexpr_clock = Clocks.new_var true;
+    eexpr_normalized = None;
+    eexpr_loc = loc }
+
+let extend_eexpr q e = { e with eexpr_quantifiers = q@e.eexpr_quantifiers }
+
+(*
+let mkepredef_call loc funname args =
+  mkeexpr loc (EExpr_appl (funname, mkeexpr loc (EExpr_tuple args), None))
+
+let mkepredef_unary_call loc funname arg =
+  mkeexpr loc (EExpr_appl (funname, arg, None))
+*)
+
+let merge_expr_annot ann1 ann2 =
+  match ann1, ann2 with
+    | None, None -> assert false
+    | Some _, None -> ann1
+    | None, Some _ -> ann2
+    | Some ann1, Some ann2 -> Some {
+      annots = ann1.annots @ ann2.annots;
+      annot_loc = ann1.annot_loc
+    }
+
+let update_expr_annot node_id e annot =
+  List.iter (fun (key, _) -> 
+    Annotations.add_expr_ann node_id e.expr_tag key
+  ) annot.annots;
+  { e with expr_annot = merge_expr_annot e.expr_annot (Some annot) }
+
+
+(***********************************************************)
+(* Fast access to nodes, by name *)
+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
+    | ImportedNode nd -> nd.nodei_id
+    | _ -> assert false
+
+let is_generic_node td =
+  match td.top_decl_desc with 
+  | Node nd         -> List.exists (fun v -> v.var_dec_const) nd.node_inputs
+  | ImportedNode nd -> List.exists (fun v -> v.var_dec_const) nd.nodei_inputs
+  | _ -> assert false
+
+let node_inputs td =
+  match td.top_decl_desc with 
+  | Node nd         -> nd.node_inputs
+  | ImportedNode nd -> nd.nodei_inputs
+  | _ -> assert false
+
+let node_from_name id =
+  try
+    Hashtbl.find node_table id
+  with Not_found -> (Format.eprintf "Unable to find any node named %s@ @?" id;
+		     assert false)
+
+let is_imported_node td =
+  match td.top_decl_desc with 
+  | Node nd         -> false
+  | ImportedNode nd -> true
+  | _ -> assert false
+
+
+(* alias and type definition table *)
+
+let mktop = mktop_decl Location.dummy_loc Version.include_path false 
+
+let top_int_type = mktop (TypeDef {tydef_id = "int"; tydef_desc = Tydec_int})
+let top_bool_type = mktop (TypeDef {tydef_id = "bool"; tydef_desc = Tydec_bool})
+let top_float_type = mktop (TypeDef {tydef_id = "float"; tydef_desc = Tydec_float})
+let top_real_type = mktop (TypeDef {tydef_id = "real"; tydef_desc = Tydec_real})
+
+let type_table =
+  Utils.create_hashtable 20 [
+    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 
+  | Tydec_float | Tydec_any | Tydec_const _ -> false
+  | Tydec_clock typ' -> is_user_type typ'
+  | _ -> true
+
+let get_repr_type typ =
+  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 =
+  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' = (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
+  | Tydec_real          , Tydec_real
+  | Tydec_float         , Tydec_float
+  | Tydec_bool          , Tydec_bool            -> true
+  | Tydec_clock ty1     , Tydec_clock ty2       -> coretype_equal ty1 ty2
+  | Tydec_array (d1,ty1), Tydec_array (d2, ty2) -> Dimension.is_eq_dimension d1 d2 && coretype_equal ty1 ty2
+  | Tydec_enum tl1      , Tydec_enum tl2        -> List.sort compare tl1 = List.sort compare tl2
+  | Tydec_struct fl1    , Tydec_struct fl2      ->
+       List.length fl1 = List.length fl2
+    && List.for_all2 (fun (f1, t1) (f2, t2) -> f1 = f2 && coretype_equal t1 t2)
+      (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)
+
+let tag_true = "true"
+let tag_false = "false"
+let tag_default = "default"
+
+let const_is_bool c =
+ match c with
+ | Const_tag t -> t = tag_true || t = tag_false
+ | _           -> false
+
+(* Computes the negation of a boolean constant *)
+let const_negation c =
+  assert (const_is_bool c);
+  match c with
+  | Const_tag t when t = tag_true  -> Const_tag tag_false
+  | _                              -> Const_tag tag_true
+
+let const_or c1 c2 =
+  assert (const_is_bool c1 && const_is_bool c2);
+  match c1, c2 with
+  | Const_tag t1, _            when t1 = tag_true -> c1
+  | _           , Const_tag t2 when t2 = tag_true -> c2
+  | _                                             -> Const_tag tag_false
+
+let const_and c1 c2 =
+  assert (const_is_bool c1 && const_is_bool c2);
+  match c1, c2 with
+  | Const_tag t1, _            when t1 = tag_false -> c1
+  | _           , Const_tag t2 when t2 = tag_false -> c2
+  | _                                              -> Const_tag tag_true
+
+let const_xor c1 c2 =
+  assert (const_is_bool c1 && const_is_bool c2);
+   match c1, c2 with
+  | Const_tag t1, Const_tag t2 when t1 <> t2  -> Const_tag tag_true
+  | _                                         -> Const_tag tag_false
+
+let const_impl c1 c2 =
+  assert (const_is_bool c1 && const_is_bool c2);
+  match c1, c2 with
+  | Const_tag t1, _ when t1 = tag_false           -> Const_tag tag_true
+  | _           , Const_tag t2 when t2 = tag_true -> Const_tag tag_true
+  | _                                             -> Const_tag tag_false
+
+(* To guarantee uniqueness of tags in enum types *)
+let tag_table =
+  Utils.create_hashtable 20 [
+   tag_true, top_bool_type;
+   tag_false, top_bool_type
+  ]
+
+(* To guarantee uniqueness of fields in struct types *)
+let field_table =
+  Utils.create_hashtable 20 [
+  ]
+
+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 (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 (typedef_of_top (Hashtbl.find type_table cty)).tydef_desc with
+                     | Tydec_struct fl -> fl
+                     | _               -> assert false)
+ | _            -> assert false
+
+let const_of_bool b =
+ Const_tag (if b then tag_true else tag_false)
+
+(* let get_const c = snd (Hashtbl.find consts_table c) *)
+
+let ident_of_expr expr =
+ match expr.expr_desc with
+ | Expr_ident id -> id
+ | _             -> assert false
+
+(* Generate a new ident expression from a declared variable *)
+let expr_of_vdecl v =
+  { expr_tag = Utils.new_tag ();
+    expr_desc = Expr_ident v.var_id;
+    expr_type = v.var_type;
+    expr_clock = v.var_clock;
+    expr_delay = Delay.new_var ();
+    expr_annot = None;
+    expr_loc = v.var_loc }
+
+(* Caution, returns an untyped and unclocked expression *)
+let expr_of_ident id loc =
+  {expr_tag = Utils.new_tag ();
+   expr_desc = Expr_ident id;
+   expr_type = Types.new_var ();
+   expr_clock = Clocks.new_var true;
+   expr_delay = Delay.new_var ();
+   expr_loc = loc;
+   expr_annot = None}
+
+let is_tuple_expr expr =
+ match expr.expr_desc with
+  | Expr_tuple _ -> true
+  | _            -> false
+
+let expr_list_of_expr expr =
+  match expr.expr_desc with
+  | Expr_tuple elist -> elist
+  | _                -> [expr]
+
+let expr_of_expr_list loc elist =
+ match elist with
+ | [t]  -> { t with expr_loc = loc }
+ | t::_ ->
+    let tlist = List.map (fun e -> e.expr_type) elist in
+    let clist = List.map (fun e -> e.expr_clock) elist in
+    { t with expr_desc = Expr_tuple elist;
+	     expr_type = Type_predef.type_tuple tlist;
+	     expr_clock = Clock_predef.ck_tuple clist;
+	     expr_tag = Utils.new_tag ();
+	     expr_loc = loc }
+ | _    -> assert false
+
+let call_of_expr expr =
+ match expr.expr_desc with
+ | Expr_appl (f, args, r) -> (f, expr_list_of_expr args, r)
+ | _                      -> assert false
+
+(* Conversion from dimension expr to standard expr, for the purpose of printing, typing, etc... *)
+let rec expr_of_dimension dim =
+ match dim.dim_desc with
+ | Dbool b        ->
+     mkexpr dim.dim_loc (Expr_const (const_of_bool b))
+ | Dint i         ->
+     mkexpr dim.dim_loc (Expr_const (Const_int i))
+ | Dident id      ->
+     mkexpr dim.dim_loc (Expr_ident id)
+ | Dite (c, t, e) ->
+     mkexpr dim.dim_loc (Expr_ite (expr_of_dimension c, expr_of_dimension t, expr_of_dimension e))
+ | Dappl (id, args) ->
+     mkexpr dim.dim_loc (Expr_appl (id, expr_of_expr_list dim.dim_loc (List.map expr_of_dimension args), None))
+ | Dlink dim'       -> expr_of_dimension dim'
+ | Dvar
+ | Dunivar          -> (Format.eprintf "internal error: Corelang.expr_of_dimension %a@." Dimension.pp_dimension dim;
+			assert false)
+
+let dimension_of_const loc const =
+ match const with
+ | Const_int i                                    -> mkdim_int loc i
+ | Const_tag t when t = tag_true || t = tag_false -> mkdim_bool loc (t = tag_true)
+ | _                                              -> raise InvalidDimension
+
+(* Conversion from standard expr to dimension expr, for the purpose of injecting static call arguments 
+   into dimension expressions *)
+let rec dimension_of_expr expr =
+  match expr.expr_desc with
+  | Expr_const c  -> dimension_of_const expr.expr_loc c
+  | Expr_ident id -> mkdim_ident expr.expr_loc id
+  | Expr_appl (f, args, None) when Basic_library.is_internal_fun f ->
+      let k = Types.get_static_value (Env.lookup_value Basic_library.type_env f) in
+      if k = None then raise InvalidDimension;
+      mkdim_appl expr.expr_loc f (List.map dimension_of_expr (expr_list_of_expr args))
+  | Expr_ite (i, t, e)        ->
+      mkdim_ite expr.expr_loc (dimension_of_expr i) (dimension_of_expr t) (dimension_of_expr e)
+  | _ -> raise InvalidDimension (* not a simple dimension expression *)
+
+
+let sort_handlers hl =
+ List.sort (fun (t, _) (t', _) -> compare t t') hl
+
+let rec is_eq_expr e1 e2 = match e1.expr_desc, e2.expr_desc with
+  | Expr_const c1, Expr_const c2 -> c1 = c2
+  | Expr_ident i1, Expr_ident i2 -> i1 = i2
+  | Expr_array el1, Expr_array el2 
+  | Expr_tuple el1, Expr_tuple el2 -> 
+    List.length el1 = List.length el2 && List.for_all2 is_eq_expr el1 el2 
+  | Expr_arrow (e1, e2), Expr_arrow (e1', e2') -> is_eq_expr e1 e1' && is_eq_expr e2 e2'
+  | Expr_fby (e1,e2), Expr_fby (e1',e2') -> is_eq_expr e1 e1' && is_eq_expr e2 e2'
+  | Expr_ite (i1, t1, e1), Expr_ite (i2, t2, e2) -> is_eq_expr i1 i2 && is_eq_expr t1 t2 && is_eq_expr e1 e2
+  (* | Expr_concat (e1,e2), Expr_concat (e1',e2') -> is_eq_expr e1 e1' && is_eq_expr e2 e2' *)
+  (* | Expr_tail e, Expr_tail e' -> is_eq_expr e e' *)
+  | Expr_pre e, Expr_pre e' -> is_eq_expr e e'
+  | Expr_when (e, i, l), Expr_when (e', i', l') -> l=l' && i=i' && is_eq_expr e e'
+  | Expr_merge(i, hl), Expr_merge(i', hl') -> i=i' && List.for_all2 (fun (t, h) (t', h') -> t=t' && is_eq_expr h h') (sort_handlers hl) (sort_handlers hl')
+  | Expr_appl (i, e, r), Expr_appl (i', e', r') -> i=i' && r=r' && is_eq_expr e e'
+  | Expr_power (e1, i1), Expr_power (e2, i2)
+  | Expr_access (e1, i1), Expr_access (e2, i2) -> is_eq_expr e1 e2 && is_eq_expr (expr_of_dimension i1) (expr_of_dimension i2)
+  | _ -> false
+
+let get_node_vars nd =
+  nd.node_inputs @ nd.node_locals @ nd.node_outputs
+
+let mk_new_node_name nd id =
+  let used_vars = get_node_vars nd in
+  let used v = List.exists (fun vdecl -> vdecl.var_id = v) used_vars in
+  mk_new_name used id
+
+let get_var id var_list =
+    List.find (fun v -> v.var_id = id) var_list
+
+let get_node_var id node =
+  get_var id (get_node_vars node)
+
+let get_node_eqs =
+  let get_eqs stmts =
+    List.fold_right
+      (fun stmt res ->
+	match stmt with
+	| Eq eq -> eq :: res
+	| Aut _ -> assert false)
+      stmts
+      [] in
+  let table_eqs = Hashtbl.create 23 in
+  (fun nd ->
+    try
+      let (old, res) = Hashtbl.find table_eqs nd.node_id
+      in if old == nd.node_stmts then res else raise Not_found
+    with Not_found -> 
+      let res = get_eqs nd.node_stmts in
+      begin
+	Hashtbl.replace table_eqs nd.node_id (nd.node_stmts, res);
+	res
+      end)
+
+let get_node_eq id node =
+ List.find (fun eq -> List.mem id eq.eq_lhs) (get_node_eqs node)
+
+let get_nodes prog = 
+  List.fold_left (
+    fun nodes decl ->
+      match decl.top_decl_desc with
+	| Node _ -> decl::nodes
+	| Const _ | ImportedNode _ | Open _ | TypeDef _ -> nodes  
+  ) [] prog
+
+let get_imported_nodes prog = 
+  List.fold_left (
+    fun nodes decl ->
+      match decl.top_decl_desc with
+	| ImportedNode _ -> decl::nodes
+	| Const _ | Node _ | Open _ | TypeDef _-> nodes  
+  ) [] prog
+
+let get_consts prog = 
+  List.fold_right (
+    fun decl consts ->
+      match decl.top_decl_desc with
+	| 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;
+  nodei_type = nd.node_type;
+  nodei_clock = nd.node_clock;
+  nodei_inputs = nd.node_inputs;
+  nodei_outputs = nd.node_outputs;
+  nodei_stateless = nd.node_dec_stateless;
+  nodei_spec = nd.node_spec;
+  nodei_prototype = None;
+  nodei_in_lib = None;
+ }
+
+(************************************************************************)
+(*        Renaming                                                      *)
+
+let rec rename_static rename cty =
+ match cty with
+ | Tydec_array (d, cty') -> Tydec_array (Dimension.expr_replace_expr rename d, rename_static rename cty')
+ | Tydec_clock cty       -> Tydec_clock (rename_static rename cty)
+ | Tydec_struct fl       -> Tydec_struct (List.map (fun (f, cty) -> f, rename_static rename cty) fl)
+ | _                      -> cty
+
+let rec rename_carrier rename cck =
+ match cck with
+ | Ckdec_bool cl -> Ckdec_bool (List.map (fun (c, l) -> rename c, l) cl)
+ | _             -> cck
+
+(*Format.eprintf "Types.rename_static %a = %a@." print_ty ty print_ty res; res*)
+
 (* applies the renaming function [fvar] to all variables of expression [expr] *)
  let rec expr_replace_var fvar expr =
   { expr with expr_desc = expr_desc_replace_var fvar expr.expr_desc }
@@ -799,7 +1783,7 @@ let vdecls_of_typ_ck cpt ty =
   List.map
     (fun _ -> incr cpt;
               let name = sprintf "_var_%d" !cpt in
-              mkvar_decl loc (name, mktyp loc Tydec_any, mkclock loc Ckdec_any, false))
+              mkvar_decl loc (name, mktyp loc Tydec_any, mkclock loc Ckdec_any, false, None))
     (Types.type_list_of_type ty)
 
 let mk_internal_node id =
@@ -979,6 +1963,33 @@ and eq_has_arrows eq =
 and node_has_arrows node =
   List.exists (fun eq -> eq_has_arrows eq) (get_node_eqs node)
 
+let copy_var_decl vdecl =
+  mkvar_decl vdecl.var_loc ~orig:vdecl.var_orig (vdecl.var_id, vdecl.var_dec_type, vdecl.var_dec_clock, vdecl.var_dec_const, vdecl.var_dec_value)
+
+let copy_const cdecl =
+  { cdecl with const_type = Types.new_var () }
+
+let copy_node nd =
+  { nd with
+    node_type     = Types.new_var ();
+    node_clock    = Clocks.new_var true;
+    node_inputs   = List.map copy_var_decl nd.node_inputs;
+    node_outputs  = List.map copy_var_decl nd.node_outputs;
+    node_locals   = List.map copy_var_decl nd.node_locals;
+    node_gencalls = [];
+    node_checks   = [];
+    node_stateless = None;
+  }
+
+let copy_top top =
+  match top.top_decl_desc with
+  | Node nd -> { top with top_decl_desc = Node (copy_node nd)  }
+  | Const c -> { top with top_decl_desc = Const (copy_const c) }
+  | _       -> top
+
+let copy_prog top_list =
+  List.map copy_top top_list
+
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
 (* End: *)
diff --git a/src/corelang.mli b/src/corelang.mli
index a0eaa6cf253498016d8ad39d2c6c9861cb7850c8..d4a1d5689f2c337a4698c3f420e02f7970acd843 100755
--- a/src/corelang.mli
+++ b/src/corelang.mli
@@ -19,7 +19,8 @@ val dummy_clock_dec: clock_dec
 
 val mktyp: Location.t -> type_dec_desc -> type_dec
 val mkclock: Location.t -> clock_dec_desc -> clock_dec
-val mkvar_decl: Location.t -> ?orig:bool -> ident * type_dec * clock_dec * bool (* is const *) -> var_decl
+val mkvar_decl: Location.t -> ?orig:bool -> ident * type_dec * clock_dec * bool (* is const *) * expr option (* value *) -> var_decl
+
 val var_decl_of_const: const_desc -> var_decl
 val mkexpr: Location.t ->  expr_desc -> expr
 val mkeq: Location.t -> ident list * expr -> eq
@@ -41,6 +42,7 @@ 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 is_clock_dec_type: type_dec_desc -> bool
 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
@@ -111,16 +113,23 @@ val get_typedefs: program -> top_decl list
 val get_dependencies : program -> top_decl list
 (* val prog_unfold_consts: program -> program *)
 
+val rename_static: (ident -> Dimension.dim_expr) -> type_dec_desc -> type_dec_desc
+val rename_carrier: (ident -> ident) -> clock_dec_desc -> clock_dec_desc
+
 val get_expr_vars: Utils.ISet.t -> expr -> Utils.ISet.t
 val expr_replace_var: (ident -> ident) -> expr -> expr
 val eq_replace_rhs_var: (ident -> bool) -> (ident -> ident) -> eq -> eq
 
 (** rename_prog f_node f_var f_const prog *)
 val rename_prog: (ident -> ident) -> (ident -> ident) -> (ident -> ident) -> program -> program
-
-
 val substitute_expr: var_decl list -> eq list -> expr -> expr
 
+val copy_var_decl: var_decl -> var_decl
+val copy_const: const_desc -> const_desc
+val copy_node: node_desc -> node_desc
+val copy_top: top_decl -> top_decl
+val copy_prog: top_decl list -> top_decl list
+
 (** Annotation expression related functions *)
 val mkeexpr: Location.t ->  expr -> eexpr
 val merge_node_annot: node_annot -> node_annot -> node_annot 
diff --git a/src/dimension.ml b/src/dimension.ml
index e703905ac52fce6ca6e88e5b5208e817936236f5..79d6f1f03ee904c1f07a1267f79b4053de34e3ab 100644
--- a/src/dimension.ml
+++ b/src/dimension.ml
@@ -220,7 +220,7 @@ let rec eval eval_op eval_const dim =
   | Dident id ->
     (match eval_const id with
     | Some val_dim -> dim.dim_desc <- Dlink val_dim
-    | None         -> raise InvalidDimension)
+    | None         -> (Format.eprintf "invalid %a@." pp_dimension dim; raise InvalidDimension))
   | Dite (c, t, e) ->
     begin
       eval eval_op eval_const c;
@@ -243,7 +243,14 @@ let rec eval eval_op eval_const dim =
     end
   | Dvar -> ()
   | Dunivar -> assert false
-
+(*
+in
+begin
+  Format.eprintf "Dimension.eval %a = " pp_dimension dim; 
+  eval eval_op eval_const dim;
+  Format.eprintf "%a@." pp_dimension dim
+end
+*)
 let uneval const univar =
   let univar = repr univar in
   match univar.dim_desc with
diff --git a/src/inliner.ml b/src/inliner.ml
index 29b008baef787c49cd3e3bff0c9171aa318cc37f..1a2dd1034d7042c705fcf0392db24650e23cca93 100644
--- a/src/inliner.ml
+++ b/src/inliner.ml
@@ -27,20 +27,6 @@ let check_node_name id = (fun t ->
   | Node nd -> nd.node_id = id 
   | _ -> false) 
 
-let get_static_inputs node args =
-  List.fold_right2 (fun vdecl arg static ->
-    if vdecl.var_dec_const then (vdecl.var_id, Corelang.dimension_of_expr arg) :: static else static)
-    node.node_inputs
-    (Corelang.expr_list_of_expr args)
-    []
-
-let get_carrier_inputs node args =
-  List.fold_right2 (fun vdecl arg carrier ->
-    if Types.get_clock_base_type vdecl.var_type <> None then (vdecl.var_id, ident_of_expr arg) :: carrier else carrier)
-    node.node_inputs
-    (Corelang.expr_list_of_expr args)
-    []
-
 let is_node_var node v =
  try
    ignore (Corelang.get_node_var v node); true
@@ -53,7 +39,21 @@ let rename_eq rename eq =
     eq_lhs = List.map rename eq.eq_lhs; 
     eq_rhs = rename_expr rename eq.eq_rhs
   }
-
+(*
+let get_static_inputs input_arg_list =
+ List.fold_right (fun (vdecl, arg) res ->
+   if vdecl.var_dec_const
+   then (vdecl.var_id, Corelang.dimension_of_expr arg) :: res
+   else res)
+   input_arg_list []
+
+let get_carrier_inputs input_arg_list =
+ List.fold_right (fun (vdecl, arg) res ->
+   if Corelang.is_clock_dec_type vdecl.var_dec_type.ty_dec_desc
+   then (vdecl.var_id, ident_of_expr arg) :: res
+   else res)
+   input_arg_list []
+*)
 (* 
     expr, locals', eqs = inline_call id args' reset locals node nodes
 
@@ -73,30 +73,49 @@ let inline_call node orig_expr args reset locals caller =
     if v = tag_true || v = tag_false || not (is_node_var node v) then v else
       Corelang.mk_new_node_name caller (Format.sprintf "%s_%i_%s" node.node_id uid v)
   in
-  let eqs' = List.map (rename_eq rename) (get_node_eqs node)
-  in
-  let static_inputs = get_static_inputs node args in
-  let carrier_inputs = get_carrier_inputs node args in
+  let eqs' = List.map (rename_eq rename) (get_node_eqs node) in
+  let input_arg_list = List.combine node.node_inputs (Corelang.expr_list_of_expr args) in
+  let static_inputs, dynamic_inputs = List.partition (fun (vdecl, arg) -> vdecl.var_dec_const) input_arg_list in
+  let static_inputs = List.map (fun (vdecl, arg) -> vdecl, Corelang.dimension_of_expr arg) static_inputs in
+  let carrier_inputs, other_inputs = List.partition (fun (vdecl, arg) -> Corelang.is_clock_dec_type vdecl.var_dec_type.ty_dec_desc) dynamic_inputs in
+  let carrier_inputs = List.map (fun (vdecl, arg) -> vdecl, Corelang.ident_of_expr arg) carrier_inputs in
   let rename_static v =
     try
-      List.assoc v static_inputs
-    with Not_found -> Dimension.mkdim_ident loc v
-    (*Format.eprintf "Inliner.rename_static %s = %a@." v Dimension.pp_dimension res; res*)
-  in
+      snd (List.find (fun (vdecl, _) -> v = vdecl.var_id) static_inputs)
+    with Not_found -> Dimension.mkdim_ident loc v in
   let rename_carrier v =
     try
-      List.assoc v carrier_inputs
+      snd (List.find (fun (vdecl, _) -> v = vdecl.var_id) carrier_inputs)
     with Not_found -> v in
   let rename_var v =
-  (*Format.eprintf "Inliner.rename_var %a@." Printers.pp_var v;*)
-    { v with
-      var_id = rename v.var_id;
-      var_type = Types.rename_static rename_static v.var_type;
-      var_clock = Clocks.rename_static rename_carrier v.var_clock;
-    } in
-  let inputs' = List.map rename_var node.node_inputs in
+    let vdecl =
+      Corelang.mkvar_decl v.var_loc
+	(rename v.var_id,
+	 { v.var_dec_type  with ty_dec_desc = Corelang.rename_static rename_static v.var_dec_type.ty_dec_desc },
+	 { v.var_dec_clock with ck_dec_desc = Corelang.rename_carrier rename_carrier v.var_dec_clock.ck_dec_desc },
+	 v.var_dec_const,
+	 Utils.option_map (rename_expr rename) v.var_dec_value) in
+    begin
+(*
+      (try
+	 Format.eprintf "Inliner.inline_call unify %a %a@." Types.print_ty vdecl.var_type Dimension.pp_dimension (List.assoc v.var_id static_inputs);
+	 Typing.unify vdecl.var_type (Type_predef.type_static (List.assoc v.var_id static_inputs) (Types.new_var ()))
+       with Not_found -> ());
+      (try
+Clock_calculus.unify vdecl.var_clock (Clock_predef.ck_carrier (List.assoc v.var_id carrier_inputs) (Clocks.new_var true))
+       with Not_found -> ());
+(*Format.eprintf "Inliner.inline_call res=%a@." Printers.pp_var vdecl;*)
+*)
+      vdecl
+    end
+    (*Format.eprintf "Inliner.rename_var %a@." Printers.pp_var v;*)
+  in
+  let inputs' = List.map (fun (vdecl, _) -> rename_var vdecl) dynamic_inputs in
   let outputs' = List.map rename_var node.node_outputs in
-  let locals' = List.map rename_var node.node_locals in
+  let locals' =
+      (List.map (fun (vdecl, arg) -> let vdecl' = rename_var vdecl in { vdecl' with var_dec_value = Some (Corelang.expr_of_dimension arg) }) static_inputs)
+    @ (List.map rename_var node.node_locals) 
+in
   (* checking we are at the appropriate (early) step: node_checks and
      node_gencalls should be empty (not yet assigned) *)
   assert (node.node_checks = []);
@@ -105,7 +124,7 @@ let inline_call node orig_expr args reset locals caller =
   (* Bug included: todo deal with reset *)
   assert (reset = None);
 
-  let assign_inputs = mkeq loc (List.map (fun v -> v.var_id) inputs', args) in
+  let assign_inputs = mkeq loc (List.map (fun v -> v.var_id) inputs', expr_of_expr_list args.expr_loc (List.map snd dynamic_inputs)) in
   let expr = expr_of_expr_list loc (List.map expr_of_vdecl outputs')
   in
   let asserts' = (* We rename variables in assert expressions *)
@@ -215,7 +234,7 @@ let rec inline_expr ?(selection_on_annotation=false) expr locals node nodes =
     { expr with expr_desc = Expr_merge (id, branches') }, l', eqs', asserts'
 
 and inline_node ?(selection_on_annotation=false) node nodes =
-  try Hashtbl.find inline_table node.node_id
+  try copy_node (Hashtbl.find inline_table node.node_id)
   with Not_found ->
   let inline_expr = inline_expr ~selection_on_annotation:selection_on_annotation in
   let new_locals, eqs, asserts = 
@@ -269,24 +288,26 @@ let witness filename main_name orig inlined type_env clock_env =
 
   (* One ok_i boolean variable  per output var *)
   let nb_outputs = List.length main_orig_node.node_outputs in
+  let ok_ident = "OK" in
   let ok_i = List.map (fun id ->
     mkvar_decl 
       loc 
-      ("OK" ^ string_of_int id,
+      (Format.sprintf "%s_%i" ok_ident id,
        {ty_dec_desc=Tydec_bool; ty_dec_loc=loc},
        {ck_dec_desc=Ckdec_any; ck_dec_loc=loc},
-       false)
+       false,
+       None)
   ) (Utils.enumerate nb_outputs) 
   in
 
   (* OK = ok_1 and ok_2 and ... ok_n-1 *)
-  let ok_ident = "OK" in
   let ok_output = mkvar_decl 
     loc 
     (ok_ident,
      {ty_dec_desc=Tydec_bool; ty_dec_loc=loc},
      {ck_dec_desc=Ckdec_any; ck_dec_loc=loc},
-     false)
+     false,
+     None)
   in
   let main_ok_expr =
     let mkv x = mkexpr loc (Expr_ident x) in
@@ -342,42 +363,35 @@ let witness filename main_name orig inlined type_env clock_env =
   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
-
-   
   let witness_file = (Options.get_witness_dir filename) ^ "/" ^ "inliner_witness.lus" in
   let witness_out = open_out witness_file in
   let witness_fmt = Format.formatter_of_out_channel witness_out in
-  Format.fprintf witness_fmt
-    "(* Generated lustre file to check validity of inlining process *)@.";
-  Printers.pp_prog witness_fmt new_prog;
-  Format.fprintf witness_fmt "@.";
-  () (* xx *)
+  begin
+    List.iter (fun vdecl -> Typing.try_unify Type_predef.type_bool vdecl.var_type vdecl.var_loc) (ok_output::ok_i);
+    Format.fprintf witness_fmt
+      "(* Generated lustre file to check validity of inlining process *)@.";
+    Printers.pp_prog witness_fmt new_prog;
+    Format.fprintf witness_fmt "@.";
+    ()
+  end (* xx *)
 
 let global_inline basename prog type_env clock_env =
   (* We select the main node desc *)
   let main_node, other_nodes, other_tops = 
-    List.fold_left 
-      (fun (main_opt, nodes, others) top -> 
+    List.fold_right
+      (fun top (main_opt, nodes, others) -> 
 	match top.top_decl_desc with 
 	| Node nd when nd.node_id = !Options.main_node -> 
 	  Some top, nodes, others
 	| Node _ -> main_opt, top::nodes, others
 	| _ -> main_opt, nodes, top::others) 
-      (None, [], []) prog 
+      prog (None, [], []) 
   in
+
   (* Recursively each call of a node in the top node is replaced *)
   let main_node = Utils.desome main_node in
   let main_node' = inline_all_calls main_node other_nodes in
-  let res = main_node'::other_tops in
-  if !Options.witnesses then (
-    witness 
-      basename
-      (match main_node.top_decl_desc  with Node nd -> nd.node_id | _ -> assert false) 
-      prog res type_env clock_env
-  );
+  let res = List.map (fun top -> if check_node_name !Options.main_node top then main_node' else top) prog in
   res
 
 let local_inline basename prog type_env clock_env =
diff --git a/src/location.ml b/src/location.ml
index 31f25234eff0dff31a9706f36cff1b004a90ef79..3b99fde85aaad526085523e45b2fb4142846bfa0 100755
--- a/src/location.ml
+++ b/src/location.ml
@@ -67,6 +67,7 @@ let print loc =
 
 
 let pp_loc fmt loc =
+  if loc == dummy_loc then () else
   let filename = loc.loc_start.Lexing.pos_fname in
   let line = loc.loc_start.Lexing.pos_lnum in
   let start_char =
diff --git a/src/lusic.ml b/src/lusic.ml
index 089cac0effd97dd2cd341ce52b6a14deb6f96c30..188990b7badb42936687b2ad6f7d697f4c91dd80 100644
--- a/src/lusic.ml
+++ b/src/lusic.ml
@@ -19,7 +19,9 @@ open Corelang
 (********************************************************************************************)
 
 type lusic =
-{ from_lusi : bool;
+{
+  obsolete  : bool;
+  from_lusi : bool;
   contents  : top_decl list;
 }
 
@@ -41,12 +43,27 @@ let extract_header dirname basename prog =
     | Open _         -> decl :: header)
    prog []
 
+let check_obsolete lusic basename =
+  if lusic.obsolete then raise (Error (Location.dummy_loc, Wrong_number basename))
+
+let check_lusic lusic basename =
+  try
+    check_obsolete lusic basename
+  with
+  | Corelang.Error (loc, err) as exc -> (
+    eprintf "Library error: %a%a@."
+      Corelang.pp_error err
+      Location.pp_loc loc;
+    raise exc
+  )
+
 (* encode and write a header in a file *)
 let write_lusic lusi (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 {from_lusi = lusi; contents = header} [];
+    Marshal.to_channel outchan (Version.number, lusi : string * bool) [];
+    Marshal.to_channel outchan (header : top_decl list) [];
     close_out outchan
   end
 
@@ -54,11 +71,27 @@ let write_lusic lusi (header : top_decl list) basename extension =
 let read_lusic basename extension =
   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 number, from_lusi = (Marshal.from_channel inchan : string * bool) in
+  if number <> Version.number
+  then
+    begin
+      close_in inchan;
+      {
+	obsolete  = true;
+	from_lusi = from_lusi;
+	contents  = [];
+      }
+    end
+  else    
+    begin
+      let lusic = (Marshal.from_channel inchan : top_decl list) in
+      close_in inchan;
+      {
+	obsolete  = false;
+	from_lusi = from_lusi;
+	contents  = lusic;
+      }
+    end
 
 let print_lusic_to_h basename extension =
   let lusic = read_lusic basename extension in
@@ -66,6 +99,7 @@ let print_lusic_to_h basename extension =
   let h_out = open_out header_name in
   let h_fmt = formatter_of_out_channel h_out in
   begin
+    check_lusic lusic basename;
     Typing.uneval_prog_generics lusic.contents;
     Clock_calculus.uneval_prog_generics lusic.contents;
     Header.print_header_from_header h_fmt (Filename.basename basename) lusic.contents;
diff --git a/src/lustreSpec.ml b/src/lustreSpec.ml
index 876ccbaa3803cab71986435b6269c4a1c72adfaa..79c9f5d4b1f9fdd2c31204b2b9f8eac8540ce1de 100644
--- a/src/lustreSpec.ml
+++ b/src/lustreSpec.ml
@@ -48,12 +48,24 @@ and clock_dec_desc =
   | Ckdec_bool of (ident * ident) list 
   | Ckdec_pclock of int * rat
 
+type constant =
+  | Const_int of int
+  | Const_real of string
+  | Const_float of float
+  | Const_array of constant list
+  | Const_tag of label
+  | Const_string of string (* used only for annotations *)
+  | Const_struct of (label * constant) list
+
+type quantifier_type = Exists | Forall
+
 type var_decl = 
     {var_id: ident;
      var_orig:bool;
      var_dec_type: type_dec;
      var_dec_clock: clock_dec;
      var_dec_const: bool;
+     var_dec_value: expr option;
      mutable var_type: Types.type_expr;
      mutable var_clock: Clocks.clock_expr;
      var_loc: Location.t}
@@ -64,20 +76,10 @@ type var_decl =
     duplicate ast structures (e.g. ast, typed_ast, clocked_ast). *)
 
 
-type constant =
-  | Const_int of int
-  | Const_real of string
-  | Const_float of float
-  | Const_array of constant list
-  | Const_tag of label
-  | Const_string of string (* used only for annotations *)
-  | Const_struct of (label * constant) list
-
-type quantifier_type = Exists | Forall
 
 (* The tag of an expression is a unique identifier used to distinguish
    different instances of the same node *)
-type expr =
+and expr =
     {expr_tag: tag;
      expr_desc: expr_desc;
      mutable expr_type: Types.type_expr;
@@ -220,6 +222,7 @@ type error =
   | Unbound_symbol of ident
   | Already_bound_symbol of ident
   | Unknown_library of ident
+  | Wrong_number of ident
 
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
diff --git a/src/machine_code.ml b/src/machine_code.ml
index 8df2baa6f49eedab125f06c5cf3cdd462087cbdc..491e94f63e29c1897322fe7c5504dcca3628930c 100644
--- a/src/machine_code.ml
+++ b/src/machine_code.ml
@@ -83,6 +83,7 @@ type machine_t = {
   minstances: (ident * static_call) list; (* sub-map of mcalls, from stateful instance to node *)
   minit: instr_t list;
   mstatic: var_decl list; (* static inputs only *)
+  mconst: instr_t list; (* assignments of node constant locals *)
   mstep: step_t;
   mspec: node_annot option;
   mannot: expr_annot list;
@@ -105,11 +106,12 @@ let pp_static_call fmt (node, args) =
 
 let pp_machine fmt m =
   Format.fprintf fmt
-    "@[<v 2>machine %s@ mem      : %a@ instances: %a@ init     : %a@ step     :@   @[<v 2>%a@]@ @  spec : @[%t@]@  annot : @[%a@]@]@ "
+    "@[<v 2>machine %s@ mem      : %a@ instances: %a@ init     : %a@ const    : %a@ step     :@   @[<v 2>%a@]@ @  spec : @[%t@]@  annot : @[%a@]@]@ "
     m.mname.node_id
     (Utils.fprintf_list ~sep:", " Printers.pp_var) m.mmemory
     (Utils.fprintf_list ~sep:", " (fun fmt (o1, o2) -> Format.fprintf fmt "(%s, %a)" o1 pp_static_call o2)) m.minstances
     (Utils.fprintf_list ~sep:"@ " pp_instr) m.minit
+    (Utils.fprintf_list ~sep:"@ " pp_instr) m.mconst
     pp_step m.mstep
     (fun fmt -> match m.mspec with | None -> () | Some spec -> Printers.pp_spec fmt spec)
     (Utils.fprintf_list ~sep:"@ " Printers.pp_expr_annot) m.mannot
@@ -137,6 +139,7 @@ let dummy_var_decl name typ =
     var_dec_type = dummy_type_dec;
     var_dec_clock = dummy_clock_dec;
     var_dec_const = false;
+    var_dec_value = None;
     var_type =  typ;
     var_clock = Clocks.new_ck (Clocks.Cvar Clocks.CSet_all) true;
     var_loc = Location.dummy_loc
@@ -183,6 +186,7 @@ let arrow_machine =
     mcalls = [];
     minstances = [];
     minit = [MStateAssign(var_state, Cst (const_of_bool true))];
+    mconst = [];
     mstatic = [];
     mstep = {
       step_inputs = arrow_desc.node_inputs;
@@ -215,6 +219,7 @@ let new_instance =
       o
     end
 
+
 (* translate_<foo> : node -> context -> <foo> -> machine code/expression *)
 (* the context contains  m : state aka memory variables  *)
 (*                      si : initialization instructions *)
@@ -284,7 +289,7 @@ let specialize_op expr =
   | "C" -> specialize_to_c expr
   | _   -> expr
 
-let rec translate_expr node ((m, si, j, d, s) as args) expr =
+let rec translate_expr ?(ite=false) node ((m, si, j, d, s) as args) expr =
   let expr = specialize_op expr in
  match expr.expr_desc with
  | Expr_const v                     -> Cst v
@@ -305,9 +310,11 @@ let rec translate_expr node ((m, si, j, d, s) as args) expr =
    (* special treatment depending on the active backend. For horn backend, ite
       are preserved in expression. While they are removed for C or Java
       backends. *)
-   match !Options.output with | "horn" ->
+   match !Options.output with
+   | "horn"
+   | ("C" | "java") when ite ->
      Fun ("ite", [translate_expr node args g; translate_expr node args t; translate_expr node args e])
-   | "C" | "java" | _ ->
+   | _ ->
      (Printers.pp_expr Format.err_formatter expr; Format.pp_print_flush Format.err_formatter (); raise NormalizationError)
  )
  | _                   -> raise NormalizationError
@@ -433,7 +440,7 @@ let find_eq xl eqs =
    to the computed schedule [sch]
 *)
 let sort_equations_from_schedule nd sch =
-(*  Format.eprintf "%s schedule: %a@."
+(*Format.eprintf "%s schedule: %a@."
 		 nd.node_id
 		 (Utils.fprintf_list ~sep:" ; " Scheduling.pp_eq_schedule) sch;*)
   let split_eqs = Splitting.tuple_split_eq_list (get_node_eqs nd) in
@@ -459,6 +466,17 @@ let sort_equations_from_schedule nd sch =
     List.rev eqs_rev
   end
 
+let constant_equations nd =
+ List.fold_right (fun vdecl eqs ->
+   if vdecl.var_dec_const
+   then
+     { eq_lhs = [vdecl.var_id];
+       eq_rhs = Utils.desome vdecl.var_dec_value;
+       eq_loc = vdecl.var_loc
+     } :: eqs
+   else eqs)
+   nd.node_locals []
+
 let translate_eqs node args eqs =
   List.fold_right (fun eq args -> translate_eq node args eq) eqs args;;
 
@@ -466,10 +484,15 @@ let translate_decl nd sch =
   (*Log.report ~level:1 (fun fmt -> Printers.pp_node fmt nd);*)
 
   let sorted_eqs = sort_equations_from_schedule nd sch in
-
+  let constant_eqs = constant_equations nd in
+  
   let init_args = ISet.empty, [], Utils.IMap.empty, List.fold_right (fun l -> ISet.add l) nd.node_locals ISet.empty, [] in
   (* memories, init instructions, node calls, local variables (including memories), step instrs *)
-  let m, init, j, locals, s = translate_eqs nd init_args sorted_eqs in
+  let m0, init0, j0, locals0, s0 = translate_eqs nd init_args constant_eqs in
+  assert (ISet.is_empty m0);
+  assert (init0 = []);
+  assert (Utils.IMap.is_empty j0);
+  let m, init, j, locals, s = translate_eqs nd (m0, init0, j0, locals0, s0) sorted_eqs in
   let mmap = Utils.IMap.fold (fun i n res -> (i, n)::res) j [] in
   {
     mname = nd;
@@ -477,6 +500,7 @@ let translate_decl nd sch =
     mcalls = mmap;
     minstances = List.filter (fun (_, (n,_)) -> not (Stateless.check_node n)) mmap;
     minit = init;
+    mconst = s0;
     mstatic = List.filter (fun v -> v.var_dec_const) nd.node_inputs;
     mstep = {
       step_inputs = nd.node_inputs;
@@ -500,7 +524,7 @@ let translate_decl nd sch =
     mannot = nd.node_annot;
   }
 
-(** takes the global delcarations and the scheduling associated to each node *)
+(** takes the global declarations and the scheduling associated to each node *)
 let translate_prog decls node_schs =
   let nodes = get_nodes decls in
   List.map
@@ -518,6 +542,46 @@ let get_machine_opt name machines =
       | None -> if m.mname.node_id = name then Some m else None)
     None machines
 
+let get_const_assign m id =
+  try
+    match (List.find (fun instr -> match instr with MLocalAssign (v, _) -> v == id | _ -> false) m.mconst) with
+    | MLocalAssign (_, e) -> e
+    | _                   -> assert false
+  with Not_found -> assert false
+
+
+let value_of_ident m id =
+  (* is is a state var *)
+  try
+    StateVar (List.find (fun v -> v.var_id = id) m.mmemory)
+  with Not_found ->
+  try (* id is a node var *)
+    LocalVar (get_node_var id m.mname)
+  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 value_of_dimension m dim =
+  match dim.Dimension.dim_desc with
+  | Dimension.Dbool b         -> Cst (Const_tag (if b then Corelang.tag_true else Corelang.tag_false))
+  | Dimension.Dint i          -> Cst (Const_int i)
+  | Dimension.Dident v        -> value_of_ident m v
+  | Dimension.Dappl (f, args) -> Fun (f, List.map (value_of_dimension m) args)
+  | Dimension.Dite (i, t, e)  -> Fun ("ite", List.map (value_of_dimension m) [i; t; e])
+  | Dimension.Dlink dim'      -> value_of_dimension m dim'
+  | _                         -> assert false
+
+let rec dimension_of_value value =
+  match value with
+  | Cst (Const_tag t) when t = Corelang.tag_true  -> Dimension.mkdim_bool  Location.dummy_loc true
+  | Cst (Const_tag t) when t = Corelang.tag_false -> Dimension.mkdim_bool  Location.dummy_loc false
+  | Cst (Const_int i)                             -> Dimension.mkdim_int   Location.dummy_loc i
+  | LocalVar v                                    -> Dimension.mkdim_ident Location.dummy_loc v.var_id
+  | Fun (f, args)                                 -> Dimension.mkdim_appl  Location.dummy_loc f (List.map dimension_of_value args)
+  | _                                             -> assert false
 
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
diff --git a/src/main_lustre_compiler.ml b/src/main_lustre_compiler.ml
index 0ce60512414cf2533e9adcc331038f445e57cf03..d0b43086d2861a10e302de531e60dc39094229b9 100644
--- a/src/main_lustre_compiler.ml
+++ b/src/main_lustre_compiler.ml
@@ -76,6 +76,7 @@ let compile_source_to_header prog computed_types_env computed_clocks_env dirname
       else
 	begin
 	  Log.report ~level:1 (fun fmt -> fprintf fmt ".. loading compiled header file %s@," header_name);
+	  Lusic.check_lusic lusic destname;
 	  let header = lusic.Lusic.contents in
 	  let (declared_types_env, declared_clocks_env) = get_envs_from_top_decls header in
 	  check_compatibility
@@ -104,15 +105,25 @@ let rec compile_source dirname basename extension =
   (* Sorting nodes *)
   let prog = SortProg.sort prog in
 
+  (* Perform inlining before any analysis *)
+  let orig, prog =
+    if !Options.global_inline && !Options.main_node <> "" then
+      (if !Options.witnesses then prog else []),
+      Inliner.global_inline basename prog type_env clock_env
+    else (* if !Option.has_local_inline *)
+      [],
+      Inliner.local_inline basename prog type_env clock_env
+  in
+
+  (* Checking stateless/stateful status *)
+  check_stateless_decls prog;
+
   (* 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
@@ -150,14 +161,22 @@ let rec compile_source dirname basename extension =
   Typing.uneval_prog_generics prog;
   Clock_calculus.uneval_prog_generics 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 (* if !Option.has_local_inline *)
-      Inliner.local_inline basename prog type_env clock_env
-  in
+  if !Options.global_inline && !Options.main_node <> "" && !Options.witnesses then
+    begin
+      let orig = Corelang.copy_prog orig in
+      Log.report ~level:1 (fun fmt -> fprintf fmt ".. generating witness file !@,");
+      check_stateless_decls orig;
+      let _ = Typing.type_prog type_env orig in
+      let _ = Clock_calculus.clock_prog clock_env orig in
+      Typing.uneval_prog_generics orig;
+      Clock_calculus.uneval_prog_generics orig;
+      Inliner.witness 
+	basename
+	!Options.main_node
+	orig prog type_env clock_env;
+      Log.report ~level:1 (fun fmt -> fprintf fmt ".. done !@,");
+    end;
+
 (*Format.eprintf "Inliner.global_inline<<@.%a@.>>@." Printers.pp_prog prog;*)
   (* Computes and stores generic calls for each node,
      only useful for ANSI C90 compliant generic node compilation *)
@@ -194,7 +213,10 @@ let rec compile_source dirname basename extension =
  *)
   let prog =
     if !Options.optimization >= 4 then
-      Optimize_prog.prog_unfold_consts prog
+      begin
+	Log.report ~level:1 (fun fmt -> fprintf fmt ".. constants elimination@,");
+	Optimize_prog.prog_unfold_consts prog
+      end
     else
       prog
   in
@@ -221,7 +243,7 @@ let rec compile_source dirname basename extension =
       end
     else
       machine_code
- in
+  in
   Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@,"
   (Utils.fprintf_list ~sep:"@ " Machine_code.pp_machine)
   machine_code);
@@ -230,8 +252,8 @@ let rec compile_source dirname basename extension =
   let basename    =  Filename.basename basename in
   let destname = !Options.dest_dir ^ "/" ^ basename in
   let _ = match !Options.output with
-      "C" ->
-	begin
+    | "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 *)
diff --git a/src/modules.ml b/src/modules.ml
index e01300b3dd776c63a6301ba20b51ed08c88848aa..6e35682203d0eb16d4e3164aa0709e54d3a3af4f 100644
--- a/src/modules.ml
+++ b/src/modules.ml
@@ -117,15 +117,25 @@ let name_dependency (local, dep) =
   ((if local then !Options.dest_dir else Version.include_path) ^ "/") ^ 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 ->
-    begin
+    let basename = name_dependency (local, dep) in
+    let extension = ".lusic" in 
+    try
+      let lusic = Lusic.read_lusic basename extension in
+      Lusic.check_obsolete lusic basename;
+      lusic
+    with Sys_error msg ->
+      begin
       (*Format.eprintf "Error: %s@." msg;*)
-      raise (Error (loc, Unknown_library basename))
-    end
+	raise (Error (loc, Unknown_library basename))
+      end
+  with
+  | Corelang.Error (loc, err) as exc -> (
+    Format.eprintf "Library error: %a%a@."
+      Corelang.pp_error err
+      Location.pp_loc loc;
+    raise exc
+  )
 
 let rec load_header_rec imported header =
   List.fold_left (fun imp decl ->
diff --git a/src/normalization.ml b/src/normalization.ml
index cd4be955b66233131e784855aa33b74cc66a0883..d38ab4ea44e6822a4c1db68b23efc5005ed444bb 100644
--- a/src/normalization.ml
+++ b/src/normalization.ml
@@ -69,6 +69,7 @@ let mk_fresh_var node loc ty ck =
     var_dec_type = dummy_type_dec;
     var_dec_clock = dummy_clock_dec;
     var_dec_const = false;
+    var_dec_value = None;
     var_type = ty;
     var_clock = ck;
     var_loc = loc
diff --git a/src/optimize_machine.ml b/src/optimize_machine.ml
index 06d9161f6e4a314892c6bb6111fd087cec6e5ee1..7fbd651d150a34d85bc788f5cc198ba3a139be6a 100644
--- a/src/optimize_machine.ml
+++ b/src/optimize_machine.ml
@@ -14,6 +14,7 @@ open LustreSpec
 open Corelang
 open Causality
 open Machine_code 
+open Dimension
 
 let pp_elim fmt elim =
   begin
@@ -47,6 +48,9 @@ and eliminate_expr elim expr =
   | Power(v1, v2) -> Power(eliminate_expr elim v1, eliminate_expr elim v2)
   | Cst _ | StateVar _ -> expr
 
+let eliminate_dim elim dim =
+  Dimension.expr_replace_expr (fun v -> try dimension_of_value (IMap.find v elim) with Not_found -> mkdim_ident dim.dim_loc v) dim
+
 let is_scalar_const c =
   match c with
   | Const_int _
@@ -116,27 +120,40 @@ and instr_unfold fanin instrs elim instr =
     2. local assigns then rewrite occurrences of the lhs in the computed accumulator
 *)
 
+let static_call_unfold elim (inst, (n, args)) =
+  let replace v =
+    try
+      Machine_code.dimension_of_value (IMap.find v elim)
+    with Not_found -> Dimension.mkdim_ident Location.dummy_loc v
+  in (inst, (n, List.map (Dimension.expr_replace_expr replace) args))
+
 (** Perform optimization on machine code:
     - iterate through step instructions and remove simple local assigns
     
 *)
 let machine_unfold fanin elim machine =
   (*Log.report ~level:1 (fun fmt -> Format.fprintf fmt "machine_unfold %a@." pp_elim elim);*)
-  let eliminated_vars, new_instrs = instrs_unfold fanin elim machine.mstep.step_instrs in
-  let new_locals = List.filter (fun v -> not (IMap.mem v.var_id eliminated_vars)) machine.mstep.step_locals 
+  let elim_consts, mconst = instrs_unfold fanin elim machine.mconst in
+  let elim_vars, instrs = instrs_unfold fanin elim_consts machine.mstep.step_instrs in
+  let locals = List.filter (fun v -> not (IMap.mem v.var_id elim_vars)) machine.mstep.step_locals in
+  let minstances = List.map (static_call_unfold elim_consts) machine.minstances in
+  let mcalls = List.map (static_call_unfold elim_consts) machine.mcalls
   in
   {
     machine with
       mstep = { 
 	machine.mstep with 
-	  step_locals = new_locals;
-	  step_instrs = new_instrs
-      }
+	  step_locals = locals;
+	  step_instrs = instrs
+      };
+      mconst = mconst;
+      minstances = minstances;
+      mcalls = mcalls;
   }
 
 let instr_of_const top_const =
   let const = const_of_top top_const in
-  let vdecl = mkvar_decl Location.dummy_loc (const.const_id, mktyp Location.dummy_loc Tydec_any, mkclock Location.dummy_loc Ckdec_any, true) in
+  let vdecl = mkvar_decl Location.dummy_loc (const.const_id, mktyp Location.dummy_loc Tydec_any, mkclock Location.dummy_loc Ckdec_any, true, None) in
   let vdecl = { vdecl with var_type = const.const_type }
   in MLocalAssign (vdecl, Cst const.const_value)
 
diff --git a/src/options.ml b/src/options.ml
index 9afd6f4c62cd575fad0ecd6aa412a05e3986b17e..5674d2bc4305eec896ad876433e70ad2774b3d78 100755
--- a/src/options.ml
+++ b/src/options.ml
@@ -67,6 +67,7 @@ let options =
     "-verbose", Arg.Set_int verbose_level, " changes verbose level <default: 1>";
     "-version", Arg.Unit print_version, " displays the version";]
 
+
 let get_witness_dir filename =
   (* Make sure the directory exists *)
   let dir = !dest_dir ^ "/" ^ (Filename.basename filename) ^ "_witnesses" in
diff --git a/src/parser_lustre.mly b/src/parser_lustre.mly
index 453609055461704ab913c33c464b07320c429c08..952de6cc1128fb9e45b3dbaea70eb70a35f381ad 100755
--- a/src/parser_lustre.mly
+++ b/src/parser_lustre.mly
@@ -78,6 +78,7 @@ let get_current_node () = try List.hd !node_stack with _ -> assert false
 
 %nonassoc prec_exists prec_forall
 %nonassoc COMMA
+%nonassoc EVERY
 %left MERGE IF
 %nonassoc ELSE
 %right ARROW FBY
@@ -533,20 +534,33 @@ dim:
 
 locals:
   {[]}
-| VAR vdecl_list SCOL {$2}
+| VAR local_vdecl_list SCOL {$2}
 
 vdecl_list:
-    vdecl {$1}
+  vdecl {$1}
 | vdecl_list SCOL vdecl {$3 @ $1}
 
 vdecl:
-/* Useless no ?*/    ident_list
-    { List.map (fun id -> mkvar_decl (id, mktyp Tydec_any, mkclock Ckdec_any, false)) $1 }
+  ident_list COL typeconst clock 
+    { List.map (fun id -> mkvar_decl (id, mktyp $3, $4, false, None)) $1 }
+| CONST ident_list /* static parameters don't have clocks */
+    { List.map (fun id -> mkvar_decl (id, mktyp Tydec_any, mkclock Ckdec_any, true, None)) $2 }
+| CONST ident_list COL typeconst /* static parameters don't have clocks */
+    { List.map (fun id -> mkvar_decl (id, mktyp $4, mkclock Ckdec_any, true, None)) $2 }
+
+local_vdecl_list:
+  local_vdecl {$1}
+| local_vdecl_list SCOL local_vdecl {$3 @ $1}
 
+local_vdecl:
+/* Useless no ?*/    ident_list
+    { List.map (fun id -> mkvar_decl (id, mktyp Tydec_any, mkclock Ckdec_any, false, None)) $1 }
 | ident_list COL typeconst clock 
-    { List.map (fun id -> mkvar_decl (id, mktyp $3, $4, false)) $1 }
-| CONST ident_list COL typeconst /* static parameters don't have clocks */
-    { List.map (fun id -> mkvar_decl (id, mktyp $4, mkclock Ckdec_any, true)) $2 }
+    { List.map (fun id -> mkvar_decl (id, mktyp $3, $4, false, None)) $1 }
+| CONST vdecl_ident EQ expr /* static parameters don't have clocks */
+    { [ mkvar_decl ($2, mktyp Tydec_any, mkclock Ckdec_any, true, Some $4) ] }
+| CONST vdecl_ident COL typeconst EQ expr /* static parameters don't have clocks */
+    { [ mkvar_decl ($2, mktyp $4, mkclock Ckdec_any, true, Some $6) ] }
 
 cdecl_list:
   cdecl SCOL { (fun itf -> [$1 itf]) }
diff --git a/src/printers.ml b/src/printers.ml
index 0a873310f205e89d78590399abc14d5748e37872..92ea74489687b3ecad93b2337611ee24d0344b87 100644
--- a/src/printers.ml
+++ b/src/printers.ml
@@ -24,6 +24,22 @@ let pp_as_c_macro pp_fun fmt v =
     pp_set_all_formatter_output_functions fmt out flush newline spaces;
   end
 
+let rec print_dec_struct_ty_field fmt (label, cty) =
+  fprintf fmt "%a : %a" pp_print_string label print_dec_ty cty
+and print_dec_ty fmt cty =
+  match (*get_repr_type*) cty with
+  | Tydec_any -> fprintf fmt "Any"
+  | Tydec_int -> fprintf fmt "int"
+  | Tydec_real 
+  | Tydec_float -> fprintf fmt "real"
+  | Tydec_bool -> fprintf fmt "bool"
+  | Tydec_clock cty' -> fprintf fmt "%a clock" print_dec_ty cty'
+  | Tydec_const c -> fprintf fmt "%s" c
+  | Tydec_enum taglist -> fprintf fmt "enum {%a }"
+      (Utils.fprintf_list ~sep:", " pp_print_string) taglist
+  | Tydec_struct fieldlist -> fprintf fmt "struct {%a }"
+      (Utils.fprintf_list ~sep:"; " print_dec_struct_ty_field) fieldlist
+  | Tydec_array (d, cty') -> fprintf fmt "%a^%a" print_dec_ty cty' Dimension.pp_dimension d
 
 let pp_var_name fmt id = fprintf fmt "%s" id.var_id
 
@@ -31,10 +47,6 @@ let pp_eq_lhs = fprintf_list ~sep:", " pp_print_string
 
 let pp_var fmt id = fprintf fmt "%s%s: %a" (if id.var_dec_const then "const " else "") id.var_id Types.print_ty id.var_type
 
-let pp_node_var fmt id = fprintf fmt "%s%s: %a%a" (if id.var_dec_const then "const " else "") id.var_id Types.print_node_ty id.var_type Clocks.print_ck_suffix id.var_clock
-
-let pp_node_args = fprintf_list ~sep:"; " pp_node_var 
-
 let pp_quantifiers fmt (q, vars) =
   match q with
     | Forall -> fprintf fmt "forall %a" (fprintf_list ~sep:"; " pp_var) vars 
@@ -125,7 +137,19 @@ and pp_expr_annot fmt expr_ann =
   in
   fprintf_list ~sep:"@ " pp_annot fmt expr_ann.annots
     
-	
+(*
+let pp_node_var fmt id = fprintf fmt "%s%s: %a(%a)%a" (if id.var_dec_const then "const " else "") id.var_id print_dec_ty id.var_dec_type.ty_dec_desc Types.print_ty id.var_type Clocks.print_ck_suffix id.var_clock
+*)
+let pp_node_var fmt id =
+  begin
+    fprintf fmt "%s%s: %a%a" (if id.var_dec_const then "const " else "") id.var_id Types.print_node_ty id.var_type Clocks.print_ck_suffix id.var_clock;
+    match id.var_dec_value with
+    | None -> () 
+    | Some v -> fprintf fmt " = %a" pp_expr v
+  end 
+
+let pp_node_args = fprintf_list ~sep:"; " pp_node_var 
+
 let pp_node_eq fmt eq = 
   fprintf fmt "%a = %a;" 
     pp_eq_lhs eq.eq_lhs
diff --git a/src/scheduling.ml b/src/scheduling.ml
index 8272bebea8aaff5b6187c0d8e17553cee278b339..8238aa7c8e69fbca13cc7a478ea27dfbf6b39ccf 100644
--- a/src/scheduling.ml
+++ b/src/scheduling.ml
@@ -152,7 +152,7 @@ let schedule_node n =
     let sort = topological_sort eq_equiv g in
     let unused = Liveness.compute_unused_variables n gg in
     let fanin = Liveness.compute_fanin n gg in
- 
+
     let (disjoint, reuse) =
       if !Options.optimization >= 3
       then
diff --git a/src/types.ml b/src/types.ml
index 7b13fa4ed5918f3ef93abb782961c5c60536e371..77d017afcef3b092665e3e593ed9efc92ad3ef48 100755
--- a/src/types.ml
+++ b/src/types.ml
@@ -41,7 +41,7 @@ type error =
     Unbound_value of ident  
   | Already_bound of ident
   | Already_defined of ident
-  | Undefined_var of (unit IMap.t)
+  | Undefined_var of ISet.t
   | Declared_but_undefined of ident
   | Unbound_type of ident
   | Not_a_dimension
@@ -158,10 +158,10 @@ let pp_error fmt = function
     fprintf fmt "Expecting %d argument(s) for homomorphic extension, found %d@." ar1 ar2
   | Type_mismatch id ->
     fprintf fmt "Definition and declaration of type %s don't agree@." id
-  | Undefined_var vmap ->
+  | Undefined_var vset ->
     fprintf fmt "No definition provided for variable(s): %a@."
       (Utils.fprintf_list ~sep:"," pp_print_string)
-      (fst (Utils.list_of_imap vmap))
+      (ISet.elements vset)
   | Declared_but_undefined id ->
      fprintf fmt "%s is declared but not defined@." id
   | Type_clash (ty1,ty2) ->
@@ -193,13 +193,6 @@ let get_static_value ty =
   | Tstatic (d, _) -> Some d
   | _              -> None
 
-let rec rename_static rename ty =
- match (repr ty).tdesc with
- | Tstatic (d, ty') -> { ty with tdesc = Tstatic (Dimension.expr_replace_expr rename d, rename_static rename ty') }
- | Tarray  (d, ty') -> { ty with tdesc = Tarray  (Dimension.expr_replace_expr rename d, rename_static rename ty') }
- | _                -> ty
-(*Format.eprintf "Types.rename_static %a = %a@." print_ty ty print_ty res; res*)
-
 let get_field_type ty label =
   match (repr ty).tdesc with
   | Tstruct fl -> (try Some (List.assoc label fl) with Not_found -> None)
diff --git a/src/typing.ml b/src/typing.ml
index 5545ddc7fe7815618cd205d437057394639b5529..45d81bd9b8f1bf7852c1e8c2ec86797edffad516 100755
--- a/src/typing.ml
+++ b/src/typing.ml
@@ -111,6 +111,7 @@ let rec type_coretype type_dim cty =
   | Tydec_struct fl -> Type_predef.type_struct (List.map (fun (f, ty) -> (f, type_coretype type_dim ty)) fl)
   | Tydec_array (d, ty) ->
     begin
+      let d = Dimension.copy (ref []) d in
       type_dim d;
       Type_predef.type_array d (type_coretype type_dim ty)
     end
@@ -311,6 +312,7 @@ let check_constant loc const_expected const_real =
   then raise (Error (loc, Not_a_constant))
 
 let rec type_add_const env const arg targ =
+(*Format.eprintf "Typing.type_add_const %a %a@." Printers.pp_expr arg Types.print_ty targ;*)
   if const
   then let d =
 	 if is_dimension_type targ
@@ -357,6 +359,7 @@ and type_appl env in_main loc const f args =
 
 (* type a call with possible dependent types. [targs] is here a list of (argument, type) pairs. *)
 and type_dependent_call env in_main loc const f targs =
+(*Format.eprintf "Typing.type_dependent_call %s@." f;*)
   let tins, touts = new_var (), new_var () in
   let tfun = Type_predef.type_arrow tins touts in
   type_subtyping_arg env in_main const (expr_of_ident f loc) tfun;
@@ -367,8 +370,10 @@ and type_dependent_call env in_main loc const f targs =
     begin
       List.iter2 (fun (a,t) ti ->
 	let t' = type_add_const env (const || Types.get_static_value ti <> None) a t
-	in try_unify ~sub:true ti t' a.expr_loc) targs tins;
-      touts
+	in try_unify ~sub:true ti t' a.expr_loc;
+      ) targs tins;
+(*Format.eprintf "Typing.type_dependent_call END@.";*)
+      touts;
     end
 
 (* type a simple call without dependent types 
@@ -506,16 +511,15 @@ and type_branches env in_main loc const hl =
 
 (** [type_eq env eq] types equation [eq] in environment [env] *)
 let type_eq env in_main undefined_vars eq =
+(*Format.eprintf "Typing.type_eq %a@." Printers.pp_node_eq eq;*)
   (* Check undefined variables, type lhs *)
   let expr_lhs = expr_of_expr_list eq.eq_loc (List.map (fun v -> expr_of_ident v eq.eq_loc) eq.eq_lhs) in
   let ty_lhs = type_expr env in_main false expr_lhs in
   (* Check multiple variable definitions *)
   let define_var id uvars =
-    try
-      ignore(IMap.find id uvars);
-      IMap.remove id uvars
-    with Not_found ->
-      raise (Error (eq.eq_loc, Already_defined id))
+    if ISet.mem id uvars
+    then ISet.remove id uvars
+    else raise (Error (eq.eq_loc, Already_defined id))
   in
   (* check assignment of declared constant, assignment of clock *)
   let ty_lhs =
@@ -566,23 +570,28 @@ let rec check_type_declaration loc cty =
  | _                   -> ()
 
 let type_var_decl vd_env env vdecl =
-(*Format.eprintf "Typing.type_var_decl START %a@." Printers.pp_var vdecl;*)
+(*Format.eprintf "Typing.type_var_decl START %a:%a@." Printers.pp_var vdecl Printers.print_dec_ty vdecl.var_dec_type.ty_dec_desc;*)
   check_type_declaration vdecl.var_loc vdecl.var_dec_type.ty_dec_desc;
   let eval_const id = Types.get_static_value (Env.lookup_value env id) in
   let type_dim d =
     begin
       type_subtyping_arg (env, vd_env) false true (expr_of_dimension d) Type_predef.type_int;
+
       Dimension.eval Basic_library.eval_env eval_const d;
     end in
   let ty = type_coretype type_dim vdecl.var_dec_type.ty_dec_desc in
-  let ty_status =
+
+  let ty_static =
     if vdecl.var_dec_const
-    then Type_predef.type_static (Dimension.mkdim_var ()) ty
+    then  Type_predef.type_static (Dimension.mkdim_var ()) ty
     else ty in
-  let new_env = Env.add_value env vdecl.var_id ty_status in
+  (match vdecl.var_dec_value with
+  | None   -> ()
+  | Some v -> type_subtyping_arg (env, vd_env) false ~sub:false true v ty_static);
+  try_unify ty_static vdecl.var_type vdecl.var_loc;
+  let new_env = Env.add_value env vdecl.var_id ty_static in
   type_coreclock (new_env,vd_env) vdecl.var_dec_clock vdecl.var_id vdecl.var_loc;
-  vdecl.var_type <- ty_status;
-(*Format.eprintf "END@.";*)
+(*Format.eprintf "END %a@." Types.print_ty ty_static;*)
   new_env
 
 let type_var_decl_list vd_env env l =
@@ -614,8 +623,8 @@ let type_node env nd loc =
   let new_env = Env.overwrite env delta_env in
   let undefined_vars_init =
     List.fold_left
-      (fun uvs v -> IMap.add v.var_id () uvs)
-      IMap.empty vd_env_ol in
+      (fun uvs v -> ISet.add v.var_id uvs)
+      ISet.empty vd_env_ol in
   let undefined_vars =
     List.fold_left (type_eq (new_env, vd_env) is_main) undefined_vars_init (get_node_eqs nd)
   in
@@ -626,7 +635,9 @@ let type_node env nd loc =
   )  nd.node_asserts;
   
   (* check that table is empty *)
-  if (not (IMap.is_empty undefined_vars)) then
+  let local_consts = List.fold_left (fun res vdecl -> if vdecl.var_dec_const then ISet.add vdecl.var_id res else res) ISet.empty nd.node_locals in
+  let undefined_vars = ISet.diff undefined_vars local_consts in
+  if (not (ISet.is_empty undefined_vars)) then
     raise (Error (loc, Undefined_var undefined_vars));
   let ty_ins = type_of_vlist nd.node_inputs in
   let ty_outs = type_of_vlist nd.node_outputs in
@@ -673,10 +684,10 @@ let rec type_top_decl env decl =
       try
 	type_node env nd decl.top_decl_loc
       with Error (loc, err) as exc -> (
-	if !Options.global_inline then
+	(*if !Options.global_inline then
 	  Format.eprintf "Type error: failing node@.%a@.@?"
 	    Printers.pp_node nd
-	;
+	;*)
 	raise exc)
   )
   | ImportedNode nd ->
diff --git a/test/tests_ok.list b/test/tests_ok.list
index b8264891ddf957cf81be39542f0570bc64b59a15..0d2a2b8c26f43ad97ab063e7e150d278799b7d5f 100644
--- a/test/tests_ok.list
+++ b/test/tests_ok.list
@@ -904,6 +904,7 @@
 ./tests/arrays_arnaud/generic1.lusi
 ./tests/arrays_arnaud/generic1.lus
 ./tests/arrays_arnaud/generic2.lus
+./tests/arrays_arnaud/generic3.lus,top,-dynamic -check-access
 ./tests/clocks/clocks1.lus,,-lusi
 ./tests/clocks/clocks1.lusi
 ./tests/clocks/clocks1.lus