From 66359a5eba92be4c94342e67c7a65529db3a9864 Mon Sep 17 00:00:00 2001
From: ploc <ploc@garoche.net>
Date: Wed, 31 Jan 2018 07:27:26 +0100
Subject: [PATCH] [general] large modification: added machine types, a second
 typing phase dealing with machine types (eg uint8)           typing was
 transformed as a functor and parametrized by basic types (int/real/bool)     
      it can also be applied multiple times on the same program

---
 src/_tags.in                                |   3 +-
 src/automata.ml                             |  16 +-
 src/backends/C/c_backend_common.ml          | 121 +++--
 src/backends/C/c_backend_header.ml          |  14 +-
 src/backends/C/c_backend_main.ml            |  21 +-
 src/backends/C/c_backend_mauve.ml           |  18 +-
 src/backends/C/c_backend_src.ml             |   8 +-
 src/backends/EMF/EMF_backend.ml             |  34 +-
 src/backends/EMF/EMF_common.ml              | 114 +++--
 src/backends/Horn/horn_backend_common.ml    |   6 +-
 src/backends/Horn/horn_backend_printers.ml  |   7 +-
 src/compiler_common.ml                      |  17 +-
 src/compiler_stages.ml                      | 111 ++++-
 src/corelang.ml                             |  12 +-
 src/corelang.mli                            |  13 +-
 src/env.ml                                  |   1 +
 src/features/machine_types/machine_types.ml | 479 ++++++++++++++++++++
 src/global.ml                               |   2 +
 src/inliner.ml                              |  12 +-
 src/lexerLustreSpec.mll                     |   4 +-
 src/lustreSpec.ml                           |   4 +-
 src/machine_code.ml                         |   8 +-
 src/main_lustre_compiler.ml                 |  98 +---
 src/normalization.ml                        |  45 +-
 src/optimize_machine.ml                     |   2 +-
 src/parserLustreSpec.mly                    |   5 +-
 src/parser_lustre.mly                       |  16 +-
 src/pathConditions.ml                       |  48 +-
 src/printers.ml                             |  10 +-
 src/type_predef.ml                          | 110 +++--
 src/types.ml                                | 326 ++++++++++---
 src/typing.ml                               | 223 +++++----
 32 files changed, 1430 insertions(+), 478 deletions(-)
 create mode 100644 src/features/machine_types/machine_types.ml

diff --git a/src/_tags.in b/src/_tags.in
index f8fa582f..7e6e8b8d 100644
--- a/src/_tags.in
+++ b/src/_tags.in
@@ -9,6 +9,7 @@ true: bin_annot, color(always)
 "plugins/salsa": include
 "plugins/scopes": include
 "plugins/mpfr": include
+"features/machine_types": include
 "tools/stateflow": include
 "tools/stateflow/common": include
 "tools/stateflow/semantics": include
@@ -46,4 +47,4 @@ true: bin_annot, color(always)
 
 # Local Variables:
 # mode: conf
-# End:
\ No newline at end of file
+# End:
diff --git a/src/automata.ml b/src/automata.ml
index 2d579a1c..890651ca 100755
--- a/src/automata.ml
+++ b/src/automata.ml
@@ -114,7 +114,7 @@ let rec handler_write writes handler =
 let node_vars_of_idents node iset =
   List.fold_right (fun v res -> if ISet.mem v.var_id iset then v :: res else res) (get_node_vars node) []
 
-let mkautomata_state used typedef loc id =
+let mkautomata_state nodeid used typedef loc id =
   let tydec_bool = { ty_dec_desc = Tydec_bool; ty_dec_loc = loc } in
   let tydec_state id = { ty_dec_desc = Tydec_const id; ty_dec_loc = loc } in
   let ckdec_any = { ck_dec_desc = Ckdec_any; ck_dec_loc = loc } in
@@ -125,12 +125,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, 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)
+    incoming_r' = mkvar_decl loc (incoming_r', tydec_bool, ckdec_any, false, None, Some nodeid);
+    incoming_s' = mkvar_decl loc (incoming_s', tydec_state typedef.tydef_id, ckdec_any, false, None, Some nodeid);
+    incoming_r = mkvar_decl loc (incoming_r, tydec_bool, ckdec_any, false, None, Some nodeid);
+    incoming_s = mkvar_decl loc (incoming_s, tydec_state typedef.tydef_id, ckdec_any, false, None, Some nodeid);
+    actual_r = mkvar_decl loc (actual_r  , tydec_bool, ckdec_any, false, None, Some nodeid);
+    actual_s = mkvar_decl loc (actual_s  , tydec_state typedef.tydef_id, ckdec_any, false, None, Some nodeid)
   }
 
 let vars_of_aut_state aut_state =
@@ -225,7 +225,7 @@ let typedef_of_automata aut =
 
 let expand_automata nused used owner typedef node aut =
   let initial = (List.hd aut.aut_handlers).hand_state in
-  let aut_state = mkautomata_state used typedef aut.aut_loc aut.aut_id in
+  let aut_state = mkautomata_state node.node_id used typedef aut.aut_loc aut.aut_id in
   let unodes = List.map (fun h -> node_of_unless nused used node aut.aut_id aut_state h) aut.aut_handlers in
   let aunodes = List.map (fun h -> node_of_assign_until nused used node aut.aut_id aut_state h) aut.aut_handlers in
   let all_outputs = List.fold_left (fun all (outputs, _, _) -> ISet.union outputs all) ISet.empty aunodes in
diff --git a/src/backends/C/c_backend_common.ml b/src/backends/C/c_backend_common.ml
index 6edd2aa3..21e54e7a 100644
--- a/src/backends/C/c_backend_common.ml
+++ b/src/backends/C/c_backend_common.ml
@@ -61,6 +61,7 @@ let mk_call_var_decl loc id =
     var_dec_clock = mkclock Location.dummy_loc Ckdec_any;
     var_dec_const = false;
     var_dec_value = None;
+    var_parent_nodeid = None;
     var_type = Type_predef.type_arrow (Types.new_var ()) (Types.new_var ());
     var_clock = Clocks.new_var true;
     var_loc = loc }
@@ -124,34 +125,41 @@ let rec pp_c_dimension fmt dim =
  | Dimension.Dunivar    -> fprintf fmt "'%s" (Utils.name_of_dimension dim.Dimension.dim_id)
 
 let is_basic_c_type t =
-  match (Types.repr t).Types.tdesc with
-  | Types.Tbool | Types.Treal | Types.Tint  -> true
-  | _                                       -> false
-
-let pp_c_basic_type_desc t_dsec =
-  match t_dsec with
-  | Types.Tbool when !Options.cpp  -> "bool"
-  | Types.Tbool                    -> "_Bool"
-  | Types.Tint                     -> !Options.int_type
-  | Types.Treal when !Options.mpfr -> Mpfr.mpfr_t
-  | Types.Treal                    -> !Options.real_type
-  | _ -> assert false (* Not a basic C type. Do not handle arrays or pointers *)
+  Types.is_int_type t || Types.is_real_type t || Types.is_bool_type t
+
+let pp_c_basic_type_desc t_desc =
+  if Types.is_bool_type t_desc then
+    if !Options.cpp then "bool" else "_Bool"
+  else if Types.is_int_type t_desc then !Options.int_type
+  else if Types.is_real_type t_desc then
+    if !Options.mpfr then Mpfr.mpfr_t else !Options.real_type
+  else
+    assert false (* Not a basic C type. Do not handle arrays or pointers *)
 
-let pp_basic_c_type fmt t = fprintf fmt "%s" (pp_c_basic_type_desc (Types.repr t).Types.tdesc)
+let pp_basic_c_type ?(var_opt=None) fmt t =
+  match var_opt with
+  | Some v when Machine_types.is_exportable v ->
+     Machine_types.pp_c_var_type fmt v
+  | _ ->
+     fprintf fmt "%s" (pp_c_basic_type_desc t)
 
-let pp_c_type var fmt t =
+let pp_c_type ?(var_opt=None) var_id fmt t =
   let rec aux t pp_suffix =
-    match (Types.repr t).Types.tdesc with
-    | Types.Tclock t'       -> aux t' pp_suffix
-    | Types.Tbool | Types.Tint | Types.Treal
-                            -> fprintf fmt "%a %s%a" pp_basic_c_type t var pp_suffix ()
-    | Types.Tarray (d, t')  ->
-      let pp_suffix' fmt () = fprintf fmt "%a[%a]" pp_suffix () pp_c_dimension d in
-      aux t' pp_suffix'
-    | Types.Tstatic (_, t') -> fprintf fmt "const "; aux t' pp_suffix
-    | Types.Tconst ty       -> fprintf fmt "%s %s" ty var
-    | Types.Tarrow (_, _)   -> fprintf fmt "void (*%s)()" var
-    | _                     -> eprintf "internal error: C_backend_common.pp_c_type %a@." Types.print_ty t; assert false
+    if is_basic_c_type  t then
+       fprintf fmt "%a %s%a"
+	 (pp_basic_c_type ~var_opt) t
+	 var_id
+	 pp_suffix ()
+    else
+      match (Types.repr t).Types.tdesc with
+      | Types.Tclock t'       -> aux t' pp_suffix
+      | Types.Tarray (d, t')  ->
+	 let pp_suffix' fmt () = fprintf fmt "%a[%a]" pp_suffix () pp_c_dimension d in
+	 aux t' pp_suffix'
+      | Types.Tstatic (_, t') -> fprintf fmt "const "; aux t' pp_suffix
+      | Types.Tconst ty       -> fprintf fmt "%s %s" ty var_id
+      | Types.Tarrow (_, _)   -> fprintf fmt "void (*%s)()" var_id
+      | _                     -> eprintf "internal error: C_backend_common.pp_c_type %a@." Types.print_ty t; assert false
   in aux t (fun fmt () -> ())
 (*
 let rec pp_c_initialize fmt t = 
@@ -241,8 +249,8 @@ let pp_c_var_write m fmt id =
 *)
 let pp_c_decl_input_var fmt id =
   if !Options.ansi && Types.is_address_type id.var_type
-  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
+  then pp_c_type ~var_opt:(Some id) (sprintf "(*%s)" id.var_id) fmt (Types.array_base_type id.var_type)
+  else pp_c_type ~var_opt:(Some id) id.var_id fmt id.var_type
 
 (* Declaration of an output variable:
    - if its type is scalar, then pass its address
@@ -252,8 +260,8 @@ let pp_c_decl_input_var fmt id =
 *)
 let pp_c_decl_output_var fmt id =
   if (not !Options.ansi) && Types.is_address_type id.var_type
-  then pp_c_type                  id.var_id  fmt id.var_type
-  else pp_c_type (sprintf "(*%s)" id.var_id) fmt (Types.array_base_type id.var_type)
+  then pp_c_type  ~var_opt:(Some id)                  id.var_id  fmt id.var_type
+  else pp_c_type  ~var_opt:(Some id) (sprintf "(*%s)" id.var_id) fmt (Types.array_base_type id.var_type)
 
 (* Declaration of a local/mem variable:
    - if it's an array/matrix/etc, its size(s) should be
@@ -264,11 +272,11 @@ 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_type  ~var_opt:(Some id) 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
+      (pp_c_type  ~var_opt:(Some id) id.var_id) id.var_type
 
 let pp_c_decl_array_mem self fmt id =
   fprintf fmt "%a = (%a) (%s->_reg.%s)"
@@ -409,7 +417,7 @@ let print_stateless_C_prototype fmt (name, inputs, outputs) =
     | _ -> assert false
   in
   fprintf fmt "%a %s (@[<v>@[%a@]@,@])"
-    pp_basic_c_type output.var_type
+    (pp_basic_c_type ~var_opt:None) output.var_type
     name
     (Utils.fprintf_list ~sep:",@ " pp_c_decl_input_var) inputs
     
@@ -650,16 +658,49 @@ let pp_instance_call m self fmt i (inputs: value_t list) (outputs: var_decl list
     aux [] fmt (List.hd inputs).value_type
   end
 
-
-(*** Common functions for main ***)
+  (*** Common functions for main ***)
 
 let print_put_var fmt file_suffix name var_type var_id =
-  match (Types.unclock_type var_type).Types.tdesc with
-  | Types.Tint -> fprintf fmt "_put_int(f_out%s, \"%s\", %s)" file_suffix name var_id
-  | Types.Tbool -> fprintf fmt "_put_bool(f_out%s, \"%s\", %s)" file_suffix name var_id
-  | Types.Treal when !Options.mpfr -> fprintf fmt "_put_double(f_out%s, \"%s\", mpfr_get_d(%s, %s), %i)" file_suffix name var_id (Mpfr.mpfr_rnd ()) !Options.print_prec_double
-  | Types.Treal -> fprintf fmt "_put_double(f_out%s, \"%s\", %s, %i)" file_suffix name var_id !Options.print_prec_double
-  | _ -> Format.eprintf "Impossible to print the _put_xx for type %a@.@?" Types.print_ty var_type; assert false
+  let unclocked_t = Types.unclock_type var_type in
+  if Types.is_int_type unclocked_t then
+    fprintf fmt "_put_int(f_out%s, \"%s\", %s)" file_suffix name var_id
+  else if Types.is_bool_type unclocked_t then
+    fprintf fmt "_put_bool(f_out%s, \"%s\", %s)" file_suffix name var_id
+  else if Types.is_real_type unclocked_t then
+    if !Options.mpfr then
+      fprintf fmt "_put_double(f_out%s, \"%s\", mpfr_get_d(%s, %s), %i)" file_suffix name var_id (Mpfr.mpfr_rnd ()) !Options.print_prec_double
+    else
+      fprintf fmt "_put_double(f_out%s, \"%s\", %s, %i)" file_suffix name var_id !Options.print_prec_double
+  else
+    (Format.eprintf "Impossible to print the _put_xx for type %a@.@?" Types.print_ty var_type; assert false)
+
+      
+let print_get_inputs fmt m =
+  let pi fmt (id, v', v) =
+
+    let unclocked_t = Types.unclock_type v.var_type in
+    if Types.is_int_type unclocked_t then
+      fprintf fmt "%s = _get_int(f_in%i, \"%s\")" v.var_id id v'.var_id
+    else if Types.is_bool_type unclocked_t then
+      fprintf fmt "%s = _get_bool(f_in%i, \"%s\")" v.var_id id v'.var_id
+    else if Types.is_real_type unclocked_t then
+      if !Options.mpfr then
+	fprintf fmt "mpfr_set_d(%s, _get_double(f_in%i, \"%s\"), %i)" v.var_id id v'.var_id (Mpfr.mpfr_prec ())
+      else
+	fprintf fmt "%s = _get_double(f_in%i, \"%s\")" v.var_id id v'.var_id
+    else
+      begin
+	Global.main_node := !Options.main_node;
+	Format.eprintf "Code generation error: %a%a@."
+	  Error.pp_error_msg Error.Main_wrong_kind
+	  Location.pp_loc v'.var_loc;
+	raise (Error (v'.var_loc, Error.Main_wrong_kind))
+      end
+  in
+  Utils.List.iteri2 (fun idx v' v ->
+    fprintf fmt "@ %a;" pi ((idx+1), v', v);
+  ) m.mname.node_inputs m.mstep.step_inputs
+
 
 (* Local Variables: *)
 (* compile-command:"make -C ../../.." *)
diff --git a/src/backends/C/c_backend_header.ml b/src/backends/C/c_backend_header.ml
index 6fda2576..0ce6fbcb 100644
--- a/src/backends/C/c_backend_header.ml
+++ b/src/backends/C/c_backend_header.ml
@@ -35,15 +35,19 @@ struct
 
 let print_import_standard fmt =
   begin
+    (* if Machine_types.has_machine_type () then *)
+    (*   begin *)
+	fprintf fmt "#include <stdint.h>@.";
+      (* end; *)
     if !Options.mpfr then
       begin
 	fprintf fmt "#include <mpfr.h>@."
       end;
-  if !Options.cpp then
-    fprintf fmt "#include \"%s/arrow.hpp\"@.@." arrow_top_decl.top_decl_owner 
-  else
-    fprintf fmt "#include \"%s/arrow.h\"@.@." arrow_top_decl.top_decl_owner 
-
+    if !Options.cpp then
+      fprintf fmt "#include \"%s/arrow.hpp\"@.@." arrow_top_decl.top_decl_owner 
+    else
+      fprintf fmt "#include \"%s/arrow.h\"@.@." arrow_top_decl.top_decl_owner 
+	
   end
 
 let rec print_static_val pp_var fmt v =
diff --git a/src/backends/C/c_backend_main.ml b/src/backends/C/c_backend_main.ml
index 04997137..4d149ee2 100644
--- a/src/backends/C/c_backend_main.ml
+++ b/src/backends/C/c_backend_main.ml
@@ -31,32 +31,13 @@ struct
 (*                         Main related functions                                           *)
 (********************************************************************************************)
 
-let print_get_inputs fmt m =
-  let pi fmt (id, v', v) =
-  match (Types.unclock_type v.var_type).Types.tdesc with
-    | Types.Tint -> fprintf fmt "%s = _get_int(f_in%i, \"%s\")" v.var_id id v'.var_id
-    | Types.Tbool -> fprintf fmt "%s = _get_bool(f_in%i, \"%s\")" v.var_id id v'.var_id
-    | Types.Treal when !Options.mpfr -> fprintf fmt "mpfr_set_d(%s, _get_double(f_in%i, \"%s\"), %i)" v.var_id id v'.var_id (Mpfr.mpfr_prec ())
-    | Types.Treal -> fprintf fmt "%s = _get_double(f_in%i, \"%s\")" v.var_id id v'.var_id
-    | _ ->
-      begin
-	Global.main_node := !Options.main_node;
-	Format.eprintf "Code generation error: %a%a@."
-	  Error.pp_error_msg Error.Main_wrong_kind
-	  Location.pp_loc v'.var_loc;
-	raise (Error (v'.var_loc, Error.Main_wrong_kind))
-      end
-  in
-  List.iteri2 (fun idx v' v ->
-    fprintf fmt "@ %a;" pi ((idx+1), v', v);
-  ) m.mname.node_inputs m.mstep.step_inputs
 
 let print_put_outputs fmt m = 
   let po fmt (id, o', o) =
     let suff = string_of_int id in
     print_put_var fmt suff o'.var_id o.var_type o.var_id
   in
-  Utils.List.iteri2 (fun idx v' v -> fprintf fmt "@ %a;" po ((idx+1), v', v)) m.mname.node_outputs m.mstep.step_outputs
+  List.iteri2 (fun idx v' v -> fprintf fmt "@ %a;" po ((idx+1), v', v)) m.mname.node_outputs m.mstep.step_outputs
 
 let print_main_inout_declaration basename fmt m =
   let mname = m.mname.node_id in
diff --git a/src/backends/C/c_backend_mauve.ml b/src/backends/C/c_backend_mauve.ml
index 0cb928ce..bd9c091b 100644
--- a/src/backends/C/c_backend_mauve.ml
+++ b/src/backends/C/c_backend_mauve.ml
@@ -43,12 +43,10 @@ let print_mauve_header fmt mauve_machine basename prog machines _ (*dependencies
 let mauve_default_value v =
   (* let v_name = v.var_id in *)
 
-  let v_type = (Types.repr v.var_type).Types.tdesc in
-  match v_type with
-  | Types.Tbool -> "false"
-  | Types.Tint  -> "0"
-  | Types.Treal -> "0.0"
-  | _ -> assert false
+  if Types.is_bool_type v.var_type then "false"
+  else if Types.is_int_type v.var_type then "0"
+  else if Types.is_real_type v.var_type then "0.0"
+  else assert false
 
 let print_mauve_default fmt mauve_machine v = 
   let v_name: string = v.var_id in
@@ -80,7 +78,7 @@ let print_mauve_shell fmt mauve_machine basename prog machines _ (*dependencies*
   List.iter
     (fun v ->
       let v_name = v.var_id in
-      let v_type = pp_c_basic_type_desc (Types.repr v.var_type).Types.tdesc in
+      let v_type = pp_c_basic_type_desc v.var_type in
       fprintf fmt "\tReadPort<%s> & port_%s = mk_readPort<%s>(\"%s\", " v_type v_name v_type v_name;
       print_mauve_default fmt mauve_machine v;
       fprintf fmt ");@.";
@@ -90,7 +88,7 @@ let print_mauve_shell fmt mauve_machine basename prog machines _ (*dependencies*
   List.iter
     (fun v ->
       let v_name = v.var_id in
-      let v_type = pp_c_basic_type_desc (Types.repr v.var_type).Types.tdesc in
+      let v_type = pp_c_basic_type_desc v.var_type in
       fprintf fmt "\tWritePort<%s> & port_%s = mk_writePort<%s>(\"%s\");@." v_type v_name v_type v_name;
     ) mauve_machine.mstep.step_outputs;
 
@@ -134,13 +132,13 @@ let print_mauve_core fmt mauve_machine basename prog machines _ (*dependencies*)
   List.iter
     (fun v ->
       let v_name = v.var_id in
-      let v_type = pp_c_basic_type_desc (Types.repr v.var_type).Types.tdesc in
+      let v_type = pp_c_basic_type_desc v.var_type in
       fprintf fmt "\t\t%s %s = port_%s.read();@." v_type v_name v_name;
     ) mauve_machine.mstep.step_inputs;
   List.iter
     (fun v ->
       let v_name = v.var_id in
-      let v_type = pp_c_basic_type_desc (Types.repr v.var_type).Types.tdesc in
+      let v_type = pp_c_basic_type_desc v.var_type in
       fprintf fmt "\t\t%s %s;@." v_type v_name;
     ) mauve_machine.mstep.step_outputs;
   print_mauve_step fmt node_name mauve_machine;
diff --git a/src/backends/C/c_backend_src.ml b/src/backends/C/c_backend_src.ml
index b60ef8f2..50ab74fb 100644
--- a/src/backends/C/c_backend_src.ml
+++ b/src/backends/C/c_backend_src.ml
@@ -608,7 +608,7 @@ let print_global_init_code fmt basename prog dependencies =
   let constants = List.map const_of_top (get_consts prog) in
   fprintf fmt "@[<v 2>%a {@,static %s init = 0;@,@[<v 2>if (!init) { @,init = 1;@,%a%t%a@]@,}@,return;@]@,}@.@."
     print_global_init_prototype baseNAME
-    (pp_c_basic_type_desc Types.Tbool)
+    (pp_c_basic_type_desc Type_predef.type_bool)
     (* constants *) 
     (Utils.fprintf_list ~sep:"@," (pp_const_initialize (pp_c_var_read Machine_code.empty_machine))) constants
     (Utils.pp_final_char_if_non_empty "@," dependencies)
@@ -620,7 +620,7 @@ let print_global_clear_code  fmt basename prog dependencies =
   let constants = List.map const_of_top (get_consts prog) in
   fprintf fmt "@[<v 2>%a {@,static %s clear = 0;@,@[<v 2>if (!clear) { @,clear = 1;@,%a%t%a@]@,}@,return;@]@,}@.@."
     print_global_clear_prototype baseNAME
-    (pp_c_basic_type_desc Types.Tbool)
+    (pp_c_basic_type_desc Type_predef.type_bool)
     (* constants *) 
     (Utils.fprintf_list ~sep:"@," (pp_const_clear (pp_c_var_read Machine_code.empty_machine))) constants
     (Utils.pp_final_char_if_non_empty "@," dependencies)
@@ -666,6 +666,10 @@ let print_machine dependencies fmt m =
 let print_import_standard source_fmt =
   begin
     fprintf source_fmt "#include <assert.h>@.";
+    if Machine_types.has_machine_type () then
+      begin
+	fprintf source_fmt "#include <stdint.h>@."
+      end;
     if not !Options.static_mem then
       begin
 	fprintf source_fmt "#include <stdlib.h>@.";
diff --git a/src/backends/EMF/EMF_backend.ml b/src/backends/EMF/EMF_backend.ml
index 283ee0f6..06d647e8 100644
--- a/src/backends/EMF/EMF_backend.ml
+++ b/src/backends/EMF/EMF_backend.ml
@@ -197,6 +197,7 @@ and branch_instr_vars m i =
 	     (reset_name f,
 	      Corelang.mktyp loc Tydec_bool, Corelang.mkclock loc Ckdec_any,
 	      false,
+	      None,
 	      None) 
 	 in
 	 VSet.add reset_var args_vars
@@ -365,23 +366,40 @@ let rec pp_emf_instr m fmt i =
     fprintf fmt "%a" pp_content i;
     fprintf fmt "@]@]@ }"
 and pp_emf_instrs m fmt instrs = fprintf_list ~sep:",@ " (pp_emf_instr m) fmt instrs
-       
+
+let pp_emf_annot cpt fmt (key, ee) =
+  let _ =
+    fprintf fmt "\"ann%i\": { @[<hov 0>\"key\": [%a],@ \"eexpr\": %a@] }"
+      !cpt
+      (fprintf_list ~sep:"," (fun fmt s -> fprintf fmt "\"%s\"" s)) key
+      pp_emf_eexpr ee
+  in
+  incr cpt
+  
+let pp_emf_annots cpt fmt annots = fprintf_list ~sep:",@ " (pp_emf_annot cpt) fmt annots.annots
+let pp_emf_annots_list cpt fmt annots_list = fprintf_list ~sep:",@ " (pp_emf_annots cpt) fmt annots_list
 let pp_machine fmt m =
   let instrs = (*merge_branches*) m.mstep.step_instrs in
   try
     fprintf fmt "@[<v 2>\"%a\": {@ "
        print_protect (fun fmt -> pp_print_string fmt m.mname.node_id);
-    fprintf fmt "\"kind\": %t,@ \"inputs\": [%a],@ \"outputs\": [%a],@ \"locals\": [%a],@ "
+    fprintf fmt "\"kind\": %t,@ "
       (fun fmt -> if not ( snd (get_stateless_status m) )
 	then fprintf fmt "\"stateful\""
-	else fprintf fmt "\"stateless\"")
-      pp_emf_vars_decl m.mstep.step_inputs
-      pp_emf_vars_decl m.mstep.step_outputs
-      pp_emf_vars_decl m.mstep.step_locals
-    ;
+	else fprintf fmt "\"stateless\"");
+    fprintf fmt "\"inputs\": [%a],@ "
+      pp_emf_vars_decl m.mstep.step_inputs;
+    fprintf fmt "\"outputs\": [%a],@ "
+      pp_emf_vars_decl m.mstep.step_outputs;
+    fprintf fmt "\"locals\": [%a],@ "
+      pp_emf_vars_decl m.mstep.step_locals;
+    fprintf fmt "\"mems\": [%a],@ "
+      pp_emf_vars_decl m.mmemory;
+    
     fprintf fmt "\"original_name\": \"%s\",@ " m.mname.node_id;
-    fprintf fmt "\"instrs\": {@[<v 0> %a@]@ }"
+    fprintf fmt "\"instrs\": {@[<v 0> %a@]@ },@ "
       (pp_emf_instrs m) instrs;
+    fprintf fmt "\"annots\": {@[<v 0> %a@]@ }" (pp_emf_annots_list (ref 0)) m.mannot;
     fprintf fmt "@]@ }"
   with Unhandled msg -> (
     eprintf "[Error] @[<v 0>EMF backend@ Issues while translating node %s@ "
diff --git a/src/backends/EMF/EMF_common.ml b/src/backends/EMF/EMF_common.ml
index 2f0be110..43c2b614 100644
--- a/src/backends/EMF/EMF_common.ml
+++ b/src/backends/EMF/EMF_common.ml
@@ -86,7 +86,7 @@ fprintf fmt "uint16"
       
    
      
-let pp_cst_type c infered_typ fmt =
+let pp_cst_type fmt c (*infered_typ*) =
   match c with
   | Const_tag t ->
      let typ = (Corelang.typedef_of_top (Hashtbl.find Corelang.tag_table t)) in
@@ -94,19 +94,17 @@ let pp_cst_type c infered_typ fmt =
        fprintf fmt "bool"
      else
        pp_tag_type fmt typ
-  | Const_int _ -> fprintf fmt "%s" !Options.int_type
-  | Const_real _ -> fprintf fmt "%s" !Options.real_type
-  | _ -> Format.eprintf "cst: %a@." Printers.pp_const c; assert false
+  | Const_int _ -> fprintf fmt "int" (*!Options.int_type*)
+  | Const_real _ -> fprintf fmt "real" (*!Options.real_type*)
+  | Const_string _ -> fprintf fmt "string" 
+  | _ -> eprintf "cst: %a@." Printers.pp_const c; assert false
 
 let rec pp_infered_type fmt t =
   let open Types in
+  if is_bool_type t  then fprintf fmt "bool" else
+  if is_int_type t then fprintf fmt "int" else (* !Options.int_type *)
+  if is_real_type t then fprintf fmt "real" else (* !Options.real_type *)
   match t.tdesc with
-  | Tint ->
-     fprintf fmt "%s" !Options.int_type
-  | Treal ->
-     fprintf fmt "%s" !Options.real_type
-  | Tbool ->
-     fprintf fmt "bool"
   | Tclock t ->
      pp_infered_type fmt t
   | Tstatic (_, t) ->
@@ -119,11 +117,12 @@ let rec pp_infered_type fmt t =
      pp_tag_type fmt typ
    | Tlink ty -> 
        pp_infered_type fmt ty 
-  | _ -> Format.eprintf "unhandled type: %a@." Types.print_node_ty t; assert false
+   | _ -> eprintf "unhandled type: %a@." Types.print_node_ty t; assert false
+     
 let rec pp_concrete_type dec_t infered_t fmt =
   match dec_t with
-  | Tydec_int -> fprintf fmt "%s" !Options.int_type
-  | Tydec_real -> fprintf fmt "%s" !Options.real_type
+  | Tydec_int -> fprintf fmt "int" (* !Options.int_type *)
+  | Tydec_real -> fprintf fmt "real" (* !Options.real_type *)
   (* TODO we could add more concrete types here if they were available in
      dec_t *)
   | Tydec_bool -> fprintf fmt "bool"
@@ -134,20 +133,25 @@ let rec pp_concrete_type dec_t infered_t fmt =
     pp_tag_type fmt typ
   )
   | Tydec_any -> pp_infered_type fmt infered_t 
-  | _ -> Format.eprintf
+  | _ -> eprintf
      "unhandled construct in type printing for EMF backend: %a@."
      Printers.pp_var_type_dec_desc dec_t; raise (Failure "var")
        
 
-let pp_cst_type fmt v =
+(*let pp_cst_type fmt v =
   match v.value_desc with
   | Cst c-> pp_cst_type c v.value_type fmt (* constants do not have declared type (yet) *)
   | _ -> assert false
-     
+*)
+       
 let pp_var_type fmt v =
   try
-  pp_concrete_type v.var_dec_type.ty_dec_desc v.var_type fmt
-  with Failure _ -> Format.eprintf "failed var: %a@." Printers.pp_var v; assert false
+    if Machine_types.is_specified v then
+      Machine_types.pp_var_type fmt v
+    else
+      pp_concrete_type v.var_dec_type.ty_dec_desc v.var_type fmt
+  with Failure _ -> eprintf "failed var: %a@." Printers.pp_var v; assert false
+    
 (******** Other print functions *)
     
 let pp_emf_var_decl fmt v =
@@ -171,16 +175,16 @@ let pp_tag_id fmt t =
   else
     let const_list = match typ.tydef_desc with Tydec_enum tl -> tl | _ -> assert false in
     fprintf fmt "%i" (get_idx t const_list)
-     
-let pp_emf_cst_or_var fmt v =
-  match v.value_desc with
-  | Cst ((Const_tag t) as c)->
+
+let pp_emf_cst fmt c =
+  match c with
+  | Const_tag t->
      let typ = (Corelang.typedef_of_top (Hashtbl.find Corelang.tag_table t)) in
      if typ.tydef_id = "bool" then (
        fprintf fmt "{@[\"type\": \"constant\",@ ";
        fprintf fmt"\"value\": \"%a\",@ "
 	 Printers.pp_const c;
-       fprintf fmt "\"datatype\": \"%a\"@ " pp_cst_type v;
+       fprintf fmt "\"datatype\": \"%a\"@ " pp_cst_type c;
        fprintf fmt "@]}"
      )
      else (
@@ -188,15 +192,25 @@ let pp_emf_cst_or_var fmt v =
 	 pp_tag_id t;
        fprintf fmt "\"origin_type\": \"%s\",@ \"origin_value\": \"%s\",@ "
 	 typ.tydef_id t;
-       fprintf fmt "\"datatype\": \"%a\"@ " pp_cst_type v;
+       fprintf fmt "\"datatype\": \"%a\"@ " pp_cst_type c;
        fprintf fmt "@]}"
      )
-  | Cst c -> (
+  | Const_string s ->
+    fprintf fmt "{@[\"type\": \"constant\",@ \"value\": \"%s\",@ " s;
+    fprintf fmt "\"datatype\": \"%a\"@ " pp_cst_type c;
+    fprintf fmt "@]}"
+     
+  | _ -> (
     fprintf fmt "{@[\"type\": \"constant\",@ \"value\": \"%a\",@ "
       Printers.pp_const c;
-    fprintf fmt "\"datatype\": \"%a\"@ " pp_cst_type v;
+    fprintf fmt "\"datatype\": \"%a\"@ " pp_cst_type c;
     fprintf fmt "@]}"
   )
+  
+  
+let pp_emf_cst_or_var fmt v =
+  match v.value_desc with
+  | Cst c -> pp_emf_cst fmt c
   | LocalVar v
   | StateVar v -> (
     fprintf fmt "{@[\"type\": \"variable\",@ \"value\": \"%a\",@ "
@@ -205,13 +219,59 @@ let pp_emf_cst_or_var fmt v =
     fprintf fmt "\"datatype\": \"%a\"@ " pp_var_type v;
     fprintf fmt "@]}"
   )
-  | _ -> Format.eprintf "Not of cst or var: %a@." Machine_code.pp_val v ; assert false (* Invalid argument *)
+  | _ -> eprintf "Not of cst or var: %a@." Machine_code.pp_val v ; assert false (* Invalid argument *)
 
 
 let pp_emf_cst_or_var_list =
   Utils.fprintf_list ~sep:",@ " pp_emf_cst_or_var
 
+(* Printer lustre expr and eexpr *)
+    
+let rec pp_emf_expr fmt e =
+  match e.expr_desc with
+  | Expr_const c -> pp_emf_cst fmt c
+  | Expr_ident id ->
+     fprintf fmt "{@[\"type\": \"variable\",@ \"value\": \"%a\",@ "
+       print_protect (fun fmt -> pp_print_string fmt id);
+    fprintf fmt "\"datatype\": \"%t\"@ "
+      (pp_concrete_type
+	 Tydec_any (* don't know much about that time since it was not
+		      declared. That may not work with clock constants *)
+	 e.expr_type
+      );
+    fprintf fmt "@]}"
+
+  | Expr_tuple el ->
+     fprintf fmt "[@[<hov 0>%a@ @]]"
+       (Utils.fprintf_list ~sep:",@ " pp_emf_expr) el
+  | _ -> (
+    Log.report ~level:2
+      (fun fmt ->
+	fprintf fmt "Warning: unhandled expression %a in annotation.@ "
+	  Printers.pp_expr e;
+	fprintf fmt "Will not be produced in the experted JSON EMF"
+      );    
+    fprintf fmt "\"unhandled construct, complain to Ploc\""
+  )
+(* Remaining constructs *)  
+(* | Expr_ite   of expr * expr * expr *)
+(* | Expr_arrow of expr * expr *)
+(* | Expr_fby of expr * expr *)
+(* | Expr_array of expr list *)
+(* | Expr_access of expr * Dimension.dim_expr *)
+(* | Expr_power of expr * Dimension.dim_expr *)
+(* | Expr_pre of expr *)
+(* | Expr_when of expr * ident * label *)
+(* | Expr_merge of ident * (label * expr) list *)
+(* | Expr_appl of call_t *)
+     
 
+let pp_emf_eexpr fmt ee =
+  fprintf fmt "{@[<hov 0>\"quantifiers\": \"%a\",@ \"qfexpr\": @[%a@]@] }"
+    (Utils.fprintf_list ~sep:"; " Printers.pp_quantifiers) ee.eexpr_quantifiers
+    pp_emf_expr ee.eexpr_qfexpr
+    
+    
 (* Local Variables: *)
 (* compile-command: "make -C ../.." *)
 (* End: *)
diff --git a/src/backends/Horn/horn_backend_common.ml b/src/backends/Horn/horn_backend_common.ml
index d00d0e1b..f1638544 100644
--- a/src/backends/Horn/horn_backend_common.ml
+++ b/src/backends/Horn/horn_backend_common.ml
@@ -19,10 +19,10 @@ let pp_machine_step_name fmt id = fprintf fmt "%s_step" id
 let pp_machine_stateless_name fmt id = fprintf fmt "%s_fun" id
 
 let rec pp_type fmt t =
+  if Types.is_bool_type t  then fprintf fmt "Bool" else
+  if Types.is_int_type t then fprintf fmt "Int" else 
+  if Types.is_real_type t then fprintf fmt "Real" else 
   match (Types.repr t).Types.tdesc with
-  | Types.Tbool           -> fprintf fmt "Bool"
-  | Types.Tint            -> fprintf fmt "Int"
-  | Types.Treal           -> fprintf fmt "Real"
   | Types.Tconst ty       -> pp_print_string fmt ty
   | Types.Tclock t        -> pp_type fmt t
   | Types.Tarray(dim,ty)   -> fprintf fmt "(Array Int "; pp_type fmt ty; fprintf fmt ")"
diff --git a/src/backends/Horn/horn_backend_printers.ml b/src/backends/Horn/horn_backend_printers.ml
index 529a033f..bcffe130 100644
--- a/src/backends/Horn/horn_backend_printers.ml
+++ b/src/backends/Horn/horn_backend_printers.ml
@@ -96,10 +96,11 @@ let rec get_type v =
    for the type integer (arrays).
 *)
 let rec pp_default_val fmt t =
+  let t = Types.dynamic_type t in
+  if Types.is_bool_type t  then fprintf fmt "true" else
+  if Types.is_int_type t then fprintf fmt "0" else 
+  if Types.is_real_type t then fprintf fmt "0" else 
   match (Types.dynamic_type t).Types.tdesc with
-  | Types.Tint -> fprintf fmt "0"
-  | Types.Treal -> fprintf fmt "0"
-  | Types.Tbool -> fprintf fmt "true"
   | Types.Tarray(dim, l) -> (* TODO PL: this strange code has to be (heavily) checked *)
      let valt = Types.array_element_type t in
      fprintf fmt "((as const (Array Int %a)) %a)"
diff --git a/src/compiler_common.ml b/src/compiler_common.ml
index 4eeb238c..351f8229 100644
--- a/src/compiler_common.ml
+++ b/src/compiler_common.ml
@@ -262,4 +262,19 @@ let track_exception () =
   else ()
 
 
-
+let update_vdecl_parents_prog prog =
+  let update_vdecl_parents parent v =
+    v.var_parent_nodeid <- Some parent
+  in
+  List.iter (
+    fun top -> match top.top_decl_desc with
+    | Node nd ->
+       List.iter
+	 (update_vdecl_parents nd.node_id)
+	 (nd.node_inputs @ nd.node_outputs @ nd.node_locals )  
+    | ImportedNode ind -> 
+       List.iter
+	 (update_vdecl_parents ind.nodei_id)
+	 (ind.nodei_inputs @ ind.nodei_outputs )  
+    | _ -> ()
+  ) prog
diff --git a/src/compiler_stages.ml b/src/compiler_stages.ml
index 78c407b7..35b2d45c 100644
--- a/src/compiler_stages.ml
+++ b/src/compiler_stages.ml
@@ -48,6 +48,9 @@ let compile_source_to_header prog computed_types_env computed_clocks_env dirname
 
 (* From prog to prog *)
 let stage1 prog dirname basename =
+  (* Updating parent node information for variables *)
+  Compiler_common.update_vdecl_parents_prog prog;
+
   (* Removing automata *)
   let prog = expand_automata prog in
   Log.report ~level:4 (fun fmt -> fprintf fmt ".. after automata expansion:@,  @[<v 2>@,%a@]@ " Printers.pp_prog prog);
@@ -83,6 +86,10 @@ let stage1 prog dirname basename =
   (* Clock calculus *)
   let computed_clocks_env = clock_decls clock_env prog in
 
+  (* Registering and checking machine types *)
+  Machine_types.load prog;
+  
+
   (* Generating a .lusi header file only *)
   if !Options.lusi then
     (* We stop here the processing and produce the current prog. It will be
@@ -131,6 +138,7 @@ let stage1 prog dirname basename =
   Typing.uneval_prog_generics prog;
   Clock_calculus.uneval_prog_generics prog;
 
+
   if !Options.global_inline && !Options.main_node <> "" && !Options.witnesses then
     begin
       let orig = Corelang.copy_prog orig in
@@ -160,7 +168,11 @@ let stage1 prog dirname basename =
     else
       prog
   in
-  
+
+
+  (* (\* Registering and checking machine types *\) *)
+  (* Machine_types.load prog; *)
+
   (* Normalization phase *)
   Log.report ~level:1 (fun fmt -> fprintf fmt ".. normalization@,");
   let prog = Normalization.normalize_prog ~backend:!Options.output prog in
@@ -187,6 +199,103 @@ let stage1 prog dirname basename =
       Access.check_prog prog;
     end;
 
+  
   let prog = SortProg.sort_nodes_locals prog in
   
   prog, dependencies
+
+
+    (* from source to machine code, with optimization *)
+let stage2 prog =    
+  (* Computation of node equation scheduling. It also breaks dependency cycles
+     and warns about unused input or memory variables *)
+  Log.report ~level:1 (fun fmt -> fprintf fmt ".. @[<v 2>scheduling@ ");
+  let prog, node_schs =
+    try 
+      Scheduling.schedule_prog prog
+    with Causality.Error _ -> (* Error is not kept. It is recomputed in a more
+				 systemtic way in AlgebraicLoop module *)
+      AlgebraicLoop.analyze prog
+  in
+  Log.report ~level:1 (fun fmt -> fprintf fmt "%a"              Scheduling.pp_warning_unused node_schs);
+  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_schedule node_schs);
+  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_fanin_table node_schs);
+  Log.report ~level:5 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_dep_graph node_schs);
+  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Printers.pp_prog prog);
+  Log.report ~level:1 (fun fmt -> fprintf fmt "@]@ ");
+
+  (* TODO Salsa optimize prog: 
+     - emits warning for programs with pre inside expressions
+     - make sure each node arguments and memory is bounded by a local annotation
+     - introduce fresh local variables for each real pure subexpression
+  *)
+  (* DFS with modular code generation *)
+  Log.report ~level:1 (fun fmt -> fprintf fmt ".. machines generation@,");
+  let machine_code = Machine_code.translate_prog prog node_schs in
+
+  Log.report ~level:3 (fun fmt -> fprintf fmt ".. generated machines (unoptimized):@ %a@ "Machine_code.pp_machines machine_code);
+
+  (* Optimize machine code *)
+  Optimize_machine.optimize prog node_schs machine_code
+
+
+(* printing code *)
+let stage3 prog machine_code dependencies basename =
+  let basename    =  Filename.basename basename in
+  match !Options.output with
+    "C" -> 
+      begin
+	Log.report ~level:1 (fun fmt -> fprintf fmt ".. C code generation@,");
+	C_backend.translate_to_c
+	  (* alloc_header_file source_lib_file source_main_file makefile_file *)
+	  basename prog machine_code dependencies
+      end
+  | "java" ->
+     begin
+       (Format.eprintf "internal error: sorry, but not yet supported !"; assert false)
+     (*let source_file = basename ^ ".java" in
+       Log.report ~level:1 (fun fmt -> fprintf fmt ".. opening file %s@,@?" source_file);
+       let source_out = open_out source_file in
+       let source_fmt = formatter_of_out_channel source_out in
+       Log.report ~level:1 (fun fmt -> fprintf fmt ".. java code generation@,@?");
+       Java_backend.translate_to_java source_fmt basename normalized_prog machine_code;*)
+     end
+  | "horn" ->
+     begin
+       let destname = !Options.dest_dir ^ "/" ^ basename in
+       let source_file = destname ^ ".smt2" in (* Could be changed *)
+       let source_out = open_out source_file in
+       let fmt = formatter_of_out_channel source_out in
+       Log.report ~level:1 (fun fmt -> fprintf fmt ".. hornification@,");
+       Horn_backend.translate fmt basename prog (Machine_code.arrow_machine::machine_code);
+       (* Tracability file if option is activated *)
+       if !Options.traces then (
+	 let traces_file = destname ^ ".traces.xml" in (* Could be changed *)
+	 let traces_out = open_out traces_file in
+	 let fmt = formatter_of_out_channel traces_out in
+         Log.report ~level:1 (fun fmt -> fprintf fmt ".. tracing info@,");
+	 Horn_backend_traces.traces_file fmt basename prog machine_code;
+       )
+     end
+  | "lustre" ->
+     begin
+       let destname = !Options.dest_dir ^ "/" ^ basename in
+       let source_file = destname ^ ".lustrec.lus" in (* Could be changed *)
+       let source_out = open_out source_file in
+       let fmt = formatter_of_out_channel source_out in
+       Printers.pp_prog fmt prog;
+       Format.fprintf fmt "@.@?";
+       (*	Lustre_backend.translate fmt basename normalized_prog machine_code *)
+       ()
+     end
+  | "emf" ->
+     begin
+       let destname = !Options.dest_dir ^ "/" ^ basename in
+       let source_file = destname ^ ".emf" in (* Could be changed *)
+       let source_out = open_out source_file in
+       let fmt = formatter_of_out_channel source_out in
+       EMF_backend.translate fmt basename prog machine_code;
+       ()
+     end
+
+  | _ -> assert false
diff --git a/src/corelang.ml b/src/corelang.ml
index 8446d910..3573a1cc 100755
--- a/src/corelang.ml
+++ b/src/corelang.ml
@@ -41,7 +41,7 @@ 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, value) =
+let mkvar_decl loc ?(orig=false) (id, ty_dec, ck_dec, is_const, value, parentid) =
   assert (value = None || is_const);
   { var_id = id;
     var_orig = orig;
@@ -49,6 +49,7 @@ let mkvar_decl loc ?(orig=false) (id, ty_dec, ck_dec, is_const, value) =
     var_dec_clock = ck_dec;
     var_dec_const = is_const;
     var_dec_value = value;
+    var_parent_nodeid = parentid;
     var_type = Types.new_var ();
     var_clock = Clocks.new_var true;
     var_loc = loc }
@@ -62,13 +63,14 @@ let mkexpr loc d =
     expr_annot = None;
     expr_loc = loc }
 
-let var_decl_of_const c =
+let var_decl_of_const ?(parentid=None) 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_parent_nodeid = parentid;
     var_type = c.const_type;
     var_clock = Clocks.new_var false;
     var_loc = c.const_loc }
@@ -626,6 +628,7 @@ let get_node_interface nd =
   nodei_outputs = nd.node_outputs;
   nodei_stateless = nd.node_dec_stateless;
   nodei_spec = nd.node_spec;
+  (* nodei_annot = nd.node_annot; *)
   nodei_prototype = None;
   nodei_in_lib = [];
  }
@@ -901,7 +904,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, None))
+              mkvar_decl loc (name, mktyp loc Tydec_any, mkclock loc Ckdec_any, false, None, None))
     (Types.type_list_of_type ty)
 
 let mk_internal_node id =
@@ -920,6 +923,7 @@ let mk_internal_node id =
 	nodei_outputs = vdecls_of_typ_ck cpt tout;
 	nodei_stateless = Types.get_static_value ty <> None;
 	nodei_spec = spec;
+	(* nodei_annot = []; *)
 	nodei_prototype = None;
        	nodei_in_lib = [];
        })
@@ -1104,7 +1108,7 @@ and node_has_arrows 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)
+  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, vdecl.var_parent_nodeid)
 
 let copy_const cdecl =
   { cdecl with const_type = Types.new_var () }
diff --git a/src/corelang.mli b/src/corelang.mli
index 17726b40..da1f8161 100755
--- a/src/corelang.mli
+++ b/src/corelang.mli
@@ -20,9 +20,16 @@ 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 *) * expr option (* value *) -> var_decl
-
-val var_decl_of_const: const_desc -> var_decl
+val mkvar_decl: Location.t -> ?orig:bool ->
+  ident *
+    type_dec *
+    clock_dec *
+    bool (* is const *) *
+    expr option (* value *) *
+    string option (* parent id *)
+  -> var_decl
+
+val var_decl_of_const: ?parentid:LustreSpec.ident option -> const_desc -> var_decl
 val mkexpr: Location.t ->  expr_desc -> expr
 val mkeq: Location.t -> ident list * expr -> eq
 val mkassert: Location.t -> expr -> assert_t
diff --git a/src/env.ml b/src/env.ml
index 9fc32db2..38c03808 100755
--- a/src/env.ml
+++ b/src/env.ml
@@ -27,6 +27,7 @@ let exists_value env ident =
   IMap.mem ident env
 
 let iter env f = IMap.iter f env
+let fold = IMap.fold
 
 (* Merges x and y. In case of conflicting definitions,
    overwrites definitions in x by definitions in y *)
diff --git a/src/features/machine_types/machine_types.ml b/src/features/machine_types/machine_types.ml
new file mode 100644
index 00000000..8d67293f
--- /dev/null
+++ b/src/features/machine_types/machine_types.ml
@@ -0,0 +1,479 @@
+(* Extension du deal with machine types annotation
+
+   In each node, node local annotations can specify the actual type of the
+   implementation uintXX, intXX, floatXX ...
+
+   The module provide utility functions to query the model:
+   - get_var_machine_type varid nodeid returns the string denoting the actual type
+
+   The actual type is used at different stages of the coompilation
+   - early stage: limited typing, ie validity of operation are checked
+      - a first version ensures that the actual type is a subtype of the declared/infered ones
+        eg uint8 is a valid subtype of int
+      - a future implementation could ensures that operations are valid
+        - each standard or unspecified operation should be homogeneous : 
+          op: real -> real -> real is valid for any same subtype t of real: op: t -> t -> t
+        - specific nodes that explicitely defined subtypes could be used to perform casts
+          eg. a int2uint8 (i: int) returns (j: int) with annotations specifying i as int and j as uint8
+   - C backend: any print of a typed variable should rely on the actual machine type when provided
+   - EMF backend: idem
+   - Horn backend: an option could enforce the bounds provided by the machine
+     type or implement the cycling behavior for integer subtypes 
+   - Salsa plugin: the information should be propagated to the plugin. 
+     One can also imagine that results of the analysis could specify or
+     substitute a type by a subtype. Eg. the analysis detects that a float32 is enough for variable z and
+     the annotation is added to the node.
+
+
+A posisble behavior could be 
+- an option to  ensure type checking
+- dedicated  conversion functions that, in C, would generate cast or calls to simple identity functions (to be inlined)
+
+
+
+TODO
+EMF: rajouter les memoires dans les caracteristiques du node
+     gerer les types plus finement:
+     propager les types machines aux variables fraiches creees par la normalisation
+
+*)
+open LustreSpec
+  
+let keyword = ["machine_types"]
+
+module MT =
+struct
+
+  type int_typ =
+    | Tint8_t
+    | Tint16_t
+    | Tint32_t
+    | Tint64_t
+    | Tuint8_t
+    | Tuint16_t
+    | Tuint32_t
+    | Tuint64_t
+
+  let pp_int fmt t =
+    match t with
+    | Tint8_t -> Format.fprintf fmt "int8"
+    | Tint16_t -> Format.fprintf fmt "int16"
+    | Tint32_t -> Format.fprintf fmt "int32"
+    | Tint64_t -> Format.fprintf fmt "int64"
+    | Tuint8_t -> Format.fprintf fmt "uint8"
+    | Tuint16_t -> Format.fprintf fmt "uint16"
+    | Tuint32_t -> Format.fprintf fmt "uint32"
+    | Tuint64_t -> Format.fprintf fmt "uint64"
+
+  let pp_c_int fmt t =
+    match t with
+    | Tint8_t -> Format.fprintf fmt "int8_t"
+    | Tint16_t -> Format.fprintf fmt "int16_t"
+    | Tint32_t -> Format.fprintf fmt "int32_t"
+    | Tint64_t -> Format.fprintf fmt "int64_t"
+    | Tuint8_t -> Format.fprintf fmt "uint8_t"
+    | Tuint16_t -> Format.fprintf fmt "uint16_t"
+    | Tuint32_t -> Format.fprintf fmt "uint32_t"
+    | Tuint64_t -> Format.fprintf fmt "uint64_t"
+
+  type t =
+    | MTint of int_typ option
+    | MTreal of string option
+    | MTbool
+    | MTstring
+
+  open Format
+  let pp fmt t =
+    match t with
+    | MTint None ->
+       fprintf fmt "int"
+    | MTint (Some s) ->
+       fprintf fmt "%a" pp_int s
+    | MTreal None ->
+       fprintf fmt "real"
+    | MTreal (Some s) ->
+       fprintf fmt "%s" s
+    | MTbool ->
+       fprintf fmt "bool"
+    | MTstring ->
+       fprintf fmt "string"
+
+  let pp_c fmt t =
+    match t with
+    | MTint (Some s) ->
+       fprintf fmt "%a" pp_c_int s
+    | MTreal (Some s) ->
+       fprintf fmt "%s" s
+    | MTint None 
+    | MTreal None 
+    | MTbool 
+    | MTstring -> assert false
+	 
+	 
+  let is_scalar_type t =
+    match t with
+    | MTbool 
+    | MTint _
+    | MTreal _ -> true
+    | _ -> false
+
+
+  let is_numeric_type t =
+    match t with
+    | MTint _ 
+    | MTreal _ -> true
+    | _ -> false
+
+  let is_int_type t = match t with MTint _ -> true | _ -> false
+  let is_real_type t = match t with MTreal _ -> true | _ -> false
+  let is_bool_type t = t = MTbool
+    
+  let is_dimension_type t =
+    match t with
+    | MTint _
+    | MTbool -> true
+ | _ -> false
+
+  let type_int_builder = MTint None
+  let type_real_builder = MTreal None
+  let type_bool_builder = MTbool
+  let type_string_builder = MTstring
+
+  let unify _ _ = ()
+  let is_unifiable b1 b2 =
+    match b1, b2 with
+    | MTint _ , MTint _
+    | MTreal _, MTreal _
+    | MTstring, MTstring
+    | MTbool, MTbool -> true
+    | _ -> false
+
+  let is_exportable b =
+    match b with
+    | MTstring
+    | MTbool
+    | MTreal None
+    | MTint None -> false
+    | _ -> true
+end
+
+module MTypes = Types.Make (MT)
+
+let type_uint8 = MTypes.new_ty (MTypes.Tbasic (MT.MTint (Some MT.Tuint8_t)))
+let type_uint16 = MTypes.new_ty (MTypes.Tbasic (MT.MTint (Some MT.Tuint16_t)))
+let type_uint32 = MTypes.new_ty (MTypes.Tbasic (MT.MTint (Some MT.Tuint32_t)))
+let type_uint64 = MTypes.new_ty (MTypes.Tbasic (MT.MTint (Some MT.Tuint64_t)))
+let type_int8 = MTypes.new_ty (MTypes.Tbasic (MT.MTint (Some MT.Tint8_t)))
+let type_int16 = MTypes.new_ty (MTypes.Tbasic (MT.MTint (Some MT.Tint16_t)))
+let type_int32 = MTypes.new_ty (MTypes.Tbasic (MT.MTint (Some MT.Tint32_t)))
+let type_int64 = MTypes.new_ty (MTypes.Tbasic (MT.MTint (Some MT.Tint64_t)))
+
+  
+module ConvTypes =
+    struct
+      type type_expr = MTypes.type_expr
+
+      let map_type_basic f_basic  =
+	let rec map_type_basic e =
+	  { MTypes.tid = e.Types.tid;
+	    MTypes.tdesc = map_type_basic_desc (Types.type_desc e)
+	  }
+	and map_type_basic_desc td =
+	  let mape = map_type_basic in
+	  match td with
+	  | Types.Tbasic b -> f_basic b
+	  | Types.Tconst c -> MTypes.Tconst c
+	  | Types.Tenum e -> MTypes.Tenum e
+	  | Types.Tvar -> MTypes.Tvar
+	  | Types.Tunivar -> MTypes.Tunivar
+	     
+	  | Types.Tclock te -> MTypes.Tclock (mape te)
+	  | Types.Tarrow (te1, te2) -> MTypes.Tarrow (mape te1, mape te2)
+	  | Types.Ttuple tel -> MTypes.Ttuple (List.map mape tel)
+	  | Types.Tstruct id_te_l -> MTypes.Tstruct (List.map (fun (id, te) -> id, mape te) id_te_l) 
+	  | Types.Tarray (de, te) -> MTypes.Tarray (de, mape te)
+	  | Types.Tstatic (de, te) -> MTypes.Tstatic (de, mape te)
+	  | Types.Tlink te -> MTypes.Tlink (mape te)
+	in
+	map_type_basic
+	  
+      let import main_typ =
+	let import_basic b =
+	  if Types.BasicT.is_int_type b then MTypes.type_int else
+	    if Types.BasicT.is_real_type b then MTypes.type_real else
+	      if Types.BasicT.is_bool_type b then MTypes.type_bool else
+		(Format.eprintf "importing %a with issues!@.@?" Types.print_ty main_typ; assert false)
+	in
+	map_type_basic import_basic main_typ
+
+	  
+      let map_mtype_basic f_basic  =
+	let rec map_mtype_basic e =
+	  { Types.tid = e.MTypes.tid;
+	    Types.tdesc = map_mtype_basic_desc (MTypes.type_desc e)
+	  }
+	and map_mtype_basic_desc td =
+	  let mape = map_mtype_basic in
+	  match td with
+	  | MTypes.Tbasic b ->
+	     (* Format.eprintf "supposely basic mtype: %a@." MTypes.BasicT.pp b; *)
+	    f_basic b 
+	  | MTypes.Tconst c -> Types.Tconst c
+	  | MTypes.Tenum e -> Types.Tenum e
+	  | MTypes.Tvar -> Types.Tvar
+	  | MTypes.Tunivar -> Types.Tunivar
+	     
+	  | MTypes.Tclock te -> Types.Tclock (mape te)
+	  | MTypes.Tarrow (te1, te2) -> Types.Tarrow (mape te1, mape te2)
+	  | MTypes.Ttuple tel -> Types.Ttuple (List.map mape tel)
+	  | MTypes.Tstruct id_te_l -> Types.Tstruct (List.map (fun (id, te) -> id, mape te) id_te_l) 
+	  | MTypes.Tarray (de, te) -> Types.Tarray (de, mape te)
+	  | MTypes.Tstatic (de, te) -> Types.Tstatic (de, mape te)
+	  | MTypes.Tlink te -> Types.Tlink (mape te)
+	in
+	map_mtype_basic
+	  
+      let export machine_type =
+	let export_basic b =
+	if MTypes.BasicT.is_int_type b then Types.type_int else
+	if MTypes.BasicT.is_real_type b then Types.type_real else
+	if MTypes.BasicT.is_bool_type b then Types.type_bool else
+          (
+	    Format.eprintf "unhandled basic mtype is %a. Issues while dealing with basic type %a@.@?" MTypes.print_ty machine_type MTypes.BasicT.pp b;
+	    assert false
+	  )
+	in
+	map_mtype_basic export_basic machine_type
+
+    end
+
+module Typing = Typing.Make (MTypes) (ConvTypes)
+				  
+(* Associate to each (node_id, var_id) its machine type *)
+let machine_type_table : (var_decl, MTypes.type_expr) Hashtbl.t = Hashtbl.create 13
+
+(* Store the node signatures, with machine types when available *)
+let typing_env = ref Env.initial
+    
+let is_specified v =
+  (* Format.eprintf "looking for var %a@." Printers.pp_var v; *)
+  Hashtbl.mem machine_type_table v
+
+let pp_table fmt =
+  Format.fprintf fmt "@[<v 0>[";
+  Hashtbl.iter
+    (fun v typ -> Format.fprintf fmt "%a -> %a,@ " Printers.pp_var v MTypes.print_ty typ )
+    machine_type_table;
+  Format.fprintf fmt "@]"
+
+    
+let get_specified_type v =
+  (* Format.eprintf "Looking for variable %a in table [%t]@.@?" *)
+  (*   Printers.pp_var v *)
+  (*   pp_table; *)
+    Hashtbl.find machine_type_table v
+
+let is_exportable v =
+  is_specified v && (
+    let typ = get_specified_type v in
+    match (MTypes.dynamic_type typ).MTypes.tdesc with
+    | MTypes.Tbasic b -> MT.is_exportable b
+    | _ -> assert false  (* TODO deal with other constructs *)
+  )      
+(* could depend on the actual computed type *)
+
+let type_name typ = 
+  MTypes.print_ty Format.str_formatter typ;
+  Format.flush_str_formatter () 
+
+let pp_var_type fmt v =
+  let typ = get_specified_type v in
+  MTypes.print_ty fmt typ
+
+let pp_c_var_type fmt v =
+  let typ = get_specified_type v in
+  MTypes.print_ty_param MT.pp_c fmt typ
+    
+(************** Checking types ******************)
+  
+let erroneous_annotation loc =
+  Format.eprintf "Invalid annotation for machine_type at loc %a@."
+    Location.pp_loc loc;
+  assert false
+
+
+let valid_subtype subtype typ =
+  let mismatch subtyp typ =
+    Format.eprintf "Subtype mismatch %a vs %a@." MTypes.print_ty subtyp Types.print_ty typ; false
+  in
+  match (MTypes.dynamic_type subtype).MTypes.tdesc with
+  
+  | MTypes.Tbasic MT.MTint _ -> Types.is_int_type typ
+  | MTypes.Tbasic MT.MTreal _ -> Types.is_real_type typ
+  | MTypes.Tbasic MT.MTbool -> Types.is_bool_type typ
+  | _ -> mismatch subtype typ
+     
+let type_of_name name =
+  match name with
+  | "uint8" -> type_uint8
+  | "uint16" -> type_uint16
+  | "uint32" -> type_uint32
+  | "uint64" -> type_uint64
+  | "int8" -> type_int8
+  | "int16" -> type_int16
+  | "int32" -> type_int32
+  | "int64" -> type_int64
+  | _ -> assert false (* unknown custom machine type *)
+     
+let register_var var typ =
+  (* let typ = type_of_name type_name in *)
+  if valid_subtype typ var.var_type then (
+    Hashtbl.add machine_type_table var typ
+  )
+  else
+    erroneous_annotation var.var_loc
+    
+(* let register_var_opt var type_name_opt = *)
+(*   match type_name_opt with *)
+(*   | None -> () *)
+(*   | Some type_name -> register_var var type_name *)
+     
+(************** Registering annotations ******************)
+
+    
+let register_node node_id vars annots =
+  List.fold_left (fun accu annot ->
+    let annl = annot.annots in
+    List.fold_left (fun accu (kwd, value) ->
+      if kwd = keyword then
+	let expr = value.eexpr_qfexpr in
+	match Corelang.expr_list_of_expr expr with
+	| [var_id; type_name] -> (
+	  match var_id.expr_desc, type_name.expr_desc with
+	  | Expr_ident var_id, Expr_const (Const_string type_name) ->
+	     let var = List.find (fun v -> v.var_id = var_id) vars in
+	     Log.report ~level:2 (fun fmt ->
+	       Format.fprintf fmt "Recorded type %s for variable %a (parent node is %s)@ "
+		 type_name
+		 Printers.pp_var var
+		 (match var.var_parent_nodeid with Some id -> id | None -> "unknown")
+	     );
+	     let typ = type_of_name type_name in
+	     register_var var typ;
+	     var::accu
+	  | _ -> erroneous_annotation expr.expr_loc
+	)
+	| _ -> erroneous_annotation expr.expr_loc
+      else
+	accu
+    ) accu annl
+  ) [] annots
+
+
+let check_node nd vars =
+(* TODO check that all access to vars are valid *)
+  ()
+  
+let type_of_vlist vars =
+  let tyl = List.map (fun v -> if is_specified v then get_specified_type v else
+      ConvTypes.import v.var_type
+  ) vars in
+  MTypes.type_of_type_list tyl
+
+  
+let load prog =
+  let init_env =
+    Env.fold (fun id typ env ->
+      Env.add_value env id (ConvTypes.import typ)
+    ) 
+    Basic_library.type_env Env.initial in
+  let env =
+    List.fold_left (fun type_env top ->
+      match top.top_decl_desc with
+      | Node nd ->
+	 (* Format.eprintf "Registeing node %s@." nd.node_id; *)
+	 let vars = nd.node_inputs @ nd.node_outputs @ nd.node_locals in
+	 let constrained_vars = register_node nd.node_id vars nd.node_annot in
+	 check_node nd constrained_vars;
+
+	 (* Computing the node type *)
+	 let ty_ins = type_of_vlist nd.node_inputs in
+	 let ty_outs = type_of_vlist nd.node_outputs in
+	 let ty_node = MTypes.new_ty (MTypes.Tarrow (ty_ins,ty_outs)) in
+	 Typing.generalize ty_node;
+	 let env = Env.add_value type_env nd.node_id ty_node in
+	 (* Format.eprintf "Env: %a" (Env.pp_env MTypes.print_ty) env; *)
+	 env
+
+      | _ -> type_env 
+    (* | ImportedNode ind -> *)
+    (*    let vars = ind.nodei_inputs @ ind.nodei_outputs in *)
+    (*    register_node ind.nodei_id vars ind.nodei_annot *)
+(*      | _ -> () TODO: shall we load something for Open statements? *)
+    ) init_env prog
+  in
+  typing_env := env
+
+let type_expr nd expr =
+  let init_env = !typing_env in
+  (* Format.eprintf "Init env: %a@." (Env.pp_env MTypes.print_ty) init_env; *)
+  let init_vars = nd.node_inputs @ nd.node_outputs @ nd.node_locals in
+  (* Rebuilding the variables environment from accumulated knowledge *)
+  let env,vars = (* First, we add non specified variables *)
+    List.fold_left (fun (env, vars) v ->
+      if not (is_specified v) then
+  	let env = Env.add_value env v.var_id (ConvTypes.import v.var_type) in
+  	env, v::vars
+      else
+	env, vars
+    ) (init_env, []) init_vars 
+  in
+  
+  (* Then declared ones *)
+  let env, vars =
+    Hashtbl.fold (fun vdecl machine_type (env, vds) ->
+      if vdecl.var_parent_nodeid = Some nd.node_id then (
+	(* Format.eprintf "Adding variable %a to the environement@." Printers.pp_var vdecl; *)
+	let env = Env.add_value env vdecl.var_id machine_type in
+	env, vdecl::vds
+      )
+      else
+	env, vds
+    ) machine_type_table (env, vars)
+  in
+
+  
+  (* Format.eprintf "env with local vars: %a@." (Env.pp_env MTypes.print_ty) env; *)
+  (* Format.eprintf "expr = %a@." Printers.pp_expr expr; *)
+  (* let res = *)
+    Typing.type_expr
+      (env,vars)
+      false (* not in main node *)
+      false (* no a constant *)
+      expr
+  (* in *)
+  (* Format.eprintf "typing ok = %a@." MTypes.print_ty res; *)
+  (* res *)
+  
+(* Typing the expression (vars = expr) in node 
+   
+*)    
+let type_def node vars expr =
+  (* Format.eprintf "Typing def %a = %a@.@." *)
+  (*   (Utils.fprintf_list ~sep:", " Printers.pp_var) vars *)
+  (*   Printers.pp_expr expr *)
+  (* ; *)
+    let typ = type_expr node expr in
+    (* Format.eprintf "Type is %a. Saving stuff@.@." MTypes.print_ty typ; *)
+    let typ = MTypes.type_list_of_type typ  in
+    List.iter2 register_var vars typ 
+
+let has_machine_type () =
+  let annl = Annotations.get_expr_annotations keyword in
+  Format.eprintf "has _mchine _type annotations: %i@." (List.length annl);
+  List.length annl > 0
+      
+(* Local Variables: *)
+(* compile-command:"make -C ../.." *)
+(* End: *)
+
diff --git a/src/global.ml b/src/global.ml
index 892f630c..638dda6f 100644
--- a/src/global.ml
+++ b/src/global.ml
@@ -1,3 +1,5 @@
+module Types = Types.Main
+
 let type_env : (Types.type_expr Env.t) ref = ref Env.initial
 let clock_env : (Clocks.clock_expr Env.t) ref = ref Env.initial
 let basename = ref ""
diff --git a/src/inliner.ml b/src/inliner.ml
index 33935a03..235c3bd7 100644
--- a/src/inliner.ml
+++ b/src/inliner.ml
@@ -137,7 +137,9 @@ let inline_call node loc uid args reset locals caller =
 	 { 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 (fun x -> x) rename) v.var_dec_value) in
+	 Utils.option_map (rename_expr (fun x -> x) rename) v.var_dec_value,
+	 v.var_parent_nodeid (* we keep the original parent name *)
+	) in
     begin
       (*
 	(try
@@ -358,7 +360,9 @@ let witness filename main_name orig inlined type_env clock_env =
        {ty_dec_desc=Tydec_bool; ty_dec_loc=loc},
        {ck_dec_desc=Ckdec_any; ck_dec_loc=loc},
        false,
-       None)
+       None,
+       None
+      )
   ) (Utils.enumerate nb_outputs) 
   in
 
@@ -369,7 +373,9 @@ let witness filename main_name orig inlined type_env clock_env =
      {ty_dec_desc=Tydec_bool; ty_dec_loc=loc},
      {ck_dec_desc=Ckdec_any; ck_dec_loc=loc},
      false,
-     None)
+     None,
+     None
+    )
   in
   let main_ok_expr =
     let mkv x = mkexpr loc (Expr_ident x) in
diff --git a/src/lexerLustreSpec.mll b/src/lexerLustreSpec.mll
index 8027d3e8..81150fc0 100644
--- a/src/lexerLustreSpec.mll
+++ b/src/lexerLustreSpec.mll
@@ -154,9 +154,9 @@ and string_parse = parse
    try
      Parser_lustre.lustre_annot(* ParserLustreSpec.lustre_annot *) token lexbuf
    with Parsing.Parse_error as _e -> (
-     Format.eprintf "Lexing error at position %a:@.unexpected token %s@.@?"
+     Format.eprintf "Lexing error at position %a:@.unexpected token %s when parsing annotation %s@.@?"
        (fun fmt p -> Format.fprintf fmt "%s l%i c%i" p.Lexing.pos_fname p.Lexing.pos_lnum p.Lexing.pos_cnum) lexbuf.Lexing.lex_curr_p
-       (Lexing.lexeme lexbuf);
+       (Lexing.lexeme lexbuf) s;
      raise (Error (Location.curr lexbuf)))
      
 
diff --git a/src/lustreSpec.ml b/src/lustreSpec.ml
index 82888e0f..e6f5ab2d 100644
--- a/src/lustreSpec.ml
+++ b/src/lustreSpec.ml
@@ -8,7 +8,7 @@
 (*  version 2.1.                                                    *)
 (*                                                                  *)
 (********************************************************************)
-
+  
 type ident = Utils.ident
 type rat = Utils.rat
 type tag = Utils.tag
@@ -63,6 +63,7 @@ type var_decl =
      var_dec_clock: clock_dec;
      var_dec_const: bool;
      var_dec_value: expr option;
+     mutable var_parent_nodeid: ident option;
      mutable var_type: Types.type_expr;
      mutable var_clock: Clocks.clock_expr;
      var_loc: Location.t}
@@ -184,6 +185,7 @@ type imported_node_desc =
      nodei_outputs: var_decl list;
      nodei_stateless: bool;
      nodei_spec: node_annot option;
+     (* nodei_annot: expr_annot list; *)
      nodei_prototype: string option;
      nodei_in_lib: string list;
     }
diff --git a/src/machine_code.ml b/src/machine_code.ml
index 7288d6ac..e583dec7 100644
--- a/src/machine_code.ml
+++ b/src/machine_code.ml
@@ -178,6 +178,7 @@ let dummy_var_decl name typ =
     var_dec_clock = dummy_clock_dec;
     var_dec_const = false;
     var_dec_value = None;
+    var_parent_nodeid = None;
     var_type =  typ;
     var_clock = Clocks.new_ck Clocks.Cvar true;
     var_loc = Location.dummy_loc
@@ -218,7 +219,7 @@ let mk_val v t = { value_desc = v;
 
 let arrow_machine =
   let state = "_first" in
-  let var_state = dummy_var_decl state (Types.new_ty Types.Tbool) in
+  let var_state = dummy_var_decl state Type_predef.type_bool(* (Types.new_ty Types.Tbool) *) in
   let var_input1 = List.nth arrow_desc.node_inputs 0 in
   let var_input2 = List.nth arrow_desc.node_inputs 1 in
   let var_output = List.nth arrow_desc.node_outputs 0 in
@@ -622,10 +623,11 @@ let translate_decl nd sch =
 	       mktyp loc Tydec_bool,
 	       mkclock loc Ckdec_any,
 	       false, (* not a constant *)
-	       None (* no default value *)
+	       None, (* no default value *)
+	       Some nd.node_id
 	      )
 	  in
-	  assert_var.var_type <- Types.new_ty (Types.Tbool); 
+	  assert_var.var_type <- Type_predef.type_bool (* Types.new_ty (Types.Tbool) *); 
 	  let eq = mkeq loc ([var_id], expr) in
 	  (i+1, assert_var::vars, eq::eqlist, {expr with expr_desc = Expr_ident var_id}::assertlist)
 	) (1, [], [], []) exprl
diff --git a/src/main_lustre_compiler.ml b/src/main_lustre_compiler.ml
index 8932d19c..51af25f9 100644
--- a/src/main_lustre_compiler.ml
+++ b/src/main_lustre_compiler.ml
@@ -55,100 +55,6 @@ let compile_header dirname  basename extension =
 
 
 
-(* from source to machine code, with optimization *)
-let stage2 prog =    
-  (* Computation of node equation scheduling. It also breaks dependency cycles
-     and warns about unused input or memory variables *)
-  Log.report ~level:1 (fun fmt -> fprintf fmt ".. @[<v 2>scheduling@ ");
-  let prog, node_schs =
-    try 
-      Scheduling.schedule_prog prog
-    with Causality.Error _ -> (* Error is not kept. It is recomputed in a more
-				 systemtic way in AlgebraicLoop module *)
-      AlgebraicLoop.analyze prog
-  in
-  Log.report ~level:1 (fun fmt -> fprintf fmt "%a"              Scheduling.pp_warning_unused node_schs);
-  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_schedule node_schs);
-  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_fanin_table node_schs);
-  Log.report ~level:5 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Scheduling.pp_dep_graph node_schs);
-  Log.report ~level:3 (fun fmt -> fprintf fmt "@[<v 2>@ %a@]@," Printers.pp_prog prog);
-  Log.report ~level:1 (fun fmt -> fprintf fmt "@]@ ");
-
-  (* TODO Salsa optimize prog: 
-     - emits warning for programs with pre inside expressions
-     - make sure each node arguments and memory is bounded by a local annotation
-     - introduce fresh local variables for each real pure subexpression
-  *)
-  (* DFS with modular code generation *)
-  Log.report ~level:1 (fun fmt -> fprintf fmt ".. machines generation@,");
-  let machine_code = Machine_code.translate_prog prog node_schs in
-
-  Log.report ~level:3 (fun fmt -> fprintf fmt ".. generated machines (unoptimized):@ %a@ "Machine_code.pp_machines machine_code);
-
-  (* Optimize machine code *)
-  Optimize_machine.optimize prog node_schs machine_code
-
-
-(* printing code *)
-let stage3 prog machine_code dependencies basename =
-  let basename    =  Filename.basename basename in
-  match !Options.output with
-    "C" -> 
-      begin
-	Log.report ~level:1 (fun fmt -> fprintf fmt ".. C code generation@,");
-	C_backend.translate_to_c
-	  (* alloc_header_file source_lib_file source_main_file makefile_file *)
-	  basename prog machine_code dependencies
-      end
-  | "java" ->
-     begin
-       (Format.eprintf "internal error: sorry, but not yet supported !"; assert false)
-     (*let source_file = basename ^ ".java" in
-       Log.report ~level:1 (fun fmt -> fprintf fmt ".. opening file %s@,@?" source_file);
-       let source_out = open_out source_file in
-       let source_fmt = formatter_of_out_channel source_out in
-       Log.report ~level:1 (fun fmt -> fprintf fmt ".. java code generation@,@?");
-       Java_backend.translate_to_java source_fmt basename normalized_prog machine_code;*)
-     end
-  | "horn" ->
-     begin
-       let destname = !Options.dest_dir ^ "/" ^ basename in
-       let source_file = destname ^ ".smt2" in (* Could be changed *)
-       let source_out = open_out source_file in
-       let fmt = formatter_of_out_channel source_out in
-       Log.report ~level:1 (fun fmt -> fprintf fmt ".. hornification@,");
-       Horn_backend.translate fmt basename prog (Machine_code.arrow_machine::machine_code);
-       (* Tracability file if option is activated *)
-       if !Options.traces then (
-	 let traces_file = destname ^ ".traces.xml" in (* Could be changed *)
-	 let traces_out = open_out traces_file in
-	 let fmt = formatter_of_out_channel traces_out in
-         Log.report ~level:1 (fun fmt -> fprintf fmt ".. tracing info@,");
-	 Horn_backend_traces.traces_file fmt basename prog machine_code;
-       )
-     end
-  | "lustre" ->
-     begin
-       let destname = !Options.dest_dir ^ "/" ^ basename in
-       let source_file = destname ^ ".lustrec.lus" in (* Could be changed *)
-       let source_out = open_out source_file in
-       let fmt = formatter_of_out_channel source_out in
-       Printers.pp_prog fmt prog;
-       Format.fprintf fmt "@.@?";
-       (*	Lustre_backend.translate fmt basename normalized_prog machine_code *)
-       ()
-     end
-  | "emf" ->
-     begin
-       let destname = !Options.dest_dir ^ "/" ^ basename in
-       let source_file = destname ^ ".emf" in (* Could be changed *)
-       let source_out = open_out source_file in
-       let fmt = formatter_of_out_channel source_out in
-       EMF_backend.translate fmt basename prog machine_code;
-       ()
-     end
-
-  | _ -> assert false
 
 (* compile a .lus source file *)
 let rec compile_source dirname basename extension =
@@ -188,7 +94,7 @@ let rec compile_source dirname basename extension =
   Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v 2>.. Phase 2 : Machines generation@,");
 
   let machine_code = 
-    stage2 prog 
+    Compiler_stages.stage2 prog 
   in
 
   Log.report ~level:1 (fun fmt -> fprintf fmt "@]@ ");
@@ -207,7 +113,7 @@ let rec compile_source dirname basename extension =
 
   let machine_code = Plugins.refine_machine_code prog machine_code in
   
-  stage3 prog machine_code dependencies basename;
+  Compiler_stages.stage3 prog machine_code dependencies basename;
   begin
     Log.report ~level:1 (fun fmt -> fprintf fmt ".. done !@ @]@.");
     (* We stop the process here *)
diff --git a/src/normalization.ml b/src/normalization.ml
index ca24d8c8..42fed931 100644
--- a/src/normalization.ml
+++ b/src/normalization.ml
@@ -90,6 +90,7 @@ let mk_fresh_var node loc ty ck =
     var_dec_clock = dummy_clock_dec;
     var_dec_const = false;
     var_dec_value = None;
+    var_parent_nodeid = Some node.node_id;
     var_type = ty;
     var_clock = ck;
     var_loc = loc
@@ -167,7 +168,10 @@ let mk_expr_alias_opt opt node (defs, vars) expr =
 	    (Clocks.clock_list_of_clock expr.expr_clock) in
 	let new_def =
 	  mkeq expr.expr_loc (List.map (fun v -> v.var_id) new_aliases, expr)
-	in (new_def::defs, new_aliases@vars), replace_expr new_aliases expr
+	in
+	(* Typing and Registering machine type *) 
+	let _ = Machine_types.type_def node new_aliases expr  in
+	(new_def::defs, new_aliases@vars), replace_expr new_aliases expr
       else
 	(defs, vars), expr
 
@@ -420,19 +424,23 @@ let normalize_node node =
     ) (vars, [], []) node.node_asserts in
   let new_locals = List.filter not_is_orig_var vars in (* we filter out inout
 							  vars and initial locals ones *)
-  let new_locals = node.node_locals @ new_locals in (* we add again, at the
+  
+  let all_locals = node.node_locals @ new_locals in (* we add again, at the
 						       beginning of the list the
 						       local declared ones *)
   (*Format.eprintf "New locals: %a@.@?" (fprintf_list ~sep:", " Printers.pp_var) new_locals;*)
 
+
+  (* Updating annotations: traceability and machine types for fresh variables *)
+  
+  (* Compute traceability info:
+     - gather newly bound variables
+     - compute the associated expression without aliases
+  *)
   let new_annots =
     if !Options.traces then
       begin
-	(* Compute traceability info:
-	   - gather newly bound variables
-	   - compute the associated expression without aliases
-	*)
-	let diff_vars = List.filter (fun v -> not (List.mem v node.node_locals) ) new_locals in
+	let diff_vars = List.filter (fun v -> not (List.mem v node.node_locals) ) all_locals in
 	let norm_traceability = {
 	  annots = List.map (fun v ->
 	    let eq =
@@ -446,6 +454,7 @@ let normalize_node node =
 	    in
 	    let expr = substitute_expr diff_vars (defs@assert_defs) eq.eq_rhs in
 	    let pair = mkeexpr expr.expr_loc (mkexpr expr.expr_loc (Expr_tuple [expr_of_ident v.var_id expr.expr_loc; expr])) in
+	    Annotations.add_expr_ann node.node_id pair.eexpr_tag ["traceability"];
 	    (["traceability"], pair)
 	  ) diff_vars;
 	  annot_loc = Location.dummy_loc
@@ -457,9 +466,29 @@ let normalize_node node =
       node.node_annot
   in
 
+  let new_annots =
+    List.fold_left (fun annots v ->
+      if Machine_types.is_exportable v then
+	let typ = Machine_types.get_specified_type v in
+  	let typ_name = Machine_types.type_name typ in
+
+	let loc = v.var_loc in
+	let typ_as_string =
+	  mkexpr
+	    loc
+	    (Expr_const
+	       (Const_string typ_name))
+	in
+	let pair = expr_to_eexpr (expr_of_expr_list loc [expr_of_vdecl v; typ_as_string]) in
+	Annotations.add_expr_ann node.node_id pair.eexpr_tag Machine_types.keyword;
+	{annots = [Machine_types.keyword, pair]; annot_loc = loc}::annots
+      else
+	annots
+    ) new_annots new_locals
+  in
   let node =
     { node with
-      node_locals = new_locals;
+      node_locals = all_locals;
       node_stmts = List.map (fun eq -> Eq eq) (defs @ assert_defs);
       node_asserts = asserts;
       node_annot = new_annots;
diff --git a/src/optimize_machine.ml b/src/optimize_machine.ml
index 71a668c8..61808b7f 100644
--- a/src/optimize_machine.ml
+++ b/src/optimize_machine.ml
@@ -261,7 +261,7 @@ let machine_unfold fanin elim machine =
 
 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, None) 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, None) in
   let vdecl = { vdecl with var_type = const.const_type }
   in mkinstr (MLocalAssign (vdecl, mk_val (Cst const.const_value) vdecl.var_type))
 
diff --git a/src/parserLustreSpec.mly b/src/parserLustreSpec.mly
index 37349acc..e3645401 100644
--- a/src/parserLustreSpec.mly
+++ b/src/parserLustreSpec.mly
@@ -123,9 +123,12 @@ dim_list:
 
 expr:
 /* constants */
-  INT {mkexpr (Expr_const (Const_int $1))}
+| INT {mkexpr (Expr_const (Const_int $1))}
 | REAL {mkexpr (Expr_const (Const_real $1))}
 | FLOAT {mkexpr (Expr_const (Const_float $1))}
+| TRUE {mkexpr (Expr_const (Const_bool true))}
+| FALSE {mkexpr (Expr_const (Const_bool false))}
+| STRING {mkexpr (Expr_const (Const_string $1))}
 /* Idents or type enum tags */
 | IDENT {
   if Hashtbl.mem tag_table $1
diff --git a/src/parser_lustre.mly b/src/parser_lustre.mly
index 8038a393..bf5ba82f 100755
--- a/src/parser_lustre.mly
+++ b/src/parser_lustre.mly
@@ -382,6 +382,8 @@ expr:
 /* constants */
   INT {mkexpr (Expr_const (Const_int $1))}
 | REAL {let c,e,s = $1 in mkexpr (Expr_const (Const_real (c,e,s)))}
+| STRING {mkexpr (Expr_const (Const_string $1))}
+
 /* | FLOAT {mkexpr (Expr_const (Const_float $1))}*/
 /* Idents or type enum tags */
 | IDENT { mkexpr (Expr_ident $1) }
@@ -579,11 +581,11 @@ vdecl_list:
 
 vdecl:
   ident_list COL typeconst clock 
-    { List.map (fun (id, loc) -> mkvar_decl (id, mktyp $3, $4, false, None) loc) $1 }
+    { List.map (fun (id, loc) -> mkvar_decl (id, mktyp $3, $4, false, None, None) loc) $1 }
 | CONST ident_list /* static parameters don't have clocks */
-    { List.map (fun (id, loc) -> mkvar_decl (id, mktyp Tydec_any, mkclock Ckdec_any, true, None) loc) $2 }
+    { List.map (fun (id, loc) -> mkvar_decl (id, mktyp Tydec_any, mkclock Ckdec_any, true, None, None) loc) $2 }
 | CONST ident_list COL typeconst /* static parameters don't have clocks */
-    { List.map (fun (id, loc) -> mkvar_decl (id, mktyp $4, mkclock Ckdec_any, true, None) loc) $2 }
+    { List.map (fun (id, loc) -> mkvar_decl (id, mktyp $4, mkclock Ckdec_any, true, None, None) loc) $2 }
 
 local_vdecl_list:
   local_vdecl {$1}
@@ -591,13 +593,13 @@ local_vdecl_list:
 
 local_vdecl:
 /* Useless no ?*/    ident_list
-    { List.map (fun (id, loc) -> mkvar_decl (id, mktyp Tydec_any, mkclock Ckdec_any, false, None) loc) $1 }
+    { List.map (fun (id, loc) -> mkvar_decl (id, mktyp Tydec_any, mkclock Ckdec_any, false, None, None) loc) $1 }
 | ident_list COL typeconst clock 
-    { List.map (fun (id, loc) -> mkvar_decl (id, mktyp $3, $4, false, None) loc) $1 }
+    { List.map (fun (id, loc) -> mkvar_decl (id, mktyp $3, $4, false, None, None) loc) $1 }
 | CONST vdecl_ident EQ expr /* static parameters don't have clocks */
-    { let (id, loc) = $2 in [ mkvar_decl (id, mktyp Tydec_any, mkclock Ckdec_any, true, Some $4) loc] }
+    { let (id, loc) = $2 in [ mkvar_decl (id, mktyp Tydec_any, mkclock Ckdec_any, true, Some $4, None) loc] }
 | CONST vdecl_ident COL typeconst EQ expr /* static parameters don't have clocks */
-    { let (id, loc) = $2 in [ mkvar_decl (id, mktyp $4, mkclock Ckdec_any, true, Some $6) loc] }
+    { let (id, loc) = $2 in [ mkvar_decl (id, mktyp $4, mkclock Ckdec_any, true, Some $6, None) loc] }
 
 cdecl_list:
   cdecl SCOL { (fun itf -> [$1 itf]) }
diff --git a/src/pathConditions.ml b/src/pathConditions.ml
index 49882401..98d4475c 100644
--- a/src/pathConditions.ml
+++ b/src/pathConditions.ml
@@ -100,7 +100,7 @@ let rec compute_neg_expr cpt_pre (expr: LustreSpec.expr) =
      let vl, neg = neg_list l in
      vl, combine (fun l' -> {expr with expr_desc = Expr_tuple l'}) neg l
        
-  | Expr_ite (i,t,e) when (Types.repr t.expr_type).Types.tdesc = Types.Tbool -> (
+  | Expr_ite (i,t,e) when (Types.is_bool_type t.expr_type) -> (
     let list = [i; t; e] in
     let vl, neg = neg_list list in
     vl, combine (fun l ->
@@ -141,7 +141,7 @@ let rec compute_neg_expr cpt_pre (expr: LustreSpec.expr) =
        (fun (v, negv) -> (v, { expr with expr_desc = Expr_appl (op_name, negv, r) } ))
        args'
 
-  | Expr_ident _ when (Types.repr expr.expr_type).Types.tdesc = Types.Tbool ->
+  | Expr_ident _ when (Types.is_bool_type expr.expr_type) ->
      [], [(expr, cpt_pre), mkpredef_call expr.expr_loc "not" [expr]]
   | _ -> [] (* empty vars *) , [] 
 and gen_mcdc_cond_var v expr =
@@ -199,18 +199,18 @@ let rec mcdc_expr cpt_pre expr =
   | _ -> []
 
 let mcdc_var_def v expr = 
-  match (Types.repr expr.expr_type).Types.tdesc with
-  | Types.Tbool ->
+  if Types.is_bool_type expr.expr_type then
      let vl = gen_mcdc_cond_var v expr in
      vl
-  | _ -> let vl = mcdc_expr 0 expr in
-	 vl
-
+  else
+    let vl = mcdc_expr 0 expr in
+    vl
+      
 let mcdc_node_eq eq =
   let vl =
-    match eq.eq_lhs, (Types.repr eq.eq_rhs.expr_type).Types.tdesc, eq.eq_rhs.expr_desc with
-    | [lhs], Types.Tbool, _ ->  gen_mcdc_cond_var lhs eq.eq_rhs 
-    | _::_, Types.Ttuple tl, Expr_tuple rhs ->
+    match eq.eq_lhs, Types.is_bool_type eq.eq_rhs.expr_type, (Types.repr eq.eq_rhs.expr_type).Types.tdesc, eq.eq_rhs.expr_desc with
+    | [lhs], true, _, _ ->  gen_mcdc_cond_var lhs eq.eq_rhs 
+    | _::_, false, Types.Ttuple tl, Expr_tuple rhs ->
        (* We iterate trough pairs, but accumulate variables aside. The resulting
 	  expression shall remain a tuple defintion *)
        let vl = List.fold_right2 (fun lhs rhs accu ->
@@ -248,17 +248,29 @@ let mcdc_top_decl td =
        Format.fprintf Format.str_formatter "__cov_%i_%i" i nb_total;
        let cov_id = Format.flush_str_formatter () in
        let cov_var = mkvar_decl loc
-	 (cov_id, mktyp loc Tydec_bool, mkclock loc Ckdec_any, false, None) in
+	 (cov_id, mktyp loc Tydec_bool, mkclock loc Ckdec_any, false, None, None) in
        let cov_def = Eq (mkeq loc ([cov_id], cov_expr)) in
-       cov_var, cov_def
+       cov_var, cov_def, cov_expr
      ) fresh_cov_defs
      in
-     let fresh_vars, fresh_eqs = List.split fresh_cov_vars in
-     let fresh_annots =
+     let fresh_vars, fresh_eqs =
+       List.fold_right
+	 (fun (v,eq,_) (accuv, accueq)-> v::accuv, eq::accueq )
+	 fresh_cov_vars
+	 ([], [])
+     in
+     let fresh_annots = (* We produce two sets of annotations: PROPERTY ones for
+			   kind2, and regular ones to keep track of the nature
+			   of the annotations. *)
        List.map
-	 (fun v -> {annots =  [["PROPERTY"], expr_to_eexpr (expr_of_vdecl v)]; annot_loc = td.top_decl_loc})
-	 fresh_vars in
-     Format.printf "We have %i coverage criteria for node %s@." nb_total nd.node_id;
+	 (fun v -> let ee = expr_to_eexpr (expr_of_vdecl v) in
+		   {annots =  [["PROPERTY"], ee;
+			       ["coverage";"mcdc"], ee
+			      ];
+		    annot_loc = v.var_loc})
+	 fresh_vars
+     in
+     Format.printf "%i coverage criteria generated for node %s@ " nb_total nd.node_id;
      (* And add them as annotations --%PROPERTY: var TODO *)
      {td with top_decl_desc = Node {nd with
        node_locals = nd.node_locals@fresh_vars;
@@ -284,6 +296,8 @@ let mcdc prog =
       | _ -> assert false);
   List.map mcdc_top_decl prog
 
+
+    
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
 (* End: *)
diff --git a/src/printers.ml b/src/printers.ml
index 09164157..da0a5157 100644
--- a/src/printers.ml
+++ b/src/printers.ml
@@ -80,6 +80,12 @@ and pp_const fmt c =
     | Const_string s -> pp_print_string fmt ("\"" ^ s ^ "\"")
 
 
+let pp_annot_key fmt kwds =
+  match kwds with
+  | [] -> assert false
+  | [x] -> Format.pp_print_string fmt x
+  | _ -> Format.fprintf fmt "/%a/" (fprintf_list ~sep:"/" Format.pp_print_string) kwds
+
 let rec pp_expr fmt expr =
   (match expr.expr_annot with 
   | None -> fprintf fmt "%t" 
@@ -164,8 +170,8 @@ and pp_s_function fmt expr_ann =
 
 and pp_expr_annot fmt expr_ann =
   let pp_annot fmt (kwds, ee) =
-    Format.fprintf fmt "(*! %t: %a; *)"
-      (fun fmt -> match kwds with | [] -> assert false | [x] -> Format.pp_print_string fmt x | _ -> Format.fprintf fmt "/%a/" (fprintf_list ~sep:"/" Format.pp_print_string) kwds)
+    Format.fprintf fmt "(*! %a: %a; *)"
+      pp_annot_key kwds
       pp_eexpr ee
   in
   fprintf_list ~sep:"@ " pp_annot fmt expr_ann.annots
diff --git a/src/type_predef.ml b/src/type_predef.ml
index e9c1cfb2..48fd3f06 100755
--- a/src/type_predef.ml
+++ b/src/type_predef.ml
@@ -12,63 +12,83 @@
 (********************************************************************)
 
 (** Base types and predefined operator types. *)
-open Types
 
-let type_int = new_ty Tint
-let type_real = new_ty Treal
-let type_bool = new_ty Tbool
-let type_clock ty = new_ty (Tclock ty)
-let type_const tname = new_ty (Tconst tname)
-let type_enum taglist = new_ty (Tenum taglist)
-let type_struct fieldlist = new_ty (Tstruct fieldlist)
-let type_tuple tl = new_ty (Ttuple tl)
-let type_arrow ty1 ty2 = new_ty (Tarrow (ty1, ty2))
-let type_array d ty = new_ty (Tarray (d, ty))
-let type_static d ty = new_ty (Tstatic (d, ty))
+  
+module Make (T: Types.S) =
+struct
+  (* module T = Types.Make (BT) *)
+  module BT = T.BasicT
+  include T 
+  
+  let type_int = new_ty type_int
+  let type_real = new_ty type_real
+  let type_bool = new_ty type_bool
+  let type_string = new_ty type_string
+  let type_clock ty = new_ty (Tclock ty)
+  let type_const tname = new_ty (Tconst tname)
+  let type_enum taglist = new_ty (Tenum taglist)
+  let type_struct fieldlist = new_ty (Tstruct fieldlist)
+  let type_tuple tl = new_ty (Ttuple tl)
+  let type_arrow ty1 ty2 = new_ty (Tarrow (ty1, ty2))
+  let type_array d ty = new_ty (Tarray (d, ty))
+  let type_static d ty = new_ty (Tstatic (d, ty))
+    
+  let type_unary_bool_op =
+    new_ty (Tarrow (type_bool, type_bool))
 
-let type_unary_bool_op =
-  new_ty (Tarrow (type_bool, type_bool))
+  let type_unary_poly_op =
+    let univ = new_univar () in
+    type_arrow univ univ
 
-let type_unary_poly_op =
-  let univ = new_univar () in
-  type_arrow univ univ
+  let type_bin_int_op =
+    type_arrow (type_tuple [type_int;type_int]) type_int
 
-let type_bin_int_op =
-  type_arrow (type_tuple [type_int;type_int]) type_int
+  let type_bin_bool_op =
+    type_arrow (type_tuple [type_bool;type_bool]) type_bool
 
-let type_bin_bool_op =
-  type_arrow (type_tuple [type_bool;type_bool]) type_bool
+  let type_ite_op =
+    let univ = new_univar () in
+    type_arrow (type_tuple [type_bool;univ;univ]) univ
 
-let type_ite_op =
-  let univ = new_univar () in
-  type_arrow (type_tuple [type_bool;univ;univ]) univ
+  let type_bin_poly_op =
+    let univ = new_univar () in
+    type_arrow (type_tuple [univ;univ]) univ
 
-let type_bin_poly_op =
-  let univ = new_univar () in
-  type_arrow (type_tuple [univ;univ]) univ
+  let type_bin_comp_op =
+    let univ = new_univar () in
+    new_ty (Tarrow (new_ty (Ttuple [univ;univ]), type_bool))
 
-let type_bin_comp_op =
-  let univ = new_univar () in
-  new_ty (Tarrow (new_ty (Ttuple [univ;univ]), type_bool))
+  let type_univ_bool_univ =
+    let univ = new_univar () in
+    type_arrow (type_tuple [univ;type_bool]) univ
 
-let type_univ_bool_univ =
-  let univ = new_univar () in
-  type_arrow (type_tuple [univ;type_bool]) univ
+  let type_bool_univ3 =
+    let univ = new_univar () in
+    type_arrow (type_tuple [type_bool;univ;univ]) univ
 
-let type_bool_univ3 =
-  let univ = new_univar () in
-  type_arrow (type_tuple [type_bool;univ;univ]) univ
+  let type_access =
+    let d = Dimension.mkdim Location.dummy_loc Dimension.Dunivar in
+    let d' = Dimension.mkdim Location.dummy_loc Dimension.Dunivar in
+    let univ = new_univar () in
+    type_arrow (type_tuple [type_array d univ; type_static d' type_int]) univ
 
-let type_access =
-  let d = Dimension.mkdim Location.dummy_loc Dimension.Dunivar in
-  let d' = Dimension.mkdim Location.dummy_loc Dimension.Dunivar in
-  let univ = new_univar () in
-  type_arrow (type_tuple [type_array d univ; type_static d' type_int]) univ
+  let type_power =
+    let d = Dimension.mkdim Location.dummy_loc Dimension.Dunivar in
+    let univ = new_univar () in
+    type_arrow (type_tuple [univ; type_static d type_int]) (type_array d univ)
+end
 
-let type_power =
-  let d = Dimension.mkdim Location.dummy_loc Dimension.Dunivar in
-  let univ = new_univar () in
-  type_arrow (type_tuple [univ; type_static d type_int]) (type_array d univ)
+
+(* module BaseBuilder = *)
+(* struct *)
+(*   let type_int_builder = Tbasic Basic.Tint *)
+(*   let type_real_builder = Tbasic Basic.Treal *)
+(*   let type_bool_builder = Tbasic Basic.Tbool *)
+(*   let type_string_builder = Tbasic Basic.Tstring *)
+(* end *)
+  
+module Main = Make (Types.Main)
+include Main
 
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
diff --git a/src/types.ml b/src/types.ml
index b7f0374a..ffec4b02 100755
--- a/src/types.ml
+++ b/src/types.ml
@@ -15,70 +15,164 @@
 open Utils
 open Dimension
 
-type type_expr =
+module type BASIC_TYPES =
+sig
+  type t
+  val pp: Format.formatter -> t -> unit
+  val pp_c: Format.formatter -> t -> unit
+  val is_scalar_type: t -> bool
+  val is_numeric_type: t -> bool
+  val is_int_type: t -> bool
+  val is_real_type: t -> bool
+  val is_bool_type: t -> bool
+  val is_dimension_type: t -> bool
+  val type_int_builder: t
+  val type_real_builder: t
+  val type_bool_builder: t
+  val type_string_builder: t
+  val unify: t -> t -> unit
+  val is_unifiable: t -> t -> bool
+end
+
+module Basic =
+struct
+  type t =
+    | Tstring
+    | Tint
+    | Treal
+    | Tbool
+    | Trat (* Actually unused for now. Only place where it can appear is
+              in a clock declaration *)
+
+  let type_string_builder = Tstring
+  let type_int_builder = Tint
+  let type_real_builder = Treal
+  let type_bool_builder = Tbool
+
+  open Format
+  let pp fmt t =
+    match t with
+    | Tint ->
+       fprintf fmt "int"
+    | Treal ->
+       fprintf fmt "real"
+    | Tstring ->
+       fprintf fmt "string"
+    | Tbool ->
+       fprintf fmt "bool"
+    | Trat ->
+       fprintf fmt "rat"
+
+  let pp_c = pp
+    
+  let is_scalar_type t =
+    match t with
+    | Tbool
+    | Tint
+    | Treal -> true
+    | _ -> false
+
+
+  let is_numeric_type t =
+    match t with
+    | Tint
+    | Treal -> true
+    | _ -> false
+
+  let is_int_type t = t = Tint
+  let is_real_type t = t = Treal
+  let is_bool_type t = t = Tbool
+
+  let is_dimension_type t =
+    match t with
+       | Tint
+ | Tbool -> true
+ | _ -> false
+
+  let is_unifiable b1 b2 = b1 == b2
+  let unify _ _ = ()
+end
+
+
+  
+module Make(BasicT : BASIC_TYPES) =
+struct
+
+  module BasicT = BasicT
+  type basic_type = BasicT.t
+  type type_expr   =
     {mutable tdesc: type_desc;
      tid: int}
-
-and type_desc =
-  | Tconst of ident (* type constant *)
-  | Tint
-  | Treal
-  | Tbool
-  | Trat (* Actually unused for now. Only place where it can appear is
-            in a clock declaration *)
-  | Tclock of type_expr (* A type expression explicitely tagged as carrying a clock *)
-  | Tarrow of type_expr * type_expr
-  | Ttuple of type_expr list
-  | Tenum of ident list
-  | Tstruct of (ident * type_expr) list
-  | Tarray of dim_expr * type_expr
-  | Tstatic of dim_expr * type_expr (* a type carried by a dimension expression *)
-  | Tlink of type_expr (* During unification, make links instead of substitutions *)
-  | Tvar (* Monomorphic type variable *)
-  | Tunivar (* Polymorphic type variable *)
-
-type error =
-    Unbound_value of ident  
-  | Already_bound of ident
-  | Already_defined of ident
-  | Undefined_var of ISet.t
-  | Declared_but_undefined of ident
-  | Unbound_type of ident
-  | Not_a_dimension
-  | Not_a_constant
-  | Assigned_constant of ident
-  | WrongArity of int * int
-  | WrongMorphism of int * int
-  | Type_mismatch of ident
-  | Type_clash of type_expr * type_expr
-  | Poly_imported_node of ident
+  and type_desc =
+    | Tconst of ident (* type constant *)
+    | Tbasic of basic_type
+    | Tclock of type_expr (* A type expression explicitely tagged as carrying a clock *)
+    | Tarrow of type_expr * type_expr
+    | Ttuple of type_expr list
+    | Tenum of ident list
+    | Tstruct of (ident * type_expr) list
+    | Tarray of dim_expr * type_expr
+    | Tstatic of dim_expr * type_expr (* a type carried by a dimension expression *)
+    | Tlink of type_expr (* During unification, make links instead of substitutions *)
+    | Tvar (* Monomorphic type variable *)
+    | Tunivar (* Polymorphic type variable *)
+
+  (*   {mutable tdesc: type_desc; *)
+  (*    tid: int} *)
+
+  (* and type_desc = *)
+  (*   | Tconst of ident (\* type constant *\) *)
+  (*   | Tbasic of BasicT.t *)
+  (*   | Tclock of type_expr (\* A type expression explicitely tagged as carrying a clock *\) *)
+  (*   | Tarrow of type_expr * type_expr *)
+  (*   | Ttuple of type_expr list *)
+  (*   | Tenum of ident list *)
+  (*   | Tstruct of (ident * type_expr) list *)
+  (*   | Tarray of dim_expr * type_expr *)
+  (*   | Tstatic of dim_expr * type_expr (\* a type carried by a dimension expression *\) *)
+  (*   | Tlink of type_expr (\* During unification, make links instead of substitutions *\) *)
+  (*   | Tvar (\* Monomorphic type variable *\) *)
+  (*   | Tunivar (\* Polymorphic type variable *\) *)
+
+  type error =
+      Unbound_value of ident  
+    | Already_bound of ident
+    | Already_defined of ident
+    | Undefined_var of ISet.t
+    | Declared_but_undefined of ident
+    | Unbound_type of ident
+    | Not_a_dimension
+    | Not_a_constant
+    | Assigned_constant of ident
+    | WrongArity of int * int
+    | WrongMorphism of int * int
+    | Type_mismatch of ident
+    | Type_clash of type_expr * type_expr
+    | Poly_imported_node of ident
 
 exception Unify of type_expr * type_expr
 exception Error of Location.t * error
 
+let mk_basic t = Tbasic t
+
+     
 (* Pretty-print*)
 open Format
 
-let rec print_struct_ty_field fmt (label, ty) =
-  fprintf fmt "%a : %a" pp_print_string label print_ty ty
-and print_ty fmt ty =
+let rec print_struct_ty_field pp_basic fmt (label, ty) =
+  fprintf fmt "%a : %a" pp_print_string label (print_ty_param pp_basic) ty
+and print_ty_param pp_basic fmt ty =
+  let print_ty = print_ty_param pp_basic in
   match ty.tdesc with
   | Tvar ->
     fprintf fmt "_%s" (name_of_type ty.tid)
-  | Tint ->
-    fprintf fmt "int"
-  | Treal ->
-    fprintf fmt "real"
-  | Tbool ->
-    fprintf fmt "bool"
+  | Tbasic t -> pp_basic fmt t
   | Tclock t ->
     fprintf fmt "%a clock" print_ty t
   | Tstatic (d, t) ->
     fprintf fmt "(%a:%a)" Dimension.pp_dimension d print_ty t
   | Tconst t ->
     fprintf fmt "%s" t
-  | Trat ->
-    fprintf fmt "rat"
   | Tarrow (ty1,ty2) ->
     fprintf fmt "%a -> %a" print_ty ty1 print_ty ty2
   | Ttuple tylist ->
@@ -89,7 +183,7 @@ and print_ty fmt ty =
       (Utils.fprintf_list ~sep:", " pp_print_string) taglist
   | Tstruct fieldlist ->
     fprintf fmt "struct {%a }"
-      (Utils.fprintf_list ~sep:"; " print_struct_ty_field) fieldlist
+      (Utils.fprintf_list ~sep:"; " (print_struct_ty_field pp_basic)) fieldlist
   | Tarray (e, ty) ->
     fprintf fmt "%a^%a" print_ty ty Dimension.pp_dimension e
   | Tlink ty ->
@@ -97,28 +191,24 @@ and print_ty fmt ty =
   | Tunivar ->
     fprintf fmt "'%s" (name_of_type ty.tid)
 
+let print_ty = print_ty_param BasicT.pp
+ 
+    
 let rec print_node_struct_ty_field fmt (label, ty) =
   fprintf fmt "%a : %a" pp_print_string label print_node_ty ty
 and print_node_ty fmt ty =
   match ty.tdesc with
   | Tvar -> begin
-(*Format.eprintf "DEBUG:Types.print_node@.";*)
+    (*Format.eprintf "DEBUG:Types.print_node@.";*)
     fprintf fmt "_%s" (name_of_type ty.tid)
-end
-  | Tint ->
-    fprintf fmt "int"
-  | Treal ->
-    fprintf fmt "real"
-  | Tbool ->
-    fprintf fmt "bool"
+  end
+  | Tbasic t -> BasicT.pp fmt t
   | Tclock t ->
     fprintf fmt "%a clock" print_node_ty t
   | Tstatic (_, t) ->
     fprintf fmt "%a" print_node_ty t
   | Tconst t ->
     fprintf fmt "%s" t
-  | Trat ->
-    fprintf fmt "rat"
   | Tarrow (ty1,ty2) ->
     fprintf fmt "%a -> %a" print_node_ty ty1 print_node_ty ty2
   | Ttuple tylist ->
@@ -201,31 +291,39 @@ let get_field_type ty label =
   | Tstruct fl -> (try Some (List.assoc label fl) with Not_found -> None)
   | _          -> None
 
+let rec is_static_type ty =
+  match (repr ty).tdesc with
+  | Tstatic (_, ty) -> true
+  | _     -> false
+
 let rec is_scalar_type ty =
   match (repr ty).tdesc with
   | Tstatic (_, ty) -> is_scalar_type ty
-  | Tbool
-  | Tint
-  | Treal -> true
+  | Tbasic t -> BasicT.is_scalar_type t
   | _     -> false
 
 let rec is_numeric_type ty =
  match (repr ty).tdesc with
  | Tstatic (_, ty) -> is_numeric_type ty
- | Tint
- | Treal -> true
+ | Tbasic t -> BasicT.is_numeric_type t
  | _     -> false
-
+    
 let rec is_real_type ty =
  match (repr ty).tdesc with
  | Tstatic (_, ty) -> is_real_type ty
- | Treal -> true
+ | Tbasic t -> BasicT.is_real_type t
+ | _     -> false
+
+let rec is_int_type ty =
+ match (repr ty).tdesc with
+ | Tstatic (_, ty) -> is_int_type ty
+ | Tbasic t -> BasicT.is_int_type t
  | _     -> false
 
 let rec is_bool_type ty =
  match (repr ty).tdesc with
  | Tstatic (_, ty) -> is_bool_type ty
- | Tbool -> true
+ | Tbasic t -> BasicT.is_bool_type t
  | _     -> false
 
 let get_clock_base_type ty =
@@ -241,8 +339,7 @@ let unclock_type ty =
 
 let rec is_dimension_type ty =
  match (repr ty).tdesc with
- | Tint
- | Tbool -> true
+ | Tbasic t -> BasicT.is_dimension_type t
  | Tclock ty'
  | Tstatic (_, ty') -> is_dimension_type ty'
  | _                -> false
@@ -341,7 +438,7 @@ let rec type_list_of_type ty =
 (** [is_polymorphic ty] returns true if [ty] is polymorphic. *)
 let rec is_polymorphic ty =
   match ty.tdesc with
-  | Tenum _ | Tvar | Tint | Treal | Tbool | Trat | Tconst _ -> false
+  | Tenum _ | Tvar | Tbasic _ | Tconst _ -> false
   | Tclock ty -> is_polymorphic ty
   | Tarrow (ty1,ty2) -> (is_polymorphic ty1) || (is_polymorphic ty2)
   | Ttuple tl -> List.exists (fun t -> is_polymorphic t) tl
@@ -355,7 +452,100 @@ let rec is_polymorphic ty =
 let mktyptuple nb typ =
   let array = Array.make nb typ in
   Ttuple (Array.to_list array)
+
+let type_desc t = t.tdesc
+
+
+
+let type_int = mk_basic BasicT.type_int_builder
+let type_real = mk_basic BasicT.type_real_builder
+let type_bool = mk_basic BasicT.type_bool_builder
+let type_string = mk_basic BasicT.type_string_builder
     
+end
+
+
+module type S = 
+sig
+  module BasicT: BASIC_TYPES 
+  type basic_type = BasicT.t
+  type type_expr   =
+    {mutable tdesc: type_desc;
+     tid: int}
+  and type_desc =
+    | Tconst of ident (* type constant *)
+    | Tbasic of basic_type
+    | Tclock of type_expr (* A type expression explicitely tagged as carrying a clock *)
+    | Tarrow of type_expr * type_expr
+    | Ttuple of type_expr list
+    | Tenum of ident list
+    | Tstruct of (ident * type_expr) list
+    | Tarray of dim_expr * type_expr
+    | Tstatic of dim_expr * type_expr (* a type carried by a dimension expression *)
+    | Tlink of type_expr (* During unification, make links instead of substitutions *)
+    | Tvar (* Monomorphic type variable *)
+    | Tunivar (* Polymorphic type variable *)
+
+  type error =
+      Unbound_value of ident  
+    | Already_bound of ident
+    | Already_defined of ident
+    | Undefined_var of ISet.t
+    | Declared_but_undefined of ident
+    | Unbound_type of ident
+    | Not_a_dimension
+    | Not_a_constant
+    | Assigned_constant of ident
+    | WrongArity of int * int
+    | WrongMorphism of int * int
+    | Type_mismatch of ident
+    | Type_clash of type_expr * type_expr
+    | Poly_imported_node of ident
+
+	  exception Unify of type_expr * type_expr
+	  exception Error of Location.t * error
+
+  val is_real_type: type_expr -> bool
+  val is_int_type: type_expr -> bool
+  val is_bool_type: type_expr -> bool
+  val is_static_type: type_expr -> bool
+  val is_array_type: type_expr -> bool
+  val is_dimension_type: type_expr -> bool
+  val is_address_type: type_expr -> bool
+  val is_generic_type: type_expr -> bool
+  val print_ty: Format.formatter -> type_expr -> unit
+  val repr: type_expr -> type_expr
+  val dynamic_type: type_expr -> type_expr
+  val type_desc: type_expr -> type_desc
+  val new_var: unit -> type_expr
+  val new_univar: unit -> type_expr
+  val new_ty: type_desc -> type_expr
+  val type_int: type_desc
+  val type_real: type_desc
+  val type_bool: type_desc
+  val type_string: type_desc
+  val array_element_type: type_expr -> type_expr
+  val type_list_of_type: type_expr -> type_expr list
+  val print_node_ty: Format.formatter -> type_expr -> unit
+  val get_clock_base_type: type_expr -> type_expr option
+  val get_static_value: type_expr -> Dimension.dim_expr option
+  val is_tuple_type: type_expr -> bool
+  val type_of_type_list: type_expr list -> type_expr
+  val split_arrow: type_expr -> type_expr * type_expr
+  val unclock_type: type_expr -> type_expr
+  val bottom: type_expr
+  val map_tuple_type: (type_expr -> type_expr) -> type_expr -> type_expr
+  val array_base_type: type_expr -> type_expr
+  val array_type_dimension: type_expr -> Dimension.dim_expr
+  val pp_error: Format.formatter -> error -> unit
+  val struct_field_type: type_expr -> ident -> type_expr
+  val array_type_multi_dimension: type_expr -> Dimension.dim_expr list
+end (* with type type_expr = BasicT.t type_expr_gen *)
+
+module type Sbasic = S with type BasicT.t = Basic.t 
+  
+module Main : Sbasic = Make (Basic)
+include Main 
 
 
 (* Local Variables: *)
diff --git a/src/typing.ml b/src/typing.ml
index 0aed94cb..471643c2 100755
--- a/src/typing.ml
+++ b/src/typing.ml
@@ -24,9 +24,31 @@ open Utils
    overwritten, yet this makes notations far lighter.*)
 open LustreSpec
 open Corelang
-open Types
+(* open Types *)
 open Format
 
+
+module type EXPR_TYPE_HUB =
+sig
+  type type_expr 
+  val import: Types.Main.type_expr -> type_expr
+  val export: type_expr -> Types.Main.type_expr 
+end
+
+module Make (T: Types.S) (Expr_type_hub: EXPR_TYPE_HUB with type type_expr = T.type_expr) =  
+struct
+
+  module TP = Type_predef.Make (T)
+  include TP
+    
+let basic_coretype_type t =
+  if is_real_type t then Tydec_real else
+    if is_int_type t then Tydec_int else
+      if is_bool_type t then Tydec_bool else
+	assert false
+
+
+
 let pp_typing_env fmt env =
   Env.pp_env print_ty fmt env
 
@@ -34,7 +56,7 @@ let pp_typing_env fmt env =
     type [ty]. False otherwise. *)
 let rec occurs tvar ty =
   let ty = repr ty in
-  match ty.tdesc with
+  match type_desc ty with
   | Tvar -> ty=tvar
   | Tarrow (t1, t2) ->
       (occurs tvar t1) || (occurs tvar t2)
@@ -46,12 +68,12 @@ let rec occurs tvar ty =
   | Tstatic (_, t)
   | Tclock t
   | Tlink t -> occurs tvar t
-  | Tenum _ | Tconst _ | Tunivar | Tint | Treal | Tbool | Trat -> false
+  | Tenum _ | Tconst _ | Tunivar | Tbasic _ -> false
 
 (** Promote monomorphic type variables to polymorphic type variables. *)
 (* Generalize by side-effects *)
 let rec generalize ty =
-  match ty.tdesc with
+  match type_desc ty with
   | Tvar ->
       (* No scopes, always generalize *)
       ty.tdesc <- Tunivar
@@ -66,13 +88,13 @@ let rec generalize ty =
   | Tclock t
   | Tlink t ->
       generalize t
-  | Tenum _ | Tconst _ | Tunivar | Tint | Treal | Tbool | Trat -> ()
+  | Tenum _ | Tconst _ | Tunivar | Tbasic _ -> ()
 
 (** Downgrade polymorphic type variables to monomorphic type variables *)
 let rec instantiate inst_vars inst_dim_vars ty =
   let ty = repr ty in
   match ty.tdesc with
-  | Tenum _ | Tconst _ | Tvar | Tint | Treal | Tbool | Trat -> ty
+  | Tenum _ | Tconst _ | Tvar | Tbasic _  -> ty
   | Tarrow (t1,t2) ->
       {ty with tdesc =
        Tarrow ((instantiate inst_vars inst_dim_vars t1), (instantiate inst_vars inst_dim_vars t2))}
@@ -101,28 +123,26 @@ let rec instantiate inst_vars inst_dim_vars ty =
 let rec type_coretype type_dim cty =
   match (*get_repr_type*) cty with
   | Tydec_any -> new_var ()
-  | Tydec_int -> Type_predef.type_int
-  | Tydec_real -> Type_predef.type_real
+  | Tydec_int -> type_int
+  | Tydec_real -> (* Type_predef. *)type_real
   (* | Tydec_float -> Type_predef.type_real *)
-  | Tydec_bool -> Type_predef.type_bool
-  | Tydec_clock ty -> Type_predef.type_clock (type_coretype type_dim ty)
-  | Tydec_const c -> Type_predef.type_const c
-  | Tydec_enum tl -> Type_predef.type_enum tl
-  | Tydec_struct fl -> Type_predef.type_struct (List.map (fun (f, ty) -> (f, type_coretype type_dim ty)) fl)
+  | Tydec_bool -> (* Type_predef. *)type_bool
+  | Tydec_clock ty -> (* Type_predef. *)type_clock (type_coretype type_dim ty)
+  | Tydec_const c -> (* Type_predef. *)type_const c
+  | Tydec_enum tl -> (* Type_predef. *)type_enum tl
+  | 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)
+      (* Type_predef. *)type_array d (type_coretype type_dim ty)
     end
 
 (* [coretype_type] is the reciprocal of [type_typecore] *)
 let rec coretype_type ty =
  match (repr ty).tdesc with
  | Tvar           -> Tydec_any
- | Tint           -> Tydec_int
- | Treal          -> Tydec_real
- | Tbool          -> Tydec_bool
+ | Tbasic _       -> basic_coretype_type ty
  | Tconst c       -> Tydec_const c
  | Tclock t       -> Tydec_clock (coretype_type t)
  | Tenum tl       -> Tydec_enum tl
@@ -149,7 +169,7 @@ let rec eq_ground t1 t2 =
   let t2 = repr t2 in
   t1==t2 ||
   match t1.tdesc, t2.tdesc with
-  | Tint, Tint | Tbool, Tbool | Trat, Trat | Treal, Treal -> true
+  | Tbasic t1, Tbasic t2 when t1 == t2 -> true
   | Tenum tl, Tenum tl' when tl == tl' -> true
   | Ttuple tl, Ttuple tl' when List.length tl = List.length tl' -> List.for_all2 eq_ground tl tl'
   | Tstruct fl, Tstruct fl' when List.map fst fl = List.map fst fl' -> List.for_all2 (fun (_, t) (_, t') -> eq_ground t t') fl fl'
@@ -211,7 +231,7 @@ let unify ?(sub=false) ?(semi=false) t1 t2 =
       | Tclock _, Tstatic _
       | Tstatic _, Tclock _ -> raise (Unify (t1, t2))
       | Tclock t1', Tclock t2' -> unif t1' t2'
-      | Tint, Tint | Tbool, Tbool | Trat, Trat | Treal, Treal
+      | Tbasic t1, Tbasic t2 when t1 == t2 -> ()
       | Tunivar, _ | _, Tunivar -> ()
       | (Tconst t, _) ->
 	let def_t = get_type_definition t in
@@ -232,6 +252,10 @@ let unify ?(sub=false) ?(semi=false) t1 t2 =
 	  Dimension.eval Basic_library.eval_env eval_const e2;
 	  Dimension.unify ~semi:semi e1 e2;
 	end
+      (* Special cases for machine_types. Rules to unify static types infered
+      	 for numerical constants with non static ones for variables with
+      	 possible machine types *)
+      | Tbasic bt1, Tbasic bt2 when BasicT.is_unifiable bt1 bt2 -> BasicT.unify bt1 bt2
       | _,_ -> raise (Unify (t1, t2))
   in unif t1 t2
 
@@ -245,27 +269,27 @@ let try_unify ?(sub=false) ?(semi=false) ty1 ty2 loc =
   | Dimension.Unify _ ->
     raise (Error (loc, Type_clash (ty1,ty2)))
 
-let rec type_struct_const_field loc (label, c) =
+let rec type_struct_const_field ?(is_annot=false) loc (label, c) =
   if Hashtbl.mem field_table label
   then let tydef = Hashtbl.find field_table label in
        let tydec = (typedef_of_top tydef).tydef_desc in 
        let tydec_struct = get_struct_type_fields tydec in
        let ty_label = type_coretype (fun d -> ()) (List.assoc label tydec_struct) in
        begin
-	 try_unify ty_label (type_const loc c) loc;
+	 try_unify ty_label (type_const ~is_annot loc c) loc;
 	 type_coretype (fun d -> ()) tydec
        end
   else raise (Error (loc, Unbound_value ("struct field " ^ label)))
 
-and type_const loc c = 
+and type_const ?(is_annot=false) loc c = 
   match c with
-  | Const_int _     -> Type_predef.type_int
-  | Const_real _    -> Type_predef.type_real
+  | Const_int _     -> (* Type_predef. *)type_int
+  | Const_real _    -> (* Type_predef. *)type_real
   (* | Const_float _   -> Type_predef.type_real *)
   | Const_array ca  -> let d = Dimension.mkdim_int loc (List.length ca) in
 		      let ty = new_var () in
-		      List.iter (fun e -> try_unify ty (type_const loc e) loc) ca;
-		      Type_predef.type_array d ty
+		      List.iter (fun e -> try_unify ty (type_const ~is_annot loc e) loc) ca;
+		      (* Type_predef. *)type_array d ty
   | Const_tag t     ->
     if Hashtbl.mem tag_table t
     then 
@@ -284,7 +308,7 @@ and type_const loc c =
 	  (fun acc (l, c) ->
 	    if List.mem l acc
 	    then raise (Error (loc, Already_bound ("struct field " ^ l)))
-	    else try_unify ty_struct (type_struct_const_field loc (l, c)) loc; l::acc)
+	    else try_unify ty_struct (type_struct_const_field ~is_annot loc (l, c)) loc; l::acc)
 	  [] fl in
       try
 	let total = List.map fst (get_struct_type_fields (coretype_type ty_struct)) in
@@ -295,7 +319,7 @@ and type_const loc c =
       with Not_found -> 
 	ty_struct
     end
-  | Const_string _ -> assert false (* string should only appear in annotations *)
+  | Const_string _ -> if is_annot then (* Type_predef. *)type_string else  assert false (* string should only appear in annotations *)
 
 (* The following typing functions take as parameter an environment [env]
    and whether the element being typed is expected to be constant [const]. 
@@ -318,10 +342,10 @@ let rec type_add_const env const arg targ =
 	 if is_dimension_type targ
 	 then dimension_of_expr arg
 	 else Dimension.mkdim_var () in
-       let eval_const id = Types.get_static_value (Env.lookup_value (fst env) id) in
+       let eval_const id = (* Types. *)get_static_value (Env.lookup_value (fst env) id) in
        Dimension.eval Basic_library.eval_env eval_const d;
-       let real_static_type = Type_predef.type_static d (Types.dynamic_type targ) in
-       (match Types.get_static_value targ with
+       let real_static_type = (* Type_predef. *)type_static d ((* Types. *)dynamic_type targ) in
+       (match (* Types. *)get_static_value targ with
        | None    -> ()
        | Some d' -> try_unify targ real_static_type arg.expr_loc);
        real_static_type
@@ -331,7 +355,7 @@ let rec type_add_const env const arg targ =
    used during node applications and assignments *)
 and type_subtyping_arg env in_main ?(sub=true) const real_arg formal_type =
   let loc = real_arg.expr_loc in
-  let const = const || (Types.get_static_value formal_type <> None) in
+  let const = const || ((* Types. *)get_static_value formal_type <> None) in
   let real_type = type_add_const env const real_arg (type_expr env in_main const real_arg) in
   (*Format.eprintf "subtyping const %B real %a:%a vs formal %a@." const Printers.pp_expr real_arg Types.print_ty real_type Types.print_ty formal_type;*)
   try_unify ~sub:sub formal_type real_type loc
@@ -348,26 +372,38 @@ and type_appl env in_main loc const f args =
   then
     try
       let targs = Utils.transpose_list (List.map type_list_of_type targs) in
-      Types.type_of_type_list (List.map (type_simple_call env in_main loc const f) targs)
-    with
+      (* Types. *)type_of_type_list (List.map (type_simple_call env in_main loc const f) targs)
+    with 
       Utils.TransposeError (l, l') -> raise (Error (loc, WrongMorphism (l, l')))
-  else
+	
+  else (
     type_dependent_call env in_main loc const f (List.combine args targs)
+  )
 
 (* 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;*)
+(* 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
+  (* Format.eprintf "tin=%a, tout=%a@." print_ty tins print_ty touts; *)
+  let tfun = (* Type_predef. *)type_arrow tins touts in
+  (* Format.eprintf "fun=%a@." print_ty tfun; *)
   type_subtyping_arg env in_main const (expr_of_ident f loc) tfun;
+  (* Format.eprintf "type subtyping@."; *)
   let tins = type_list_of_type tins in
   if List.length targs <> List.length tins then
     raise (Error (loc, WrongArity (List.length tins, List.length targs)))
   else
     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;
+      List.iter2 (
+	fun (a,t) ti ->
+	  let t' = type_add_const env (const || (* Types. *)get_static_value ti <> None) a t in
+	  (* Format.eprintf "uniying ti=%a t'=%a touts=%a@." print_ty ti print_ty t' print_ty touts;  *)
+	  try_unify ~sub:true ti t' a.expr_loc;
+	  (* Format.eprintf "unified ti=%a t'=%a touts=%a@." print_ty ti print_ty t' print_ty touts;  *)
+	    
+      )
+	targs
+	tins;
       touts
     end
 
@@ -376,7 +412,7 @@ and type_dependent_call env in_main loc const f targs =
    [targs] is here a list of arguments' types. *)
 and type_simple_call env in_main loc const f targs =
   let tins, touts = new_var (), new_var () in
-  let tfun = Type_predef.type_arrow tins touts in
+  let tfun = (* Type_predef. *)type_arrow tins touts in
   type_subtyping_arg env in_main const (expr_of_ident f loc) tfun;
   (*Format.eprintf "try unify %a %a@." Types.print_ty tins Types.print_ty (type_of_type_list targs);*)
   try_unify ~sub:true tins (type_of_type_list targs) loc;
@@ -384,60 +420,60 @@ and type_simple_call env in_main loc const f targs =
 
 (** [type_expr env in_main expr] types expression [expr] in environment
     [env], expecting it to be [const] or not. *)
-and type_expr env in_main const expr =
+and type_expr ?(is_annot=false) env in_main const expr =
   let resulting_ty = 
   match expr.expr_desc with
   | Expr_const c ->
-    let ty = type_const expr.expr_loc c in
-    let ty = Type_predef.type_static (Dimension.mkdim_var ()) ty in
-    expr.expr_type <- ty;
+    let ty = type_const ~is_annot expr.expr_loc c in
+    let ty = (* Type_predef. *)type_static (Dimension.mkdim_var ()) ty in
+    expr.expr_type <- Expr_type_hub.export ty;
     ty
   | Expr_ident v ->
     let tyv =
       try
         Env.lookup_value (fst env) v
       with Not_found ->
-	Format.eprintf "Failure in typing expr %a@." Printers.pp_expr expr;
+	Format.eprintf "Failure in typing expr %a. Not in typing environement@." Printers.pp_expr expr;
         raise (Error (expr.expr_loc, Unbound_value ("identifier " ^ v)))
     in
     let ty = instantiate (ref []) (ref []) tyv in
     let ty' =
       if const
-      then Type_predef.type_static (Dimension.mkdim_var ()) (new_var ())
+      then (* Type_predef. *)type_static (Dimension.mkdim_var ()) (new_var ())
       else new_var () in
     try_unify ty ty' expr.expr_loc;
-    expr.expr_type <- ty;
+    expr.expr_type <- Expr_type_hub.export ty;
     ty 
   | Expr_array elist ->
     let ty_elt = new_var () in
     List.iter (fun e -> try_unify ty_elt (type_appl env in_main expr.expr_loc const "uminus" [e]) e.expr_loc) elist;
     let d = Dimension.mkdim_int expr.expr_loc (List.length elist) in
-    let ty = Type_predef.type_array d ty_elt in
-    expr.expr_type <- ty;
+    let ty = (* Type_predef. *)type_array d ty_elt in
+    expr.expr_type <- Expr_type_hub.export ty;
     ty
   | Expr_access (e1, d) ->
-    type_subtyping_arg env in_main false (* not necessary a constant *) (expr_of_dimension d) Type_predef.type_int;
+    type_subtyping_arg env in_main false (* not necessary a constant *) (expr_of_dimension d) (* Type_predef. *)type_int;
     let ty_elt = new_var () in
     let d = Dimension.mkdim_var () in
-    type_subtyping_arg env in_main const e1 (Type_predef.type_array d ty_elt);
-    expr.expr_type <- ty_elt;
+    type_subtyping_arg env in_main const e1 ((* Type_predef. *)type_array d ty_elt);
+    expr.expr_type <- Expr_type_hub.export ty_elt;
     ty_elt
   | Expr_power (e1, d) ->
-    let eval_const id = Types.get_static_value (Env.lookup_value (fst env) id) in
-    type_subtyping_arg env in_main true (expr_of_dimension d) Type_predef.type_int;
+    let eval_const id = (* Types. *)get_static_value (Env.lookup_value (fst env) id) in
+    type_subtyping_arg env in_main true (expr_of_dimension d) (* Type_predef. *)type_int;
     Dimension.eval Basic_library.eval_env eval_const d;
     let ty_elt = type_appl env in_main expr.expr_loc const "uminus" [e1] in
-    let ty = Type_predef.type_array d ty_elt in
-    expr.expr_type <- ty;
+    let ty = (* Type_predef. *)type_array d ty_elt in
+    expr.expr_type <- Expr_type_hub.export ty;
     ty
   | Expr_tuple elist ->
-    let ty = new_ty (Ttuple (List.map (type_expr env in_main const) elist)) in
-    expr.expr_type <- ty;
+    let ty = new_ty (Ttuple (List.map (type_expr ~is_annot env in_main const) elist)) in
+    expr.expr_type <- Expr_type_hub.export ty;
     ty
   | Expr_ite (c, t, e) ->
-    type_subtyping_arg env in_main const c Type_predef.type_bool;
+    type_subtyping_arg env in_main const c (* Type_predef. *)type_bool;
     let ty = type_appl env in_main expr.expr_loc const "+" [t; e] in
-    expr.expr_type <- ty;
+    expr.expr_type <- Expr_type_hub.export ty;
     ty
   | Expr_appl (id, args, r) ->
     (* application of non internal function is not legal in a constant
@@ -446,54 +482,55 @@ and type_expr env in_main const expr =
     | None        -> ()
     | Some c -> 
       check_constant expr.expr_loc const false;	
-      type_subtyping_arg env in_main const c Type_predef.type_bool);
+      type_subtyping_arg env in_main const c (* Type_predef. *)type_bool);
     let args_list = expr_list_of_expr args in
+    let targs = new_ty (Ttuple (List.map (fun a -> Expr_type_hub.import a.expr_type) args_list)) in
+    args.expr_type <- Expr_type_hub.export targs;
     let touts = type_appl env in_main expr.expr_loc const id args_list in
-    args.expr_type <- new_ty (Ttuple (List.map (fun a -> a.expr_type) args_list));
-    expr.expr_type <- touts;
+    expr.expr_type <- Expr_type_hub.export touts;
     touts
   | Expr_fby (e1,e2)
   | Expr_arrow (e1,e2) ->
     (* fby/arrow is not legal in a constant expression *)
     check_constant expr.expr_loc const false;
     let ty = type_appl env in_main expr.expr_loc const "+" [e1; e2] in
-    expr.expr_type <- ty;
+    expr.expr_type <- Expr_type_hub.export ty;
     ty
   | Expr_pre e ->
     (* pre is not legal in a constant expression *)
     check_constant expr.expr_loc const false;
     let ty = type_appl env in_main expr.expr_loc const "uminus" [e] in
-    expr.expr_type <- ty;
+    expr.expr_type <- Expr_type_hub.export ty;
     ty
   | Expr_when (e1,c,l) ->
     (* when is not legal in a constant expression *)
     check_constant expr.expr_loc const false;
-    let typ_l = Type_predef.type_clock (type_const expr.expr_loc (Const_tag l)) in
+    let typ_l = (* Type_predef. *)type_clock (type_const ~is_annot expr.expr_loc (Const_tag l)) in
     let expr_c = expr_of_ident c expr.expr_loc in
     type_subtyping_arg env in_main ~sub:false const expr_c typ_l;
     let ty = type_appl env in_main expr.expr_loc const "uminus" [e1] in
-    expr.expr_type <- ty;
+    expr.expr_type <- Expr_type_hub.export ty;
     ty
   | Expr_merge (c,hl) ->
     (* merge is not legal in a constant expression *)
     check_constant expr.expr_loc const false;
     let typ_in, typ_out = type_branches env in_main expr.expr_loc const hl in
     let expr_c = expr_of_ident c expr.expr_loc in
-    let typ_l = Type_predef.type_clock typ_in in
+    let typ_l = (* Type_predef. *)type_clock typ_in in
     type_subtyping_arg env in_main ~sub:false const expr_c typ_l;
-    expr.expr_type <- typ_out;
+    expr.expr_type <- Expr_type_hub.export typ_out;
     typ_out
   in 
-  Log.report ~level:3 (fun fmt -> Format.fprintf fmt "Type of expr %a: %a@." Printers.pp_expr expr Types.print_ty resulting_ty);
+  Log.report ~level:3 (fun fmt -> Format.fprintf fmt "Type of expr %a: %a@." Printers.pp_expr expr (* Types. *)print_ty resulting_ty);
   resulting_ty
 
-and type_branches env in_main loc const hl =
+and type_branches ?(is_annot=false) env in_main loc const hl =
   let typ_in = new_var () in
   let typ_out = new_var () in
   try
     let used_labels =
       List.fold_left (fun accu (t, h) ->
-	unify typ_in (type_const loc (Const_tag t));
+	unify typ_in (type_const ~is_annot loc (Const_tag t));
 	type_subtyping_arg env in_main const h typ_out;
 	if List.mem t accu
 	then raise (Error (loc, Already_bound t))
@@ -548,7 +585,7 @@ let type_coreclock env ck id loc =
           (fun expr (x, l) ->
                 {expr_tag = new_tag ();
                  expr_desc= Expr_when (expr,x,l);
-                 expr_type = new_var ();
+                 expr_type = Types.Main.new_var ();
                  expr_clock = Clocks.new_var true;
                  expr_delay = Delay.new_var ();
                  expr_loc=loc;
@@ -571,22 +608,22 @@ let rec check_type_declaration loc cty =
 let type_var_decl vd_env env 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 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;
+      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_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
   (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;
+  try_unify ty_static (Expr_type_hub.import 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;
 (*Format.eprintf "END %a@." Types.print_ty ty_static;*)
@@ -596,7 +633,7 @@ let type_var_decl_list vd_env env l =
   List.fold_left (type_var_decl vd_env) env l
 
 let type_of_vlist vars =
-  let tyl = List.map (fun v -> v.var_type) vars in
+  let tyl = List.map (fun v -> Expr_type_hub.import v.var_type) vars in
   type_of_type_list tyl
 
 let add_vdecl vd_env vdecl =
@@ -631,8 +668,12 @@ let type_node env nd loc =
   (* Typing asserts *)
   List.iter (fun assert_ ->
     let assert_expr =  assert_.assert_expr in
-    type_subtyping_arg (new_env, vd_env) is_main false assert_expr Type_predef.type_bool
+    type_subtyping_arg (new_env, vd_env) is_main false assert_expr (* Type_predef. *)type_bool
   )  nd.node_asserts;
+  (* Typing annots *)
+  List.iter (fun annot ->
+    List.iter (fun (_, eexpr) -> ignore (type_expr ~is_annot:true (new_env, vd_env) false false eexpr.eexpr_qfexpr)) annot.annots
+  ) nd.node_annot;
   
   (* check that table is empty *)
   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
@@ -644,7 +685,7 @@ let type_node env nd loc =
   let ty_node = new_ty (Tarrow (ty_ins,ty_outs)) in
   generalize ty_node;
   (* TODO ? Check that no node in the hierarchy remains polymorphic ? *)
-  nd.node_type <- ty_node;
+  nd.node_type <- Expr_type_hub.export ty_node;
   Env.add_value env nd.node_id ty_node
 
 let type_imported_node env nd loc =
@@ -661,7 +702,7 @@ let type_imported_node env nd loc =
     raise (Error (loc, Poly_imported_node nd.nodei_id));
 *)
   let new_env = Env.add_value env nd.nodei_id ty_node in
-  nd.nodei_type <- ty_node;
+  nd.nodei_type <- Expr_type_hub.export ty_node;
   new_env
 
 let type_top_const env cdecl =
@@ -670,9 +711,9 @@ let type_top_const env cdecl =
     if is_dimension_type ty
     then dimension_of_const cdecl.const_loc cdecl.const_value
     else Dimension.mkdim_var () in
-  let ty = Type_predef.type_static d ty in
+  let ty = (* Type_predef. *)type_static d ty in
   let new_env = Env.add_value env cdecl.const_id ty in
-  cdecl.const_type <- ty;
+  cdecl.const_type <- Expr_type_hub.export ty;
   new_env
 
 let type_top_consts env clist =
@@ -700,10 +741,10 @@ let rec type_top_decl env decl =
 let get_type_of_call decl =
   match decl.top_decl_desc with
   | Node nd         ->
-    let (in_typ, out_typ) = split_arrow nd.node_type in
+    let (in_typ, out_typ) = split_arrow (Expr_type_hub.import nd.node_type) in
     type_list_of_type in_typ, type_list_of_type out_typ
   | ImportedNode nd ->
-    let (in_typ, out_typ) = split_arrow nd.nodei_type in
+    let (in_typ, out_typ) = split_arrow (Expr_type_hub.import nd.nodei_type) in
     type_list_of_type in_typ, type_list_of_type out_typ
   | _               -> assert false
 
@@ -723,8 +764,8 @@ with Failure _ as exc -> raise exc
 let uneval_vdecl_generics vdecl =
  if vdecl.var_dec_const
  then
-   match get_static_value vdecl.var_type with
-   | None   -> (Format.eprintf "internal error: %a@." Types.print_ty vdecl.var_type; assert false)
+   match get_static_value (Expr_type_hub.import vdecl.var_type) with
+   | None   -> (Format.eprintf "internal error: %a@." (* Types. *)print_ty (Expr_type_hub.import vdecl.var_type); assert false)
    | Some d -> Dimension.uneval vdecl.var_id d
 
 let uneval_node_generics vdecls =
@@ -788,7 +829,13 @@ let check_typedef_top decl =
 
 let check_typedef_compat header =
   List.iter check_typedef_top header
+end
 
+include  Make(Types.Main) (struct
+  type type_expr  = Types.Main.type_expr
+  let import x = x
+  let export x = x
+end)
 (* Local Variables: *)
 (* compile-command:"make -C .." *)
 (* End: *)
-- 
GitLab